diff --git a/.hgtags b/.hgtags index 462b081a399..9ac115a08b5 100644 --- a/.hgtags +++ b/.hgtags @@ -345,3 +345,4 @@ f9bcdce2df26678c3fe468130b535c0342c69b89 jdk-9+99 4379223f8806626852c46c52d4e7a27a584b406e jdk-9+100 80f67512daa15cf37b4825c1c62a675d524d7c49 jdk-9+101 2dc4c11fe48831854916d53c3913bdb7d49023ea jdk-9+102 +4a652e4ca9523422149958673033e0ac740d5e1e jdk-9+103 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index ae78a92b7f7..9de50aa4824 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -345,3 +345,4 @@ cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90 c1f30ac14db0eaff398429c04cd9fab92e1b4b2a jdk-9+100 c4d72a1620835b5d657b7b6792c2879367d0154f jdk-9+101 6406ecf5d39482623225bb1b3098c2cac6f7d450 jdk-9+102 +47d6462e514b2097663305a57d9c844c15d5b609 jdk-9+103 diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index c295b3bf838..0fdc4605014 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -787,8 +787,6 @@ CPP ac_ct_CXX CXXFLAGS CXX -ac_ct_PROPER_COMPILER_CXX -PROPER_COMPILER_CXX TOOLCHAIN_PATH_CXX POTENTIAL_CXX OBJEXT @@ -798,8 +796,6 @@ CPPFLAGS LDFLAGS CFLAGS CC -ac_ct_PROPER_COMPILER_CC -PROPER_COMPILER_CC TOOLCHAIN_PATH_CC POTENTIAL_CC TOOLCHAIN_VERSION @@ -4119,16 +4115,6 @@ pkgadd_help() { - # -g is already added by ENABLE_DEBUG_SYMBOLS and the hotspot makefiles - # will basically do slowdebug builds when DEBUG_BINARIES is set for - # fastdebug builds - DEBUG_BINARIES=false - # Fastdebug builds with this setting will essentially be slowdebug - # in hotspot. - # -g is already added by ENABLE_DEBUG_SYMBOLS and the hotspot makefiles - # will basically do slowdebug builds when DEBUG_BINARIES is set for - # fastdebug builds - DEBUG_BINARIES=false # # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -4849,7 +4835,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1453385294 +DATE_WHEN_GENERATED=1454146111 ############################################################################### # @@ -32022,12 +32008,10 @@ $as_echo "$as_me: Rewriting CC to \"$new_complete\"" >&6;} fi TEST_COMPILER="$CC" - # Don't remove symbolic links on AIX because 'xlc_r' and 'xlC_r' may all be links - # to 'xlc' but it is crucial that we invoke the compiler with the right name! - if test "x$OPENJDK_BUILD_OS" != xaix; then - # FIXME: This test should not be needed anymore; we don't do that for any platform. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking resolved symbolic links for CC" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking resolved symbolic links for CC" >&5 $as_echo_n "checking resolved symbolic links for CC... " >&6; } + SYMLINK_ORIGINAL="$TEST_COMPILER" if test "x$OPENJDK_BUILD_OS" != xwindows; then # Follow a chain of symbolic links. Use readlink @@ -32046,13 +32030,13 @@ $as_echo_n "checking resolved symbolic links for CC... " >&6; } fi if test "x$READLINK" != x; then - TEST_COMPILER=`$READLINK -f $TEST_COMPILER` + SYMLINK_ORIGINAL=`$READLINK -f $SYMLINK_ORIGINAL` else # Save the current directory for restoring afterwards STARTDIR=$PWD COUNTER=0 - sym_link_dir=`$DIRNAME $TEST_COMPILER` - sym_link_file=`$BASENAME $TEST_COMPILER` + sym_link_dir=`$DIRNAME $SYMLINK_ORIGINAL` + sym_link_file=`$BASENAME $SYMLINK_ORIGINAL` cd $sym_link_dir # Use -P flag to resolve symlinks in directories. cd `$THEPWDCMD -P` @@ -32072,474 +32056,25 @@ $as_echo_n "checking resolved symbolic links for CC... " >&6; } let COUNTER=COUNTER+1 done cd $STARTDIR - TEST_COMPILER=$sym_link_dir/$sym_link_file + SYMLINK_ORIGINAL=$sym_link_dir/$sym_link_file fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEST_COMPILER" >&5 -$as_echo "$TEST_COMPILER" >&6; } - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if CC is disguised ccache" >&5 -$as_echo_n "checking if CC is disguised ccache... " >&6; } - - COMPILER_BASENAME=`$BASENAME "$TEST_COMPILER"` - if test "x$COMPILER_BASENAME" = "xccache"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, trying to find proper $COMPILER_NAME compiler" >&5 -$as_echo "yes, trying to find proper $COMPILER_NAME compiler" >&6; } - # We /usr/lib/ccache in the path, so cc is a symlink to /usr/bin/ccache. - # We want to control ccache invocation ourselves, so ignore this cc and try - # searching again. - - # Remove the path to the fake ccache cc from the PATH - RETRY_COMPILER_SAVED_PATH="$PATH" - COMPILER_DIRNAME=`$DIRNAME $CC` - PATH="`$ECHO $PATH | $SED -e "s,$COMPILER_DIRNAME,,g" -e "s,::,:,g" -e "s,^:,,g"`" - - # Try again looking for our compiler - if test -n "$ac_tool_prefix"; then - for ac_prog in $TOOLCHAIN_CC_BINARY - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$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_prog_PROPER_COMPILER_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$PROPER_COMPILER_CC"; then - ac_cv_prog_PROPER_COMPILER_CC="$PROPER_COMPILER_CC" # 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_PROPER_COMPILER_CC="$ac_tool_prefix$ac_prog" - $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 -PROPER_COMPILER_CC=$ac_cv_prog_PROPER_COMPILER_CC -if test -n "$PROPER_COMPILER_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PROPER_COMPILER_CC" >&5 -$as_echo "$PROPER_COMPILER_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$PROPER_COMPILER_CC" && break - done -fi -if test -z "$PROPER_COMPILER_CC"; then - ac_ct_PROPER_COMPILER_CC=$PROPER_COMPILER_CC - for ac_prog in $TOOLCHAIN_CC_BINARY -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_prog_ac_ct_PROPER_COMPILER_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_PROPER_COMPILER_CC"; then - ac_cv_prog_ac_ct_PROPER_COMPILER_CC="$ac_ct_PROPER_COMPILER_CC" # 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_ac_ct_PROPER_COMPILER_CC="$ac_prog" - $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 -ac_ct_PROPER_COMPILER_CC=$ac_cv_prog_ac_ct_PROPER_COMPILER_CC -if test -n "$ac_ct_PROPER_COMPILER_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_PROPER_COMPILER_CC" >&5 -$as_echo "$ac_ct_PROPER_COMPILER_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_PROPER_COMPILER_CC" && break -done - - if test "x$ac_ct_PROPER_COMPILER_CC" = x; then - PROPER_COMPILER_CC="" + if test "x$TEST_COMPILER" = "x$SYMLINK_ORIGINAL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no symlink" >&5 +$as_echo "no symlink" >&6; } else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - PROPER_COMPILER_CC=$ac_ct_PROPER_COMPILER_CC - fi -fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SYMLINK_ORIGINAL" >&5 +$as_echo "$SYMLINK_ORIGINAL" >&6; } - - # Only process if variable expands to non-empty - - if test "x$PROPER_COMPILER_CC" != x; then - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$PROPER_COMPILER_CC" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin 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=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin 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=`$CYGPATH -u "$path"` + # We can't handle ccache by gcc wrappers, since we need to know if we're + # using ccache. Instead ccache usage must be controlled by a configure option. + COMPILER_BASENAME=`$BASENAME "$SYMLINK_ORIGINAL"` + if test "x$COMPILER_BASENAME" = "xccache"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Please use --enable-ccache instead of providing a wrapped compiler." >&5 +$as_echo "$as_me: Please use --enable-ccache instead of providing a wrapped compiler." >&6;} + as_fn_error $? "$TEST_COMPILER is a symbolic link to ccache. This is not supported." "$LINENO" 5 fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CC, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of PROPER_COMPILER_CC, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CC" "$LINENO" 5 - fi - fi - - # 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 presence. - # 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 - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CC, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of PROPER_COMPILER_CC, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CC" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # 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-style (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 $input_to_shortpath | $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 - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$PROPER_COMPILER_CC" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - 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 - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - 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 - - - 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. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CC, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of PROPER_COMPILER_CC, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CC" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $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 \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_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 - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # 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}") - fi - - else - # We're on a unix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$PROPER_COMPILER_CC" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - # This is an absolute path, we can use it without further modifications. - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CC, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of PROPER_COMPILER_CC, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CC" "$LINENO" 5 - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - PROPER_COMPILER_CC="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting PROPER_COMPILER_CC to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting PROPER_COMPILER_CC to \"$new_complete\"" >&6;} - fi - fi - - PATH="$RETRY_COMPILER_SAVED_PATH" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for resolved symbolic links for CC" >&5 -$as_echo_n "checking for resolved symbolic links for CC... " >&6; } - - if test "x$OPENJDK_BUILD_OS" != xwindows; then - # Follow a chain of symbolic links. Use readlink - # where it exists, else fall back to horribly - # complicated shell code. - if test "x$READLINK_TESTED" != yes; then - # On MacOSX there is a readlink tool with a different - # purpose than the GNU readlink tool. Check the found readlink. - ISGNU=`$READLINK --version 2>&1 | $GREP GNU` - if test "x$ISGNU" = x; then - # A readlink that we do not know how to use. - # Are there other non-GNU readlinks out there? - READLINK_TESTED=yes - READLINK= - fi - fi - - if test "x$READLINK" != x; then - PROPER_COMPILER_CC=`$READLINK -f $PROPER_COMPILER_CC` - else - # Save the current directory for restoring afterwards - STARTDIR=$PWD - COUNTER=0 - sym_link_dir=`$DIRNAME $PROPER_COMPILER_CC` - sym_link_file=`$BASENAME $PROPER_COMPILER_CC` - cd $sym_link_dir - # Use -P flag to resolve symlinks in directories. - cd `$THEPWDCMD -P` - sym_link_dir=`$THEPWDCMD -P` - # Resolve file symlinks - while test $COUNTER -lt 20; do - ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'` - if test "x$ISLINK" == x; then - # This is not a symbolic link! We are done! - break - fi - # Again resolve directory symlinks since the target of the just found - # link could be in a different directory - cd `$DIRNAME $ISLINK` - sym_link_dir=`$THEPWDCMD -P` - sym_link_file=`$BASENAME $ISLINK` - let COUNTER=COUNTER+1 - done - cd $STARTDIR - PROPER_COMPILER_CC=$sym_link_dir/$sym_link_file - fi - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PROPER_COMPILER_CC" >&5 -$as_echo "$PROPER_COMPILER_CC" >&6; } - CC="$PROPER_COMPILER_CC" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, keeping CC" >&5 -$as_echo "no, keeping CC" >&6; } fi @@ -33770,12 +33305,10 @@ $as_echo "$as_me: Rewriting CXX to \"$new_complete\"" >&6;} fi TEST_COMPILER="$CXX" - # Don't remove symbolic links on AIX because 'xlc_r' and 'xlC_r' may all be links - # to 'xlc' but it is crucial that we invoke the compiler with the right name! - if test "x$OPENJDK_BUILD_OS" != xaix; then - # FIXME: This test should not be needed anymore; we don't do that for any platform. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking resolved symbolic links for CXX" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking resolved symbolic links for CXX" >&5 $as_echo_n "checking resolved symbolic links for CXX... " >&6; } + SYMLINK_ORIGINAL="$TEST_COMPILER" if test "x$OPENJDK_BUILD_OS" != xwindows; then # Follow a chain of symbolic links. Use readlink @@ -33794,13 +33327,13 @@ $as_echo_n "checking resolved symbolic links for CXX... " >&6; } fi if test "x$READLINK" != x; then - TEST_COMPILER=`$READLINK -f $TEST_COMPILER` + SYMLINK_ORIGINAL=`$READLINK -f $SYMLINK_ORIGINAL` else # Save the current directory for restoring afterwards STARTDIR=$PWD COUNTER=0 - sym_link_dir=`$DIRNAME $TEST_COMPILER` - sym_link_file=`$BASENAME $TEST_COMPILER` + sym_link_dir=`$DIRNAME $SYMLINK_ORIGINAL` + sym_link_file=`$BASENAME $SYMLINK_ORIGINAL` cd $sym_link_dir # Use -P flag to resolve symlinks in directories. cd `$THEPWDCMD -P` @@ -33820,474 +33353,25 @@ $as_echo_n "checking resolved symbolic links for CXX... " >&6; } let COUNTER=COUNTER+1 done cd $STARTDIR - TEST_COMPILER=$sym_link_dir/$sym_link_file + SYMLINK_ORIGINAL=$sym_link_dir/$sym_link_file fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEST_COMPILER" >&5 -$as_echo "$TEST_COMPILER" >&6; } - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if CXX is disguised ccache" >&5 -$as_echo_n "checking if CXX is disguised ccache... " >&6; } - - COMPILER_BASENAME=`$BASENAME "$TEST_COMPILER"` - if test "x$COMPILER_BASENAME" = "xccache"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, trying to find proper $COMPILER_NAME compiler" >&5 -$as_echo "yes, trying to find proper $COMPILER_NAME compiler" >&6; } - # We /usr/lib/ccache in the path, so cc is a symlink to /usr/bin/ccache. - # We want to control ccache invocation ourselves, so ignore this cc and try - # searching again. - - # Remove the path to the fake ccache cc from the PATH - RETRY_COMPILER_SAVED_PATH="$PATH" - COMPILER_DIRNAME=`$DIRNAME $CXX` - PATH="`$ECHO $PATH | $SED -e "s,$COMPILER_DIRNAME,,g" -e "s,::,:,g" -e "s,^:,,g"`" - - # Try again looking for our compiler - if test -n "$ac_tool_prefix"; then - for ac_prog in $TOOLCHAIN_CXX_BINARY - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$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_prog_PROPER_COMPILER_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$PROPER_COMPILER_CXX"; then - ac_cv_prog_PROPER_COMPILER_CXX="$PROPER_COMPILER_CXX" # 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_PROPER_COMPILER_CXX="$ac_tool_prefix$ac_prog" - $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 -PROPER_COMPILER_CXX=$ac_cv_prog_PROPER_COMPILER_CXX -if test -n "$PROPER_COMPILER_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PROPER_COMPILER_CXX" >&5 -$as_echo "$PROPER_COMPILER_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$PROPER_COMPILER_CXX" && break - done -fi -if test -z "$PROPER_COMPILER_CXX"; then - ac_ct_PROPER_COMPILER_CXX=$PROPER_COMPILER_CXX - for ac_prog in $TOOLCHAIN_CXX_BINARY -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_prog_ac_ct_PROPER_COMPILER_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_PROPER_COMPILER_CXX"; then - ac_cv_prog_ac_ct_PROPER_COMPILER_CXX="$ac_ct_PROPER_COMPILER_CXX" # 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_ac_ct_PROPER_COMPILER_CXX="$ac_prog" - $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 -ac_ct_PROPER_COMPILER_CXX=$ac_cv_prog_ac_ct_PROPER_COMPILER_CXX -if test -n "$ac_ct_PROPER_COMPILER_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_PROPER_COMPILER_CXX" >&5 -$as_echo "$ac_ct_PROPER_COMPILER_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_PROPER_COMPILER_CXX" && break -done - - if test "x$ac_ct_PROPER_COMPILER_CXX" = x; then - PROPER_COMPILER_CXX="" + if test "x$TEST_COMPILER" = "x$SYMLINK_ORIGINAL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no symlink" >&5 +$as_echo "no symlink" >&6; } else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - PROPER_COMPILER_CXX=$ac_ct_PROPER_COMPILER_CXX - fi -fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SYMLINK_ORIGINAL" >&5 +$as_echo "$SYMLINK_ORIGINAL" >&6; } - - # Only process if variable expands to non-empty - - if test "x$PROPER_COMPILER_CXX" != x; then - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$PROPER_COMPILER_CXX" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - new_path=`$CYGPATH -u "$path"` - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin 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=`$CYGPATH -u "$path"` - fi - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - new_path=`$CYGPATH -u "$path"` - new_path=`$WHICH "$new_path" 2> /dev/null` - # bat and cmd files are not always considered executable in cygwin 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=`$CYGPATH -u "$path"` + # We can't handle ccache by gcc wrappers, since we need to know if we're + # using ccache. Instead ccache usage must be controlled by a configure option. + COMPILER_BASENAME=`$BASENAME "$SYMLINK_ORIGINAL"` + if test "x$COMPILER_BASENAME" = "xccache"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Please use --enable-ccache instead of providing a wrapped compiler." >&5 +$as_echo "$as_me: Please use --enable-ccache instead of providing a wrapped compiler." >&6;} + as_fn_error $? "$TEST_COMPILER is a symbolic link to ccache. This is not supported." "$LINENO" 5 fi - if test "x$new_path" = x; then - # It's still not found. Now this is an unrecoverable error. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CXX, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of PROPER_COMPILER_CXX, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CXX" "$LINENO" 5 - fi - fi - - # 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 presence. - # 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 - # Short path failed, file does not exist as specified. - # Try adding .exe or .cmd - if test -f "${new_path}.exe"; then - input_to_shortpath="${new_path}.exe" - elif test -f "${new_path}.cmd"; then - input_to_shortpath="${new_path}.cmd" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CXX, which resolves as \"$new_path\", is invalid." >&5 -$as_echo "$as_me: The path of PROPER_COMPILER_CXX, which resolves as \"$new_path\", is invalid." >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&5 -$as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" >&6;} - as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CXX" "$LINENO" 5 - fi - else - input_to_shortpath="$new_path" - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - new_path="$input_to_shortpath" - - input_path="$input_to_shortpath" - # 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-style (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 $input_to_shortpath | $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 - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - # First separate the path from the arguments. This will split at the first - # space. - complete="$PROPER_COMPILER_CXX" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Input might be given as Windows format, start by converting to - # unix format. - 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 - - - # Now try to locate executable using which - new_path=`$WHICH "$new_path" 2> /dev/null` - - if test "x$new_path" = x; then - # Oops. Which didn't find the executable. - # The splitting of arguments from the executable at a space might have been incorrect, - # since paths with space are more likely in Windows. Give it another try with the whole - # argument. - path="$complete" - arguments="EOL" - 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 - - - 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. - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CXX, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of PROPER_COMPILER_CXX, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: You might be mixing spaces in the path and extra arguments, which is not allowed." >&5 -$as_echo "$as_me: You might be mixing spaces in the path and extra arguments, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CXX" "$LINENO" 5 - fi - fi - - # Now new_path has a complete unix path to the binary - if test "x`$ECHO $new_path | $GREP ^/bin/`" != x; then - # Keep paths in /bin as-is, but remove trailing .exe if any - new_path="${new_path/%.exe/}" - # Do not save /bin paths to all_fixpath_prefixes! - else - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $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 \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - # Output is in $new_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 - - # remove trailing .exe if any - new_path="${new_path/%.exe/}" - - # 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}") - fi - - else - # We're on a unix platform. Hooray! :) - # First separate the path from the arguments. This will split at the first - # space. - complete="$PROPER_COMPILER_CXX" - path="${complete%% *}" - tmp="$complete EOL" - arguments="${tmp#* }" - - # Cannot rely on the command "which" here since it doesn't always work. - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test -z "$is_absolute_path"; then - # Path to executable is not absolute. Find it. - IFS_save="$IFS" - IFS=: - for p in $PATH; do - if test -f "$p/$path" && test -x "$p/$path"; then - new_path="$p/$path" - break - fi - done - IFS="$IFS_save" - else - # This is an absolute path, we can use it without further modifications. - new_path="$path" - fi - - if test "x$new_path" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CXX, which resolves as \"$complete\", is not found." >&5 -$as_echo "$as_me: The path of PROPER_COMPILER_CXX, which resolves as \"$complete\", is not found." >&6;} - has_space=`$ECHO "$complete" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: This might be caused by spaces in the path, which is not allowed." >&5 -$as_echo "$as_me: This might be caused by spaces in the path, which is not allowed." >&6;} - fi - as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CXX" "$LINENO" 5 - fi - fi - - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi - - if test "x$complete" != "x$new_complete"; then - PROPER_COMPILER_CXX="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting PROPER_COMPILER_CXX to \"$new_complete\"" >&5 -$as_echo "$as_me: Rewriting PROPER_COMPILER_CXX to \"$new_complete\"" >&6;} - fi - fi - - PATH="$RETRY_COMPILER_SAVED_PATH" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for resolved symbolic links for CXX" >&5 -$as_echo_n "checking for resolved symbolic links for CXX... " >&6; } - - if test "x$OPENJDK_BUILD_OS" != xwindows; then - # Follow a chain of symbolic links. Use readlink - # where it exists, else fall back to horribly - # complicated shell code. - if test "x$READLINK_TESTED" != yes; then - # On MacOSX there is a readlink tool with a different - # purpose than the GNU readlink tool. Check the found readlink. - ISGNU=`$READLINK --version 2>&1 | $GREP GNU` - if test "x$ISGNU" = x; then - # A readlink that we do not know how to use. - # Are there other non-GNU readlinks out there? - READLINK_TESTED=yes - READLINK= - fi - fi - - if test "x$READLINK" != x; then - PROPER_COMPILER_CXX=`$READLINK -f $PROPER_COMPILER_CXX` - else - # Save the current directory for restoring afterwards - STARTDIR=$PWD - COUNTER=0 - sym_link_dir=`$DIRNAME $PROPER_COMPILER_CXX` - sym_link_file=`$BASENAME $PROPER_COMPILER_CXX` - cd $sym_link_dir - # Use -P flag to resolve symlinks in directories. - cd `$THEPWDCMD -P` - sym_link_dir=`$THEPWDCMD -P` - # Resolve file symlinks - while test $COUNTER -lt 20; do - ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'` - if test "x$ISLINK" == x; then - # This is not a symbolic link! We are done! - break - fi - # Again resolve directory symlinks since the target of the just found - # link could be in a different directory - cd `$DIRNAME $ISLINK` - sym_link_dir=`$THEPWDCMD -P` - sym_link_file=`$BASENAME $ISLINK` - let COUNTER=COUNTER+1 - done - cd $STARTDIR - PROPER_COMPILER_CXX=$sym_link_dir/$sym_link_file - fi - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PROPER_COMPILER_CXX" >&5 -$as_echo "$PROPER_COMPILER_CXX" >&6; } - CXX="$PROPER_COMPILER_CXX" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, keeping CXX" >&5 -$as_echo "no, keeping CXX" >&6; } fi @@ -58558,6 +57642,10 @@ fi fi done + # Due to https://llvm.org/bugs/show_bug.cgi?id=16902, llvm does not + # always properly detect -ltinfo + LLVM_LIBS="${LLVM_LIBS} -ltinfo" + diff --git a/common/autoconf/hotspot.m4 b/common/autoconf/hotspot.m4 index e6849af3af4..ec357f99572 100644 --- a/common/autoconf/hotspot.m4 +++ b/common/autoconf/hotspot.m4 @@ -266,14 +266,3 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_BUILD_TWEAKS], HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" AC_SUBST(HOTSPOT_MAKE_ARGS) ]) - - # -g is already added by ENABLE_DEBUG_SYMBOLS and the hotspot makefiles - # will basically do slowdebug builds when DEBUG_BINARIES is set for - # fastdebug builds - DEBUG_BINARIES=false - # Fastdebug builds with this setting will essentially be slowdebug - # in hotspot. - # -g is already added by ENABLE_DEBUG_SYMBOLS and the hotspot makefiles - # will basically do slowdebug builds when DEBUG_BINARIES is set for - # fastdebug builds - DEBUG_BINARIES=false \ No newline at end of file diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index cb3cddd7f92..7bae405555e 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -144,6 +144,10 @@ AC_DEFUN_ONCE([LIB_SETUP_LLVM], fi done + # Due to https://llvm.org/bugs/show_bug.cgi?id=16902, llvm does not + # always properly detect -ltinfo + LLVM_LIBS="${LLVM_LIBS} -ltinfo" + AC_SUBST(LLVM_CFLAGS) AC_SUBST(LLVM_LDFLAGS) AC_SUBST(LLVM_LIBS) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index e2a73d20ccf..a78b30ba5ad 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -500,7 +500,7 @@ JAVAC_FLAGS?=@JAVAC_FLAGS@ INTERIM_LANGTOOLS_JAR = $(BUILDTOOLS_OUTPUTDIR)/interim_langtools.jar INTERIM_LANGTOOLS_ARGS = "-Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR)" -cp $(INTERIM_LANGTOOLS_JAR) NEW_JAVAC = $(INTERIM_LANGTOOLS_ARGS) com.sun.tools.javac.Main -NEW_JAVADOC = $(INTERIM_LANGTOOLS_ARGS) com.sun.tools.javadoc.Main +NEW_JAVADOC = $(INTERIM_LANGTOOLS_ARGS) jdk.javadoc.internal.tool.Main # Base flags for RC # Guarding this against resetting value. Legacy make files include spec multiple diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 4254d86a4fb..5741294f309 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -433,39 +433,22 @@ AC_DEFUN([TOOLCHAIN_FIND_COMPILER], # Now we have a compiler binary in $1. Make sure it's okay. BASIC_FIXUP_EXECUTABLE($1) TEST_COMPILER="[$]$1" - # Don't remove symbolic links on AIX because 'xlc_r' and 'xlC_r' may all be links - # to 'xlc' but it is crucial that we invoke the compiler with the right name! - if test "x$OPENJDK_BUILD_OS" != xaix; then - # FIXME: This test should not be needed anymore; we don't do that for any platform. - AC_MSG_CHECKING([resolved symbolic links for $1]) - BASIC_REMOVE_SYMBOLIC_LINKS(TEST_COMPILER) - AC_MSG_RESULT([$TEST_COMPILER]) - fi - AC_MSG_CHECKING([if $1 is disguised ccache]) - COMPILER_BASENAME=`$BASENAME "$TEST_COMPILER"` - if test "x$COMPILER_BASENAME" = "xccache"; then - AC_MSG_RESULT([yes, trying to find proper $COMPILER_NAME compiler]) - # We /usr/lib/ccache in the path, so cc is a symlink to /usr/bin/ccache. - # We want to control ccache invocation ourselves, so ignore this cc and try - # searching again. - - # Remove the path to the fake ccache cc from the PATH - RETRY_COMPILER_SAVED_PATH="$PATH" - COMPILER_DIRNAME=`$DIRNAME [$]$1` - PATH="`$ECHO $PATH | $SED -e "s,$COMPILER_DIRNAME,,g" -e "s,::,:,g" -e "s,^:,,g"`" - - # Try again looking for our compiler - AC_CHECK_TOOLS(PROPER_COMPILER_$1, $3) - BASIC_FIXUP_EXECUTABLE(PROPER_COMPILER_$1) - PATH="$RETRY_COMPILER_SAVED_PATH" - - AC_MSG_CHECKING([for resolved symbolic links for $1]) - BASIC_REMOVE_SYMBOLIC_LINKS(PROPER_COMPILER_$1) - AC_MSG_RESULT([$PROPER_COMPILER_$1]) - $1="$PROPER_COMPILER_$1" + AC_MSG_CHECKING([resolved symbolic links for $1]) + SYMLINK_ORIGINAL="$TEST_COMPILER" + BASIC_REMOVE_SYMBOLIC_LINKS(SYMLINK_ORIGINAL) + if test "x$TEST_COMPILER" = "x$SYMLINK_ORIGINAL"; then + AC_MSG_RESULT([no symlink]) else - AC_MSG_RESULT([no, keeping $1]) + AC_MSG_RESULT([$SYMLINK_ORIGINAL]) + + # We can't handle ccache by gcc wrappers, since we need to know if we're + # using ccache. Instead ccache usage must be controlled by a configure option. + COMPILER_BASENAME=`$BASENAME "$SYMLINK_ORIGINAL"` + if test "x$COMPILER_BASENAME" = "xccache"; then + AC_MSG_NOTICE([Please use --enable-ccache instead of providing a wrapped compiler.]) + AC_MSG_ERROR([$TEST_COMPILER is a symbolic link to ccache. This is not supported.]) + fi fi TOOLCHAIN_CHECK_COMPILER_VERSION([$1], [$COMPILER_NAME]) diff --git a/common/bin/compare.sh b/common/bin/compare.sh index 9e680f08b0a..b417e8ed819 100644 --- a/common/bin/compare.sh +++ b/common/bin/compare.sh @@ -306,7 +306,7 @@ compare_general_files() { ! -name "*.lib" ! -name "*.war" ! -name "JavaControlPanel" \ ! -name "*.obj" ! -name "*.o" ! -name "JavaControlPanelHelper" \ ! -name "JavaUpdater" ! -name "JavaWSApplicationStub" \ - ! -name "jspawnhelper" \ + ! -name "jspawnhelper" ! -name "*.a" \ | $GREP -v "./bin/" | $SORT | $FILTER) echo Other files with binary differences... @@ -939,7 +939,7 @@ compare_all_libs() { WORK_DIR=$3 LIBS=$(cd $THIS_DIR && $FIND . -type f \( -name 'lib*.so' -o -name '*.dylib' \ - -o -name '*.dll' -o -name '*.obj' -o -name '*.o' \ + -o -name '*.dll' -o -name '*.obj' -o -name '*.o' -o -name '*.a' \ -o -name '*.cpl' \) | $SORT | $FILTER) if [ -n "$LIBS" ]; then diff --git a/corba/.hgtags b/corba/.hgtags index d486a0a69bb..ba693c7dd28 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -345,3 +345,4 @@ ea285530245cf4e0edf0479121a41347d3030eba jdk-9+98 791d0d3ac0138faeb6110bd840a4545bc1950df2 jdk-9+100 30dfb3bd3d06b4bb80a087babc0d1841edba187b jdk-9+101 9c4662334d933d299928d1f599d02ff50777cbf8 jdk-9+102 +0680fb7dae4da1ee6cf783c4b74184e3e08d3179 jdk-9+103 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 4731b6143c4..fbc7ac926fb 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -505,3 +505,4 @@ f008e8cc10d5b3212fb22d58c96fa01d38654f19 jdk-9+99 bdb0acafc63c42e84d9d8195bf2e2b25ee9c3306 jdk-9+100 9f45d3d57d6948cf526fbc2e2891a9a74ac6941a jdk-9+101 d5239fc1b69749ae50793c61b899fcdacf3df857 jdk-9+102 +c5f55130b1b69510d9a6f4a3105b58e21cd7ffe1 jdk-9+103 diff --git a/hotspot/test/gc/metaspace/TestPerfCountersAndMemoryPools.java b/hotspot/test/gc/metaspace/TestPerfCountersAndMemoryPools.java index c04f8ad9377..5d7d3852f43 100644 --- a/hotspot/test/gc/metaspace/TestPerfCountersAndMemoryPools.java +++ b/hotspot/test/gc/metaspace/TestPerfCountersAndMemoryPools.java @@ -64,14 +64,18 @@ public class TestPerfCountersAndMemoryPools { throws Exception { MemoryPoolMXBean pool = getMemoryPool(memoryPoolName); + // First, call all the methods to let them allocate their own slab of metadata + getMinCapacity(perfNS); + getCapacity(perfNS); + getUsed(perfNS); + pool.getUsage().getInit(); + pool.getUsage().getUsed(); + pool.getUsage().getCommitted(); + assertEQ(1L, 1L); + // Must do a GC to update performance counters System.gc(); assertEQ(getMinCapacity(perfNS), pool.getUsage().getInit()); - - // Must do a second GC to update the perfomance counters again, since - // the call pool.getUsage().getInit() could have allocated some - // metadata. - System.gc(); assertEQ(getUsed(perfNS), pool.getUsage().getUsed()); assertEQ(getCapacity(perfNS), pool.getUsage().getCommitted()); } diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 06990f8df41..75132348c9c 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -345,3 +345,4 @@ c8d0845877a811ab4350935892f826929359a3ff jdk-9+95 d45bcd374f6057851e3c2dcd45607cd362afadfa jdk-9+100 d3e834ff74e724a2b92a558e18e8cbf81c6dbc59 jdk-9+101 9dcf193c0b6cf22c0e89e2dc705a2c0f520ae064 jdk-9+102 +bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 25d05bf7a7f..9909ccb59aa 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -348,3 +348,4 @@ b55cebc47555293cf9c2aefb3bf63c56e847ab19 jdk-9+96 d0a97e57d2336238edf6a4cd60aafe67deb7258d jdk-9+100 3e99318616da903e0dc8f07f9f9203dc1bd49921 jdk-9+101 0868b93587cc99df3a4f4d3817a1aa756bea60ab jdk-9+102 +eb5e005a17e50d7d8340daaf21a5c3c5ae358d68 jdk-9+103 diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java index a0329cf7744..b6d9f4d2dc9 100644 --- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java +++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,11 +29,12 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; @@ -105,9 +106,9 @@ class ContextFinder { /** * If the {@link InvocationTargetException} wraps an exception that shouldn't be wrapped, - * throw the wrapped exception. + * throw the wrapped exception. Otherwise returns exception to be wrapped for further processing. */ - private static void handleInvocationTargetException(InvocationTargetException x) throws JAXBException { + private static Throwable handleInvocationTargetException(InvocationTargetException x) throws JAXBException { Throwable t = x.getTargetException(); if (t != null) { if (t instanceof JAXBException) @@ -118,7 +119,9 @@ class ContextFinder { throw (RuntimeException) t; if (t instanceof Error) throw (Error) t; + return t; } + return x; } @@ -157,9 +160,10 @@ class ContextFinder { } catch (ClassNotFoundException x) { throw new JAXBException(Messages.format(Messages.PROVIDER_NOT_FOUND, className), x); - } catch (RuntimeException x) { + } catch (RuntimeException | JAXBException x) { // avoid wrapping RuntimeException to JAXBException, // because it indicates a bug in this code. + // JAXBException re-thrown as is throw x; } catch (Exception x) { // can't catch JAXBException because the method is hidden behind @@ -189,8 +193,9 @@ class ContextFinder { try { Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class, Map.class); // any failure in invoking this method would be considered fatal - context = m.invoke(null, contextPath, classLoader, properties); - } catch (NoSuchMethodException e) { + Object obj = instantiateProviderIfNecessary(m); + context = m.invoke(obj, contextPath, classLoader, properties); + } catch (NoSuchMethodException ignored) { // it's not an error for the provider not to have this method. } @@ -198,8 +203,9 @@ class ContextFinder { // try the old method that doesn't take properties. compatible with 1.0. // it is an error for an implementation not to have both forms of the createContext method. Method m = spFactory.getMethod("createContext", String.class, ClassLoader.class); + Object obj = instantiateProviderIfNecessary(m); // any failure in invoking this method would be considered fatal - context = m.invoke(null, contextPath, classLoader); + context = m.invoke(obj, contextPath, classLoader); } if (!(context instanceof JAXBContext)) { @@ -208,18 +214,11 @@ class ContextFinder { } return (JAXBContext) context; } catch (InvocationTargetException x) { - handleInvocationTargetException(x); - // for other exceptions, wrap the internal target exception - // with a JAXBException - Throwable e = x; - if (x.getTargetException() != null) - e = x.getTargetException(); - + // throw if it is exception not to be wrapped + // otherwise, wrap with a JAXBException + Throwable e = handleInvocationTargetException(x); throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, spFactory, e), e); - } catch (RuntimeException x) { - // avoid wrapping RuntimeException to JAXBException, - // because it indicates a bug in this code. - throw x; + } catch (Exception x) { // can't catch JAXBException because the method is hidden behind // reflection. Root element collisions detected in the call to @@ -229,6 +228,23 @@ class ContextFinder { } } + private static Object instantiateProviderIfNecessary(Method m) throws JAXBException { + Class declaringClass = m.getDeclaringClass(); + try { + if (JAXBContextFactory.class.isAssignableFrom(declaringClass)) { + return AccessController.doPrivileged(new PrivilegedExceptionAction() { + @Override + public Object run() throws Exception { + return declaringClass.newInstance(); + } + }); + } + return null; + } catch (PrivilegedActionException e) { + throw new JAXBException(Messages.format(Messages.COULD_NOT_INSTANTIATE, declaringClass, e), e); + } + } + /** * Create an instance of a class using the thread context ClassLoader */ @@ -255,7 +271,8 @@ class ContextFinder { try { Method m = spFactory.getMethod("createContext", Class[].class, Map.class); - Object context = m.invoke(null, classes, properties); + Object obj = instantiateProviderIfNecessary(m); + Object context = m.invoke(obj, classes, properties); if (!(context instanceof JAXBContext)) { // the cast would fail, so generate an exception with a nice message throw handleClassCastException(context.getClass(), JAXBContext.class); @@ -264,13 +281,10 @@ class ContextFinder { } catch (NoSuchMethodException | IllegalAccessException e) { throw new JAXBException(e); - } catch (InvocationTargetException e) { - handleInvocationTargetException(e); - - Throwable x = e; - if (e.getTargetException() != null) - x = e.getTargetException(); + // throw if it is exception not to be wrapped + // otherwise, wrap with a JAXBException + Throwable x = handleInvocationTargetException(e); throw new JAXBException(x); } diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java index c5185236400..adfb479a849 100644 --- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java +++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,7 +94,7 @@ import java.io.InputStream; * allows the merging of global elements and type definitions across a set of schemas (listed * in the {@code contextPath}). Since each schema in the schema set can belong * to distinct namespaces, the unification of schemas to an unmarshalling - * context should be namespace independent. This means that a client + * context must be namespace independent. This means that a client * application is able to unmarshal XML documents that are instances of * any of the schemas listed in the {@code contextPath}. For example: * @@ -200,21 +200,28 @@ import java.io.InputStream; * *

Discovery of JAXB implementation

*

- * When one of the {@code newInstance} methods is called, a JAXB implementation is discovered - * by the following steps. + * To create an instance of {@link JAXBContext}, one of {@code JAXBContext.newInstance(...)} methods is invoked. After + * JAX-B implementation is discovered, call is delegated to appropriate provider's method {@code createContext(...)} + * passing parameters from the original call. + *

+ * JAX-B implementation discovery happens each time {@code JAXBContext.newInstance} is invoked. If there is no user + * specific configuration provided, default JAX-B provider must be returned. + *

+ * Implementation discovery consists of following steps: * *

    * *
  1. - * For each package/class explicitly passed in to the {@link #newInstance} method, in the order they are specified, - * {@code jaxb.properties} file is looked up in its package, by using the associated classloader — + * Packages/classes explicitly passed in to the {@link #newInstance} method are processed in the order they are + * specified, until {@code jaxb.properties} file is looked up in its package, by using the associated classloader — * this is {@link Class#getClassLoader() the owner class loader} for a {@link Class} argument, and for a package * the specified {@link ClassLoader}. * *

    - * If such a file is discovered, it is {@link Properties#load(InputStream) loaded} as a property file, and - * the value of the {@link #JAXB_CONTEXT_FACTORY} key will be assumed to be the provider factory class. - * This class is then loaded by the associated class loader discussed above. + * If such a resource is discovered, it is {@link Properties#load(InputStream) loaded} as a property file, and + * the value of the {@link #JAXB_CONTEXT_FACTORY} key will be assumed to be the provider factory class. If no value + * found, {@code "javax.xml.bind.context.factory"} is used as a key for backwards compatibility reasons. This class is + * then loaded by the associated class loader discussed above. * *

    * This phase of the look up allows some packages to force the use of a certain JAXB implementation. @@ -222,7 +229,9 @@ import java.io.InputStream; * *

  2. * If the system property {@link #JAXB_CONTEXT_FACTORY} exists, then its value is assumed to be the provider - * factory class. This phase of the look up enables per-JVM override of the JAXB implementation. + * factory class. If no such property exists, properties {@code "javax.xml.bind.context.factory"} and + * {@code "javax.xml.bind.JAXBContext"} are checked too (in this order), for backwards compatibility reasons. This phase + * of the look up enables per-JVM override of the JAXB implementation. * *
  3. * Provider of {@link javax.xml.bind.JAXBContextFactory} is loaded using the service-provider loading @@ -235,43 +244,58 @@ import java.io.InputStream; *
    * In case of {@link java.util.ServiceConfigurationError service * configuration error} a {@link javax.xml.bind.JAXBException} will be thrown. - *
  4. * *
  5. * Look for resource {@code /META-INF/services/javax.xml.bind.JAXBContext} using provided class loader. * Methods without class loader parameter use {@code Thread.currentThread().getContextClassLoader()}. - * If such a resource exists, its content is assumed to be the provider factory class and must supply - * an implementation class containing the following method signatures: + * If such a resource exists, its content is assumed to be the provider factory class. * - *
    - *
    - * public static JAXBContext createContext(
    - *                                      String contextPath,
    - *                                      ClassLoader classLoader,
    - *                                      Map<String,Object> properties throws JAXBException
    - *
    - * public static JAXBContext createContext(
    - *                                      Class[] classes,
    - *                                      Map<String,Object> properties ) throws JAXBException
    - * 
    * This configuration method is deprecated. * *
  6. * Finally, if all the steps above fail, then the rest of the look up is unspecified. That said, * the recommended behavior is to simply look for some hard-coded platform default JAXB implementation. - * This phase of the look up is so that JavaSE can have its own JAXB implementation as the last resort. + * This phase of the look up is so that Java SE can have its own JAXB implementation as the last resort. *
* *

- * Once the provider factory class {@link javax.xml.bind.JAXBContextFactory} is discovered, one of its methods - * {@link javax.xml.bind.JAXBContextFactory#createContext(String, ClassLoader, java.util.Map)} or - * {@link javax.xml.bind.JAXBContextFactory#createContext(Class[], java.util.Map)} is invoked - * to create a {@link JAXBContext}. + * Once the provider factory class is discovered, context creation is delegated to one of its + * {@code createContext(...)} methods. + * + * For backward compatibility reasons, there are two ways how to implement provider factory class: + *

    + *
  1. the class is implementation of {@link javax.xml.bind.JAXBContextFactory}. It must also implement no-arg + * constructor. If discovered in other step then 3, new instance using no-arg constructor is created first. + * After that, appropriate instance method is invoked on this instance. + *
  2. the class is not implementation of interface above and then it is mandated to implement the following + * static method signatures: + *
    + *
    + * public static JAXBContext createContext(
    + *                                      String contextPath,
    + *                                      ClassLoader classLoader,
    + *                                      Map<String,Object> properties ) throws JAXBException
    + *
    + * public static JAXBContext createContext(
    + *                                      Class[] classes,
    + *                                      Map<String,Object> properties ) throws JAXBException
    + * 
    + * In this scenario, appropriate static method is used instead of instance method. This approach is incompatible + * with {@link java.util.ServiceLoader} so it can't be used with step 3. + *
+ *

+ * There is no difference in behavior of given method {@code createContext(...)} regardless of whether it uses approach + * 1 (JAXBContextFactory) or 2 (no interface, static methods). * * @apiNote - *

Service discovery method using file /META-INF/services/javax.xml.bind.JAXBContext (described in step 4) - * and leveraging provider's static methods is supported only to allow backwards compatibility, but it is strongly - * recommended to migrate to standard ServiceLoader mechanism (described in step 3). + * Service discovery method using resource {@code /META-INF/services/javax.xml.bind.JAXBContext} (described in step 4) + * is supported only to allow backwards compatibility, it is strongly recommended to migrate to standard + * {@link java.util.ServiceLoader} mechanism (described in step 3). The difference here is the resource name, which + * doesn't match service's type name. + *

+ * Also using providers implementing interface {@link JAXBContextFactory} is preferred over using ones defining + * static methods, same as {@link JAXBContext#JAXB_CONTEXT_FACTORY} property is preferred over property + * {@code "javax.xml.bind.context.factory"} * * @implNote * Within the last step, if Glassfish AS environment detected, its specific service loader is used to find factory class. @@ -308,16 +332,10 @@ public abstract class JAXBContext { * the context class loader of the current thread. * * @throws JAXBException if an error was encountered while creating the - * {@code JAXBContext} such as - *

    - *
  1. failure to locate either ObjectFactory.class or jaxb.index in the packages
  2. - *
  3. an ambiguity among global elements contained in the contextPath
  4. - *
  5. failure to locate a value for the context factory provider property
  6. - *
  7. mixing schema derived packages from different providers on the same contextPath
  8. - *
+ * {@code JAXBContext}. See {@link JAXBContext#newInstance(String, ClassLoader, Map)} for details. */ public static JAXBContext newInstance( String contextPath ) - throws JAXBException { + throws JAXBException { //return newInstance( contextPath, JAXBContext.class.getClassLoader() ); return newInstance( contextPath, getContextClassLoader()); @@ -405,13 +423,7 @@ public abstract class JAXBContext { * * @return a new instance of a {@code JAXBContext} * @throws JAXBException if an error was encountered while creating the - * {@code JAXBContext} such as - *
    - *
  1. failure to locate either ObjectFactory.class or jaxb.index in the packages
  2. - *
  3. an ambiguity among global elements contained in the contextPath
  4. - *
  5. failure to locate a value for the context factory provider property
  6. - *
  7. mixing schema derived packages from different providers on the same contextPath
  8. - *
+ * {@code JAXBContext}. See {@link JAXBContext#newInstance(String, ClassLoader, Map)} for details. */ public static JAXBContext newInstance( String contextPath, ClassLoader classLoader ) throws JAXBException { @@ -427,7 +439,7 @@ public abstract class JAXBContext { * the instantiation of {@link JAXBContext}. * *

- * The interpretation of properties is up to implementations. Implementations should + * The interpretation of properties is up to implementations. Implementations must * throw {@code JAXBException} if it finds properties that it doesn't understand. * * @param contextPath list of java package names that contain schema derived classes @@ -439,13 +451,7 @@ public abstract class JAXBContext { * * @return a new instance of a {@code JAXBContext} * @throws JAXBException if an error was encountered while creating the - * {@code JAXBContext} such as - *

    - *
  1. failure to locate either ObjectFactory.class or jaxb.index in the packages
  2. - *
  3. an ambiguity among global elements contained in the contextPath
  4. - *
  5. failure to locate a value for the context factory provider property
  6. - *
  7. mixing schema derived packages from different providers on the same contextPath
  8. - *
+ * {@code JAXBContext}. See {@link #newInstance(String, ClassLoader)} for details. * @since 1.6, JAXB 2.0 */ public static JAXBContext newInstance( String contextPath, @@ -454,14 +460,14 @@ public abstract class JAXBContext { return ContextFinder.find( /* The default property name according to the JAXB spec */ - JAXB_CONTEXT_FACTORY, + JAXB_CONTEXT_FACTORY, /* the context path supplied by the client app */ - contextPath, + contextPath, /* class loader to be used */ - classLoader, - properties ); + classLoader, + properties ); } // TODO: resurrect this once we introduce external annotations @@ -583,17 +589,8 @@ public abstract class JAXBContext { * @return * A new instance of a {@code JAXBContext}. * - * @throws JAXBException - * if an error was encountered while creating the - * {@code JAXBContext}, such as (but not limited to): - *
    - *
  1. No JAXB implementation was discovered - *
  2. Classes use JAXB annotations incorrectly - *
  3. Classes have colliding annotations (i.e., two classes with the same type name) - *
  4. The JAXB implementation was unable to locate - * provider-specific out-of-band information (such as additional - * files generated at the development time.) - *
+ * @throws JAXBException if an error was encountered while creating the + * {@code JAXBContext}. See {@link JAXBContext#newInstance(Class[], Map)} for details. * * @throws IllegalArgumentException * if the parameter contains {@code null} (i.e., {@code newInstance(null);}) @@ -601,7 +598,7 @@ public abstract class JAXBContext { * @since 1.6, JAXB 2.0 */ public static JAXBContext newInstance( Class ... classesToBeBound ) - throws JAXBException { + throws JAXBException { return newInstance(classesToBeBound,Collections.emptyMap()); } @@ -614,7 +611,7 @@ public abstract class JAXBContext { * to configure 'properties' for this instantiation of {@link JAXBContext}. * *

- * The interpretation of properties is up to implementations. Implementations should + * The interpretation of properties is up to implementations. Implementations must * throw {@code JAXBException} if it finds properties that it doesn't understand. * * @param classesToBeBound @@ -646,10 +643,10 @@ public abstract class JAXBContext { * @since 1.6, JAXB 2.0 */ public static JAXBContext newInstance( Class[] classesToBeBound, Map properties ) - throws JAXBException { + throws JAXBException { if (classesToBeBound == null) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException(); } // but it is an error to have nulls in it. diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java index 09630484dc9..ef98dc61e4f 100644 --- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java +++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,14 +56,7 @@ public interface JAXBContextFactory { * * @throws JAXBException * if an error was encountered while creating the - * {@code JAXBContext}, such as (but not limited to): - *

    - *
  1. Classes use JAXB annotations incorrectly - *
  2. Classes have colliding annotations (i.e., two classes with the same type name) - *
  3. The JAXB implementation was unable to locate - * provider-specific out-of-band information (such as additional - * files generated at the development time.) - *
+ * {@code JAXBContext}. See {@link JAXBContext#newInstance(Class[], Map)} for details. * * @throws IllegalArgumentException * if the parameter contains {@code null} (i.e., {@code newInstance(null,someMap);}) @@ -81,7 +74,7 @@ public interface JAXBContextFactory { * For semantics see {@link javax.xml.bind.JAXBContext#newInstance(String, ClassLoader, java.util.Map)} * *

- * The interpretation of properties is up to implementations. Implementations should + * The interpretation of properties is up to implementations. Implementations must * throw {@code JAXBException} if it finds properties that it doesn't understand. * * @param contextPath list of java package names that contain schema derived classes @@ -93,13 +86,8 @@ public interface JAXBContextFactory { * * @return a new instance of a {@code JAXBContext} * @throws JAXBException if an error was encountered while creating the - * {@code JAXBContext} such as - *

    - *
  1. failure to locate either ObjectFactory.class or jaxb.index in the packages
  2. - *
  3. an ambiguity among global elements contained in the contextPath
  4. - *
  5. failure to locate a value for the context factory provider property
  6. - *
  7. mixing schema derived packages from different providers on the same contextPath
  8. - *
+ * {@code JAXBContext}. See {@link JAXBContext#newInstance(String, ClassLoader, Map)} for details. + * * @since 9, JAXB 2.3 */ JAXBContext createContext(String contextPath, diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index 5cbeb4b03f7..ea7c7f3c991 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -247,6 +247,13 @@ ifeq ($(OPENJDK_TARGET_OS), aix) LIBJIMAGE_TOOLCHAIN := TOOLCHAIN_LINK_CXX endif # OPENJDK_TARGET_OS aix +JIMAGELIB_CPPFLAGS := \ + -I$(JDK_TOPDIR)/src/java.base/share/native/libjava \ + -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ + -I$(JDK_TOPDIR)/src/java.base/share/native/libjimage \ + -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ + # + $(eval $(call SetupNativeCompilation,BUILD_LIBJIMAGE, \ LIBRARY := jimage, \ TOOLCHAIN := $(LIBJIMAGE_TOOLCHAIN), \ @@ -255,12 +262,8 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJIMAGE, \ SRC := $(JDK_TOPDIR)/src/java.base/share/native/libjimage \ $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjimage, \ EXCLUDES := $(LIBJIMAGE_EXCLUDES), \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(JIMAGELIB_CPPFLAGS) \ - -I$(JDK_TOPDIR)/src/java.base/share/native/libjava \ - -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ - -I$(JDK_TOPDIR)/src/java.base/share/native/libjimage \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base, \ + CFLAGS := $(CFLAGS_JDKLIB) $(JIMAGELIB_CPPFLAGS), \ + CXXFLAGS := $(CXXFLAGS_JDKLIB) $(JIMAGELIB_CPPFLAGS), \ CFLAGS_unix := -UDEBUG, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjimage/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ 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 48019cd31b3..ae93a7ca827 100644 --- a/jdk/src/java.base/share/classes/java/lang/Long.java +++ b/jdk/src/java.base/share/classes/java/lang/Long.java @@ -401,18 +401,6 @@ public final class Long extends Number implements Comparable { * @param offset the offset in the destination buffer to start at * @param len the number of characters to write */ - static void formatUnsignedLong(long val, int shift, char[] buf, int offset, int len) { - // assert shift > 0 && shift <=5 : "Illegal shift value"; - // assert offset >= 0 && offset < buf.length : "illegal offset"; - // assert len > 0 && (offset + len) <= buf.length : "illegal length"; - int charPos = offset + len; - int radix = 1 << shift; - int mask = radix - 1; - do { - buf[--charPos] = Integer.digits[((int) val) & mask]; - val >>>= shift; - } while (charPos > offset); - } /** byte[]/LATIN1 version */ static void formatUnsignedLong0(long val, int shift, byte[] buf, int offset, int len) { @@ -436,6 +424,39 @@ public final class Long extends Number implements Comparable { } while (charPos > offset); } + static String fastUUID(long lsb, long msb) { + if (COMPACT_STRINGS) { + byte[] buf = new byte[36]; + formatUnsignedLong0(lsb, 4, buf, 24, 12); + formatUnsignedLong0(lsb >>> 48, 4, buf, 19, 4); + formatUnsignedLong0(msb, 4, buf, 14, 4); + formatUnsignedLong0(msb >>> 16, 4, buf, 9, 4); + formatUnsignedLong0(msb >>> 32, 4, buf, 0, 8); + + buf[23] = '-'; + buf[18] = '-'; + buf[13] = '-'; + buf[8] = '-'; + + return new String(buf, LATIN1); + } else { + byte[] buf = new byte[72]; + + formatUnsignedLong0UTF16(lsb, 4, buf, 24, 12); + formatUnsignedLong0UTF16(lsb >>> 48, 4, buf, 19, 4); + formatUnsignedLong0UTF16(msb, 4, buf, 14, 4); + formatUnsignedLong0UTF16(msb >>> 16, 4, buf, 9, 4); + formatUnsignedLong0UTF16(msb >>> 32, 4, buf, 0, 8); + + StringUTF16.putChar(buf, 23, '-'); + StringUTF16.putChar(buf, 18, '-'); + StringUTF16.putChar(buf, 13, '-'); + StringUTF16.putChar(buf, 8, '-'); + + return new String(buf, UTF16); + } + } + /** * Returns a {@code String} object representing the specified * {@code long}. The argument is converted to signed decimal diff --git a/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java b/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java index d9517e5226f..1504e6ff37d 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java +++ b/jdk/src/java.base/share/classes/java/lang/StringConcatHelper.java @@ -342,4 +342,12 @@ final class StringConcatHelper { return new String(buf, coder); } + /** + * Provides the initial coder for the String. + * @return initial coder + */ + static byte initialCoder() { + return String.COMPACT_STRINGS ? String.LATIN1 : String.UTF16; + } + } 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 16b1e6b57e3..1919264ce52 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1911,11 +1911,8 @@ public final class System { public void invokeFinalize(Object o) throws Throwable { o.finalize(); } - public void formatUnsignedLong(long val, int shift, char[] buf, int offset, int len) { - Long.formatUnsignedLong(val, shift, buf, offset, len); - } - public void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) { - Integer.formatUnsignedInt(val, shift, buf, offset, len); + public String fastUUID(long lsb, long msb) { + return Long.fastUUID(lsb, msb); } }); } 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 f00be9c067e..e9bb8046246 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 @@ -30,7 +30,7 @@ import java.lang.reflect.Field; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; -import sun.misc.Cleaner; +import jdk.internal.ref.Cleaner; /** * The JVM interface for the method handles package is all here. diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatException.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatException.java index f6bc7e9bd87..1cf0a66e370 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatException.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatException.java @@ -26,6 +26,8 @@ package java.lang.invoke; /** * StringConcatException is thrown by {@link StringConcatFactory} when linkage * invariants are violated. + * + * @since 9 */ public class StringConcatException extends Exception { private static final long serialVersionUID = 292L + 9L; diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 6b0cfb8289c..008a4161bd5 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -30,7 +30,7 @@ import jdk.internal.org.objectweb.asm.Label; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.vm.annotation.ForceInline; -import sun.misc.Unsafe; +import jdk.internal.misc.Unsafe; import java.lang.invoke.MethodHandles.Lookup; import java.security.AccessController; @@ -96,6 +96,8 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; * more than 200 argument slots. Users requiring more than 200 argument slots in * concatenation are expected to split the large concatenation in smaller * expressions. + * + * @since 9 */ public final class StringConcatFactory { @@ -955,6 +957,22 @@ public final class StringConcatFactory { storage trimming, which defeats the purpose of exact strategies. */ + /* + The logic for this check is as follows: + + Stack before: Op: + (SB) dup, dup + (SB, SB, SB) capacity() + (int, SB, SB) swap + (SB, int, SB) toString() + (S, int, SB) length() + (int, int, SB) if_icmpeq + (SB) + + Note that it leaves the same StringBuilder on exit, like the one on enter. + */ + + mv.visitInsn(DUP); mv.visitInsn(DUP); mv.visitMethodInsn( @@ -965,7 +983,7 @@ public final class StringConcatFactory { false ); - mv.visitIntInsn(ISTORE, 0); + mv.visitInsn(SWAP); mv.visitMethodInsn( INVOKEVIRTUAL, @@ -975,8 +993,6 @@ public final class StringConcatFactory { false ); - mv.visitInsn(DUP); - mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/String", @@ -985,8 +1001,6 @@ public final class StringConcatFactory { false ); - mv.visitIntInsn(ILOAD, 0); - Label l0 = new Label(); mv.visitJumpInsn(IF_ICMPEQ, l0); @@ -1001,16 +1015,16 @@ public final class StringConcatFactory { mv.visitInsn(ATHROW); mv.visitLabel(l0); - } else { - mv.visitMethodInsn( - INVOKEVIRTUAL, - "java/lang/StringBuilder", - "toString", - "()Ljava/lang/String;", - false - ); } + mv.visitMethodInsn( + INVOKEVIRTUAL, + "java/lang/StringBuilder", + "toString", + "()Ljava/lang/String;", + false + ); + mv.visitInsn(ARETURN); mv.visitMaxs(-1, -1); @@ -1483,7 +1497,7 @@ public final class StringConcatFactory { // // The method handle shape after all length and coder mixers is: // (int, byte, )String = ("index", "coder", ) - byte initialCoder = 0; // initial coder + byte initialCoder = INITIAL_CODER; int initialLen = 0; // initial length, in characters for (RecipeElement el : recipe.getElements()) { switch (el.getTag()) { @@ -1616,11 +1630,14 @@ public final class StringConcatFactory { private static final ConcurrentMap, MethodHandle> LENGTH_MIXERS; private static final ConcurrentMap, MethodHandle> CODER_MIXERS; private static final Class STRING_HELPER; + private static final byte INITIAL_CODER; static { try { STRING_HELPER = Class.forName("java.lang.StringConcatHelper"); - } catch (ClassNotFoundException e) { + MethodHandle initCoder = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "initialCoder", byte.class); + INITIAL_CODER = (byte) initCoder.invoke(); + } catch (Throwable e) { throw new AssertionError(e); } diff --git a/jdk/src/java.base/share/classes/java/lang/ref/Reference.java b/jdk/src/java.base/share/classes/java/lang/ref/Reference.java index 0f06a6c937f..0a6728d007e 100644 --- a/jdk/src/java.base/share/classes/java/lang/ref/Reference.java +++ b/jdk/src/java.base/share/classes/java/lang/ref/Reference.java @@ -26,10 +26,10 @@ package java.lang.ref; import jdk.internal.vm.annotation.DontInline; -import sun.misc.Cleaner; import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.misc.JavaLangRefAccess; import jdk.internal.misc.SharedSecrets; +import jdk.internal.ref.Cleaner; /** * Abstract base class for reference objects. This class defines the diff --git a/jdk/src/java.base/share/classes/java/net/URI.java b/jdk/src/java.base/share/classes/java/net/URI.java index 862588019fd..069aedb685f 100644 --- a/jdk/src/java.base/share/classes/java/net/URI.java +++ b/jdk/src/java.base/share/classes/java/net/URI.java @@ -1080,11 +1080,8 @@ public final class URI * If a protocol handler for the URL could not be found, * or if some other error occurred while constructing the URL */ - public URL toURL() - throws MalformedURLException { - if (!isAbsolute()) - throw new IllegalArgumentException("URI is not absolute"); - return new URL(toString()); + public URL toURL() throws MalformedURLException { + return URL.fromURI(this); } // -- Component access methods -- diff --git a/jdk/src/java.base/share/classes/java/net/URL.java b/jdk/src/java.base/share/classes/java/net/URL.java index 8891a47dbdd..598e4103cf7 100644 --- a/jdk/src/java.base/share/classes/java/net/URL.java +++ b/jdk/src/java.base/share/classes/java/net/URL.java @@ -659,6 +659,44 @@ public final class URL implements java.io.Serializable { } } + /** + * Creates a URL from a URI, as if by invoking {@code uri.toURL()}. + * + * @see java.net.URI#toURL() + */ + static URL fromURI(URI uri) throws MalformedURLException { + if (!uri.isAbsolute()) { + throw new IllegalArgumentException("URI is not absolute"); + } + String protocol = uri.getScheme(); + + // In general we need to go via Handler.parseURL, but for the jrt + // protocol we enforce that the Handler is not overrideable and can + // optimize URI to URL conversion. + // + // Case-sensitive comparison for performance; malformed protocols will + // be handled correctly by the slow path. + if (protocol.equals("jrt") && !uri.isOpaque() + && uri.getRawFragment() == null) { + + String query = uri.getRawQuery(); + String path = uri.getRawPath(); + String file = (query == null) ? path : path + "?" + query; + + // URL represent undefined host as empty string while URI use null + String host = uri.getHost(); + if (host == null) { + host = ""; + } + + int port = uri.getPort(); + + return new URL("jrt", host, port, file, null); + } else { + return new URL((URL)null, uri.toString(), null); + } + } + /* * Returns true if specified string is a valid protocol name. */ @@ -1275,11 +1313,28 @@ public final class URL implements java.io.Serializable { } } - private static final String[] NON_OVERRIDEABLE_PROTOCOLS = {"file", "jrt"}; - private static boolean isOverrideable(String protocol) { - for (String p : NON_OVERRIDEABLE_PROTOCOLS) - if (protocol.equalsIgnoreCase(p)) + + /** + * Non-overrideable protocols: "jrt" and "file" + * + * Character-based comparison for performance reasons; also ensures + * case-insensitive comparison in a locale-independent fashion. + */ + static boolean isOverrideable(String protocol) { + if (protocol.length() == 3) { + if ((Character.toLowerCase(protocol.charAt(0)) == 'j') && + (Character.toLowerCase(protocol.charAt(1)) == 'r') && + (Character.toLowerCase(protocol.charAt(2)) == 't')) { return false; + } + } else if (protocol.length() == 4) { + if ((Character.toLowerCase(protocol.charAt(0)) == 'f') && + (Character.toLowerCase(protocol.charAt(1)) == 'i') && + (Character.toLowerCase(protocol.charAt(2)) == 'l') && + (Character.toLowerCase(protocol.charAt(3)) == 'e')) { + return false; + } + } return true; } diff --git a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index 16e495a4fba..76aa4a9c61b 100644 --- a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template @@ -28,9 +28,9 @@ package java.nio; import java.io.FileDescriptor; -import sun.misc.Cleaner; import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; +import jdk.internal.ref.Cleaner; import sun.nio.ch.DirectBuffer; diff --git a/jdk/src/java.base/share/classes/java/nio/file/Path.java b/jdk/src/java.base/share/classes/java/nio/file/Path.java index ac497c3c0cf..e7307e65640 100644 --- a/jdk/src/java.base/share/classes/java/nio/file/Path.java +++ b/jdk/src/java.base/share/classes/java/nio/file/Path.java @@ -150,7 +150,7 @@ public interface Path * #normalize normalize} method, to eliminate redundant names, for cases where * shell-like navigation is required. * - *

If this path has one or more elements, and no root component, then + *

If this path has more than one element, and no root component, then * this method is equivalent to evaluating the expression: *

      * subpath(0, getNameCount()-1);
diff --git a/jdk/src/java.base/share/classes/java/time/LocalDate.java b/jdk/src/java.base/share/classes/java/time/LocalDate.java
index 3d8c034fa91..940f21f0f1e 100644
--- a/jdk/src/java.base/share/classes/java/time/LocalDate.java
+++ b/jdk/src/java.base/share/classes/java/time/LocalDate.java
@@ -100,6 +100,8 @@ import java.time.temporal.ValueRange;
 import java.time.zone.ZoneOffsetTransition;
 import java.time.zone.ZoneRules;
 import java.util.Objects;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
 
 /**
  * A date without a time-zone in the ISO-8601 calendar system,
@@ -1715,6 +1717,89 @@ public final class LocalDate
         return Period.of(Math.toIntExact(years), months, days);
     }
 
+    /**
+     * Returns a sequential ordered stream of dates. The returned stream starts from this date
+     * (inclusive) and goes to {@code endExclusive} (exclusive) by an incremental step of 1 day.
+     * 

+ * This method is equivalent to {@code datesUntil(endExclusive, Period.ofDays(1))}. + * + * @param endExclusive the end date, exclusive, not null + * @return a sequential {@code Stream} for the range of {@code LocalDate} values + * @throws IllegalArgumentException if end date is before this date + * @since 9 + */ + public Stream datesUntil(LocalDate endExclusive) { + long end = endExclusive.toEpochDay(); + long start = toEpochDay(); + if (end < start) { + throw new IllegalArgumentException(endExclusive + " < " + this); + } + return LongStream.range(start, end).mapToObj(LocalDate::ofEpochDay); + } + + /** + * Returns a sequential ordered stream of dates by given incremental step. The returned stream + * starts from this date (inclusive) and goes to {@code endExclusive} (exclusive). + *

+ * The n-th date which appears in the stream is equal to {@code this.plus(step.multipliedBy(n))} + * (but the result of step multiplication never overflows). For example, if this date is + * {@code 2015-01-31}, the end date is {@code 2015-05-01} and the step is 1 month, then the + * stream contains {@code 2015-01-31}, {@code 2015-02-28}, {@code 2015-03-31}, and + * {@code 2015-04-30}. + * + * @param endExclusive the end date, exclusive, not null + * @param step the non-zero, non-negative {@code Period} which represents the step. + * @return a sequential {@code Stream} for the range of {@code LocalDate} values + * @throws IllegalArgumentException if step is zero, or {@code step.getDays()} and + * {@code step.toTotalMonths()} have opposite sign, or end date is before this date + * and step is positive, or end date is after this date and step is negative + * @since 9 + */ + public Stream datesUntil(LocalDate endExclusive, Period step) { + if (step.isZero()) { + throw new IllegalArgumentException("step is zero"); + } + long end = endExclusive.toEpochDay(); + long start = toEpochDay(); + long until = end - start; + long months = step.toTotalMonths(); + long days = step.getDays(); + if ((months < 0 && days > 0) || (months > 0 && days < 0)) { + throw new IllegalArgumentException("period months and days are of opposite sign"); + } + if (until == 0) { + return Stream.empty(); + } + int sign = months > 0 || days > 0 ? 1 : -1; + if (sign < 0 ^ until < 0) { + throw new IllegalArgumentException(endExclusive + (sign < 0 ? " > " : " < ") + this); + } + if (months == 0) { + long steps = (until - sign) / days; // non-negative + return LongStream.rangeClosed(0, steps).mapToObj( + n -> LocalDate.ofEpochDay(start + n * days)); + } + // 48699/1600 = 365.2425/12, no overflow, non-negative result + long steps = until * 1600 / (months * 48699 + days * 1600) + 1; + long addMonths = months * steps; + long addDays = days * steps; + long maxAddMonths = months > 0 ? MAX.getProlepticMonth() - getProlepticMonth() + : getProlepticMonth() - MIN.getProlepticMonth(); + // adjust steps estimation + if (addMonths * sign > maxAddMonths + || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) { + steps--; + addMonths -= months; + addDays -= days; + if (addMonths * sign > maxAddMonths + || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) { + steps--; + } + } + return LongStream.rangeClosed(0, steps).mapToObj( + n -> this.plusMonths(months * n).plusDays(days * n)); + } + /** * Formats this date using the specified formatter. *

diff --git a/jdk/src/java.base/share/classes/java/util/Map.java b/jdk/src/java.base/share/classes/java/util/Map.java index 0967523eba3..615bb0a5344 100644 --- a/jdk/src/java.base/share/classes/java/util/Map.java +++ b/jdk/src/java.base/share/classes/java/util/Map.java @@ -649,7 +649,7 @@ public interface Map { try { k = entry.getKey(); v = entry.getValue(); - } catch(IllegalStateException ise) { + } catch (IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } @@ -704,7 +704,7 @@ public interface Map { try { k = entry.getKey(); v = entry.getValue(); - } catch(IllegalStateException ise) { + } catch (IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } @@ -714,7 +714,7 @@ public interface Map { try { entry.setValue(v); - } catch(IllegalStateException ise) { + } catch (IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } @@ -887,7 +887,7 @@ public interface Map { * or atomicity properties of this method. Any implementation providing * atomicity guarantees must override this method and document its * concurrency properties. - * + * * @param key key with which the specified value is associated * @param value value to be associated with the specified key * @return the previous value associated with the specified key, or @@ -984,6 +984,9 @@ public interface Map { * @throws ClassCastException if the class of the specified key or value * prevents it from being stored in this map * (optional) + * @throws IllegalArgumentException if some property of the specified key + * or value prevents it from being stored in this map + * (optional) * @since 1.8 */ default V computeIfAbsent(K key, @@ -1058,6 +1061,9 @@ public interface Map { * @throws ClassCastException if the class of the specified key or value * prevents it from being stored in this map * (optional) + * @throws IllegalArgumentException if some property of the specified key + * or value prevents it from being stored in this map + * (optional) * @since 1.8 */ default V computeIfPresent(K key, @@ -1103,7 +1109,7 @@ public interface Map { *

 {@code
      * V oldValue = map.get(key);
      * V newValue = remappingFunction.apply(key, oldValue);
-     * if (oldValue != null ) {
+     * if (oldValue != null) {
      *    if (newValue != null)
      *       map.put(key, newValue);
      *    else
@@ -1147,6 +1153,9 @@ public interface Map {
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (optional)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (optional)
      * @since 1.8
      */
     default V compute(K key,
@@ -1239,6 +1248,9 @@ public interface Map {
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
      *         (optional)
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
+     *         (optional)
      * @throws NullPointerException if the specified key is null and this map
      *         does not support null keys or the value or remappingFunction is
      *         null
@@ -1251,7 +1263,7 @@ public interface Map {
         V oldValue = get(key);
         V newValue = (oldValue == null) ? value :
                    remappingFunction.apply(oldValue, value);
-        if(newValue == null) {
+        if (newValue == null) {
             remove(key);
         } else {
             put(key, newValue);
diff --git a/jdk/src/java.base/share/classes/java/util/Queue.java b/jdk/src/java.base/share/classes/java/util/Queue.java
index b5456b99f2f..7d5e39c7030 100644
--- a/jdk/src/java.base/share/classes/java/util/Queue.java
+++ b/jdk/src/java.base/share/classes/java/util/Queue.java
@@ -129,14 +129,6 @@ package java.util;
  * 
  * Java Collections Framework.
  *
- * @see java.util.Collection
- * @see LinkedList
- * @see PriorityQueue
- * @see java.util.concurrent.LinkedBlockingQueue
- * @see java.util.concurrent.BlockingQueue
- * @see java.util.concurrent.ArrayBlockingQueue
- * @see java.util.concurrent.LinkedBlockingQueue
- * @see java.util.concurrent.PriorityBlockingQueue
  * @since 1.5
  * @author Doug Lea
  * @param  the type of elements held in this queue
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 a7f5f6bc63e..db9e907110b 100644
--- a/jdk/src/java.base/share/classes/java/util/UUID.java
+++ b/jdk/src/java.base/share/classes/java/util/UUID.java
@@ -392,17 +392,7 @@ public final class UUID implements java.io.Serializable, Comparable {
      * @return  A string representation of this {@code UUID}
      */
     public String toString() {
-        char[] chars = new char[36];
-        jla.formatUnsignedLong(mostSigBits >> 32, 4, chars, 0, 8);
-        chars[8] = '-';
-        jla.formatUnsignedLong(mostSigBits >> 16, 4, chars, 9, 4);
-        chars[13] = '-';
-        jla.formatUnsignedLong(mostSigBits, 4, chars, 14, 4);
-        chars[18] = '-';
-        jla.formatUnsignedLong(leastSigBits >> 48, 4, chars, 19, 4);
-        chars[23] = '-';
-        jla.formatUnsignedLong(leastSigBits, 4, chars, 24, 12);
-        return jla.newStringUnsafe(chars);
+        return jla.fastUUID(leastSigBits, mostSigBits);
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java
index 37b97c36265..d301de9eee6 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java
@@ -301,19 +301,15 @@ public interface ConcurrentMap extends Map {
      *
      * @implSpec
      * The default implementation is equivalent to the following steps for this
-     * {@code map}, then returning the current value or {@code null} if now
-     * absent:
+     * {@code map}:
      *
      * 
 {@code
-     * if (map.get(key) == null) {
-     *   V newValue = mappingFunction.apply(key);
-     *   if (newValue != null)
-     *     return map.putIfAbsent(key, newValue);
-     * }}
- * - * The default implementation may retry these steps when multiple - * threads attempt updates including potentially calling the mapping - * function multiple times. + * V oldValue, newValue; + * return ((oldValue = map.get(key)) == null + * && (newValue = mappingFunction.apply(key)) != null + * && (oldValue = map.putIfAbsent(key, newValue)) == null) + * ? newValue + * : oldValue;}
* *

This implementation assumes that the ConcurrentMap cannot contain null * values and {@code get()} returning null unambiguously means the key is @@ -323,16 +319,19 @@ public interface ConcurrentMap extends Map { * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} * @since 1.8 */ @Override default V computeIfAbsent(K key, Function mappingFunction) { Objects.requireNonNull(mappingFunction); - V v, newValue; - return ((v = get(key)) == null && - (newValue = mappingFunction.apply(key)) != null && - (v = putIfAbsent(key, newValue)) == null) ? newValue : v; + V oldValue, newValue; + return ((oldValue = get(key)) == null + && (newValue = mappingFunction.apply(key)) != null + && (oldValue = putIfAbsent(key, newValue)) == null) + ? newValue + : oldValue; } /** @@ -340,22 +339,19 @@ public interface ConcurrentMap extends Map { * * @implSpec * The default implementation is equivalent to performing the following - * steps for this {@code map}, then returning the current value or - * {@code null} if now absent: + * steps for this {@code map}: * *

 {@code
-     * if (map.get(key) != null) {
-     *   V oldValue = map.get(key);
+     * for (V oldValue; (oldValue = map.get(key)) != null; ) {
      *   V newValue = remappingFunction.apply(key, oldValue);
-     *   if (newValue != null)
-     *     map.replace(key, oldValue, newValue);
-     *   else
-     *     map.remove(key, oldValue);
-     * }}
- * - * The default implementation may retry these steps when multiple threads - * attempt updates including potentially calling the remapping function - * multiple times. + * if ((newValue == null) + * ? map.remove(key, oldValue) + * : map.replace(key, oldValue, newValue)) + * return newValue; + * } + * return null;}
+ * When multiple threads attempt updates, map operations and the + * remapping function may be called multiple times. * *

This implementation assumes that the ConcurrentMap cannot contain null * values and {@code get()} returning null unambiguously means the key is @@ -365,22 +361,21 @@ public interface ConcurrentMap extends Map { * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} * @since 1.8 */ @Override default V computeIfPresent(K key, BiFunction remappingFunction) { Objects.requireNonNull(remappingFunction); - V oldValue; - while ((oldValue = get(key)) != null) { + for (V oldValue; (oldValue = get(key)) != null; ) { V newValue = remappingFunction.apply(key, oldValue); - if (newValue != null) { - if (replace(key, oldValue, newValue)) - return newValue; - } else if (remove(key, oldValue)) - return null; + if ((newValue == null) + ? remove(key, oldValue) + : replace(key, oldValue, newValue)) + return newValue; } - return oldValue; + return null; } /** @@ -388,27 +383,23 @@ public interface ConcurrentMap extends Map { * * @implSpec * The default implementation is equivalent to performing the following - * steps for this {@code map}, then returning the current value or - * {@code null} if absent: + * steps for this {@code map}: * *

 {@code
-     * V oldValue = map.get(key);
-     * V newValue = remappingFunction.apply(key, oldValue);
-     * if (oldValue != null ) {
-     *   if (newValue != null)
-     *     map.replace(key, oldValue, newValue);
-     *   else
-     *     map.remove(key, oldValue);
-     * } else {
-     *   if (newValue != null)
-     *     map.putIfAbsent(key, newValue);
-     *   else
+     * for (;;) {
+     *   V oldValue = map.get(key);
+     *   V newValue = remappingFunction.apply(key, oldValue);
+     *   if (newValue != null) {
+     *     if ((oldValue != null)
+     *       ? map.replace(key, oldValue, newValue)
+     *       : map.putIfAbsent(key, newValue) == null)
+     *       return newValue;
+     *   } else if (oldValue == null || map.remove(key, oldValue)) {
      *     return null;
+     *   }
      * }}
- * - * The default implementation may retry these steps when multiple - * threads attempt updates including potentially calling the remapping - * function multiple times. + * When multiple threads attempt updates, map operations and the + * remapping function may be called multiple times. * *

This implementation assumes that the ConcurrentMap cannot contain null * values and {@code get()} returning null unambiguously means the key is @@ -418,50 +409,29 @@ public interface ConcurrentMap extends Map { * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} * @since 1.8 */ @Override default V compute(K key, - BiFunction remappingFunction) { - Objects.requireNonNull(remappingFunction); - V oldValue = get(key); - for (;;) { - V newValue = remappingFunction.apply(key, oldValue); - if (newValue == null) { - // delete mapping - if (oldValue != null || containsKey(key)) { - // something to remove - if (remove(key, oldValue)) { - // removed the old value as expected - return null; + BiFunction remappingFunction) { + retry: for (;;) { + V oldValue = get(key); + // if putIfAbsent fails, opportunistically use its return value + haveOldValue: for (;;) { + V newValue = remappingFunction.apply(key, oldValue); + if (newValue != null) { + if (oldValue != null) { + if (replace(key, oldValue, newValue)) + return newValue; } - - // some other value replaced old value. try again. - oldValue = get(key); - } else { - // nothing to do. Leave things as they were. + else if ((oldValue = putIfAbsent(key, newValue)) == null) + return newValue; + else continue haveOldValue; + } else if (oldValue == null || remove(key, oldValue)) { return null; } - } else { - // add or replace old mapping - if (oldValue != null) { - // replace - if (replace(key, oldValue, newValue)) { - // replaced as expected. - return newValue; - } - - // some other value replaced old value. try again. - oldValue = get(key); - } else { - // add (replace if oldValue was null) - if ((oldValue = putIfAbsent(key, newValue)) == null) { - // replaced - return newValue; - } - - // some other value replaced old value. try again. - } + continue retry; } } } @@ -471,21 +441,25 @@ public interface ConcurrentMap extends Map { * * @implSpec * The default implementation is equivalent to performing the following - * steps for this {@code map}, then returning the current value or - * {@code null} if absent: + * steps for this {@code map}: * *

 {@code
-     * V oldValue = map.get(key);
-     * V newValue = (oldValue == null) ? value :
-     *     remappingFunction.apply(oldValue, value);
-     * if (newValue == null)
-     *   map.remove(key);
-     * else
-     *   map.put(key, newValue);}
- * - *

The default implementation may retry these steps when multiple - * threads attempt updates including potentially calling the remapping - * function multiple times. + * for (;;) { + * V oldValue = map.get(key); + * if (oldValue != null) { + * V newValue = remappingFunction.apply(oldValue, value); + * if (newValue != null) { + * if (map.replace(key, oldValue, newValue)) + * return newValue; + * } else if (map.remove(key, oldValue)) { + * return null; + * } + * } else if (map.putIfAbsent(key, value) == null) { + * return value; + * } + * }} + * When multiple threads attempt updates, map operations and the + * remapping function may be called multiple times. * *

This implementation assumes that the ConcurrentMap cannot contain null * values and {@code get()} returning null unambiguously means the key is @@ -495,6 +469,7 @@ public interface ConcurrentMap extends Map { * @throws UnsupportedOperationException {@inheritDoc} * @throws ClassCastException {@inheritDoc} * @throws NullPointerException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} * @since 1.8 */ @Override @@ -502,20 +477,23 @@ public interface ConcurrentMap extends Map { BiFunction remappingFunction) { Objects.requireNonNull(remappingFunction); Objects.requireNonNull(value); - V oldValue = get(key); - for (;;) { - if (oldValue != null) { - V newValue = remappingFunction.apply(oldValue, value); - if (newValue != null) { - if (replace(key, oldValue, newValue)) - return newValue; - } else if (remove(key, oldValue)) { - return null; - } - oldValue = get(key); - } else { - if ((oldValue = putIfAbsent(key, value)) == null) { - return value; + retry: for (;;) { + V oldValue = get(key); + // if putIfAbsent fails, opportunistically use its return value + haveOldValue: for (;;) { + if (oldValue != null) { + V newValue = remappingFunction.apply(oldValue, value); + if (newValue != null) { + if (replace(key, oldValue, newValue)) + return newValue; + } else if (remove(key, oldValue)) { + return null; + } + continue retry; + } else { + if ((oldValue = putIfAbsent(key, value)) == null) + return value; + continue haveOldValue; } } } diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java b/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java index 44268d97fbd..1395886faa5 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java @@ -35,6 +35,9 @@ package java.util.concurrent; +import java.time.temporal.ChronoUnit; +import java.util.Objects; + /** * A {@code TimeUnit} represents time durations at a given unit of * granularity and provides utility methods to convert across units, @@ -390,4 +393,48 @@ public enum TimeUnit { } } + /** + * Converts this {@code TimeUnit} to the equivalent {@code ChronoUnit}. + * + * @return the converted equivalent ChronoUnit + * @since 9 + */ + public ChronoUnit toChronoUnit() { + switch (this) { + case NANOSECONDS: return ChronoUnit.NANOS; + case MICROSECONDS: return ChronoUnit.MICROS; + case MILLISECONDS: return ChronoUnit.MILLIS; + case SECONDS: return ChronoUnit.SECONDS; + case MINUTES: return ChronoUnit.MINUTES; + case HOURS: return ChronoUnit.HOURS; + case DAYS: return ChronoUnit.DAYS; + default: throw new AssertionError(); + } + } + + /** + * Converts a {@code ChronoUnit} to the equivalent {@code TimeUnit}. + * + * @param chronoUnit the ChronoUnit to convert + * @return the converted equivalent TimeUnit + * @throws IllegalArgumentException if {@code chronoUnit} has no + * equivalent TimeUnit + * @throws NullPointerException if {@code chronoUnit} is null + * @since 9 + */ + public static TimeUnit of(ChronoUnit chronoUnit) { + switch (Objects.requireNonNull(chronoUnit, "chronoUnit")) { + case NANOS: return TimeUnit.NANOSECONDS; + case MICROS: return TimeUnit.MICROSECONDS; + case MILLIS: return TimeUnit.MILLISECONDS; + case SECONDS: return TimeUnit.SECONDS; + case MINUTES: return TimeUnit.MINUTES; + case HOURS: return TimeUnit.HOURS; + case DAYS: return TimeUnit.DAYS; + default: + throw new IllegalArgumentException( + "No TimeUnit equivalent for " + chronoUnit); + } + } + } diff --git a/jdk/src/java.base/share/classes/jdk/Version.java b/jdk/src/java.base/share/classes/jdk/Version.java new file mode 100644 index 00000000000..9ce9ec9314d --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/Version.java @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk; + +import java.math.BigInteger; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * A representation of the JDK version-string which contains a version + * number optionally followed by pre-release and build information. + * + *

Version numbers

+ * + * A version number, {@code $VNUM}, is a non-empty sequence of + * non-negative integer numerals, without leading or trailing zeroes, + * separated by period characters (U+002E); i.e., it matches the regular + * expression {@code ^[1-9][0-9]*(((\.0)*\.[1-9][0-9]*)*)*$}. The sequence may + * be of arbitrary length but the first three elements are assigned specific + * meanings, as follows: + * + *
+ *     $MAJOR.$MINOR.$SECURITY
+ * 
+ * + *
    + * + *
  • {@code $MAJOR} --- The major version number, + * incremented for a major release that contains significant new features as + * specified in a new edition of the Java SE Platform Specification, + * e.g., JSR 337 + * for Java SE 8. Features may be removed in a major release, given + * advance notice at least one major release ahead of time, and incompatible + * changes may be made when justified. The {@code $MAJOR} version number of + * JDK 8 was {@code 8}; the {@code $MAJOR} version number of JDK 9 + * is {@code 9}.

  • + * + *
  • {@code $MINOR} --- The minor version number, + * incremented for a minor update release that may contain compatible bug + * fixes, revisions to standard APIs mandated by a Maintenance Release of + * the relevant Platform Specification, and implementation features outside + * the scope of that Specification such as new JDK-specific APIs, additional + * service providers, new garbage collectors, and ports to new hardware + * architectures. {@code $MINOR} is reset to zero when {@code $MAJOR} is + * incremented.

  • + * + *
  • {@code $SECURITY} --- The security level, + * incremented for a security-update release that contains critical fixes + * including those necessary to improve security. {@code $SECURITY} is reset + * to zero only when {@code $MAJOR} is incremented. A higher + * value of {@code $SECURITY} for a given {@code $MAJOR} value, therefore, + * always indicates a more secure release, regardless of the value of {@code + * $MINOR}.

  • + * + *
+ * + *

The fourth and later elements of a version number are free for use by + * downstream consumers of the JDK code base. Such a consumer may, + * e.g., use the fourth element to identify patch releases which + * contain a small number of critical non-security fixes in addition to the + * security fixes in the corresponding security release.

+ * + *

The version number does not include trailing zero elements; + * i.e., {@code $SECURITY} is omitted if it has the value zero, and + * {@code $MINOR} is omitted if both {@code $MINOR} and {@code $SECURITY} have + * the value zero.

+ * + *

The sequence of numerals in a version number is compared to another + * such sequence in numerical, pointwise fashion; e.g., {@code 9.9.1} + * is less than {@code 9.10.0}. If one sequence is shorter than another then + * the missing elements of the shorter sequence are considered to be zero; + * e.g., {@code 9.1.2} is equal to {@code 9.1.2.0} but less than + * {@code 9.1.2.1}.

+ * + *

Version strings

+ * + *

A version string {@code $VSTR} consists of a version number + * {@code $VNUM}, as described above, optionally followed by pre-release and + * build information, in the format

+ * + *
+ *     $VNUM(-$PRE)?(\+($BUILD)?(-$OPT)?)?
+ * 
+ * + *

where:

+ * + *
    + * + *
  • {@code $PRE}, matching {@code ([a-zA-Z0-9]+)} --- + * A pre-release identifier. Typically {@code ea}, for an early-access + * release that's under active development and potentially unstable, or {@code + * internal}, for an internal developer build. + * + *

  • {@code $BUILD}, matching {@code + * (0|[1-9][0-9]*)} --- The build number, incremented for each promoted build. + * {@code $BUILD} is reset to {@code 1} when any portion of {@code $VNUM} is + * incremented.

    + * + *
  • {@code $OPT}, matching {@code ([-a-zA-Z0-9\.]+)} + * --- Additional build information, if desired. In the case of an {@code + * internal} build this will often contain the date and time of the + * build.

    + * + *
+ * + *

When comparing two version strings the value of {@code $OPT}, if + * present, may or may not be significant depending on the chosen comparison + * method. The comparison methods {@link #compareTo(Version) compareTo()} and + * {@link #compareToIgnoreOpt(Version) compareToIgnoreOpt{}} should be used + * consistently with the corresponding methods {@link #equals(Object) equals()} + * and {@link #equalsIgnoreOpt(Object) equalsIgnoreOpt()}.

+ * + *

A short version string ({@code $SVSTR}), often useful in less + * formal contexts, is simply {@code $VNUM} optionally ended with {@code + * -$PRE}.

+ * + * @since 9 + */ +public final class Version + implements Comparable +{ + private final List version; + private final Optional pre; + private final Optional build; + private final Optional optional; + + private static Version current; + + // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)? + // RE limits the format of version strings + // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))? + + private static final String VNUM + = "(?[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)"; + private static final String VNUM_GROUP = "VNUM"; + + private static final String PRE = "(?:-(?
[a-zA-Z0-9]+))?";
+    private static final String PRE_GROUP   = "PRE";
+
+    private static final String BUILD
+        = "(?:(?\\+)(?0|[1-9][0-9]*)?)?";
+    private static final String PLUS_GROUP  = "PLUS";
+    private static final String BUILD_GROUP = "BUILD";
+
+    private static final String OPT      = "(?:-(?[-a-zA-Z0-9.]+))?";
+    private static final String OPT_GROUP   = "OPT";
+
+    private static final String VSTR_FORMAT
+        = "^" + VNUM + PRE + BUILD + OPT + "$";
+    private static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
+
+    /**
+     * Constructs a valid JDK version string containing a
+     * version number followed by pre-release and build
+     * information.
+     *
+     * @param  s
+     *         A string to be interpreted as a version
+     *
+     * @throws  IllegalArgumentException
+     *          If the given string cannot be interpreted a valid version
+     *
+     * @throws  NullPointerException
+     *          If {@code s} is {@code null}
+     *
+     * @throws  NumberFormatException
+     *          If an element of the version number or the build number cannot
+     *          be represented as an {@link Integer}
+     */
+    private Version(String s) {
+        if (s == null)
+            throw new NullPointerException();
+
+        Matcher m = VSTR_PATTERN.matcher(s);
+        if (!m.matches())
+            throw new IllegalArgumentException("Invalid version string: '"
+                                               + s + "'");
+
+        // $VNUM is a dot-separated list of integers of arbitrary length
+        version
+            = Collections.unmodifiableList(
+                  Arrays.stream(m.group(VNUM_GROUP).split("\\."))
+                  .map(Integer::parseInt)
+                  .collect(Collectors.toList()));
+
+        pre = Optional.ofNullable(m.group(PRE_GROUP));
+
+        String b = m.group(BUILD_GROUP);
+        // $BUILD is an integer
+        build = (b == null)
+             ? Optional.empty()
+             : Optional.ofNullable(Integer.parseInt(b));
+
+        optional = Optional.ofNullable(m.group(OPT_GROUP));
+
+        // empty '+'
+        if ((m.group(PLUS_GROUP) != null) && !build.isPresent()) {
+            if (optional.isPresent()) {
+                if (pre.isPresent())
+                    throw new IllegalArgumentException("'+' found with"
+                        + " pre-release and optional components:'" + s + "'");
+            } else {
+                throw new IllegalArgumentException("'+' found with neither"
+                    + " build or optional components: '" + s + "'");
+            }
+        }
+    }
+
+    /**
+     * Parses the given string as a valid JDK version string containing a version number followed by pre-release and
+     * build information.
+     *
+     * @param  s
+     *         A string to interpret as a version
+     *
+     * @throws  IllegalArgumentException
+     *          If the given string cannot be interpreted a valid version
+     *
+     * @throws  NullPointerException
+     *          If the given string is {@code null}
+     *
+     * @throws  NumberFormatException
+     *          If an element of the version number or the build number cannot
+     *          be represented as an {@link Integer}
+     *
+     * @return  This version
+     */
+    public static Version parse(String s) {
+        return new Version(s);
+    }
+
+    /**
+     * Returns {@code System.getProperty("java.version")} as a Version.
+     *
+     * @throws  SecurityException
+     *          If a security manager exists and its {@link
+     *          SecurityManager#checkPropertyAccess(String)
+     *          checkPropertyAccess} method does not allow access to the
+     *          system property "java.version"
+     *
+     * @return  {@code System.getProperty("java.version")} as a Version
+     */
+    public static Version current() {
+        if (current == null) {
+            current = parse(AccessController.doPrivileged(
+                new PrivilegedAction<>() {
+                    public String run() {
+                        return System.getProperty("java.version");
+                    }
+                }));
+        }
+        return current;
+    }
+
+    /**
+     * Returns the major version number.
+     *
+     * @return  The major version number
+     */
+    public int major() {
+        return version.get(0);
+    }
+
+    /**
+     * Returns the minor version number or zero if it was
+     * not set.
+     *
+     * @return  The minor version number or zero if it was not set
+     */
+    public int minor() {
+        return (version.size() > 1 ? version.get(1) : 0);
+    }
+
+    /**
+     * Returns the security version number or zero if
+     * it was not set.
+     *
+     * @return  The security version number or zero if it was not set
+     */
+    public int security() {
+        return (version.size() > 2 ? version.get(2) : 0);
+    }
+
+    /**
+     * Returns an unmodifiable {@link java.util.List List} of the
+     * integer numerals contained in the version
+     * number.  The {@code List} always contains at least one
+     * element corresponding to the major version
+     * number.
+     *
+     * @return  An unmodifiable list of the integer numerals
+     *          contained in the version number
+     */
+    public List version() {
+        return version;
+    }
+
+    /**
+     * Returns the optional pre-release information.
+     *
+     * @return  The optional pre-release information as a String
+     */
+    public Optional pre() {
+        return pre;
+    }
+
+    /**
+     * Returns the build number.
+     *
+     * @return The optional build number.
+     */
+    public Optional build() {
+        return build;
+    }
+
+    /**
+     * Returns optional additional identifying build
+     * information.
+     *
+     * @return  Additional build information as a String
+     */
+    public Optional optional() {
+        return optional;
+    }
+
+    /**
+     * Compares this version to another.
+     *
+     * 

Each of the components in the version is + * compared in the follow order of precedence: version numbers, + * pre-release identifiers, build numbers, optional build information.

+ * + *

Comparison begins by examining the sequence of version numbers. If + * one sequence is shorter than another, then the missing elements of the + * shorter sequence are considered to be zero.

+ * + *

A version with a pre-release identifier is always considered to be + * less than a version without one. Pre-release identifiers are compared + * numerically when they consist only of digits, and lexicographically + * otherwise. Numeric identifiers are considered to be less than + * non-numeric identifiers.

+ * + *

A version without a build number is always less than one with a + * build number; otherwise build numbers are compared numerically.

+ * + *

The optional build information is compared lexicographically. + * During this comparison, a version with optional build information is + * considered to be greater than a version without one.

+ * + *

A version is not comparable to any other type of object. + * + * @param ob + * The object to be compared + * + * @return A negative integer, zero, or a positive integer if this + * {@code Version} is less than, equal to, or greater than the + * given {@code Version} + * + * @throws NullPointerException + * If the given object is {@code null} + */ + @Override + public int compareTo(Version ob) { + return compare(ob, false); + } + + /** + * Compares this version to another disregarding optional build + * information. + * + *

Two versions are compared by examining the version string as + * described in {@link #compareTo(Version)} with the exception that the + * optional build information is always ignored.

+ * + *

A version is not comparable to any other type of object. + * + * @param ob + * The object to be compared + * + * @return A negative integer, zero, or a positive integer if this + * {@code Version} is less than, equal to, or greater than the + * given {@code Version} + * + * @throws NullPointerException + * If the given object is {@code null} + */ + public int compareToIgnoreOpt(Version ob) { + return compare(ob, true); + } + + private int compare(Version ob, boolean ignoreOpt) { + if (ob == null) + throw new NullPointerException("Invalid argument"); + + int ret = compareVersion(ob); + if (ret != 0) + return ret; + + ret = comparePre(ob); + if (ret != 0) + return ret; + + ret = compareBuild(ob); + if (ret != 0) + return ret; + + if (!ignoreOpt) + return compareOpt(ob); + + return 0; + } + + private int compareVersion(Version ob) { + int size = version.size(); + int oSize = ob.version().size(); + int min = Math.min(size, oSize); + for (int i = 0; i < min; i++) { + Integer val = version.get(i); + Integer oVal = ob.version().get(i); + if (val != oVal) + return val - oVal; + } + if (size != oSize) + return size - oSize; + return 0; + } + + private int comparePre(Version ob) { + Optional oPre = ob.pre(); + if (!pre.isPresent()) { + if (oPre.isPresent()) + return 1; + } else { + if (!oPre.isPresent()) + return -1; + String val = pre.get(); + String oVal = oPre.get(); + if (val.matches("\\d+")) { + return (oVal.matches("\\d+") + ? (new BigInteger(val)).compareTo(new BigInteger(oVal)) + : -1); + } else { + return (oVal.matches("\\d+") + ? 1 + : val.compareTo(oVal)); + } + } + return 0; + } + + private int compareBuild(Version ob) { + Optional oBuild = ob.build(); + if (oBuild.isPresent()) { + return (build.isPresent() + ? build.get().compareTo(oBuild.get()) + : 1); + } else if (build.isPresent()) { + return -1; + } + return 0; + } + + private int compareOpt(Version ob) { + Optional oOpt = ob.optional(); + if (!optional.isPresent()) { + if (oOpt.isPresent()) + return -1; + } else { + if (!oOpt.isPresent()) + return 1; + return optional.get().compareTo(oOpt.get()); + } + return 0; + } + + /** + * Returns a string representation of this version. + * + * @return The version string + */ + @Override + public String toString() { + StringBuilder sb + = new StringBuilder(version.stream() + .map(Object::toString) + .collect(Collectors.joining("."))); + pre.ifPresent(v -> sb.append("-").append(v)); + + if (build.isPresent()) { + sb.append("+").append(build.get()); + if (optional.isPresent()) + sb.append("-").append(optional.get()); + } else { + if (optional.isPresent()) { + sb.append(pre.isPresent() ? "-" : "+-"); + sb.append(optional.get()); + } + } + + return sb.toString(); + } + + /** + * Determines whether this {@code Version} is equal to another object. + * + *

Two {@code Version}s are equal if and only if they represent the + * same version string. + * + *

This method satisfies the general contract of the {@link + * Object#equals(Object) Object.equals} method.

+ * + * @param ob + * The object to which this {@code Version} is to be compared + * + * @return {@code true} if, and only if, the given object is a {@code + * Version} that is identical to this {@code Version} + * + */ + @Override + public boolean equals(Object ob) { + boolean ret = equalsIgnoreOpt(ob); + if (!ret) + return false; + + Version that = (Version)ob; + return (this.optional().equals(that.optional())); + } + + /** + * Determines whether this {@code Version} is equal to another + * disregarding optional build information. + * + *

Two {@code Version}s are equal if and only if they represent the + * same version string disregarding the optional build information. + * + * @param ob + * The object to which this {@code Version} is to be compared + * + * @return {@code true} if, and only if, the given object is a {@code + * Version} that is identical to this {@code Version} + * ignoring the optinal build information + * + */ + public boolean equalsIgnoreOpt(Object ob) { + if (this == ob) + return true; + if (!(ob instanceof Version)) + return false; + + Version that = (Version)ob; + return (this.version().equals(that.version()) + && this.pre().equals(that.pre()) + && this.build().equals(that.build())); + } + + /** + * Returns the hash code of this version. + * + *

This method satisfies the general contract of the {@link + * Object#hashCode Object.hashCode} method. + * + * @return The hashcode of this version + */ + @Override + public int hashCode() { + int h = 1; + int p = 17; + + h = p * h + version.hashCode(); + h = p * h + pre.hashCode(); + h = p * h + build.hashCode(); + h = p * h + optional.hashCode(); + + return h; + } +} diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java index c513894a086..75ba73da5b2 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java @@ -124,12 +124,7 @@ public interface JavaLangAccess { void invokeFinalize(Object o) throws Throwable; /** - * Invokes Long.formatUnsignedLong(long val, int shift, char[] buf, int offset, int len) + * Invokes Long.fastUUID */ - void formatUnsignedLong(long val, int shift, char[] buf, int offset, int len); - - /** - * Invokes Integer.formatUnsignedInt(long val, int shift, char[] buf, int offset, int len) - */ - void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len); + String fastUUID(long lsb, long msb); } diff --git a/jdk/src/java.base/share/classes/sun/misc/Cleaner.java b/jdk/src/java.base/share/classes/jdk/internal/ref/Cleaner.java similarity index 95% rename from jdk/src/java.base/share/classes/sun/misc/Cleaner.java rename to jdk/src/java.base/share/classes/jdk/internal/ref/Cleaner.java index ea473a17712..84c0f618a91 100644 --- a/jdk/src/java.base/share/classes/sun/misc/Cleaner.java +++ b/jdk/src/java.base/share/classes/jdk/internal/ref/Cleaner.java @@ -23,7 +23,7 @@ * questions. */ -package sun.misc; +package jdk.internal.ref; import java.lang.ref.*; import java.security.AccessController; @@ -58,6 +58,7 @@ import java.security.PrivilegedAction; public class Cleaner extends PhantomReference + implements Runnable { // Dummy reference queue, needed because the PhantomReference constructor @@ -153,4 +154,11 @@ public class Cleaner } } + @Override public void run() { + SecurityManager security = System.getSecurityManager(); + if (security != null) + security.checkPackageAccess("jdk.internal.ref"); + this.clean(); + } + } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java b/jdk/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java index 577ed7b16da..cba31015f0c 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java @@ -25,7 +25,7 @@ package sun.nio.ch; -import sun.misc.Cleaner; +import jdk.internal.ref.Cleaner; public interface DirectBuffer { diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index 1c4e1ca5075..671fe79efcc 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -47,7 +47,7 @@ import java.util.List; import jdk.internal.misc.JavaIOFileDescriptorAccess; import jdk.internal.misc.JavaNioAccess; import jdk.internal.misc.SharedSecrets; -import sun.misc.Cleaner; +import jdk.internal.ref.Cleaner; import sun.security.action.GetPropertyAction; public class FileChannelImpl diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java b/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java index 0b09fe752bf..d2c03a34fea 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java @@ -26,7 +26,7 @@ package sun.nio.ch; import java.nio.ByteBuffer; -import sun.misc.*; +import jdk.internal.ref.Cleaner; /** diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java index f2095540180..a580b82c4d0 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java @@ -33,7 +33,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import jdk.internal.misc.Unsafe; -import sun.misc.Cleaner; +import jdk.internal.ref.Cleaner; import sun.security.action.GetPropertyAction; diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java index 8acc0c198a1..91efac348e8 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java @@ -26,7 +26,7 @@ package sun.nio.fs; import jdk.internal.misc.Unsafe; -import sun.misc.Cleaner; +import jdk.internal.ref.Cleaner; /** * A light-weight buffer in native memory. diff --git a/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java b/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java index 9f9c86d99e2..1db2d089932 100644 --- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java +++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -653,6 +653,7 @@ public final class ProviderList { String type = null; String algorithm; String provider; + String alternateName = null; PreferredEntry(String t, String p) { int i = t.indexOf('.'); @@ -664,6 +665,11 @@ public final class ProviderList { } provider = p; + if (algorithm.compareToIgnoreCase("SHA1") == 0) { + alternateName = "SHA-1"; + } else if (algorithm.compareToIgnoreCase("SHA-1") == 0) { + alternateName = "SHA1"; + } } boolean match(String t, String a) { @@ -685,6 +691,15 @@ public final class ProviderList { return true; } + if (alternateName != null && + a.compareToIgnoreCase(alternateName) == 0) { + if (debug != null) { + debug.println("Config entry found (alternateName): " + + toString()); + } + return true; + } + // No match return false; } diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index be48902f550..e71a2c3ff8d 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -109,7 +109,8 @@ security.provider.tbd=sun.security.pkcs11.SunPKCS11 # jdk.security.provider.preferred=AES/GCM/NoPadding:SunJCE, \ # MessageDigest.SHA-256:SUN #ifdef solaris-sparc -jdk.security.provider.preferred=AES:SunJCE, SHA-256:SUN, SHA-384:SUN, SHA-512:SUN +jdk.security.provider.preferred=AES:SunJCE, SHA1:SUN, SHA-224:SUN, \ + SHA-256:SUN, SHA-384:SUN, SHA-512:SUN #endif #ifdef solaris-x86 jdk.security.provider.preferred=AES:SunJCE, RSA:SunRsaSign diff --git a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp index 32aa7d0c29f..124995dd0a2 100644 --- a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp +++ b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -210,7 +210,7 @@ static jlong* JIMAGE_FindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* ra // Locate resource location data. ImageLocation location; bool found = reader->find_location(path, location); - delete path; + delete[] path; // Resource not found. if (!found) return NULL; // Expand stream into array. diff --git a/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp b/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp index e3110f060ab..edf88b5e85b 100644 --- a/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp +++ b/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,7 @@ void ImageDecompressor::image_decompressor_init() { } void ImageDecompressor::image_decompressor_close() { - delete _decompressors; + delete[] _decompressors; } /* @@ -135,13 +135,13 @@ void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed, decompressor->decompress_resource(compressed_resource, decompressed_resource, &_header, strings); if (compressed_resource_base != compressed) { - delete compressed_resource_base; + delete[] compressed_resource_base; } compressed_resource = decompressed_resource; } } while (has_header); memcpy(uncompressed, decompressed_resource, uncompressed_size); - delete decompressed_resource; + delete[] decompressed_resource; } // Zip decompressor @@ -190,8 +190,8 @@ void SharedStringDecompressor::decompress_resource(u1* data, { // String in Strings table *uncompressed_resource = 1; uncompressed_resource += 1; - int i = decompress_int(data); - const char * string = strings->get(i); + int k = decompress_int(data); + const char * string = strings->get(k); int str_length = (int) strlen(string); Endian::set_java(uncompressed_resource, str_length); uncompressed_resource += 2; @@ -241,7 +241,7 @@ void SharedStringDecompressor::decompress_resource(u1* data, *fullpkg = '/'; memcpy(uncompressed_resource, pkg_base, len); uncompressed_resource += len; - delete pkg_base; + delete[] pkg_base; desc_length += len; } else { // Empty package // Nothing to do. diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/Application.java b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/Application.java index 19d1edd43dc..3535b4ae3d6 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/Application.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/Application.java @@ -39,7 +39,7 @@ import sun.lwawt.LWWindowPeer; import sun.lwawt.macosx.CPlatformWindow; /** - * The Application class allows you to integrate your Java application with the native Mac OS X environment. + * The {@code Application} class allows you to integrate your Java application with the native Mac OS X environment. * You can provide your Mac OS X users a greatly enhanced experience by implementing a few basic handlers for standard system events. * * For example: @@ -142,7 +142,7 @@ public class Application { /** * Installs a handler to show a custom About window for your application. * - * Setting the {@link AboutHandler} to null reverts it to the default Cocoa About window. + * Setting the {@link AboutHandler} to {@code null} reverts it to the default Cocoa About window. * * @param aboutHandler the handler to respond to the {@link AboutHandler#handleAbout()} message * @since Java for Mac OS X 10.6 Update 3 @@ -155,7 +155,7 @@ public class Application { /** * Installs a handler to create the Preferences menu item in your application's app menu. * - * Setting the {@link PreferencesHandler} to null will remove the Preferences item from the app menu. + * Setting the {@link PreferencesHandler} to {@code null} will remove the Preferences item from the app menu. * * @param preferencesHandler * @since Java for Mac OS X 10.6 Update 3 @@ -167,8 +167,8 @@ public class Application { /** * Installs the handler which is notified when the application is asked to open a list of files. - * The {@link OpenFilesHandler#openFiles(AppEvent.OpenFilesEvent)} notifications are only sent if the Java app is a bundled application, with a CFBundleDocumentTypes array present in it's Info.plist. - * See the Info.plist Key Reference for more information about adding a CFBundleDocumentTypes key to your app's Info.plist. + * The {@link OpenFilesHandler#openFiles(AppEvent.OpenFilesEvent)} notifications are only sent if the Java app is a bundled application, with a {@code CFBundleDocumentTypes} array present in it's Info.plist. + * See the Info.plist Key Reference for more information about adding a {@code CFBundleDocumentTypes} key to your app's Info.plist. * * @param openFileHandler * @since Java for Mac OS X 10.6 Update 3 @@ -180,8 +180,8 @@ public class Application { /** * Installs the handler which is notified when the application is asked to print a list of files. - * The {@link PrintFilesHandler#printFiles(AppEvent.PrintFilesEvent)} notifications are only sent if the Java app is a bundled application, with a CFBundleDocumentTypes array present in it's Info.plist. - * See the Info.plist Key Reference for more information about adding a CFBundleDocumentTypes key to your app's Info.plist. + * The {@link PrintFilesHandler#printFiles(AppEvent.PrintFilesEvent)} notifications are only sent if the Java app is a bundled application, with a {@code CFBundleDocumentTypes} array present in it's Info.plist. + * See the Info.plist Key Reference for more information about adding a {@code CFBundleDocumentTypes} key to your app's Info.plist. * * @param printFileHandler * @since Java for Mac OS X 10.6 Update 3 @@ -193,10 +193,10 @@ public class Application { /** * Installs the handler which is notified when the application is asked to open a URL. - * The {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} notifications are only sent if the Java app is a bundled application, with a CFBundleURLTypes array present in it's Info.plist. - * See the Info.plist Key Reference for more information about adding a CFBundleURLTypes key to your app's Info.plist. + * The {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} notifications are only sent if the Java app is a bundled application, with a {@code CFBundleURLTypes} array present in it's Info.plist. + * See the Info.plist Key Reference for more information about adding a {@code CFBundleURLTypes} key to your app's Info.plist. * - * Setting the handler to null causes all {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} requests to be enqueued until another handler is set. + * Setting the handler to {@code null} causes all {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} requests to be enqueued until another handler is set. * * @param openURIHandler * @since Java for Mac OS X 10.6 Update 3 @@ -209,7 +209,7 @@ public class Application { /** * Installs the handler which determines if the application should quit. * The handler is passed a one-shot {@link QuitResponse} which can cancel or proceed with the quit. - * Setting the handler to null causes all quit requests to directly perform the default {@link QuitStrategy}. + * Setting the handler to {@code null} causes all quit requests to directly perform the default {@link QuitStrategy}. * * @param quitHandler the handler that is called when the application is asked to quit * @since Java for Mac OS X 10.6 Update 3 @@ -432,11 +432,11 @@ public class Application { /** * Enables the Preferences item in the application menu. The ApplicationListener receives a callback for - * selection of the Preferences item in the application menu only if this is set to true. + * selection of the Preferences item in the application menu only if this is set to {@code true}. * * If a Preferences item isn't present, this method adds and enables it. * - * @param enable specifies whether the Preferences item in the application menu should be enabled (true) or not (false) + * @param enable specifies whether the Preferences item in the application menu should be enabled ({@code true}) or not ({@code false}) * * @deprecated no replacement * @since 1.4 @@ -449,12 +449,12 @@ public class Application { /** * Enables the About item in the application menu. The ApplicationListener receives a callback for - * selection of the About item in the application menu only if this is set to true. Because AWT supplies - * a standard About window when an application may not, by default this is set to true. + * selection of the About item in the application menu only if this is set to {@code true}. Because AWT supplies + * a standard About window when an application may not, by default this is set to {@code true}. * * If the About item isn't present, this method adds and enables it. * - * @param enable specifies whether the About item in the application menu should be enabled (true) or not (false) + * @param enable specifies whether the About item in the application menu should be enabled ({@code true}) or not ({@code false}) * * @deprecated no replacement * @since 1.4 @@ -553,7 +553,7 @@ public class Application { } /** - * @deprecated Use java.awt.MouseInfo.getPointerInfo().getLocation(). + * @deprecated Use {@code java.awt.MouseInfo.getPointerInfo().getLocation()}. * * @since 1.4 */ diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationAdapter.java b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationAdapter.java index bf78e586311..17339373153 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationAdapter.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationAdapter.java @@ -26,7 +26,7 @@ package com.apple.eawt; /** - * An abstract adapter class for receiving ApplicationEvents. + * An abstract adapter class for receiving {@code ApplicationEvents}. * * ApplicationEvents are deprecated. Use individual app event listeners or handlers instead. * diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationEvent.java b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationEvent.java index 908c8257b01..0cfe0741682 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationEvent.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationEvent.java @@ -50,9 +50,9 @@ public class ApplicationEvent extends EventObject { /** * Determines whether an ApplicationListener has acted on a particular event. - * An event is marked as having been handled with setHandled(true). + * An event is marked as having been handled with {@code setHandled(true)}. * - * @return true if the event has been handled, otherwise false + * @return {@code true} if the event has been handled, otherwise {@code false} * * @since 1.4 * @deprecated @@ -65,10 +65,10 @@ public class ApplicationEvent extends EventObject { /** * Marks the event as handled. * After this method handles an ApplicationEvent, it may be useful to specify that it has been handled. - * This is usually used in conjunction with getHandled(). - * Set to true to designate that this event has been handled. By default it is false. + * This is usually used in conjunction with {@code getHandled()}. + * Set to {@code true} to designate that this event has been handled. By default it is {@code false}. * - * @param state true if the event has been handled, otherwise false. + * @param state {@code true} if the event has been handled, otherwise {@code false}. * * @since 1.4 * @deprecated @@ -84,7 +84,7 @@ public class ApplicationEvent extends EventObject { * For example, the Print and Open events refer to specific files. * For these cases, this returns the appropriate file name. * - * @return the full path to the file associated with the event, if applicable, otherwise null + * @return the full path to the file associated with the event, if applicable, otherwise {@code null} * * @since 1.4 * @deprecated use {@link OpenFilesHandler} or {@link PrintFilesHandler} instead diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationListener.java b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationListener.java index 14e3386134e..ea2efcf0ede 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationListener.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/ApplicationListener.java @@ -53,9 +53,9 @@ import java.util.EventListener; @Deprecated public interface ApplicationListener extends EventListener { /** - * Called when the user selects the About item in the application menu. If event is not handled by - * setting isHandled(true), a default About window consisting of the application's name and icon is - * displayed. To display a custom About window, designate the event as being handled and display the + * Called when the user selects the About item in the application menu. If {@code event} is not handled by + * setting {@code isHandled(true)}, a default About window consisting of the application's name and icon is + * displayed. To display a custom About window, designate the {@code event} as being handled and display the * appropriate About window. * * @param event an ApplicationEvent initiated by the user choosing About in the application menu @@ -99,7 +99,7 @@ public interface ApplicationListener extends EventListener { * Called when the Preference item in the application menu is selected. Native Mac OS X applications make their * Preferences window available through the application menu. Java applications are automatically given an application * menu in Mac OS X. By default, the Preferences item is disabled in that menu. If you are deploying an application - * on Mac OS X, you should enable the preferences item with setEnabledPreferencesMenu(true) in the + * on Mac OS X, you should enable the preferences item with {@code setEnabledPreferencesMenu(true)} in the * Application object and then display your Preferences window in this handler. * * @param event triggered when the user selects Preferences from the application menu @@ -130,8 +130,8 @@ public interface ApplicationListener extends EventListener { * application menu, when the user types Command-Q, or when the user control clicks on your application icon in the * Dock and chooses Quit. You can either accept or reject the request to quit. You might want to reject the request * to quit if the user has unsaved work. Reject the request, move into your code to save changes, then quit your - * application. To accept the request to quit, and terminate the application, set isHandled(true) for the - * event. To reject the quit, set isHandled(false). + * application. To accept the request to quit, and terminate the application, set {@code isHandled(true)} for the + * {@code event}. To reject the quit, set {@code isHandled(false)}. * * @param event a Quit Application event * @deprecated use {@link QuitHandler} and {@link QuitResponse} diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/OpenURIHandler.java b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/OpenURIHandler.java index 3197f1528f5..1964344f94a 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/OpenURIHandler.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/OpenURIHandler.java @@ -29,8 +29,8 @@ import com.apple.eawt.AppEvent.OpenURIEvent; /** * An implementor is notified when the application is asked to open a URI. - * The application only sends {@link com.apple.eawt.EAWTEvent.OpenURIEvent}s when it has been launched as a bundled Mac application, and it's Info.plist claims URL schemes in it's CFBundleURLTypes entry. - * See the Info.plist Key Reference for more information about adding a CFBundleURLTypes key to your app's Info.plist. + * The application only sends {@link com.apple.eawt.EAWTEvent.OpenURIEvent}s when it has been launched as a bundled Mac application, and it's Info.plist claims URL schemes in it's {@code CFBundleURLTypes} entry. + * See the Info.plist Key Reference for more information about adding a {@code CFBundleURLTypes} key to your app's Info.plist. * * @see Application#setOpenURIHandler(OpenURIHandler) * diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/QuitStrategy.java b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/QuitStrategy.java index 89c8be0465f..a0140d9ba78 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/QuitStrategy.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/QuitStrategy.java @@ -38,7 +38,7 @@ package com.apple.eawt; */ public enum QuitStrategy { /** - * Shuts down the application by calling System.exit(0). This is the default strategy. + * Shuts down the application by calling {@code System.exit(0)}. This is the default strategy. */ SYSTEM_EXIT_0, diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java b/jdk/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java index 5dec385d5aa..90841e426c0 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java @@ -32,19 +32,19 @@ import java.io.*; * attributes. These attributes in turn are dependent on HFS and HFS+ file systems. As such, it is important to recognize * their limitation when writing code that must function well across multiple platforms.

* - * In addition to file name suffixes, Mac OS X can use Finder attributes like file type and creator codes to - * identify and handle files. These codes are unique 4-byte identifiers. The file type is a string that describes the - * contents of a file. For example, the file type APPL identifies the file as an application and therefore - * executable. A file type of TEXT means that the file contains raw text. Any application that can read raw - * text can open a file of type TEXT. Applications that use proprietary file types might assign their files a proprietary - * file type code. + * In addition to file name suffixes, Mac OS X can use Finder attributes like file {@code type} and {@code creator} codes to + * identify and handle files. These codes are unique 4-byte identifiers. The file {@code type} is a string that describes the + * contents of a file. For example, the file type {@code APPL} identifies the file as an application and therefore + * executable. A file type of {@code TEXT} means that the file contains raw text. Any application that can read raw + * text can open a file of type {@code TEXT}. Applications that use proprietary file types might assign their files a proprietary + * file {@code type} code. *

- * To identify the application that can handle a document, the Finder can look at the creator. For example, if a user - * double-clicks on a document with the ttxt creator, it opens up in Text Edit, the application registered - * with the ttxt creator code. Note that the creator + * To identify the application that can handle a document, the Finder can look at the {@code creator}. For example, if a user + * double-clicks on a document with the {@code ttxt creator}, it opens up in Text Edit, the application registered + * with the {@code ttxt creator} code. Note that the {@code creator} * code can be set to any application, not necessarily the application that created it. For example, if you - * use an editor to create an HTML document, you might want to assign a browser's creator code for the file rather than - * the HTML editor's creator code. Double-clicking on the document then opens the appropriate browser rather than the + * use an editor to create an HTML document, you might want to assign a browser's {@code creator} code for the file rather than + * the HTML editor's {@code creator} code. Double-clicking on the document then opens the appropriate browser rather than the *HTML editor. *

* If you plan to publicly distribute your application, you must register its creator and any proprietary file types with the Apple @@ -126,7 +126,7 @@ public class FileManager { } /** - * Sets the file type and creator codes for a file or folder. + * Sets the file {@code type} and {@code creator} codes for a file or folder. * * @since 1.4 */ @@ -140,7 +140,7 @@ public class FileManager { private static native void _setFileTypeAndCreator(String filename, int type, int creator) throws IOException; /** - * Sets the file type code for a file or folder. + * Sets the file {@code type} code for a file or folder. * * @since 1.4 */ @@ -154,7 +154,7 @@ public class FileManager { private static native void _setFileType(String filename, int type) throws IOException; /** - * Sets the file creator code for a file or folder. + * Sets the file {@code creator} code for a file or folder. * * @since 1.4 */ @@ -168,7 +168,7 @@ public class FileManager { private static native void _setFileCreator(String filename, int creator) throws IOException; /** - * Obtains the file type code for a file or folder. + * Obtains the file {@code type} code for a file or folder. * * @since 1.4 */ @@ -182,7 +182,7 @@ public class FileManager { private static native int _getFileType(String filename) throws IOException; /** - * Obtains the file creator code for a file or folder. + * Obtains the file {@code creator} code for a file or folder. * * @since 1.4 */ @@ -200,11 +200,11 @@ public class FileManager { * Locates a folder of a particular type. Mac OS X recognizes certain specific folders that have distinct purposes. * For example, the user's desktop or temporary folder. These folders have corresponding codes. Given one of these codes, * this method returns the path to that particular folder. Certain folders of a given type may appear in more than - * one domain. For example, although there is only one root folder, there are multiple pref - * folders. If this method is called to find the pref folder, it will return the first one it finds, - * the user's preferences folder in ~/Library/Preferences. To explicitly locate a folder in a certain - * domain use findFolder(short domain, int folderType) or findFolder(short domain, int folderType, - * boolean createIfNeeded). + * one domain. For example, although there is only one {@code root} folder, there are multiple {@code pref} + * folders. If this method is called to find the {@code pref} folder, it will return the first one it finds, + * the user's preferences folder in {@code ~/Library/Preferences}. To explicitly locate a folder in a certain + * domain use {@code findFolder(short domain, int folderType)} or + * {@code findFolder(short domain, int folderType, boolean createIfNeeded)}. * * @return the path to the folder searched for * @@ -215,8 +215,8 @@ public class FileManager { } /** - * Locates a folder of a particular type, within a given domain. Similar to findFolder(int folderType) - * except that the domain to look in can be specified. Valid values for domaininclude: + * Locates a folder of a particular type, within a given domain. Similar to {@code findFolder(int folderType)} + * except that the domain to look in can be specified. Valid values for {@code domain} include: *

*
user
*
The User domain contains resources specific to the user who is currently logged in
@@ -239,12 +239,12 @@ public class FileManager { /** * Locates a folder of a particular type within a given domain and optionally creating the folder if it does - * not exist. The behavior is similar to findFolder(int folderType) and - * findFolder(short domain, int folderType) except that it can create the folder if it does not already exist. + * not exist. The behavior is similar to {@code findFolder(int folderType)} and + * {@code findFolder(short domain, int folderType)} except that it can create the folder if it does not already exist. * * @param createIfNeeded - * set to true, by setting to false the behavior will be the - * same as findFolder(short domain, int folderType, boolean createIfNeeded) + * set to {@code true}, by setting to {@code false} the behavior will be the + * same as {@code findFolder(short domain, int folderType, boolean createIfNeeded)} * @return the path to the folder searched for * * @since 1.4 @@ -263,9 +263,9 @@ public class FileManager { /** - * Opens the path specified by a URL in the appropriate application for that URL. HTTP URL's (http://) - * open in the default browser as set in the Internet pane of System Preferences. File (file://) and - * FTP URL's (ftp://) open in the Finder. Note that opening an FTP URL will prompt the user for where + * Opens the path specified by a URL in the appropriate application for that URL. HTTP URL's ({@code http://}) + * open in the default browser as set in the Internet pane of System Preferences. File ({@code file://}) and + * FTP URL's ({@code ftp://}) open in the Finder. Note that opening an FTP URL will prompt the user for where * they want to save the downloaded file(s). * * @param url diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java index 887ab5c8bd3..05eddcea4d8 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java @@ -26,6 +26,7 @@ package com.apple.laf; +import java.awt.ComponentOrientation; import java.beans.*; import java.io.File; import java.util.*; @@ -85,6 +86,15 @@ class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeLi } else if (prop == JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY) { invalidateFileCache(); validateFileCache(); + } else if (prop.equals("componentOrientation")) { + ComponentOrientation o = (ComponentOrientation) e.getNewValue(); + JFileChooser cc = (JFileChooser) e.getSource(); + if (o != e.getOldValue()) { + cc.applyComponentOrientation(o); + } + fFileList.setComponentOrientation(o); + fFileList.getParent().getParent().setComponentOrientation(o); + } if (prop == SORT_BY_CHANGED) {// $ Ought to just resort fSortNames = (((Integer)e.getNewValue()).intValue() == 0); diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameManager.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameManager.java index 49a9a19d201..c2ce10b0e4a 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameManager.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameManager.java @@ -105,7 +105,9 @@ public class AquaInternalFrameManager extends DefaultDesktopManager { // Position depends on *current* position of frame, unlike super which reuses the first position final Rectangle r = getBoundsForIconOf(f); desktopIcon.setBounds(r.x, r.y, r.width, r.height); - + if (!wasIcon(f)) { + setWasIcon(f, Boolean.TRUE); + } c = f.getParent(); if (c == null) return; 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 530b5c6d999..74b40511795 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 @@ -295,9 +295,9 @@ public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingCo } /** - * Installs necessary mouse handlers on newPane + * Installs necessary mouse handlers on {@code newPane} * and adds it to the frame. - * Reverse process for the currentPane. + * Reverse process for the {@code currentPane}. */ @Override protected void replacePane(final JComponent currentPane, final JComponent newPane) { diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java index 44b9be288f5..f04d42de03b 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java @@ -82,9 +82,9 @@ public class AquaLookAndFeel extends BasicLookAndFeel { } /** - * Returns true if the LookAndFeel returned - * RootPaneUI instances support providing Window decorations - * in a JRootPane. + * Returns true if the {@code LookAndFeel} returned + * {@code RootPaneUI} instances support providing Window decorations + * in a {@code JRootPane}. *

* The default implementation returns false, subclasses that support * Window decorations should override this and return true. @@ -174,20 +174,20 @@ public class AquaLookAndFeel extends BasicLookAndFeel { } /** - * Returns an ActionMap. + * Returns an {@code ActionMap}. *

- * This ActionMap contains Actions that + * This {@code ActionMap} contains {@code Actions} that * embody the ability to render an auditory cue. These auditory * cues map onto user and system activities that may be useful * for an end user to know about (such as a dialog box appearing). *

- * At the appropriate time in a JComponent UI's lifecycle, + * At the appropriate time in a {@code JComponent} UI's lifecycle, * the ComponentUI is responsible for getting the appropriate - * Action out of the ActionMap and passing - * it on to playSound. + * {@code Action} out of the {@code ActionMap} and passing + * it on to {@code playSound}. *

- * The Actions in this ActionMap are - * created by the createAudioAction method. + * The {@code Actions} in this {@code ActionMap} are + * created by the {@code createAudioAction} method. * * @return an ActionMap containing Actions * responsible for rendering auditory cues diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaOptionPaneUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaOptionPaneUI.java index c1a57e503df..c62eab5f08b 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaOptionPaneUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaOptionPaneUI.java @@ -47,7 +47,7 @@ public class AquaOptionPaneUI extends BasicOptionPaneUI { /** * Creates and returns a Container containin the buttons. The buttons - * are created by calling getButtons. + * are created by calling {@code getButtons}. */ protected Container createButtonArea() { final Container bottom = super.createButtonArea(); @@ -141,5 +141,27 @@ public class AquaOptionPaneUI extends BasicOptionPaneUI { xLocation += xOffset; } } + + @Override + public Dimension minimumLayoutSize(Container c) { + if (c != null) { + Component[] children = c.getComponents(); + if (children != null && children.length > 0) { + int numChildren = children.length; + Insets cInsets = c.getInsets(); + int extraHeight = cInsets.top + cInsets.bottom; + int extraWidth = cInsets.left + cInsets.right; + int okCancelButtonWidth = extraWidth + + (kOKCancelButtonWidth * numChildren) + + (numChildren - 1) * padding; + int okbuttonHeight = extraHeight + kButtonHeight; + Dimension minSize = super.minimumLayoutSize(c); + return new Dimension(Math.max(minSize.width, + okCancelButtonWidth), + Math.max(minSize.height, okbuttonHeight)); + } + } + return new Dimension(0, 0); + } } } diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java index 1ac16c320b7..9f5f09bbd1e 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaProgressBarUI.java @@ -180,10 +180,19 @@ public class AquaProgressBarUI extends ProgressBarUI implements ChangeListener, final int width = progressBar.getWidth() - (i.right + i.left); final int height = progressBar.getHeight() - (i.bottom + i.top); + Graphics2D g2 = (Graphics2D) g; + final AffineTransform savedAT = g2.getTransform(); + if (!progressBar.getComponentOrientation().isLeftToRight()) { + //Scale operation: Flips component about pivot + //Translate operation: Moves component back into original position + g2.scale(-1, 1); + g2.translate(-progressBar.getWidth(), 0); + } painter.paint(g, progressBar, i.left, i.top, width, height); + g2.setTransform(savedAT); if (progressBar.isStringPainted() && !progressBar.isIndeterminate()) { - paintString(g, i.left, i.top, width, height); + paintString(g, i.left, i.top, width, height); } } diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java index 3ab83b037c8..a4e179645a9 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaRootPaneUI.java @@ -164,7 +164,7 @@ public class AquaRootPaneUI extends BasicRootPaneUI implements AncestorListener, /** * Invoked when a property changes on the root pane. If the event - * indicates the defaultButton has changed, this will + * indicates the {@code defaultButton} has changed, this will * update the animation. * If the enabled state changed, it will start or stop the animation */ diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java index d2d9a76500b..219e739bcfb 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaSpinnerUI.java @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package com.apple.laf; import java.awt.*; @@ -45,33 +44,37 @@ import com.apple.laf.AquaUtils.RecyclableSingleton; import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; /** - * This is originally derived from BasicSpinnerUI, but they made everything private - * so we can't subclass! + * This is originally derived from BasicSpinnerUI, but they made everything + * private so we can't subclass! */ public class AquaSpinnerUI extends SpinnerUI { + private static final RecyclableSingleton propertyChangeListener = new RecyclableSingletonFromDefaultConstructor<>(PropertyChangeHandler.class); + static PropertyChangeListener getPropertyChangeListener() { return propertyChangeListener.get(); } private static final RecyclableSingleton nextButtonHandler = new RecyclableSingleton() { - @Override - protected ArrowButtonHandler getInstance() { - return new ArrowButtonHandler("increment", true); - } - }; + @Override + protected ArrowButtonHandler getInstance() { + return new ArrowButtonHandler("increment", true); + } + }; + static ArrowButtonHandler getNextButtonHandler() { return nextButtonHandler.get(); } private static final RecyclableSingleton previousButtonHandler = new RecyclableSingleton() { - @Override - protected ArrowButtonHandler getInstance() { - return new ArrowButtonHandler("decrement", false); - } - }; + @Override + protected ArrowButtonHandler getInstance() { + return new ArrowButtonHandler("decrement", false); + } + }; + static ArrowButtonHandler getPreviousButtonHandler() { return previousButtonHandler.get(); } @@ -92,9 +95,10 @@ public class AquaSpinnerUI extends SpinnerUI { } boolean wasOpaque; + @Override public void installUI(final JComponent c) { - this.spinner = (JSpinner)c; + this.spinner = (JSpinner) c; installDefaults(); installListeners(); next = createNextButton(); @@ -110,8 +114,7 @@ public class AquaSpinnerUI extends SpinnerUI { installKeyboardActions(); // this doesn't work because JSpinner calls setOpaque(true) directly in it's constructor - // LookAndFeel.installProperty(spinner, "opaque", Boolean.FALSE); - + // LookAndFeel.installProperty(spinner, "opaque", Boolean.FALSE); // ...so we have to handle the is/was opaque ourselves wasOpaque = spinner.isOpaque(); spinner.setOpaque(false); @@ -208,6 +211,7 @@ public class AquaSpinnerUI extends SpinnerUI { @SuppressWarnings("serial") // Superclass is not serializable across versions class TransparentButton extends JButton implements SwingConstants { + boolean interceptRepaints = false; public TransparentButton() { @@ -219,14 +223,17 @@ public class AquaSpinnerUI extends SpinnerUI { } @Override - public void paint(final Graphics g) {} + public void paint(final Graphics g) { + } @Override public void repaint() { // only intercept repaints if we are after this has been initialized // otherwise we can't talk to our containing class if (interceptRepaints) { - if (spinPainter == null) return; + if (spinPainter == null) { + return; + } spinPainter.repaint(); } super.repaint(); @@ -246,7 +253,9 @@ public class AquaSpinnerUI extends SpinnerUI { } protected void fixupEditor(final JComponent editor) { - if (!(editor instanceof DefaultEditor)) return; + if (!(editor instanceof DefaultEditor)) { + return; + } editor.setOpaque(false); editor.setInheritsPopupMenu(true); @@ -255,7 +264,7 @@ public class AquaSpinnerUI extends SpinnerUI { editor.setFont(new FontUIResource(spinner.getFont())); } - final JFormattedTextField editorTextField = ((DefaultEditor)editor).getTextField(); + final JFormattedTextField editorTextField = ((DefaultEditor) editor).getTextField(); if (editorTextField.getFont() instanceof UIResource) { editorTextField.setFont(new FontUIResource(spinner.getFont())); } @@ -277,7 +286,7 @@ public class AquaSpinnerUI extends SpinnerUI { child.setEnabled(enabled); if (child instanceof Container) { - updateEnabledState((Container)child, enabled); + updateEnabledState((Container) child, enabled); } } } @@ -290,13 +299,13 @@ public class AquaSpinnerUI extends SpinnerUI { private InputMap getInputMap(final int condition) { if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { - return (InputMap)UIManager.get("Spinner.ancestorInputMap"); + return (InputMap) UIManager.get("Spinner.ancestorInputMap"); } return null; } private ActionMap getActionMap() { - ActionMap map = (ActionMap)UIManager.get("Spinner.actionMap"); + ActionMap map = (ActionMap) UIManager.get("Spinner.actionMap"); if (map == null) { map = createActionMap(); @@ -316,6 +325,7 @@ public class AquaSpinnerUI extends SpinnerUI { @SuppressWarnings("serial") // Superclass is not serializable across versions private static class ArrowButtonHandler extends AbstractAction implements MouseListener { + final javax.swing.Timer autoRepeatTimer; final boolean isNext; JSpinner spinner = null; @@ -330,9 +340,9 @@ public class AquaSpinnerUI extends SpinnerUI { private JSpinner eventToSpinner(final AWTEvent e) { Object src = e.getSource(); while ((src instanceof Component) && !(src instanceof JSpinner)) { - src = ((Component)src).getParent(); + src = ((Component) src).getParent(); } - return (src instanceof JSpinner) ? (JSpinner)src : null; + return (src instanceof JSpinner) ? (JSpinner) src : null; } @Override @@ -342,13 +352,15 @@ public class AquaSpinnerUI extends SpinnerUI { spinner = eventToSpinner(e); } - if (spinner == null) return; + if (spinner == null) { + return; + } try { final int calendarField = getCalendarField(spinner); spinner.commitEdit(); if (calendarField != -1) { - ((SpinnerDateModel)spinner.getModel()).setCalendarField(calendarField); + ((SpinnerDateModel) spinner.getModel()).setCalendarField(calendarField); } final Object value = (isNext) ? spinner.getNextValue() : spinner.getPreviousValue(); if (value != null) { @@ -368,37 +380,46 @@ public class AquaSpinnerUI extends SpinnerUI { */ private void select(final JSpinner spinnerComponent) { final JComponent editor = spinnerComponent.getEditor(); - if (!(editor instanceof JSpinner.DateEditor)) return; + if (!(editor instanceof JSpinner.DateEditor)) { + return; + } - final JSpinner.DateEditor dateEditor = (JSpinner.DateEditor)editor; + final JSpinner.DateEditor dateEditor = (JSpinner.DateEditor) editor; final JFormattedTextField ftf = dateEditor.getTextField(); final Format format = dateEditor.getFormat(); Object value; - if (format == null || (value = spinnerComponent.getValue()) == null) return; + if (format == null || (value = spinnerComponent.getValue()) == null) { + return; + } final SpinnerDateModel model = dateEditor.getModel(); final DateFormat.Field field = DateFormat.Field.ofCalendarField(model.getCalendarField()); - if (field == null) return; + if (field == null) { + return; + } try { final AttributedCharacterIterator iterator = format.formatToCharacterIterator(value); if (!select(ftf, iterator, field) && field == DateFormat.Field.HOUR0) { select(ftf, iterator, DateFormat.Field.HOUR1); } - } catch (final IllegalArgumentException iae) {} + } catch (final IllegalArgumentException iae) { + } } /** - * Selects the passed in field, returning true if it is found, - * false otherwise. + * Selects the passed in field, returning true if it is found, false + * otherwise. */ private boolean select(final JFormattedTextField ftf, final AttributedCharacterIterator iterator, final DateFormat.Field field) { final int max = ftf.getDocument().getLength(); iterator.first(); do { - final Map attrs = iterator.getAttributes(); - if (attrs == null || !attrs.containsKey(field)) continue; + final Map attrs = iterator.getAttributes(); + if (attrs == null || !attrs.containsKey(field)) { + continue; + } final int start = iterator.getRunStart(field); final int end = iterator.getRunLimit(field); @@ -412,29 +433,35 @@ public class AquaSpinnerUI extends SpinnerUI { } /** - * Returns the calendarField under the start of the selection, or - * -1 if there is no valid calendar field under the selection (or - * the spinner isn't editing dates. + * Returns the calendarField under the start of the selection, or -1 if + * there is no valid calendar field under the selection (or the spinner + * isn't editing dates. */ private int getCalendarField(final JSpinner spinnerComponent) { final JComponent editor = spinnerComponent.getEditor(); - if (!(editor instanceof JSpinner.DateEditor)) return -1; + if (!(editor instanceof JSpinner.DateEditor)) { + return -1; + } - final JSpinner.DateEditor dateEditor = (JSpinner.DateEditor)editor; + final JSpinner.DateEditor dateEditor = (JSpinner.DateEditor) editor; final JFormattedTextField ftf = dateEditor.getTextField(); final int start = ftf.getSelectionStart(); final JFormattedTextField.AbstractFormatter formatter = ftf.getFormatter(); - if (!(formatter instanceof InternationalFormatter)) return -1; + if (!(formatter instanceof InternationalFormatter)) { + return -1; + } - final Format.Field[] fields = ((InternationalFormatter)formatter).getFields(start); + final Format.Field[] fields = ((InternationalFormatter) formatter).getFields(start); for (final Field element : fields) { - if (!(element instanceof DateFormat.Field)) continue; + if (!(element instanceof DateFormat.Field)) { + continue; + } int calendarField; if (element == DateFormat.Field.HOUR1) { calendarField = Calendar.HOUR; } else { - calendarField = ((DateFormat.Field)element).getCalendarField(); + calendarField = ((DateFormat.Field) element).getCalendarField(); } if (calendarField != -1) { @@ -446,7 +473,9 @@ public class AquaSpinnerUI extends SpinnerUI { @Override public void mousePressed(final MouseEvent e) { - if (!SwingUtilities.isLeftMouseButton(e) || !e.getComponent().isEnabled()) return; + if (!SwingUtilities.isLeftMouseButton(e) || !e.getComponent().isEnabled()) { + return; + } spinner = eventToSpinner(e); autoRepeatTimer.start(); @@ -460,26 +489,35 @@ public class AquaSpinnerUI extends SpinnerUI { } @Override - public void mouseClicked(final MouseEvent e) {} + public void mouseClicked(final MouseEvent e) { + } + @Override - public void mouseEntered(final MouseEvent e) {} + public void mouseEntered(final MouseEvent e) { + } + @Override - public void mouseExited(final MouseEvent e) {} + public void mouseExited(final MouseEvent e) { + } /** - * Requests focus on a child of the spinner if the spinner doesn't - * have focus. + * Requests focus on a child of the spinner if the spinner doesn't have + * focus. */ private void focusSpinnerIfNecessary() { final Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - if (!spinner.isRequestFocusEnabled() || (fo != null && (SwingUtilities.isDescendingFrom(fo, spinner)))) return; + if (!spinner.isRequestFocusEnabled() || (fo != null && (SwingUtilities.isDescendingFrom(fo, spinner)))) { + return; + } Container root = spinner; if (!root.isFocusCycleRoot()) { root = root.getFocusCycleRootAncestor(); } - if (root == null) return; + if (root == null) { + return; + } final FocusTraversalPolicy ftp = root.getFocusTraversalPolicy(); final Component child = ftp.getComponentAfter(root, spinner); @@ -491,6 +529,7 @@ public class AquaSpinnerUI extends SpinnerUI { @SuppressWarnings("serial") // Superclass is not serializable across versions class SpinPainter extends JComponent { + final AquaPainter painter = AquaPainter.create(JRSUIStateFactory.getSpinnerArrows()); ButtonModel fTopModel; @@ -551,11 +590,12 @@ public class AquaSpinnerUI extends SpinnerUI { } /** - * A simple layout manager for the editor and the next/previous buttons. - * See the AquaSpinnerUI javadoc for more information about exactly - * how the components are arranged. + * A simple layout manager for the editor and the next/previous buttons. See + * the AquaSpinnerUI javadoc for more information about exactly how the + * components are arranged. */ static class SpinnerLayout implements LayoutManager { + private Component nextButton = null; private Component previousButton = null; private Component editor = null; @@ -656,26 +696,38 @@ public class AquaSpinnerUI extends SpinnerUI { } /** - * Detect JSpinner property changes we're interested in and delegate. Subclasses - * shouldn't need to replace the default propertyChangeListener (although they - * can by overriding createPropertyChangeListener) since all of the interesting - * property changes are delegated to protected methods. + * Detect JSpinner property changes we're interested in and delegate. + * Subclasses shouldn't need to replace the default propertyChangeListener + * (although they can by overriding createPropertyChangeListener) since all + * of the interesting property changes are delegated to protected methods. */ static class PropertyChangeHandler implements PropertyChangeListener { + @Override public void propertyChange(final PropertyChangeEvent e) { final String propertyName = e.getPropertyName(); - final JSpinner spinner = (JSpinner)(e.getSource()); + final JSpinner spinner = (JSpinner) (e.getSource()); final SpinnerUI spinnerUI = spinner.getUI(); if (spinnerUI instanceof AquaSpinnerUI) { - final AquaSpinnerUI ui = (AquaSpinnerUI)spinnerUI; + final AquaSpinnerUI ui = (AquaSpinnerUI) spinnerUI; if ("editor".equals(propertyName)) { - final JComponent oldEditor = (JComponent)e.getOldValue(); - final JComponent newEditor = (JComponent)e.getNewValue(); + final JComponent oldEditor = (JComponent) e.getOldValue(); + final JComponent newEditor = (JComponent) e.getNewValue(); ui.replaceEditor(oldEditor, newEditor); ui.updateEnabledState(); + } else if ("componentOrientation".equals(propertyName)) { + ComponentOrientation o + = (ComponentOrientation) e.getNewValue(); + if (o != e.getOldValue()) { + JComponent editor = spinner.getEditor(); + if (editor != null) { + editor.applyComponentOrientation(o); + } + spinner.revalidate(); + spinner.repaint(); + } } else if ("enabled".equals(propertyName)) { ui.updateEnabledState(); } else if (JComponent.TOOL_TIP_TEXT_KEY.equals(propertyName)) { @@ -683,8 +735,8 @@ public class AquaSpinnerUI extends SpinnerUI { } else if ("font".equals(propertyName)) { JComponent editor = spinner.getEditor(); if (editor instanceof JSpinner.DefaultEditor) { - JTextField tf = - ((JSpinner.DefaultEditor) editor).getTextField(); + JTextField tf + = ((JSpinner.DefaultEditor) editor).getTextField(); if (tf != null) { if (tf.getFont() instanceof UIResource) { tf.setFont(new FontUIResource(spinner.getFont())); @@ -703,12 +755,12 @@ public class AquaSpinnerUI extends SpinnerUI { final Component[] children = spinnerComponent.getComponents(); for (final Component element : children) { if (element instanceof JSpinner.DefaultEditor) { - final JTextField tf = ((JSpinner.DefaultEditor)element).getTextField(); + final JTextField tf = ((JSpinner.DefaultEditor) element).getTextField(); if (tf != null) { tf.setToolTipText(toolTipText); } } else if (element instanceof JComponent) { - ((JComponent)element).setToolTipText(toolTipText); + ((JComponent) element).setToolTipText(toolTipText); } } } 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 94d69294407..92df95b6db2 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 @@ -235,9 +235,9 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing } /** - * Invoked by installUI to create + * Invoked by {@code installUI} to create * a layout manager object to manage - * the JTabbedPane. + * the {@code JTabbedPane}. * * @return a layout manager object * @@ -536,7 +536,7 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing /** * Sets the tab the mouse is over by location. This is a cover method - * for setRolloverTab(tabForCoordinate(x, y, false)). + * for {@code setRolloverTab(tabForCoordinate(x, y, false))}. */ private void setRolloverTab(final int x, final int y) { // NOTE: @@ -547,8 +547,8 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing } /** - * Sets the tab the mouse is currently over to index. - * index will be -1 if the mouse is no longer over any + * Sets the tab the mouse is currently over to {@code index}. + * {@code index} will be -1 if the mouse is no longer over any * tab. No checking is done to ensure the passed in index identifies a * valid tab. * @@ -676,7 +676,7 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing /** * Returns the amount the baseline is offset by. This is typically - * the same as getTabLabelShiftY. + * the same as {@code getTabLabelShiftY}. * * @return amount to offset the baseline by * @since 1.6 @@ -765,10 +765,10 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing /** * Paints the tabs in the tab area. * Invoked by paint(). - * The graphics parameter must be a valid Graphics + * The graphics parameter must be a valid {@code Graphics} * object. Tab placement may be either: - * JTabbedPane.TOP, JTabbedPane.BOTTOM, - * JTabbedPane.LEFT, or JTabbedPane.RIGHT. + * {@code JTabbedPane.TOP}, {@code JTabbedPane.BOTTOM}, + * {@code JTabbedPane.LEFT}, or {@code JTabbedPane.RIGHT}. * The selected index must be a valid tabbed pane tab index (0 to * tab count - 1, inclusive) or -1 if no tab is currently selected. * The handling of invalid parameters is unspecified. @@ -1406,7 +1406,7 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing * designated Rectangle object (rather than instantiating and returning * a new Rectangle each time). The tab index parameter must be a valid * tabbed pane tab index (0 to tab count - 1, inclusive). The destination - * rectangle parameter must be a valid Rectangle instance. + * rectangle parameter must be a valid {@code Rectangle} instance. * The handling of invalid parameters is unspecified. * * @param tabIndex the index of the tab @@ -3717,7 +3717,7 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing /** * An ActionMap that populates its contents as necessary. The - * contents are populated by invoking the loadActionMap + * contents are populated by invoking the {@code loadActionMap} * method on the passed in Object. * * @version 1.6, 11/17/05 @@ -3726,14 +3726,14 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing @SuppressWarnings("serial") // Superclass is not serializable across versions static class LazyActionMap extends ActionMapUIResource { /** - * Object to invoke loadActionMap on. This may be + * Object to invoke {@code loadActionMap} on. This may be * a Class object. */ private transient Object _loader; /** * Installs an ActionMap that will be populated by invoking the - * loadActionMap method on the specified Class + * {@code loadActionMap} method on the specified Class * when necessary. *

* This should be used if the ActionMap can be shared. @@ -3755,7 +3755,7 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing /** * Returns an ActionMap that will be populated by invoking the - * loadActionMap method on the specified Class + * {@code loadActionMap} method on the specified Class * when necessary. *

* This should be used if the ActionMap can be shared. diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTreeUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTreeUI.java index 1b73f2a987a..2de5975051a 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTreeUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTreeUI.java @@ -179,8 +179,8 @@ public class AquaTreeUI extends BasicTreeUI { } /** - * Paints the expand (toggle) part of a row. The receiver should NOT modify clipBounds, or - * insets. + * Paints the expand (toggle) part of a row. The receiver should NOT modify {@code clipBounds}, or + * {@code insets}. */ protected void paintExpandControl(final Graphics g, final Rectangle clipBounds, final Insets insets, final Rectangle bounds, final TreePath path, final int row, final boolean isExpanded, final boolean hasBeenExpanded, final boolean isLeaf) { final Object value = path.getLastPathComponent(); diff --git a/jdk/src/java.desktop/macosx/classes/sun/font/NativeFont.java b/jdk/src/java.desktop/macosx/classes/sun/font/NativeFont.java index 0eb6db7e6e0..d3203da3980 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/font/NativeFont.java +++ b/jdk/src/java.desktop/macosx/classes/sun/font/NativeFont.java @@ -41,7 +41,7 @@ public class NativeFont extends PhysicalFont { /** * Verifies native font is accessible. - * @throws FontFormatException - if the font can't be located. + * @throws FontFormatException if the font can't be located. */ public NativeFont(String platName, boolean isBitmapDelegate) throws FontFormatException { diff --git a/jdk/src/java.desktop/macosx/classes/sun/java2d/DataBufferNIOInt.java b/jdk/src/java.desktop/macosx/classes/sun/java2d/DataBufferNIOInt.java index 08f5ef206e9..8447ba159d1 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/java2d/DataBufferNIOInt.java +++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/DataBufferNIOInt.java @@ -37,10 +37,10 @@ public final class DataBufferNIOInt extends DataBuffer { IntBuffer bankdata[]; /** - * Constructs an integer-based DataBuffer with a single bank + * Constructs an integer-based {@code DataBuffer} with a single bank * and the specified size. * - * @param size The size of the DataBuffer. + * @param size The size of the {@code DataBuffer}. */ public DataBufferNIOInt(int size) { super(TYPE_INT,size); @@ -51,7 +51,7 @@ public final class DataBufferNIOInt extends DataBuffer { } /** - * Returns the default (first) IntBuffer in DataBuffer. + * Returns the default (first) IntBuffer in {@code DataBuffer}. * * @return The first IntBuffer. */ @@ -70,7 +70,7 @@ public final class DataBufferNIOInt extends DataBuffer { } /** - * Returns the default (first) int data array in DataBuffer. + * Returns the default (first) int data array in {@code DataBuffer}. * * @return The first integer data array. */ @@ -137,7 +137,7 @@ public final class DataBufferNIOInt extends DataBuffer { /** * Sets the requested data array element in the specified bank - * to the integer value i. + * to the integer value {@code i}. * @param bank The bank in which you want to set the data array element. * @param i The data array element you want to set. * @param val The integer value to which you want to set the specified data array element. diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDesktopPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDesktopPeer.java index 39e5afe9f81..1bc37a7aa46 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDesktopPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDesktopPeer.java @@ -33,7 +33,7 @@ import java.net.URI; /** - * Concrete implementation of the interface DesktopPeer for MacOS X + * Concrete implementation of the interface {@code DesktopPeer} for MacOS X * * @see DesktopPeer */ diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java index a1606d2f959..276e0f9260a 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java @@ -101,7 +101,7 @@ public class CInputMethod extends InputMethodAdapter { * method. * * @param context the input method context for this input method - * @exception NullPointerException if context is null + * @exception NullPointerException if {@code context} is null */ public void setInputMethodContext(InputMethodContext context) { fIMContext = context; @@ -124,7 +124,7 @@ public class CInputMethod extends InputMethodAdapter { * * @param lang locale to input * @return whether the specified locale is supported - * @exception NullPointerException if locale is null + * @exception NullPointerException if {@code locale} is null */ public boolean setLocale(Locale lang) { return setLocale(lang, false); @@ -205,7 +205,7 @@ public class CInputMethod extends InputMethodAdapter { * are dispatched to the current input method for this component before * they are dispatched to the component's methods or event listeners. * The input method decides whether it needs to handle the event. If it - * does, it also calls the event's consume method; this + * does, it also calls the event's {@code consume} method; this * causes the event to not get dispatched to the component's event * processing methods or event listeners. *

@@ -216,7 +216,7 @@ public class CInputMethod extends InputMethodAdapter { * This method is called by {@link java.awt.im.InputContext#dispatchEvent InputContext.dispatchEvent}. * * @param event the event being dispatched to the input method - * @exception NullPointerException if event is null + * @exception NullPointerException if {@code event} is null */ public void dispatchEvent(final AWTEvent event) { // No-op for Mac OS X. diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java index 5457b1f291a..8d8c00b6a19 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java @@ -75,8 +75,7 @@ final class CPlatformResponder { jclickCount = clickCount; } - int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber, - modifierFlags); + int jmodifiers = NSEvent.nsToJavaModifiers(modifierFlags); boolean jpopupTrigger = NSEvent.isPopupTrigger(jmodifiers); eventNotifier.notifyMouseEvent(jeventType, System.currentTimeMillis(), jbuttonNumber, @@ -90,9 +89,7 @@ final class CPlatformResponder { void handleScrollEvent(final int x, final int y, final int absX, final int absY, final int modifierFlags, final double deltaX, final double deltaY) { - final int buttonNumber = CocoaConstants.kCGMouseButtonCenter; - int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber, - modifierFlags); + int jmodifiers = NSEvent.nsToJavaModifiers(modifierFlags); final boolean isShift = (jmodifiers & InputEvent.SHIFT_DOWN_MASK) != 0; // Vertical scroll. @@ -187,8 +184,7 @@ final class CPlatformResponder { postsTyped = false; } - - int jmodifiers = NSEvent.nsToJavaKeyModifiers(modifierFlags); + int jmodifiers = NSEvent.nsToJavaModifiers(modifierFlags); long when = System.currentTimeMillis(); if (jeventType == KeyEvent.KEY_PRESSED) { diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDevice.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDevice.java index c47b213b3a7..7450508cdfb 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDevice.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDevice.java @@ -35,8 +35,8 @@ public class CPrinterDevice extends GraphicsDevice { } /** - * Returns the type of this GraphicsDevice. - * @return the type of this GraphicsDevice, which can + * Returns the type of this {@code GraphicsDevice}. + * @return the type of this {@code GraphicsDevice}, which can * either be TYPE_RASTER_SCREEN, TYPE_PRINTER or TYPE_IMAGE_BUFFER. * @see #TYPE_RASTER_SCREEN * @see #TYPE_PRINTER @@ -48,30 +48,30 @@ public class CPrinterDevice extends GraphicsDevice { /** * Returns the identification string associated with this - * GraphicsDevice. - * @return a String that is the identification - * of this GraphicsDevice. + * {@code GraphicsDevice}. + * @return a {@code String} that is the identification + * of this {@code GraphicsDevice}. */ public String getIDstring() { return ("Printer"); } /** - * Returns all of the GraphicsConfiguration - * objects associated with this GraphicsDevice. - * @return an array of GraphicsConfiguration + * Returns all of the {@code GraphicsConfiguration} + * objects associated with this {@code GraphicsDevice}. + * @return an array of {@code GraphicsConfiguration} * objects that are associated with this - * GraphicsDevice. + * {@code GraphicsDevice}. */ public GraphicsConfiguration[] getConfigurations() { return new GraphicsConfiguration[] { gc }; } /** - * Returns the default GraphicsConfiguration - * associated with this GraphicsDevice. - * @return the default GraphicsConfiguration - * of this GraphicsDevice. + * Returns the default {@code GraphicsConfiguration} + * associated with this {@code GraphicsDevice}. + * @return the default {@code GraphicsConfiguration} + * of this {@code GraphicsDevice}. */ public GraphicsConfiguration getDefaultConfiguration() { return gc; diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterGraphicsConfig.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterGraphicsConfig.java index 89363a5b907..64f564abc1c 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterGraphicsConfig.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterGraphicsConfig.java @@ -49,9 +49,9 @@ public class CPrinterGraphicsConfig extends GraphicsConfiguration { /** * Returns the {@link GraphicsDevice} associated with this - * GraphicsConfiguration. - * @return a GraphicsDevice object that is - * associated with this GraphicsConfiguration. + * {@code GraphicsConfiguration}. + * @return a {@code GraphicsDevice} object that is + * associated with this {@code GraphicsConfiguration}. */ public GraphicsDevice getDevice() { return gd; @@ -59,16 +59,16 @@ public class CPrinterGraphicsConfig extends GraphicsConfiguration { /** * Returns a {@link BufferedImage} with a data layout and color model - * compatible with this GraphicsConfiguration. This + * compatible with this {@code GraphicsConfiguration}. This * method has nothing to do with memory-mapping - * a device. The returned BufferedImage has + * a device. The returned {@code BufferedImage} has * a layout and color model that is closest to this native device * configuration and can therefore be optimally blitted to this * device. - * @param width the width of the returned BufferedImage - * @param height the height of the returned BufferedImage - * @return a BufferedImage whose data layout and color - * model is compatible with this GraphicsConfiguration. + * @param width the width of the returned {@code BufferedImage} + * @param height the height of the returned {@code BufferedImage} + * @return a {@code BufferedImage} whose data layout and color + * model is compatible with this {@code GraphicsConfiguration}. */ public BufferedImage createCompatibleImage(int width, int height) { return createCompatibleImage(width, height, Transparency.OPAQUE); @@ -76,15 +76,15 @@ public class CPrinterGraphicsConfig extends GraphicsConfiguration { /** * Returns a {@link VolatileImage} with a data layout and color model - * compatible with this GraphicsConfiguration. - * The returned VolatileImage + * compatible with this {@code GraphicsConfiguration}. + * The returned {@code VolatileImage} * may have data that is stored optimally for the underlying graphics * device and may therefore benefit from platform-specific rendering * acceleration. - * @param width the width of the returned VolatileImage - * @param height the height of the returned VolatileImage - * @return a VolatileImage whose data layout and color - * model is compatible with this GraphicsConfiguration. + * @param width the width of the returned {@code VolatileImage} + * @param height the height of the returned {@code VolatileImage} + * @return a {@code VolatileImage} whose data layout and color + * model is compatible with this {@code GraphicsConfiguration}. * @see Component#createVolatileImage(int, int) */ public VolatileImage createCompatibleVolatileImage(int width, int height) { @@ -97,18 +97,18 @@ public class CPrinterGraphicsConfig extends GraphicsConfiguration { } /** - * Returns a BufferedImage that supports the specified + * Returns a {@code BufferedImage} that supports the specified * transparency and has a data layout and color model - * compatible with this GraphicsConfiguration. This + * compatible with this {@code GraphicsConfiguration}. This * method has nothing to do with memory-mapping - * a device. The returned BufferedImage has a layout and + * a device. The returned {@code BufferedImage} has a layout and * color model that can be optimally blitted to a device - * with this GraphicsConfiguration. - * @param width the width of the returned BufferedImage - * @param height the height of the returned BufferedImage + * with this {@code GraphicsConfiguration}. + * @param width the width of the returned {@code BufferedImage} + * @param height the height of the returned {@code BufferedImage} * @param transparency the specified transparency mode - * @return a BufferedImage whose data layout and color - * model is compatible with this GraphicsConfiguration + * @return a {@code BufferedImage} whose data layout and color + * model is compatible with this {@code GraphicsConfiguration} * and also supports the specified transparency. * @see Transparency#OPAQUE * @see Transparency#BITMASK @@ -121,21 +121,21 @@ public class CPrinterGraphicsConfig extends GraphicsConfiguration { /** * Returns the {@link ColorModel} associated with this - * GraphicsConfiguration. - * @return a ColorModel object that is associated with - * this GraphicsConfiguration. + * {@code GraphicsConfiguration}. + * @return a {@code ColorModel} object that is associated with + * this {@code GraphicsConfiguration}. */ public ColorModel getColorModel() { return getColorModel(Transparency.OPAQUE); } /** - * Returns the ColorModel associated with this - * GraphicsConfiguration that supports the specified + * Returns the {@code ColorModel} associated with this + * {@code GraphicsConfiguration} that supports the specified * transparency. * @param transparency the specified transparency mode - * @return a ColorModel object that is associated with - * this GraphicsConfiguration and supports the + * @return a {@code ColorModel} object that is associated with + * this {@code GraphicsConfiguration} and supports the * specified transparency. */ public ColorModel getColorModel(int transparency) { @@ -144,22 +144,22 @@ public class CPrinterGraphicsConfig extends GraphicsConfiguration { /** * Returns the default {@link AffineTransform} for this - * GraphicsConfiguration. This - * AffineTransform is typically the Identity transform - * for most normal screens. The default AffineTransform + * {@code GraphicsConfiguration}. This + * {@code AffineTransform} is typically the Identity transform + * for most normal screens. The default {@code AffineTransform} * maps coordinates onto the device such that 72 user space * coordinate units measure approximately 1 inch in device * space. The normalizing transform can be used to make * this mapping more exact. Coordinates in the coordinate space - * defined by the default AffineTransform for screen and + * defined by the default {@code AffineTransform} for screen and * printer devices have the origin in the upper left-hand corner of * the target region of the device, with X coordinates * increasing to the right and Y coordinates increasing downwards. * For image buffers not associated with a device, such as those not - * created by createCompatibleImage, - * this AffineTransform is the Identity transform. - * @return the default AffineTransform for this - * GraphicsConfiguration. + * created by {@code createCompatibleImage}, + * this {@code AffineTransform} is the Identity transform. + * @return the default {@code AffineTransform} for this + * {@code GraphicsConfiguration}. */ public AffineTransform getDefaultTransform() { return new AffineTransform(); @@ -167,9 +167,9 @@ public class CPrinterGraphicsConfig extends GraphicsConfiguration { /** * - * Returns a AffineTransform that can be concatenated - * with the default AffineTransform - * of a GraphicsConfiguration so that 72 units in user + * Returns a {@code AffineTransform} that can be concatenated + * with the default {@code AffineTransform} + * of a {@code GraphicsConfiguration} so that 72 units in user * space equals 1 inch in device space. *

* For a particular {@link Graphics2D}, g, one @@ -181,16 +181,16 @@ public class CPrinterGraphicsConfig extends GraphicsConfiguration { * g.setTransform(gc.getDefaultTransform()); * g.transform(gc.getNormalizingTransform()); * - * Note that sometimes this AffineTransform is identity, + * Note that sometimes this {@code AffineTransform} is identity, * such as for printers or metafile output, and that this - * AffineTransform is only as accurate as the information + * {@code AffineTransform} is only as accurate as the information * supplied by the underlying system. For image buffers not * associated with a device, such as those not created by - * createCompatibleImage, this - * AffineTransform is the Identity transform + * {@code createCompatibleImage}, this + * {@code AffineTransform} is the Identity transform * since there is no valid distance measurement. - * @return an AffineTransform to concatenate to the - * default AffineTransform so that 72 units in user + * @return an {@code AffineTransform} to concatenate to the + * default {@code AffineTransform} so that 72 units in user * space is mapped to 1 inch in device space. */ public AffineTransform getNormalizingTransform() { @@ -198,12 +198,12 @@ public class CPrinterGraphicsConfig extends GraphicsConfiguration { } /** - * Returns the bounds of the GraphicsConfiguration + * Returns the bounds of the {@code GraphicsConfiguration} * in the device coordinates. In a multi-screen environment * with a virtual device, the bounds can have negative X * or Y origins. * @return the bounds of the area covered by this - * GraphicsConfiguration. + * {@code GraphicsConfiguration}. * @since 1.3 */ public Rectangle getBounds() { diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index c28e83bfbf2..491b257765f 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -83,13 +83,13 @@ public final class CPrinterJob extends RasterPrinterJob { * to these native print services. * To present the cross platform print dialog for all services, * including native ones instead use - * printDialog(PrintRequestAttributeSet). + * {@code printDialog(PrintRequestAttributeSet)}. *

* PrinterJob implementations which can use PrintService's will update * the PrintService for this PrinterJob to reflect the new service * selected by the user. - * @return true if the user does not cancel the dialog; - * false otherwise. + * @return {@code true} if the user does not cancel the dialog; + * {@code false} otherwise. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless @@ -117,19 +117,19 @@ public final class CPrinterJob extends RasterPrinterJob { /** * Displays a dialog that allows modification of a - * PageFormat instance. - * The page argument is used to initialize controls + * {@code PageFormat} instance. + * The {@code page} argument is used to initialize controls * in the page setup dialog. * If the user cancels the dialog then this method returns the - * original page object unmodified. + * original {@code page} object unmodified. * If the user okays the dialog then this method returns a new - * PageFormat object with the indicated changes. - * In either case, the original page object is + * {@code PageFormat} object with the indicated changes. + * In either case, the original {@code page} object is * not modified. - * @param page the default PageFormat presented to the + * @param page the default {@code PageFormat} presented to the * user for modification - * @return the original page object if the dialog - * is cancelled; a new PageFormat object + * @return the original {@code page} object if the dialog + * is cancelled; a new {@code PageFormat} object * containing the format indicated by the user if the * dialog is acknowledged. * @exception HeadlessException if GraphicsEnvironment.isHeadless() @@ -157,11 +157,11 @@ public final class CPrinterJob extends RasterPrinterJob { } /** - * Clones the PageFormat argument and alters the + * Clones the {@code PageFormat} argument and alters the * clone to describe a default page size and orientation. - * @param page the PageFormat to be cloned and altered - * @return clone of page, altered to describe a default - * PageFormat. + * @param page the {@code PageFormat} to be cloned and altered + * @return clone of {@code page}, altered to describe a default + * {@code PageFormat}. */ @Override public PageFormat defaultPage(PageFormat page) { diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java index e8bdb1fe6c8..940858e1d4f 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CRobot.java @@ -73,7 +73,7 @@ class CRobot implements RobotPeer { * Presses one or more mouse buttons. * * @param buttons the button mask (combination of - * InputEvent.BUTTON1/2/3_MASK) + * {@code InputEvent.BUTTON1/2/3_MASK}) */ @Override public void mousePress(int buttons) { @@ -87,7 +87,7 @@ class CRobot implements RobotPeer { * Releases one or more mouse buttons. * * @param buttons the button mask (combination of - * InputEvent.BUTTON1/2/3_MASK) + * {@code InputEvent.BUTTON1/2/3_MASK}) */ @Override public void mouseRelease(int buttons) { @@ -133,14 +133,14 @@ class CRobot implements RobotPeer { * Presses a given key. *

* Key codes that have more than one physical key associated with them - * (e.g. KeyEvent.VK_SHIFT could mean either the + * (e.g. {@code KeyEvent.VK_SHIFT} could mean either the * left or right shift key) will map to the left key. *

* Assumes that the * peer implementations will throw an exception for other bogus * values e.g. -1, 999999 * - * @param keycode the key to press (e.g. KeyEvent.VK_A) + * @param keycode the key to press (e.g. {@code KeyEvent.VK_A}) */ @Override public void keyPress(final int keycode) { @@ -151,14 +151,14 @@ class CRobot implements RobotPeer { * Releases a given key. *

* Key codes that have more than one physical key associated with them - * (e.g. KeyEvent.VK_SHIFT could mean either the + * (e.g. {@code KeyEvent.VK_SHIFT} could mean either the * left or right shift key) will map to the left key. *

* Assumes that the * peer implementations will throw an exception for other bogus * values e.g. -1, 999999 * - * @param keycode the key to release (e.g. KeyEvent.VK_A) + * @param keycode the key to release (e.g. {@code KeyEvent.VK_A}) */ @Override public void keyRelease(final int keycode) { diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java index 0e0d0a475e0..2d82a2eb1c1 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java @@ -214,7 +214,7 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer { jclickCount = nsEvent.getClickCount(); } - int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber, + int jmodifiers = NSEvent.nsToJavaModifiers( nsEvent.getModifierFlags()); boolean isPopupTrigger = NSEvent.isPopupTrigger(jmodifiers); 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 8f9e1459103..cc3d345eb9f 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 @@ -515,13 +515,13 @@ public final class LWCToolkit extends LWToolkit { * key for menu shortcuts. *

* Menu shortcuts, which are embodied in the - * MenuShortcut class, are handled by the - * MenuBar class. + * {@code MenuShortcut} class, are handled by the + * {@code MenuBar} class. *

- * By default, this method returns Event.CTRL_MASK. + * By default, this method returns {@code Event.CTRL_MASK}. * Toolkit implementations should override this method if the * Control key isn't the correct key for accelerators. - * @return the modifier mask on the Event class + * @return the modifier mask on the {@code Event} class * that is used for menu shortcuts on this toolkit. * @see java.awt.MenuBar * @see java.awt.MenuShortcut diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java index d30a39cdfb9..290e52965a3 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,16 +231,14 @@ final class NSEvent { return jeventType; } - /* - * Converts NSEvent mouse modifiers to AWT mouse modifiers. + /** + * Converts NSEvent key modifiers to AWT key modifiers. Note that this + * method adds the current mouse state as a mouse modifiers. + * + * @param modifierFlags the NSEvent key modifiers + * @return the java key and mouse modifiers */ - static native int nsToJavaMouseModifiers(int buttonNumber, - int modifierFlags); - - /* - * Converts NSEvent key modifiers to AWT key modifiers. - */ - static native int nsToJavaKeyModifiers(int modifierFlags); + static native int nsToJavaModifiers(int modifierFlags); /* * Converts NSEvent key info to AWT key info. diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m index 51bacfcd5e4..07bb7fab938 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -579,7 +579,7 @@ NSUInteger JavaModifiersToNsKeyModifiers(jint javaModifiers, BOOL isExtMods) } -jint GetJavaMouseModifiers(NSInteger button, NSUInteger modifierFlags) +jint GetJavaMouseModifiers(NSUInteger modifierFlags) { // Mousing needs the key modifiers jint modifiers = NsKeyModifiersToJavaModifiers(modifierFlags, YES); @@ -632,38 +632,18 @@ Java_java_awt_AWTEvent_nativeSetSource /* * Class: sun_lwawt_macosx_NSEvent - * Method: nsToJavaMouseModifiers + * Method: nsToJavaModifiers * Signature: (II)I */ JNIEXPORT jint JNICALL -Java_sun_lwawt_macosx_NSEvent_nsToJavaMouseModifiers -(JNIEnv *env, jclass cls, jint buttonNumber, jint modifierFlags) -{ - jint jmodifiers = 0; - -JNF_COCOA_ENTER(env); - - jmodifiers = GetJavaMouseModifiers(buttonNumber, modifierFlags); - -JNF_COCOA_EXIT(env); - - return jmodifiers; -} - -/* - * Class: sun_lwawt_macosx_NSEvent - * Method: nsToJavaKeyModifiers - * Signature: (I)I - */ -JNIEXPORT jint JNICALL -Java_sun_lwawt_macosx_NSEvent_nsToJavaKeyModifiers +Java_sun_lwawt_macosx_NSEvent_nsToJavaModifiers (JNIEnv *env, jclass cls, jint modifierFlags) { jint jmodifiers = 0; JNF_COCOA_ENTER(env); - jmodifiers = NsKeyModifiersToJavaModifiers(modifierFlags, YES); + jmodifiers = GetJavaMouseModifiers(modifierFlags); JNF_COCOA_EXIT(env); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m index 994bda41982..79cdf5bf7a3 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m @@ -562,6 +562,17 @@ CGGI_CreateImageForGlyph (CGGI_GlyphCanvas *canvas, const CGGlyph glyph, GlyphInfo *info, const CGGI_RenderingMode *mode) { + if (isnan(info->topLeftX) || isnan(info->topLeftY)) { + // Explicitly set glyphInfo width/height to be 0 to ensure + // zero length glyph image is copied into GlyphInfo from canvas + info->width = 0; + info->height = 0; + + // copy the "empty" glyph from the canvas into the info + (*mode->glyphDescriptor->copyFxnPtr)(canvas, info); + return; + } + // clean the canvas CGGI_ClearCanvas(canvas, info); @@ -570,7 +581,6 @@ CGGI_CreateImageForGlyph -info->topLeftX, canvas->image->height + info->topLeftY, &glyph, 1); - // copy the glyph from the canvas into the info (*mode->glyphDescriptor->copyFxnPtr)(canvas, info); } diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphOutlines.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphOutlines.m index 29a579f66b4..4fde4a3825d 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphOutlines.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphOutlines.m @@ -259,6 +259,10 @@ AWTGetGlyphOutline(CGGlyph *glyphs, NSFont *font, OSStatus status = noErr; + if ( isnan(tx->a) || isnan(tx->b) || isnan(tx->c) || + isnan(tx->d) || isnan(tx->tx) || isnan(tx->ty)) { + return status; + } glyphs = glyphs + inStartIndex; // advanceArray = advanceArray + inStartIndex; // TODO(cpc): use advance diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileReader b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileReader index 624dac1c026..f0536e70d0e 100644 --- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileReader +++ b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileReader @@ -3,4 +3,5 @@ com.sun.media.sound.AuFileReader com.sun.media.sound.AiffFileReader com.sun.media.sound.WaveFileReader com.sun.media.sound.WaveFloatFileReader +com.sun.media.sound.WaveExtensibleFileReader com.sun.media.sound.SoftMidiAudioFileReader diff --git a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileWriter b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileWriter index bd84a769a36..83ac2b98105 100644 --- a/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileWriter +++ b/jdk/src/java.desktop/share/classes/META-INF/services/javax.sound.sampled.spi.AudioFileWriter @@ -2,3 +2,4 @@ com.sun.media.sound.AuFileWriter com.sun.media.sound.AiffFileWriter com.sun.media.sound.WaveFileWriter +com.sun.media.sound.WaveFloatFileWriter diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java index 27a935d715a..5809fff5f25 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java @@ -74,7 +74,7 @@ import com.sun.imageio.plugins.common.I18N; /** This class is the Java Image IO plugin reader for BMP images. * It may subsample the image, clip the image, select sub-bands, * and shift the decoded image origin if the proper decoding parameter - * are set in the provided ImageReadParam. + * are set in the provided {@code ImageReadParam}. * * This class supports Microsoft Windows Bitmap Version 3-5, * as well as OS/2 Bitmap Version 2.x (for single-image BMP file). @@ -159,8 +159,8 @@ public class BMPImageReader extends ImageReader implements BMPConstants { /** source and destination bands. */ private int[] sourceBands, destBands; - /** Constructs BMPImageReader from the provided - * ImageReaderSpi. + /** Constructs {@code BMPImageReader} from the provided + * {@code ImageReaderSpi}. */ public BMPImageReader(ImageReaderSpi originator) { super(originator); @@ -1681,8 +1681,8 @@ public class BMPImageReader extends ImageReader implements BMPConstants { /** Decodes the jpeg/png image embedded in the bitmap using any jpeg * ImageIO-style plugin. * - * @param bi The destination BufferedImage. - * @param bmpParam The ImageReadParam for decoding this + * @param bi The destination {@code BufferedImage}. + * @param bmpParam The {@code ImageReadParam} for decoding this * BMP image. The parameters for subregion, band selection and * subsampling are used in decoding the jpeg image. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java index fd90e2edbb7..164aa9769ae 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java @@ -69,7 +69,7 @@ import com.sun.imageio.plugins.common.I18N; * a BMP format. * * The encoding process may clip, subsample using the parameters - * specified in the ImageWriteParam. + * specified in the {@code ImageWriteParam}. * * @see javax.imageio.plugins.bmp.BMPImageWriteParam */ @@ -88,8 +88,8 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants { private short[] spixels; private int[] ipixels; - /** Constructs BMPImageWriter based on the provided - * ImageWriterSpi. + /** Constructs {@code BMPImageWriter} based on the provided + * {@code ImageWriterSpi}. */ public BMPImageWriter(ImageWriterSpi originator) { super(originator); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java index 81924044610..b6f73efc712 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/BogusColorSpace.java @@ -28,7 +28,7 @@ package com.sun.imageio.plugins.common; import java.awt.color.ColorSpace; /** - * A dummy ColorSpace to enable ColorModel + * A dummy {@code ColorSpace} to enable {@code ColorModel} * for image data which do not have an innate color representation. */ @SuppressWarnings("serial") // JDK-implementation class @@ -37,8 +37,8 @@ public class BogusColorSpace extends ColorSpace { * Return the type given the number of components. * * @param numComponents The number of components in the - * ColorSpace. - * @exception IllegalArgumentException if numComponents + * {@code ColorSpace}. + * @exception IllegalArgumentException if {@code numComponents} * is less than 1. */ private static int getType(int numComponents) { @@ -62,11 +62,11 @@ public class BogusColorSpace extends ColorSpace { } /** - * Constructs a bogus ColorSpace. + * Constructs a bogus {@code ColorSpace}. * * @param numComponents The number of components in the - * ColorSpace. - * @exception IllegalArgumentException if numComponents + * {@code ColorSpace}. + * @exception IllegalArgumentException if {@code numComponents} * is less than 1. */ public BogusColorSpace(int numComponents) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/I18NImpl.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/I18NImpl.java index 4c6d36ac695..c2885cf5a8e 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/I18NImpl.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/I18NImpl.java @@ -37,9 +37,9 @@ import java.net.URL; * the file from the jar as the package name is included automatically. * *

Extenders need only provide a static method - * getString(String) which calls the static method in this + * {@code getString(String)} which calls the static method in this * class with the name of the invoking class and returns a - * String. + * {@code String}. */ public class I18NImpl { /** diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ImageUtil.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ImageUtil.java index ddaad6e78d6..b7fa186896b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ImageUtil.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ImageUtil.java @@ -58,35 +58,35 @@ import javax.imageio.spi.ImageWriterSpi; public class ImageUtil { /** - * Creates a ColorModel that may be used with the - * specified SampleModel. If a suitable - * ColorModel cannot be found, this method returns - * null. + * Creates a {@code ColorModel} that may be used with the + * specified {@code SampleModel}. If a suitable + * {@code ColorModel} cannot be found, this method returns + * {@code null}. * - *

Suitable ColorModels are guaranteed to exist - * for all instances of ComponentSampleModel. - * For 1- and 3- banded SampleModels, the returned - * ColorModel will be opaque. For 2- and 4-banded - * SampleModels, the output will use alpha transparency + *

Suitable {@code ColorModel}s are guaranteed to exist + * for all instances of {@code ComponentSampleModel}. + * For 1- and 3- banded {@code SampleModel}s, the returned + * {@code ColorModel} will be opaque. For 2- and 4-banded + * {@code SampleModel}s, the output will use alpha transparency * which is not premultiplied. 1- and 2-banded data will use a - * grayscale ColorSpace, and 3- and 4-banded data a sRGB - * ColorSpace. Data with 5 or more bands will have a - * BogusColorSpace.

+ * grayscale {@code ColorSpace}, and 3- and 4-banded data a sRGB + * {@code ColorSpace}. Data with 5 or more bands will have a + * {@code BogusColorSpace}.

* - *

An instance of DirectColorModel will be created for - * instances of SinglePixelPackedSampleModel with no more + *

An instance of {@code DirectColorModel} will be created for + * instances of {@code SinglePixelPackedSampleModel} with no more * than 4 bands.

* - *

An instance of IndexColorModel will be created for - * instances of MultiPixelPackedSampleModel. The colormap - * will be a grayscale ramp with 1 << numberOfBits + *

An instance of {@code IndexColorModel} will be created for + * instances of {@code MultiPixelPackedSampleModel}. The colormap + * will be a grayscale ramp with 1 << numberOfBits * entries ranging from zero to at most 255.

* - * @return An instance of ColorModel that is suitable for - * the supplied SampleModel, or null. + * @return An instance of {@code ColorModel} that is suitable for + * the supplied {@code SampleModel}, or {@code null}. * - * @throws IllegalArgumentException If sampleModel is - * null. + * @throws IllegalArgumentException If {@code sampleModel} is + * {@code null}. */ public static final ColorModel createColorModel(SampleModel sampleModel) { // Check the parameter. @@ -194,19 +194,19 @@ public class ImageUtil { } /** - * For the case of binary data (isBinary() returns - * true), return the binary data as a packed byte array. + * For the case of binary data ({@code isBinary()} returns + * {@code true}), return the binary data as a packed byte array. * The data will be packed as eight bits per byte with no bit offset, * i.e., the first bit in each image line will be the left-most of the * first byte of the line. The line stride in bytes will be - * (int)((getWidth()+7)/8). The length of the returned - * array will be the line stride multiplied by getHeight() + * {@code (int)((getWidth()+7)/8)}. The length of the returned + * array will be the line stride multiplied by {@code getHeight()} * * @return the binary data as a packed array of bytes with zero offset - * of null if the data are not binary. - * @throws IllegalArgumentException if isBinary() returns - * false with the SampleModel of the - * supplied Raster as argument. + * of {@code null} if the data are not binary. + * @throws IllegalArgumentException if {@code isBinary()} returns + * {@code false} with the {@code SampleModel} of the + * supplied {@code Raster} as argument. */ public static byte[] getPackedBinaryData(Raster raster, Rectangle rect) { @@ -387,11 +387,11 @@ public class ImageUtil { /** * Returns the binary data unpacked into an array of bytes. - * The line stride will be the width of the Raster. + * The line stride will be the width of the {@code Raster}. * - * @throws IllegalArgumentException if isBinary() returns - * false with the SampleModel of the - * supplied Raster as argument. + * @throws IllegalArgumentException if {@code isBinary()} returns + * {@code false} with the {@code SampleModel} of the + * supplied {@code Raster} as argument. */ public static byte[] getUnpackedBinaryData(Raster raster, Rectangle rect) { @@ -467,13 +467,13 @@ public class ImageUtil { } /** - * Sets the supplied Raster's data from an array + * Sets the supplied {@code Raster}'s data from an array * of packed binary data of the form returned by - * getPackedBinaryData(). + * {@code getPackedBinaryData()}. * - * @throws IllegalArgumentException if isBinary() returns - * false with the SampleModel of the - * supplied Raster as argument. + * @throws IllegalArgumentException if {@code isBinary()} returns + * {@code false} with the {@code SampleModel} of the + * supplied {@code Raster} as argument. */ public static void setPackedBinaryData(byte[] binaryDataArray, WritableRaster raster, @@ -713,16 +713,16 @@ public class ImageUtil { } /** - * Copies data into the packed array of the Raster + * Copies data into the packed array of the {@code Raster} * from an array of unpacked data of the form returned by - * getUnpackedBinaryData(). + * {@code getUnpackedBinaryData()}. * *

If the data are binary, then the target bit will be set if * and only if the corresponding byte is non-zero. * - * @throws IllegalArgumentException if isBinary() returns - * false with the SampleModel of the - * supplied Raster as argument. + * @throws IllegalArgumentException if {@code isBinary()} returns + * {@code false} with the {@code SampleModel} of the + * supplied {@code Raster} as argument. */ public static void setUnpackedBinaryData(byte[] bdata, WritableRaster raster, @@ -983,7 +983,7 @@ public class ImageUtil { * @param g The green channel color indices. * @param b The blue channel color indices. * @return If all the indices have 256 entries, and are identical mappings, - * return true; otherwise, return false. + * return {@code true}; otherwise, return {@code false}. */ public static boolean isIndicesForGrayscale(byte[] r, byte[] g, byte[] b) { if (r.length != g.length || r.length != b.length) @@ -1004,7 +1004,7 @@ public class ImageUtil { return true; } - /** Converts the provided object to String */ + /** Converts the provided object to {@code String} */ public static String convertObjectToString(Object obj) { if (obj == null) return ""; @@ -1035,10 +1035,10 @@ public class ImageUtil { } - /** Checks that the provided ImageWriter can encode - * the provided ImageTypeSpecifier or not. If not, an - * IIOException will be thrown. - * @param writer The provided ImageWriter. + /** Checks that the provided {@code ImageWriter} can encode + * the provided {@code ImageTypeSpecifier} or not. If not, an + * {@code IIOException} will be thrown. + * @param writer The provided {@code ImageWriter}. * @param type The image to be tested. * @throws IIOException If the writer cannot encoded the provided image. */ @@ -1053,12 +1053,12 @@ public class ImageUtil { } } - /** Checks that the provided ImageWriter can encode - * the provided ColorModel and SampleModel. - * If not, an IIOException will be thrown. - * @param writer The provided ImageWriter. - * @param colorModel The provided ColorModel. - * @param sampleModel The provided SampleModel. + /** Checks that the provided {@code ImageWriter} can encode + * the provided {@code ColorModel} and {@code SampleModel}. + * If not, an {@code IIOException} will be thrown. + * @param writer The provided {@code ImageWriter}. + * @param colorModel The provided {@code ColorModel}. + * @param sampleModel The provided {@code SampleModel}. * @throws IIOException If the writer cannot encoded the provided image. */ public static final void canEncodeImage(ImageWriter writer, diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/LZWStringTable.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/LZWStringTable.java index c90ed4b2b44..645c8e7fc54 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/LZWStringTable.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/LZWStringTable.java @@ -31,9 +31,9 @@ import java.io.PrintStream; * General purpose LZW String Table. * Extracted from GIFEncoder by Adam Doppelt * Comments added by Robin Luiten - * expandCode added by Robin Luiten + * {@code expandCode} added by Robin Luiten * The strLen table to give quick access to the lenght of an expanded - * code for use by the expandCode method added by Robin. + * code for use by the {@code expandCode} method added by Robin. **/ public class LZWStringTable { /** codesize + Reserved Codes */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/PaletteBuilder.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/PaletteBuilder.java index 35506ecdca5..4eae8a8f402 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/PaletteBuilder.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/PaletteBuilder.java @@ -70,19 +70,19 @@ public class PaletteBuilder { /** * Creates an image representing given image - * src using IndexColorModel. + * {@code src} using {@code IndexColorModel}. * * Lossless conversion is not always possible (e.g. if number * of colors in the given image exceeds maximum palette size). * Result image then is an approximation constructed by octree * quantization method. * - * @exception IllegalArgumentException if src is - * null. + * @exception IllegalArgumentException if {@code src} is + * {@code null}. * * @exception UnsupportedOperationException if implemented method - * is unable to create approximation of src - * and canCreatePalette returns false. + * is unable to create approximation of {@code src} + * and {@code canCreatePalette} returns {@code false}. * * @see createIndexColorModel * @@ -97,15 +97,15 @@ public class PaletteBuilder { /** * Creates an palette representing colors from given image - * img. If number of colors in the given image exceeds + * {@code img}. If number of colors in the given image exceeds * maximum palette size closest colors would be merged. * - * @exception IllegalArgumentException if img is - * null. + * @exception IllegalArgumentException if {@code img} is + * {@code null}. * * @exception UnsupportedOperationException if implemented method - * is unable to create approximation of img - * and canCreatePalette returns false. + * is unable to create approximation of {@code img} + * and {@code canCreatePalette} returns {@code false}. * * @see createIndexedImage * @@ -119,17 +119,17 @@ public class PaletteBuilder { } /** - * Returns true if PaletteBuilder is able to create + * Returns {@code true} if PaletteBuilder is able to create * palette for given image type. * - * @param type an instance of ImageTypeSpecifier to be + * @param type an instance of {@code ImageTypeSpecifier} to be * indexed. * - * @return true if the PaletteBuilder + * @return {@code true} if the {@code PaletteBuilder} * is likely to be able to create palette for this image type. * - * @exception IllegalArgumentException if type - * is null. + * @exception IllegalArgumentException if {@code type} + * is {@code null}. */ public static boolean canCreatePalette(ImageTypeSpecifier type) { if (type == null) { @@ -139,17 +139,17 @@ public class PaletteBuilder { } /** - * Returns true if PaletteBuilder is able to create + * Returns {@code true} if PaletteBuilder is able to create * palette for given rendered image. * - * @param image an instance of RenderedImage to be + * @param image an instance of {@code RenderedImage} to be * indexed. * - * @return true if the PaletteBuilder + * @return {@code true} if the {@code PaletteBuilder} * is likely to be able to create palette for this image type. * - * @exception IllegalArgumentException if image - * is null. + * @exception IllegalArgumentException if {@code image} + * is {@code null}. */ public static boolean canCreatePalette(RenderedImage image) { if (image == null) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java index cedc428c3b4..0f8d1d66a28 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java @@ -134,25 +134,25 @@ public class ReaderUtil { * pixels that will be written during a particular decoding pass. * The intent is to simplify the work done by readers in combining * the source region, source subsampling, and destination offset - * information obtained from the ImageReadParam with + * information obtained from the {@code ImageReadParam} with * the offsets and periods of a progressive or interlaced decoding * pass. * - * @param sourceRegion a Rectangle containing the + * @param sourceRegion a {@code Rectangle} containing the * source region being read, offset by the source subsampling * offsets, and clipped against the source bounds, as returned by - * the getSourceRegion method. - * @param destinationOffset a Point containing the + * the {@code getSourceRegion} method. + * @param destinationOffset a {@code Point} containing the * coordinates of the upper-left pixel to be written in the * destination. * @param dstMinX the smallest X coordinate (inclusive) of the - * destination Raster. + * destination {@code Raster}. * @param dstMinY the smallest Y coordinate (inclusive) of the - * destination Raster. + * destination {@code Raster}. * @param dstMaxX the largest X coordinate (inclusive) of the destination - * Raster. + * {@code Raster}. * @param dstMaxY the largest Y coordinate (inclusive) of the destination - * Raster. + * {@code Raster}. * @param sourceXSubsampling the X subsampling factor. * @param sourceYSubsampling the Y subsampling factor. * @param passXStart the smallest source X coordinate (inclusive) @@ -168,7 +168,7 @@ public class ReaderUtil { * @param passPeriodY the Y period (vertical spacing between * pixels) of the current progressive pass. * - * @return an array of 6 ints containing the + * @return an array of 6 {@code int}s containing the * destination min X, min Y, width, height, X period and Y period * of the region that will be updated. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java index 82814627077..74ac23eb62e 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java @@ -1017,7 +1017,7 @@ public class GIFImageReader extends ImageReader { /** * Remove all settings including global settings such as - * Locales and listeners, as well as stream settings. + * {@code Locale}s and listeners, as well as stream settings. */ public void reset() { super.reset(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java index 0c4fc02e038..afb81aa2307 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java @@ -70,7 +70,7 @@ public class GIFImageWriter extends ImageWriter { GIFWritableImageMetadata.NATIVE_FORMAT_NAME; /** - * The output case to an ImageOutputStream. + * The {@code output} case to an {@code ImageOutputStream}. */ private ImageOutputStream stream = null; @@ -272,7 +272,7 @@ public class GIFImageWriter extends ImageWriter { } /** - * Merges inData into outData. The supplied + * Merges {@code inData} into {@code outData}. The supplied * metadata format name is attempted first and failing that the standard * metadata format name is attempted. */ @@ -554,8 +554,8 @@ public class GIFImageWriter extends ImageWriter { * * @param writeHeader Whether to write the header. * @param writeTrailer Whether to write the trailer. - * @param sm The stream metadata or null if - * writeHeader is false. + * @param sm The stream metadata or {@code null} if + * {@code writeHeader} is {@code false}. * @param iioimage The image and image metadata. * @param p The write parameters. * @@ -564,10 +564,10 @@ public class GIFImageWriter extends ImageWriter { * greater than 8. * @throws IllegalArgumentException if the color component size is * greater than 8. - * @throws IllegalArgumentException if writeHeader is - * true and sm is null. - * @throws IllegalArgumentException if writeHeader is - * false and a sequence is not being written. + * @throws IllegalArgumentException if {@code writeHeader} is + * {@code true} and {@code sm} is {@code null}. + * @throws IllegalArgumentException if {@code writeHeader} is + * {@code false} and a sequence is not being written. */ private void write(boolean writeHeader, boolean writeTrailer, diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java index 7e03f0fb98a..3aca0e5c356 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFMetadata.java @@ -32,7 +32,7 @@ import org.w3c.dom.Node; /** * Class which adds utility DOM element attribute access methods to - * IIOMetadata for subclass use. + * {@code IIOMetadata} for subclass use. */ abstract class GIFMetadata extends IIOMetadata { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java index c53cf35c865..d4a996ee3ee 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/COMMarkerSegment.java @@ -39,7 +39,7 @@ import org.w3c.dom.Node; * comment data as it is read from the stream. If the marker segment is * constructed from a String, then local default encoding is assumed * when creating the byte array. If the marker segment is created from - * an IIOMetadataNode, the user object, if present is + * an {@code IIOMetadataNode}, the user object, if present is * assumed to be a byte array containing the comment data. If there is * no user object then the comment attribute is used to create the * byte array, again assuming the default local encoding. @@ -49,7 +49,7 @@ class COMMarkerSegment extends MarkerSegment { /** * Constructs a marker segment from the given buffer, which contains - * data from an ImageInputStream. This is used when + * data from an {@code ImageInputStream}. This is used when * reading metadata from a stream. */ COMMarkerSegment(JPEGBuffer buffer) throws IOException { @@ -69,7 +69,7 @@ class COMMarkerSegment extends MarkerSegment { /** * Constructs a marker segment from a native tree node. If the node - * is an IIOMetadataNode and contains a user object, + * is an {@code IIOMetadataNode} and contains a user object, * that object is used rather than the string attribute. If the * string attribute is used, the default encoding is used. */ @@ -103,7 +103,7 @@ class COMMarkerSegment extends MarkerSegment { } /** - * Returns an IIOMetadataNode containing the data array + * Returns an {@code IIOMetadataNode} containing the data array * as a user object and a string encoded using ISO-8895-1, as an * attribute. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java index fb59d7b2119..b42eec68d10 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java @@ -90,7 +90,7 @@ class JFIFMarkerSegment extends MarkerSegment { private final boolean debug = false; /** - * Set to true when reading the chunks of an + * Set to {@code true} when reading the chunks of an * ICC profile. All chunks are consolidated to create a single * "segment" containing all the chunks. This flag is a state * variable identifying whether to construct a new segment or @@ -594,10 +594,10 @@ class JFIFMarkerSegment extends MarkerSegment { /** * Writes out a default JFIF marker segment to the given - * output stream. If thumbnails is not null, + * output stream. If {@code thumbnails} is not {@code null}, * writes out the set of thumbnail images as JFXX marker segments, or * incorporated into the JFIF segment if appropriate. - * If iccProfile is not null, + * If {@code iccProfile} is not {@code null}, * writes out the profile after the JFIF segment using as many APP2 * marker segments as necessary. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java index e18e9509e22..8acbf84bd8a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java @@ -36,7 +36,7 @@ import java.awt.color.ICC_ColorSpace; /** * A class containing JPEG-related constants, definitions, and * static methods. This class and its constants must be public so that - * JPEGImageWriteParam can see it. + * {@code JPEGImageWriteParam} can see it. */ public class JPEG { @@ -234,10 +234,10 @@ public class JPEG { public static final float DEFAULT_QUALITY = 0.75F; /** - * Returns true if the given ColorSpace + * Returns {@code true} if the given {@code ColorSpace} * object is an instance of ICC_ColorSpace but is not one of the - * standard ColorSpaces returned by - * ColorSpace.getInstance(). + * standard {@code ColorSpaces} returned by + * {@code ColorSpace.getInstance()}. */ static boolean isNonStandardICC(ColorSpace cs) { boolean retval = false; @@ -255,8 +255,8 @@ public class JPEG { /** - * Returns true if the given imageType can be used - * in a JFIF file. If input is true, then the + * Returns {@code true} if the given imageType can be used + * in a JFIF file. If {@code input} is true, then the * image type is considered before colorspace conversion. */ static boolean isJFIFcompliant(ImageTypeSpecifier imageType, @@ -295,7 +295,7 @@ public class JPEG { /** * Given an image type, return the Adobe transform corresponding to * that type, or ADOBE_IMPOSSIBLE if the image type is incompatible - * with an Adobe marker segment. If input is true, then + * with an Adobe marker segment. If {@code input} is true, then * the image type is considered before colorspace conversion. */ static int transformForType(ImageTypeSpecifier imageType, boolean input) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGBuffer.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGBuffer.java index 60bdbf08772..9c2f8b26088 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGBuffer.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGBuffer.java @@ -75,12 +75,12 @@ class JPEGBuffer { } /** - * Ensures that there are at least count bytes available + * Ensures that there are at least {@code count} bytes available * in the buffer, loading more data and moving any remaining * bytes to the front. A count of 0 means to just fill the buffer. * If the count is larger than the buffer size, just fills the buffer. * If the end of the stream is encountered before a non-0 count can - * be satisfied, an IIOException is thrown with the + * be satisfied, an {@code IIOException} is thrown with the * message "Image Format Error". */ void loadBuf(int count) throws IOException { @@ -122,7 +122,7 @@ class JPEGBuffer { * the buffer and then reading directly from the stream * if necessary. The buffer is left in an appropriate * state. If the end of the stream is encountered, an - * IIOException is thrown with the + * {@code IIOException} is thrown with the * message "Image Format Error". */ void readData(byte [] data) throws IOException { @@ -149,9 +149,9 @@ class JPEGBuffer { } /** - * Skips count bytes, leaving the buffer + * Skips {@code count} bytes, leaving the buffer * in an appropriate state. If the end of the stream is - * encountered, an IIOException is thrown with the + * encountered, an {@code IIOException} is thrown with the * message "Image Format Error". */ void skipData(int count) throws IOException { @@ -195,8 +195,8 @@ class JPEGBuffer { * the buffer as necessary. The buffer position is left * pointing to the first non-0xff byte after a run of * 0xff bytes. If the end of the stream is encountered, - * an EOI marker is inserted into the buffer and true - * is returned. Otherwise returns false. + * an EOI marker is inserted into the buffer and {@code true} + * is returned. Otherwise returns {@code false}. */ boolean scanForFF(JPEGImageReader reader) throws IOException { boolean retval = false; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java index 5a0e560f9ae..1773b200f65 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -544,7 +544,7 @@ public class JPEGImageReader extends ImageReader { } /** - * Returns true if there is an image beyond + * Returns {@code true} if there is an image beyond * the current stream position. Does not disturb the * stream position. */ @@ -614,13 +614,13 @@ public class JPEGImageReader extends ImageReader { /** * Read in the header information starting from the current - * stream position, returning true if the + * stream position, returning {@code true} if the * header was a tables-only image. After this call, the * native IJG decompression struct will contain the image * information required by most query calls below * (e.g. getWidth, getHeight, etc.), if the header was not * a tables-only image. - * If reset is true, the state of the IJG + * If reset is {@code true}, the state of the IJG * object is reset so that it can read a header again. * This happens automatically if the header was a tables-only * image. @@ -867,7 +867,7 @@ public class JPEGImageReader extends ImageReader { * Checks the implied color conversion between the stream and * the target image, altering the IJG output color space if necessary. * If a java color conversion is required, then this sets up - * convert. + * {@code convert}. * If bands are being rearranged at all (either source or destination * bands are specified in the param), then the default color * conversions are assumed to be correct. @@ -1394,7 +1394,7 @@ public class JPEGImageReader extends ImageReader { } /** - * Returns true if the read was aborted. + * Returns {@code true} if the read was aborted. */ private native boolean readImage(long structPointer, byte [] buffer, @@ -1788,6 +1788,8 @@ class ImageTypeProducer { case JPEG.JCS_GRAYSCALE: return ImageTypeSpecifier.createFromBufferedImageType (BufferedImage.TYPE_BYTE_GRAY); + case JPEG.JCS_YCbCr: + //there is no YCbCr raw type so by default we assume it as RGB case JPEG.JCS_RGB: return ImageTypeSpecifier.createInterleaved(JPEG.JCS.sRGB, JPEG.bOffsRGB, diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java index bc24343f9ba..12b94711cff 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java @@ -1130,10 +1130,10 @@ public class JPEGImageWriter extends ImageWriter { /* * from jpeg_metadata.html: * If no stream metadata is supplied to - * ImageWriter.prepareWriteSequence, then no + * {@code ImageWriter.prepareWriteSequence}, then no * tables-only image is written. If stream metadata containing * no tables is supplied to - * ImageWriter.prepareWriteSequence, then a tables-only + * {@code ImageWriter.prepareWriteSequence}, then a tables-only * image containing default visually lossless tables is written. */ if (streamMetadata != null) { @@ -1699,7 +1699,7 @@ public class JPEGImageWriter extends ImageWriter { private native void setDest(long structPointer); /** - * Returns true if the write was aborted. + * Returns {@code true} if the write was aborted. */ private native boolean writeImage(long structPointer, byte [] data, diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java index 7975efda580..e560a53f3ca 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java @@ -66,17 +66,17 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable { private static final boolean debug = false; /** - * A copy of markerSequence, created the first time the - * markerSequence is modified. This is used by reset + * A copy of {@code markerSequence}, created the first time the + * {@code markerSequence} is modified. This is used by reset * to restore the original state. */ private List resetSequence = null; /** - * Set to true when reading a thumbnail stored as + * Set to {@code true} when reading a thumbnail stored as * JPEG. This is used to enforce the prohibition of JFIF thumbnails * containing any JFIF marker segments, and to ensure generation of - * a correct native subtree during getAsTree. + * a correct native subtree during {@code getAsTree}. */ private boolean inThumb = false; @@ -93,7 +93,7 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable { /////// Package-access variables /** - * All data is a list of MarkerSegment objects. + * All data is a list of {@code MarkerSegment} objects. * When accessing the list, use the tag to identify the particular * subclass. Any JFIF marker segment must be the first element * of the list if it is present, and any JFXX or APP2ICC marker @@ -132,17 +132,17 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable { } /* - * Constructs a JPEGMetadata object by reading the - * contents of an ImageInputStream. Has package-only + * Constructs a {@code JPEGMetadata} object by reading the + * contents of an {@code ImageInputStream}. Has package-only * access. * * @param isStream A boolean indicating whether this object will be * stream or image metadata. * @param isThumb A boolean indicating whether this metadata object * is for an image or for a thumbnail stored as JPEG. - * @param iis An ImageInputStream from which to read + * @param iis An {@code ImageInputStream} from which to read * the metadata. - * @param reader The JPEGImageReader calling this + * @param reader The {@code JPEGImageReader} calling this * constructor, to which warnings should be sent. */ JPEGMetadata(boolean isStream, @@ -365,7 +365,7 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable { } /** - * Constructs a default stream JPEGMetadata object appropriate + * Constructs a default stream {@code JPEGMetadata} object appropriate * for the given write parameters. */ JPEGMetadata(ImageWriteParam param, JPEGImageWriter writer) { @@ -398,7 +398,7 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable { } /** - * Constructs a default image JPEGMetadata object appropriate + * Constructs a default image {@code JPEGMetadata} object appropriate * for the given image type and write parameters. */ JPEGMetadata(ImageTypeSpecifier imageType, @@ -2248,7 +2248,7 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable { /** * Check that this metadata object is in a consistent state and - * return true if it is or false + * return {@code true} if it is or {@code false} * otherwise. All the constructors and modifiers should call * this method at the end to guarantee that the data is always * consistent, as the writer relies on this. diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadataFormat.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadataFormat.java index 63dce67b055..475cc36359e 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadataFormat.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadataFormat.java @@ -133,12 +133,12 @@ abstract class JPEGMetadataFormat extends IIOMetadataFormatImpl { } /** - * Returns true if the named element occurs in the + * Returns {@code true} if the named element occurs in the * subtree of the format starting with the node named by - * subtreeName, including the node - * itself. subtreeName may be any node in + * {@code subtreeName}, including the node + * itself. {@code subtreeName} may be any node in * the format. If it is not, an - * IllegalArgumentException is thrown. + * {@code IllegalArgumentException} is thrown. */ protected boolean isInSubtree(String elementName, String subtreeName) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/MarkerSegment.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/MarkerSegment.java index 2952635b7f2..6f51fee8b8a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/MarkerSegment.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/MarkerSegment.java @@ -51,8 +51,8 @@ class MarkerSegment implements Cloneable { boolean unknown = false; // Set to true if the tag is not recognized /** - * Constructor for creating MarkerSegments by reading - * from an ImageInputStream. + * Constructor for creating {@code MarkerSegment}s by reading + * from an {@code ImageInputStream}. */ MarkerSegment(JPEGBuffer buffer) throws IOException { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java index 278882e5385..e58c7af8b18 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java @@ -26,16 +26,13 @@ package com.sun.imageio.plugins.png; import java.awt.Rectangle; -import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.io.ByteArrayOutputStream; -import java.io.DataOutput; import java.io.IOException; -import java.io.OutputStream; import java.util.Iterator; import java.util.Locale; import java.util.zip.Deflater; @@ -46,14 +43,13 @@ import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; -import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageOutputStreamImpl; -class CRC { +final class CRC { - private static int[] crcTable = new int[256]; + private static final int[] crcTable = new int[256]; private int crc = 0xffffffff; static { @@ -72,23 +68,25 @@ class CRC { } } - public CRC() {} + CRC() {} - public void reset() { + void reset() { crc = 0xffffffff; } - public void update(byte[] data, int off, int len) { + void update(byte[] data, int off, int len) { + int c = crc; for (int n = 0; n < len; n++) { - crc = crcTable[(crc ^ data[off + n]) & 0xff] ^ (crc >>> 8); + c = crcTable[(c ^ data[off + n]) & 0xff] ^ (c >>> 8); } + crc = c; } - public void update(int data) { + void update(int data) { crc = crcTable[(crc ^ data) & 0xff] ^ (crc >>> 8); } - public int getValue() { + int getValue() { return crc ^ 0xffffffff; } } @@ -96,11 +94,11 @@ class CRC { final class ChunkStream extends ImageOutputStreamImpl { - private ImageOutputStream stream; - private long startPos; - private CRC crc = new CRC(); + private final ImageOutputStream stream; + private final long startPos; + private final CRC crc = new CRC(); - public ChunkStream(int type, ImageOutputStream stream) throws IOException { + ChunkStream(int type, ImageOutputStream stream) throws IOException { this.stream = stream; this.startPos = stream.getStreamPosition(); @@ -108,25 +106,29 @@ final class ChunkStream extends ImageOutputStreamImpl { writeInt(type); } + @Override public int read() throws IOException { throw new RuntimeException("Method not available"); } + @Override public int read(byte[] b, int off, int len) throws IOException { throw new RuntimeException("Method not available"); } + @Override public void write(byte[] b, int off, int len) throws IOException { crc.update(b, off, len); stream.write(b, off, len); } + @Override public void write(int b) throws IOException { crc.update(b); stream.write(b); } - public void finish() throws IOException { + void finish() throws IOException { // Write CRC stream.writeInt(crc.getValue()); @@ -140,6 +142,7 @@ final class ChunkStream extends ImageOutputStreamImpl { stream.flushBefore(pos); } + @Override protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) @@ -150,24 +153,29 @@ final class ChunkStream extends ImageOutputStreamImpl { // fixed length. final class IDATOutputStream extends ImageOutputStreamImpl { - private static byte[] chunkType = { + private static final byte[] chunkType = { (byte)'I', (byte)'D', (byte)'A', (byte)'T' }; - private ImageOutputStream stream; - private int chunkLength; + private final ImageOutputStream stream; + private final int chunkLength; private long startPos; - private CRC crc = new CRC(); + private final CRC crc = new CRC(); - Deflater def = new Deflater(Deflater.BEST_COMPRESSION); - byte[] buf = new byte[512]; + private final Deflater def; + private final byte[] buf = new byte[512]; + // reused 1 byte[] array: + private final byte[] wbuf1 = new byte[1]; private int bytesRemaining; - public IDATOutputStream(ImageOutputStream stream, int chunkLength) - throws IOException { + IDATOutputStream(ImageOutputStream stream, int chunkLength, + int deflaterLevel) throws IOException + { this.stream = stream; this.chunkLength = chunkLength; + this.def = new Deflater(deflaterLevel); + startChunk(); } @@ -206,14 +214,17 @@ final class IDATOutputStream extends ImageOutputStreamImpl { } } + @Override public int read() throws IOException { throw new RuntimeException("Method not available"); } + @Override public int read(byte[] b, int off, int len) throws IOException { throw new RuntimeException("Method not available"); } + @Override public void write(byte[] b, int off, int len) throws IOException { if (len == 0) { return; @@ -227,7 +238,7 @@ final class IDATOutputStream extends ImageOutputStreamImpl { } } - public void deflate() throws IOException { + void deflate() throws IOException { int len = def.deflate(buf, 0, buf.length); int off = 0; @@ -247,13 +258,13 @@ final class IDATOutputStream extends ImageOutputStreamImpl { } } + @Override public void write(int b) throws IOException { - byte[] wbuf = new byte[1]; - wbuf[0] = (byte)b; - write(wbuf, 0, 1); + wbuf1[0] = (byte)b; + write(wbuf1, 0, 1); } - public void finish() throws IOException { + void finish() throws IOException { try { if (!def.finished()) { def.finish(); @@ -267,6 +278,7 @@ final class IDATOutputStream extends ImageOutputStreamImpl { } } + @Override protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) @@ -274,18 +286,76 @@ final class IDATOutputStream extends ImageOutputStreamImpl { } -class PNGImageWriteParam extends ImageWriteParam { +final class PNGImageWriteParam extends ImageWriteParam { - public PNGImageWriteParam(Locale locale) { + /** Default quality level = 0.5 ie medium compression */ + private static final float DEFAULT_QUALITY = 0.5f; + + private static final String[] compressionNames = {"Deflate"}; + private static final float[] qualityVals = { 0.00F, 0.30F, 0.75F, 1.00F }; + private static final String[] qualityDescs = { + "High compression", // 0.00 -> 0.30 + "Medium compression", // 0.30 -> 0.75 + "Low compression" // 0.75 -> 1.00 + }; + + PNGImageWriteParam(Locale locale) { super(); this.canWriteProgressive = true; this.locale = locale; + this.canWriteCompressed = true; + this.compressionTypes = compressionNames; + this.compressionType = compressionTypes[0]; + this.compressionMode = MODE_DEFAULT; + this.compressionQuality = DEFAULT_QUALITY; + } + + /** + * Removes any previous compression quality setting. + * + *

The default implementation resets the compression quality + * to 0.5F. + * + * @exception IllegalStateException if the compression mode is not + * MODE_EXPLICIT. + */ + @Override + public void unsetCompression() { + super.unsetCompression(); + this.compressionType = compressionTypes[0]; + this.compressionQuality = DEFAULT_QUALITY; + } + + /** + * Returns true since the PNG plug-in only supports + * lossless compression. + * + * @return true. + */ + @Override + public boolean isCompressionLossless() { + return true; + } + + @Override + public String[] getCompressionQualityDescriptions() { + super.getCompressionQualityDescriptions(); + return qualityDescs.clone(); + } + + @Override + public float[] getCompressionQualityValues() { + super.getCompressionQualityValues(); + return qualityVals.clone(); } } /** */ -public class PNGImageWriter extends ImageWriter { +public final class PNGImageWriter extends ImageWriter { + + /** Default compression level = 4 ie medium compression */ + private static final int DEFAULT_COMPRESSION_LEVEL = 4; ImageOutputStream stream = null; @@ -334,6 +404,7 @@ public class PNGImageWriter extends ImageWriter { super(originatingProvider); } + @Override public void setOutput(Object output) { super.setOutput(output); if (output != null) { @@ -346,16 +417,17 @@ public class PNGImageWriter extends ImageWriter { } } - private static int[] allowedProgressivePasses = { 1, 7 }; - + @Override public ImageWriteParam getDefaultWriteParam() { return new PNGImageWriteParam(getLocale()); } + @Override public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) { return null; } + @Override public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) { PNGMetadata m = new PNGMetadata(); @@ -363,11 +435,13 @@ public class PNGImageWriter extends ImageWriter { return m; } + @Override public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) { return null; } + @Override public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) { @@ -934,8 +1008,11 @@ public class PNGImageWriter extends ImageWriter { } // Use sourceXOffset, etc. - private void write_IDAT(RenderedImage image) throws IOException { - IDATOutputStream ios = new IDATOutputStream(stream, 32768); + private void write_IDAT(RenderedImage image, int deflaterLevel) + throws IOException + { + IDATOutputStream ios = new IDATOutputStream(stream, 32768, + deflaterLevel); try { if (metadata.IHDR_interlaceMethod == 1) { for (int i = 0; i < 7; i++) { @@ -1028,6 +1105,7 @@ public class PNGImageWriter extends ImageWriter { } } + @Override public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IIOException { @@ -1110,7 +1188,23 @@ public class PNGImageWriter extends ImageWriter { metadata = new PNGMetadata(); } + // reset compression level to default: + int deflaterLevel = DEFAULT_COMPRESSION_LEVEL; + if (param != null) { + switch(param.getCompressionMode()) { + case ImageWriteParam.MODE_DISABLED: + deflaterLevel = Deflater.NO_COMPRESSION; + break; + case ImageWriteParam.MODE_EXPLICIT: + float quality = param.getCompressionQuality(); + if (quality >= 0f && quality <= 1f) { + deflaterLevel = 9 - Math.round(9f * quality); + } + break; + default: + } + // Use Adam7 interlacing if set in write param switch (param.getProgressiveMode()) { case ImageWriteParam.MODE_DEFAULT: @@ -1119,8 +1213,9 @@ public class PNGImageWriter extends ImageWriter { case ImageWriteParam.MODE_DISABLED: metadata.IHDR_interlaceMethod = 0; break; - // MODE_COPY_FROM_METADATA should alreay be taken care of + // MODE_COPY_FROM_METADATA should already be taken care of // MODE_EXPLICIT is not allowed + default: } } @@ -1165,7 +1260,7 @@ public class PNGImageWriter extends ImageWriter { writeUnknownChunks(); - write_IDAT(im); + write_IDAT(im, deflaterLevel); if (abortRequested()) { processWriteAborted(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java index f02dd4391f0..2c7720c7f19 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java @@ -254,7 +254,7 @@ public class PNGMetadata extends IIOMetadata implements Cloneable { /** * Sets the IHDR_bitDepth and IHDR_colorType variables. - * The numBands parameter is necessary since + * The {@code numBands} parameter is necessary since * we may only be writing a subset of the image bands. */ public void initialize(ImageTypeSpecifier imageType, int numBands) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java index e8f4a5d05b3..c60a98c793b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java @@ -362,9 +362,9 @@ public class TIFFIFD extends TIFFDirectory { offsets.add(f); } + List byteCounts = new ArrayList<>(); if (offsets.size() > 0) { // StripByteCounts - List byteCounts = new ArrayList<>(); f = getTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS); if (f != null) { if (f.getCount() != count) { @@ -415,6 +415,12 @@ public class TIFFIFD extends TIFFDirectory { } } + // Ensure there is at least a data pointer for JPEG interchange format or + // both data offsets and byte counts for other compression types. + if (jpegOffset == null && (offsets.size() == 0 || byteCounts.size() == 0)) { + throw new IIOException("Insufficient data offsets or byte counts"); + } + // JPEGQTables - one 64-byte table for each offset. f = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_Q_TABLES); if (f != null) { @@ -480,14 +486,16 @@ public class TIFFIFD extends TIFFDirectory { stream.skipBytes(4); continue; } - int count = (int)stream.readUnsignedInt(); + long longCount = stream.readUnsignedInt(); // Get the associated TIFFTag. TIFFTag tag = getTag(tagNumber, tagSetList); - // Ignore unknown fields. + // Ignore unknown fields, fields with unknown type, and fields + // with count out of int range. if((tag == null && ignoreUnknownFields) - || (tag != null && !tag.isDataTypeOK(type))) { + || (tag != null && !tag.isDataTypeOK(type)) + || longCount > Integer.MAX_VALUE) { // Skip the value/offset so as to leave the stream // position at the start of the next IFD entry. stream.skipBytes(4); @@ -496,6 +504,8 @@ public class TIFFIFD extends TIFFDirectory { continue; } + int count = (int)longCount; + if (tag == null) { tag = new TIFFTag(TIFFTag.UNKNOWN_TAG_NAME, tagNumber, 1 << type, count); @@ -518,7 +528,14 @@ public class TIFFIFD extends TIFFDirectory { } } - int size = count*sizeOfType; + long longSize = longCount*sizeOfType; + if (longSize > Integer.MAX_VALUE) { + // Continue with the next IFD entry. + stream.skipBytes(4); + continue; + } + int size = (int)longSize; + if (size > 4 || tag.isIFDPointer()) { // The IFD entry value is a pointer to the actual field value. long offset = stream.readUnsignedInt(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java index 6a90e0677c9..ea819e9e968 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java @@ -266,6 +266,8 @@ public class TIFFImageWriter extends ImageWriter { super.setOutput(output); if (output != null) { + reset(); + if (!(output instanceof ImageOutputStream)) { throw new IllegalArgumentException ("output not an ImageOutputStream!"); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java index 1bab31408c8..a9edc1e2c3a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java @@ -50,7 +50,7 @@ import com.sun.imageio.plugins.common.ReaderUtil; /** This class is the Java Image IO plugin reader for WBMP images. * It may subsample the image, clip the image, * and shift the decoded image origin if the proper decoding parameter - * are set in the provided WBMPImageReadParam. + * are set in the provided {@code WBMPImageReadParam}. */ public class WBMPImageReader extends ImageReader { /** The input stream where reads from */ @@ -69,8 +69,8 @@ public class WBMPImageReader extends ImageReader { private WBMPMetadata metadata; - /** Constructs WBMPImageReader from the provided - * ImageReaderSpi. + /** Constructs {@code WBMPImageReader} from the provided + * {@code ImageReaderSpi}. */ public WBMPImageReader(ImageReaderSpi originator) { super(originator); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriter.java index 45d3187b2c8..8fd3a459fe1 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriter.java @@ -57,7 +57,7 @@ import com.sun.imageio.plugins.common.I18N; * a WBMP format. * * The encoding process may clip, subsample using the parameters - * specified in the ImageWriteParam. + * specified in the {@code ImageWriteParam}. * * @see com.sun.media.imageio.plugins.WBMPImageWriteParam */ @@ -92,8 +92,8 @@ public class WBMPImageWriter extends ImageWriter { return multiBytes; } - /** Constructs WBMPImageWriter based on the provided - * ImageWriterSpi. + /** Constructs {@code WBMPImageWriter} based on the provided + * {@code ImageWriterSpi}. */ public WBMPImageWriter(ImageWriterSpi originator) { super(originator); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java index 5e9e3c45cce..0a4788df804 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,23 +25,22 @@ package com.sun.media.sound; -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - import java.io.BufferedOutputStream; -import java.io.DataOutputStream; -import java.io.FileOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.RandomAccessFile; import java.io.SequenceInputStream; import java.util.Objects; import javax.sound.sampled.AudioFileFormat; -import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; //$$fb this class is buggy. Should be replaced in future. @@ -63,6 +62,7 @@ public final class AiffFileWriter extends SunFileWriter { // METHODS TO IMPLEMENT AudioFileWriter + @Override public AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream) { AudioFileFormat.Type[] filetypes = new AudioFileFormat.Type[types.length]; @@ -84,6 +84,7 @@ public final class AiffFileWriter extends SunFileWriter { } + @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException { Objects.requireNonNull(stream); Objects.requireNonNull(fileType); @@ -106,6 +107,7 @@ public final class AiffFileWriter extends SunFileWriter { } + @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException { Objects.requireNonNull(stream); Objects.requireNonNull(fileType); @@ -160,6 +162,9 @@ public final class AiffFileWriter extends SunFileWriter { * Throws IllegalArgumentException if not supported. */ private AudioFileFormat getAudioFileFormat(AudioFileFormat.Type type, AudioInputStream stream) { + if (!isFileTypeSupported(type, stream)) { + throw new IllegalArgumentException("File type " + type + " not supported."); + } AudioFormat format = null; AiffFileFormat fileFormat = null; @@ -177,10 +182,6 @@ public final class AiffFileWriter extends SunFileWriter { int fileSize; boolean convert8to16 = false; - if( !types[0].equals(type) ) { - throw new IllegalArgumentException("File type " + type + " not supported."); - } - if( (AudioFormat.Encoding.ALAW.equals(streamEncoding)) || (AudioFormat.Encoding.ULAW.equals(streamEncoding)) ) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AlawCodec.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AlawCodec.java index fcc0e709f2b..e117348dbdf 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AlawCodec.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AlawCodec.java @@ -135,45 +135,48 @@ public final class AlawCodec extends SunCodec { AudioFormat sourceFormat = sourceStream.getFormat(); AudioFormat.Encoding sourceEncoding = sourceFormat.getEncoding(); + if( !isConversionSupported(targetEncoding,sourceStream.getFormat()) ) { + throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString()); + } if( sourceEncoding.equals( targetEncoding ) ) { return sourceStream; - } else { - AudioFormat targetFormat = null; - if( !isConversionSupported(targetEncoding,sourceStream.getFormat()) ) { - throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString()); - } - if( sourceEncoding.equals( AudioFormat.Encoding.ALAW ) && - targetEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) ) { - - targetFormat = new AudioFormat( targetEncoding, - sourceFormat.getSampleRate(), - 16, - sourceFormat.getChannels(), - 2*sourceFormat.getChannels(), - sourceFormat.getSampleRate(), - sourceFormat.isBigEndian()); - - } else if( sourceEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) && - targetEncoding.equals( AudioFormat.Encoding.ALAW ) ) { - - targetFormat = new AudioFormat( targetEncoding, - sourceFormat.getSampleRate(), - 8, - sourceFormat.getChannels(), - sourceFormat.getChannels(), - sourceFormat.getSampleRate(), - false); - } else { - throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString()); - } - return getAudioInputStream( targetFormat, sourceStream ); } + AudioFormat targetFormat = null; + if( sourceEncoding.equals( AudioFormat.Encoding.ALAW ) && + targetEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) ) { + + targetFormat = new AudioFormat( targetEncoding, + sourceFormat.getSampleRate(), + 16, + sourceFormat.getChannels(), + 2*sourceFormat.getChannels(), + sourceFormat.getSampleRate(), + sourceFormat.isBigEndian()); + + } else if( sourceEncoding.equals( AudioFormat.Encoding.PCM_SIGNED ) && + targetEncoding.equals( AudioFormat.Encoding.ALAW ) ) { + + targetFormat = new AudioFormat( targetEncoding, + sourceFormat.getSampleRate(), + 8, + sourceFormat.getChannels(), + sourceFormat.getChannels(), + sourceFormat.getSampleRate(), + false); + } else { + throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString()); + } + return getConvertedStream(targetFormat, sourceStream); } /** * use old code... */ public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream){ + if (!isConversionSupported(targetFormat, sourceStream.getFormat())) + throw new IllegalArgumentException("Unsupported conversion: " + + sourceStream.getFormat().toString() + " to " + + targetFormat.toString()); return getConvertedStream( targetFormat, sourceStream ); } @@ -218,33 +221,28 @@ public final class AlawCodec extends SunCodec { Vector formats = new Vector<>(); AudioFormat format; - if ( AudioFormat.Encoding.PCM_SIGNED.equals(inputFormat.getEncoding())) { + if (inputFormat.getSampleSizeInBits() == 16 + && AudioFormat.Encoding.PCM_SIGNED.equals(inputFormat.getEncoding())) { format = new AudioFormat(AudioFormat.Encoding.ALAW, - inputFormat.getSampleRate(), - 8, + inputFormat.getSampleRate(), 8, inputFormat.getChannels(), inputFormat.getChannels(), - inputFormat.getSampleRate(), - false ); + inputFormat.getSampleRate(), false); formats.addElement(format); } - - if (AudioFormat.Encoding.ALAW.equals(inputFormat.getEncoding())) { + if (inputFormat.getSampleSizeInBits() == 8 + && AudioFormat.Encoding.ALAW.equals(inputFormat.getEncoding())) { format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, - inputFormat.getSampleRate(), - 16, + inputFormat.getSampleRate(), 16, inputFormat.getChannels(), - inputFormat.getChannels()*2, - inputFormat.getSampleRate(), - false ); + inputFormat.getChannels() * 2, + inputFormat.getSampleRate(), false); formats.addElement(format); format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, - inputFormat.getSampleRate(), - 16, + inputFormat.getSampleRate(), 16, inputFormat.getChannels(), - inputFormat.getChannels()*2, - inputFormat.getSampleRate(), - true ); + inputFormat.getChannels() * 2, + inputFormat.getSampleRate(), true); formats.addElement(format); } @@ -256,7 +254,7 @@ public final class AlawCodec extends SunCodec { } - final class AlawCodecStream extends AudioInputStream { + private final class AlawCodecStream extends AudioInputStream { // tempBuffer required only for encoding (when encode is true) private static final int tempBufferSize = 64; @@ -446,5 +444,12 @@ public final class AlawCodec extends SunCodec { return (i - off); } } + + @Override + public long skip(final long n) throws IOException { + // Implementation of this method assumes that we support + // encoding/decoding from/to 8/16 bits only + return encode ? super.skip(n * 2) / 2 : super.skip(n / 2) * 2; + } } // end class AlawCodecStream } // end class ALAW diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileFormat.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileFormat.java index 185efb9e6b0..7a8c5bc6a68 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileFormat.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,24 +25,18 @@ package com.sun.media.sound; - import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; - /** * AU file format. * * @author Jan Borgersen */ - final class AuFileFormat extends AudioFileFormat { // magic numbers - static final int AU_SUN_MAGIC = 0x2e736e64; - static final int AU_SUN_INV_MAGIC = 0x646e732e; - static final int AU_DEC_MAGIC = 0x2e736400; - static final int AU_DEC_INV_MAGIC = 0x0064732e; + static final int AU_SUN_MAGIC = 0x2e736e64; // ".snd" // encodings static final int AU_ULAW_8 = 1; /* 8-bit ISDN u-law */ @@ -62,11 +56,6 @@ final class AuFileFormat extends AudioFileFormat { private int auType; - AuFileFormat( AudioFileFormat aff ) { - - this( aff.getType(), aff.getByteLength(), aff.getFormat(), aff.getFrameLength() ); - } - AuFileFormat(AudioFileFormat.Type type, int lengthInBytes, AudioFormat format, int lengthInFrames) { super(type,lengthInBytes,format,lengthInFrames); @@ -94,12 +83,9 @@ final class AuFileFormat extends AudioFileFormat { auType = AU_LINEAR_32; } } - } public int getAuType() { - return auType; } - } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileReader.java index 7e83180dffa..180f45c9076 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileReader.java @@ -46,45 +46,25 @@ public final class AuFileReader extends SunFileReader { @Override public AudioFileFormat getAudioFileFormatImpl(final InputStream stream) throws UnsupportedAudioFileException, IOException { - boolean bigendian = false; - int headerSize = -1; - int dataSize = -1; - int encoding_local = -1; - int sampleRate = -1; - int frameRate = -1; - int frameSize = -1; - int channels = -1; - final int sampleSizeInBits; - int length = 0; - int nread = 0; - AudioFormat.Encoding encoding = null; - - DataInputStream dis = new DataInputStream( stream ); - - final int magic = dis.readInt(); nread += 4; - - if (! (magic == AuFileFormat.AU_SUN_MAGIC) || (magic == AuFileFormat.AU_DEC_MAGIC) || - (magic == AuFileFormat.AU_SUN_INV_MAGIC) || (magic == AuFileFormat.AU_DEC_INV_MAGIC) ) { + final DataInputStream dis = new DataInputStream(stream); + final int magic = dis.readInt(); + if (magic != AuFileFormat.AU_SUN_MAGIC) { // not AU, throw exception throw new UnsupportedAudioFileException("not an AU file"); } - if ((magic == AuFileFormat.AU_SUN_MAGIC) || (magic == AuFileFormat.AU_DEC_MAGIC)) { - bigendian = true; // otherwise little-endian - } - - headerSize = (bigendian==true ? dis.readInt() : rllong(dis) ); nread += 4; - dataSize = (bigendian==true ? dis.readInt() : rllong(dis) ); nread += 4; - encoding_local = (bigendian==true ? dis.readInt() : rllong(dis) ); nread += 4; - sampleRate = (bigendian==true ? dis.readInt() : rllong(dis) ); nread += 4; - channels = (bigendian==true ? dis.readInt() : rllong(dis) ); nread += 4; + final int headerSize = dis.readInt(); + final int dataSize = dis.readInt(); + final int encoding_local = dis.readInt(); + final int sampleRate = dis.readInt(); + final int channels = dis.readInt(); if (channels <= 0) { throw new UnsupportedAudioFileException("Invalid number of channels"); } - frameRate = sampleRate; - + final int sampleSizeInBits; + final AudioFormat.Encoding encoding; switch (encoding_local) { case AuFileFormat.AU_ULAW_8: encoding = AudioFormat.Encoding.ULAW; @@ -138,24 +118,24 @@ public final class AuFileReader extends SunFileReader { break; */ default: - // unsupported filetype, throw exception - throw new UnsupportedAudioFileException("not a valid AU file"); + // unsupported filetype, throw exception + throw new UnsupportedAudioFileException("not a valid AU file"); } - frameSize = calculatePCMFrameSize(sampleSizeInBits, channels); + final int frameSize = calculatePCMFrameSize(sampleSizeInBits, channels); //$$fb 2002-11-02: fix for 4629669: AU file reader: problems with empty files - if( dataSize < 0 ) { + final int length; + if (dataSize < 0) { length = AudioSystem.NOT_SPECIFIED; } else { //$$fb 2003-10-20: fix for 4940459: AudioInputStream.getFrameLength() returns 0 instead of NOT_SPECIFIED length = dataSize / frameSize; } // now seek past the header - dis.skipBytes(headerSize - nread); - AudioFormat format = new AudioFormat(encoding, sampleRate, - sampleSizeInBits, channels, - frameSize, (float) frameRate, - bigendian); + dis.skipBytes(headerSize - AuFileFormat.AU_HEADERSIZE); + final AudioFormat format = new AudioFormat(encoding, sampleRate, + sampleSizeInBits, channels, + frameSize, sampleRate, true); return new AuFileFormat(AudioFileFormat.Type.AU, dataSize + headerSize, format, length); } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileWriter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileWriter.java index 1c2ccf5b74c..b498c916435 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AuFileWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,26 +25,24 @@ package com.sun.media.sound; -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - import java.io.BufferedOutputStream; -import java.io.DataOutputStream; -import java.io.FileOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.RandomAccessFile; import java.io.SequenceInputStream; import java.util.Objects; import javax.sound.sampled.AudioFileFormat; -import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; - /** * AU file writer. * @@ -52,8 +50,10 @@ import javax.sound.sampled.AudioSystem; */ public final class AuFileWriter extends SunFileWriter { - //$$fb value for length field if length is not known - public static final int UNKNOWN_SIZE=-1; + /** + * Value for length field if length is not known. + */ + private static final int UNKNOWN_SIZE = -1; /** * Constructs a new AuFileWriter object. @@ -62,6 +62,7 @@ public final class AuFileWriter extends SunFileWriter { super(new AudioFileFormat.Type[]{AudioFileFormat.Type.AU}); } + @Override public AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream) { AudioFileFormat.Type[] filetypes = new AudioFileFormat.Type[types.length]; @@ -82,7 +83,7 @@ public final class AuFileWriter extends SunFileWriter { return new AudioFileFormat.Type[0]; } - + @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException { Objects.requireNonNull(stream); Objects.requireNonNull(fileType); @@ -96,13 +97,10 @@ public final class AuFileWriter extends SunFileWriter { // throws IllegalArgumentException if not supported AuFileFormat auFileFormat = (AuFileFormat)getAudioFileFormat(fileType, stream); - - int bytesWritten = writeAuFile(stream, auFileFormat, out); - return bytesWritten; + return writeAuFile(stream, auFileFormat, out); } - - + @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException { Objects.requireNonNull(stream); Objects.requireNonNull(fileType); @@ -137,7 +135,6 @@ public final class AuFileWriter extends SunFileWriter { return bytesWritten; } - // ------------------------------------------------------------- /** @@ -145,6 +142,9 @@ public final class AuFileWriter extends SunFileWriter { * Throws IllegalArgumentException if not supported. */ private AudioFileFormat getAudioFileFormat(AudioFileFormat.Type type, AudioInputStream stream) { + if (!isFileTypeSupported(type, stream)) { + throw new IllegalArgumentException("File type " + type + " not supported."); + } AudioFormat format = null; AuFileFormat fileFormat = null; @@ -154,17 +154,9 @@ public final class AuFileWriter extends SunFileWriter { AudioFormat.Encoding streamEncoding = streamFormat.getEncoding(); - float sampleRate; int sampleSizeInBits; - int channels; - int frameSize; - float frameRate; int fileSize; - if( !types[0].equals(type) ) { - throw new IllegalArgumentException("File type " + type + " not supported."); - } - if( (AudioFormat.Encoding.ALAW.equals(streamEncoding)) || (AudioFormat.Encoding.ULAW.equals(streamEncoding)) ) { @@ -206,14 +198,12 @@ public final class AuFileWriter extends SunFileWriter { return fileFormat; } - - private InputStream getFileStream(AuFileFormat auFileFormat, InputStream audioStream) throws IOException { + private InputStream getFileStream(AuFileFormat auFileFormat, AudioInputStream audioStream) throws IOException { // private method ... assumes auFileFormat is a supported file type AudioFormat format = auFileFormat.getFormat(); - int magic = AuFileFormat.AU_SUN_MAGIC; int headerSize = AuFileFormat.AU_HEADERSIZE; long dataSize = auFileFormat.getFrameLength(); //$$fb fix for Bug 4351296 @@ -225,9 +215,6 @@ public final class AuFileWriter extends SunFileWriter { int encoding_local = auFileFormat.getAuType(); int sampleRate = (int)format.getSampleRate(); int channels = format.getChannels(); - //$$fb below is the fix for 4297100. - //boolean bigendian = format.isBigEndian(); - boolean bigendian = true; // force bigendian byte header[] = null; ByteArrayInputStream headerStream = null; @@ -243,54 +230,37 @@ public final class AuFileWriter extends SunFileWriter { codedAudioStream = audioStream; - if( audioStream instanceof AudioInputStream ) { + audioStreamFormat = audioStream.getFormat(); + encoding = audioStreamFormat.getEncoding(); + + //$$ fb 2001-07-13: Bug 4391108 + if( (AudioFormat.Encoding.PCM_UNSIGNED.equals(encoding)) || + (AudioFormat.Encoding.PCM_SIGNED.equals(encoding) + && !audioStreamFormat.isBigEndian()) ) { + // We always write big endian au files, this is by far the standard + codedAudioStream = AudioSystem.getAudioInputStream( new AudioFormat ( + AudioFormat.Encoding.PCM_SIGNED, + audioStreamFormat.getSampleRate(), + audioStreamFormat.getSampleSizeInBits(), + audioStreamFormat.getChannels(), + audioStreamFormat.getFrameSize(), + audioStreamFormat.getFrameRate(), + true), + audioStream ); - audioStreamFormat = ((AudioInputStream)audioStream).getFormat(); - encoding = audioStreamFormat.getEncoding(); - - //$$ fb 2001-07-13: Bug 4391108 - if( (AudioFormat.Encoding.PCM_UNSIGNED.equals(encoding)) || - (AudioFormat.Encoding.PCM_SIGNED.equals(encoding) - && bigendian != audioStreamFormat.isBigEndian()) ) { - - // plug in the transcoder to convert to PCM_SIGNED, bigendian - // NOTE: little endian AU is not common, so we're always converting - // to big endian unless the passed in audioFileFormat is little. - // $$fb this NOTE is superseded. We always write big endian au files, this is by far the standard. - codedAudioStream = AudioSystem.getAudioInputStream( new AudioFormat ( - AudioFormat.Encoding.PCM_SIGNED, - audioStreamFormat.getSampleRate(), - audioStreamFormat.getSampleSizeInBits(), - audioStreamFormat.getChannels(), - audioStreamFormat.getFrameSize(), - audioStreamFormat.getFrameRate(), - bigendian), - (AudioInputStream)audioStream ); - - - } } baos = new ByteArrayOutputStream(); dos = new DataOutputStream(baos); - if (bigendian) { - dos.writeInt(AuFileFormat.AU_SUN_MAGIC); - dos.writeInt(headerSize); - dos.writeInt((int)dataSizeInBytes); - dos.writeInt(encoding_local); - dos.writeInt(sampleRate); - dos.writeInt(channels); - } else { - dos.writeInt(AuFileFormat.AU_SUN_INV_MAGIC); - dos.writeInt(big2little(headerSize)); - dos.writeInt(big2little((int)dataSizeInBytes)); - dos.writeInt(big2little(encoding_local)); - dos.writeInt(big2little(sampleRate)); - dos.writeInt(big2little(channels)); - } + dos.writeInt(AuFileFormat.AU_SUN_MAGIC); + dos.writeInt(headerSize); + dos.writeInt((int)dataSizeInBytes); + dos.writeInt(encoding_local); + dos.writeInt(sampleRate); + dos.writeInt(channels); // Now create a new InputStream from headerStream and the InputStream // in audioStream @@ -304,7 +274,7 @@ public final class AuFileWriter extends SunFileWriter { return auStream; } - private int writeAuFile(InputStream in, AuFileFormat auFileFormat, OutputStream out) throws IOException { + private int writeAuFile(AudioInputStream in, AuFileFormat auFileFormat, OutputStream out) throws IOException { int bytesRead = 0; int bytesWritten = 0; @@ -332,6 +302,4 @@ public final class AuFileWriter extends SunFileWriter { return bytesWritten; } - - } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java index a1e522afb40..21ee186cb71 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java @@ -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.IOException; @@ -475,6 +476,11 @@ public final class AudioFloatFormatConverter extends FormatConversionProvider { public AudioInputStream getAudioInputStream(Encoding targetEncoding, AudioInputStream sourceStream) { + if (!isConversionSupported(targetEncoding, sourceStream.getFormat())) { + throw new IllegalArgumentException( + "Unsupported conversion: " + sourceStream.getFormat() + .toString() + " to " + targetEncoding.toString()); + } if (sourceStream.getFormat().getEncoding().equals(targetEncoding)) return sourceStream; AudioFormat format = sourceStream.getFormat(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioSynthesizer.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioSynthesizer.java index 786b7ba97bf..7479357c580 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioSynthesizer.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioSynthesizer.java @@ -32,9 +32,9 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.SourceDataLine; /** - * AudioSynthesizer is a Synthesizer - * which renders it's output audio into SourceDataLine - * or AudioInputStream. + * {@code AudioSynthesizer} is a {@code Synthesizer} + * which renders it's output audio into {@code SourceDataLine} + * or {@code AudioInputStream}. * * @see MidiSystem#getSynthesizer * @see Synthesizer @@ -59,7 +59,7 @@ public interface AudioSynthesizer extends Synthesizer { * Gets information about the possible properties for the synthesizer. * * @param info a proposed list of tag/value pairs that will be sent on open. - * @return an array of AudioSynthesizerPropertyInfo objects + * @return an array of {@code AudioSynthesizerPropertyInfo} objects * describing possible properties. This array may be an empty array if * no properties are required. */ @@ -68,7 +68,7 @@ public interface AudioSynthesizer extends Synthesizer { /** * Opens the synthesizer and starts rendering audio into - * SourceDataLine. + * {@code SourceDataLine}. * *

An application opening a synthesizer explicitly with this call * has to close the synthesizer by calling {@link #close}. This is @@ -77,13 +77,13 @@ public interface AudioSynthesizer extends Synthesizer { * *

Note that some synthesizers, once closed, cannot be reopened. * Attempts to reopen such a synthesizer will always result in - * a MidiUnavailableException. + * a {@code MidiUnavailableException}. * - * @param line which AudioSynthesizer writes output audio into. - * If line is null, then line from system default mixer is used. - * @param info a Map object containing + * @param line which {@code AudioSynthesizer} writes output audio into. + * If {@code line} is null, then line from system default mixer is used. + * @param info a {@code Map} object containing * properties for additional configuration supported by synthesizer. - * If info is null then default settings are used. + * If {@code info} is null then default settings are used. * * @throws MidiUnavailableException thrown if the synthesizer cannot be * opened due to resource restrictions. @@ -98,7 +98,7 @@ public interface AudioSynthesizer extends Synthesizer { /** * Opens the synthesizer and renders audio into returned - * AudioInputStream. + * {@code AudioInputStream}. * *

An application opening a synthesizer explicitly with this call * has to close the synthesizer by calling {@link #close}. This is @@ -107,13 +107,13 @@ public interface AudioSynthesizer extends Synthesizer { * *

Note that some synthesizers, once closed, cannot be reopened. * Attempts to reopen such a synthesizer will always result in - * a MidiUnavailableException. + * a {@code MidiUnavailableException}. * - * @param targetFormat specifies the AudioFormat - * used in returned AudioInputStream. - * @param info a Map object containing + * @param targetFormat specifies the {@code AudioFormat} + * used in returned {@code AudioInputStream}. + * @param info a {@code Map} object containing * properties for additional configuration supported by synthesizer. - * If info is null then default settings are used. + * If {@code info} is null then default settings are used. * * @throws MidiUnavailableException thrown if the synthesizer cannot be * opened due to resource restrictions. diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java index 16bfaa20790..3fadc82e448 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java @@ -25,16 +25,16 @@ package com.sun.media.sound; /** - * Information about property used in opening AudioSynthesizer. + * Information about property used in opening {@code AudioSynthesizer}. * * @author Karl Helgason */ public final class AudioSynthesizerPropertyInfo { /** - * Constructs a AudioSynthesizerPropertyInfo object with a given - * name and value. The description and choices - * are initialized by null values. + * Constructs a {@code AudioSynthesizerPropertyInfo} object with a given + * name and value. The {@code description} and {@code choices} + * are initialized by {@code null} values. * * @param name the name of the property * @param value the current value or class used for values. @@ -60,18 +60,18 @@ public final class AudioSynthesizerPropertyInfo { */ public String description = null; /** - * The value field specifies the current value of + * The {@code value} field specifies the current value of * the property. */ public Object value = null; /** - * The valueClass field specifies class - * used in value field. + * The {@code valueClass} field specifies class + * used in {@code value} field. */ public Class valueClass = null; /** * An array of possible values if the value for the field - * AudioSynthesizerPropertyInfo.value may be selected + * {@code AudioSynthesizerPropertyInfo.value} may be selected * from a particular set of values; otherwise null. */ public Object[] choices = null; diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java index a56b5eca48e..b68750ad416 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java @@ -250,7 +250,7 @@ public final class MidiUtils { /** * Binary search for the event indexes of the track * - * @param tick - tick number of index to be found in array + * @param tick tick number of index to be found in array * @return index in track which is on or after "tick". * if no entries are found that follow after tick, track.size() is returned */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/PCMtoPCMCodec.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/PCMtoPCMCodec.java index 6ef8268f34c..5ba0558099d 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/PCMtoPCMCodec.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/PCMtoPCMCodec.java @@ -33,7 +33,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; - /** * Converts among signed/unsigned and little/big endianness of sampled. * @@ -52,11 +51,6 @@ public final class PCMtoPCMCodec extends SunCodec { AudioFormat.Encoding.PCM_UNSIGNED, }; - - - private static final int tempBufferSize = 64; - private byte tempBuffer [] = null; - /** * Constructs a new PCMtoPCM codec object. */ @@ -67,21 +61,31 @@ public final class PCMtoPCMCodec extends SunCodec { // NEW CODE + public AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat) { - /** - */ - public AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat){ - - if( sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_SIGNED ) || - sourceFormat.getEncoding().equals( AudioFormat.Encoding.PCM_UNSIGNED ) ) { - - AudioFormat.Encoding encs[] = new AudioFormat.Encoding[2]; - encs[0] = AudioFormat.Encoding.PCM_SIGNED; - encs[1] = AudioFormat.Encoding.PCM_UNSIGNED; - return encs; - } else { - return new AudioFormat.Encoding[0]; + final int sampleSize = sourceFormat.getSampleSizeInBits(); + AudioFormat.Encoding encoding = sourceFormat.getEncoding(); + if (sampleSize == 8) { + if (encoding.equals(AudioFormat.Encoding.PCM_SIGNED)) { + return new AudioFormat.Encoding[]{ + AudioFormat.Encoding.PCM_UNSIGNED + }; } + if (encoding.equals(AudioFormat.Encoding.PCM_UNSIGNED)) { + return new AudioFormat.Encoding[]{ + AudioFormat.Encoding.PCM_SIGNED + }; + } + } else if (sampleSize == 16) { + if (encoding.equals(AudioFormat.Encoding.PCM_SIGNED) + || encoding.equals(AudioFormat.Encoding.PCM_UNSIGNED)) { + return new AudioFormat.Encoding[]{ + AudioFormat.Encoding.PCM_UNSIGNED, + AudioFormat.Encoding.PCM_SIGNED + }; + } + } + return new AudioFormat.Encoding[0]; } @@ -125,7 +129,7 @@ public final class PCMtoPCMCodec extends SunCodec { sourceFormat.getFrameRate(), sourceFormat.isBigEndian() ); - return getAudioInputStream( targetFormat, sourceStream ); + return getConvertedStream(targetFormat, sourceStream); } else { throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString() ); @@ -136,7 +140,10 @@ public final class PCMtoPCMCodec extends SunCodec { * use old code */ public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream){ - + if (!isConversionSupported(targetFormat, sourceStream.getFormat())) + throw new IllegalArgumentException("Unsupported conversion: " + + sourceStream.getFormat().toString() + " to " + + targetFormat.toString()); return getConvertedStream( targetFormat, sourceStream ); } @@ -166,7 +173,6 @@ public final class PCMtoPCMCodec extends SunCodec { } else { cs = (AudioInputStream) (new PCMtoPCMCodecStream(stream, outputFormat)); - tempBuffer = new byte[tempBufferSize]; } return cs; } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftControl.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftControl.java index 85b3d276c71..e36295742c8 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftControl.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftControl.java @@ -25,7 +25,7 @@ package com.sun.media.sound; /** - * SoftControl are the basic controls + * {@code SoftControl} are the basic controls * used for control-rate processing. * * @author Karl Helgason 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 caf80f0e737..715cfcf9e76 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 @@ -25,6 +25,7 @@ package com.sun.media.sound; +import java.io.EOFException; import java.io.IOException; import java.io.InputStream; @@ -131,7 +132,8 @@ public final class SoftMidiAudioFileReader extends SunFileReader { stream.mark(200); try { return getAudioInputStream(MidiSystem.getSequence(stream)); - } catch (final InvalidMidiDataException ignored) { + } catch (InvalidMidiDataException | EOFException ignored) { + // stream is unsupported or the header is less than was expected stream.reset(); throw new UnsupportedAudioFileException(); } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunCodec.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunCodec.java index 232789352c5..773fea0e515 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunCodec.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunCodec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,8 @@ package com.sun.media.sound; import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioInputStream; - import javax.sound.sampled.spi.FormatConversionProvider; - /** * A codec can encode and/or decode audio data. It provides an * AudioInputStream from which processed data may be read. @@ -73,23 +70,4 @@ abstract class SunCodec extends FormatConversionProvider { System.arraycopy(outputEncodings, 0, encodings, 0, outputEncodings.length); return encodings; } - - /** - */ - public abstract AudioFormat.Encoding[] getTargetEncodings(AudioFormat sourceFormat); - - - /** - */ - public abstract AudioFormat[] getTargetFormats(AudioFormat.Encoding targetEncoding, AudioFormat sourceFormat); - - - /** - */ - public abstract AudioInputStream getAudioInputStream(AudioFormat.Encoding targetEncoding, AudioInputStream sourceStream); - /** - */ - public abstract AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream); - - } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java index bca1a5616ce..a9e40ff33c5 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java @@ -27,6 +27,7 @@ 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.IOException; @@ -51,6 +52,9 @@ abstract class SunFileReader extends AudioFileReader { stream.mark(200); // The biggest value which was historically used try { return getAudioFileFormatImpl(stream); + } catch (final EOFException ignored) { + // the header is less than was expected + throw new UnsupportedAudioFileException(); } finally { stream.reset(); } @@ -61,6 +65,9 @@ abstract class SunFileReader extends AudioFileReader { throws UnsupportedAudioFileException, IOException { try (InputStream is = url.openStream()) { return getAudioFileFormatImpl(new BufferedInputStream(is)); + } catch (final EOFException ignored) { + // the header is less than was expected + throw new UnsupportedAudioFileException(); } } @@ -69,6 +76,9 @@ abstract class SunFileReader extends AudioFileReader { throws UnsupportedAudioFileException, IOException { try (InputStream is = new FileInputStream(file)) { return getAudioFileFormatImpl(new BufferedInputStream(is)); + } catch (final EOFException ignored) { + // the header is less than was expected + throw new UnsupportedAudioFileException(); } } @@ -82,9 +92,10 @@ abstract class SunFileReader extends AudioFileReader { // beginning of the audio data, so return an AudioInputStream return new AudioInputStream(stream, fileFormat.getFormat(), fileFormat.getFrameLength()); - } catch (final UnsupportedAudioFileException e) { + } catch (UnsupportedAudioFileException | EOFException ignored) { + // stream is unsupported or the header is less than was expected stream.reset(); - throw e; + throw new UnsupportedAudioFileException(); } } @@ -125,6 +136,9 @@ abstract class SunFileReader extends AudioFileReader { * @throws UnsupportedAudioFileException if the stream does not point to * valid audio file data recognized by the system * @throws IOException if an I/O exception occurs + * @throws EOFException is used incorrectly by our readers instead of + * UnsupportedAudioFileException if the header is less than was + * expected */ abstract AudioFileFormat getAudioFileFormatImpl(InputStream stream) throws UnsupportedAudioFileException, IOException; diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileWriter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileWriter.java index d771bad119e..8e9cf96889d 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,19 +25,13 @@ package com.sun.media.sound; -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; import javax.sound.sampled.AudioFileFormat; -import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.spi.AudioFileWriter; - - - /** * Abstract File Writer class. * @@ -75,14 +69,6 @@ abstract class SunFileWriter extends AudioFileWriter { return localArray; } - - public abstract AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream); - - public abstract int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException; - - public abstract int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException; - - // HELPER METHODS diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/UlawCodec.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/UlawCodec.java index dc088ee459c..9dfcb444efd 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/UlawCodec.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/UlawCodec.java @@ -26,13 +26,12 @@ package com.sun.media.sound; import java.io.IOException; - import java.util.Objects; import java.util.Vector; import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioSystem; import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; /** @@ -126,43 +125,46 @@ public final class UlawCodec extends SunCodec { AudioFormat sourceFormat = sourceStream.getFormat(); AudioFormat.Encoding sourceEncoding = sourceFormat.getEncoding(); + if (!isConversionSupported(targetEncoding,sourceStream.getFormat())) { + throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString()); + } if (sourceEncoding.equals(targetEncoding)) { return sourceStream; - } else { - AudioFormat targetFormat = null; - if (!isConversionSupported(targetEncoding,sourceStream.getFormat())) { - throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString()); - } - if (AudioFormat.Encoding.ULAW.equals(sourceEncoding) && - AudioFormat.Encoding.PCM_SIGNED.equals(targetEncoding) ) { - targetFormat = new AudioFormat( targetEncoding, - sourceFormat.getSampleRate(), - 16, - sourceFormat.getChannels(), - 2*sourceFormat.getChannels(), - sourceFormat.getSampleRate(), - sourceFormat.isBigEndian()); - } else if (AudioFormat.Encoding.PCM_SIGNED.equals(sourceEncoding) && - AudioFormat.Encoding.ULAW.equals(targetEncoding)) { - targetFormat = new AudioFormat( targetEncoding, - sourceFormat.getSampleRate(), - 8, - sourceFormat.getChannels(), - sourceFormat.getChannels(), - sourceFormat.getSampleRate(), - false); - } else { - throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString()); - } - - return getAudioInputStream( targetFormat, sourceStream ); } + AudioFormat targetFormat = null; + if (AudioFormat.Encoding.ULAW.equals(sourceEncoding) && + AudioFormat.Encoding.PCM_SIGNED.equals(targetEncoding) ) { + targetFormat = new AudioFormat( targetEncoding, + sourceFormat.getSampleRate(), + 16, + sourceFormat.getChannels(), + 2*sourceFormat.getChannels(), + sourceFormat.getSampleRate(), + sourceFormat.isBigEndian()); + } else if (AudioFormat.Encoding.PCM_SIGNED.equals(sourceEncoding) && + AudioFormat.Encoding.ULAW.equals(targetEncoding)) { + targetFormat = new AudioFormat( targetEncoding, + sourceFormat.getSampleRate(), + 8, + sourceFormat.getChannels(), + sourceFormat.getChannels(), + sourceFormat.getSampleRate(), + false); + } else { + throw new IllegalArgumentException("Unsupported conversion: " + sourceStream.getFormat().toString() + " to " + targetEncoding.toString()); + } + + return getConvertedStream(targetFormat, sourceStream); } /** * use old code... */ public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream sourceStream){ + if (!isConversionSupported(targetFormat, sourceStream.getFormat())) + throw new IllegalArgumentException("Unsupported conversion: " + + sourceStream.getFormat().toString() + " to " + + targetFormat.toString()); return getConvertedStream(targetFormat, sourceStream); } @@ -215,24 +217,20 @@ public final class UlawCodec extends SunCodec { false ); formats.addElement(format); } - - if (AudioFormat.Encoding.ULAW.equals(inputFormat.getEncoding())) { + if (inputFormat.getSampleSizeInBits() == 8 + && AudioFormat.Encoding.ULAW.equals(inputFormat.getEncoding())) { format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, - inputFormat.getSampleRate(), - 16, + inputFormat.getSampleRate(), 16, inputFormat.getChannels(), - inputFormat.getChannels()*2, - inputFormat.getSampleRate(), - false ); + inputFormat.getChannels() * 2, + inputFormat.getSampleRate(), false); formats.addElement(format); format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, - inputFormat.getSampleRate(), - 16, + inputFormat.getSampleRate(), 16, inputFormat.getChannels(), - inputFormat.getChannels()*2, - inputFormat.getSampleRate(), - true ); + inputFormat.getChannels() * 2, + inputFormat.getSampleRate(), true); formats.addElement(format); } @@ -244,7 +242,7 @@ public final class UlawCodec extends SunCodec { } - class UlawCodecStream extends AudioInputStream { + private final class UlawCodecStream extends AudioInputStream { private static final int tempBufferSize = 64; private byte tempBuffer [] = null; @@ -416,6 +414,12 @@ public final class UlawCodec extends SunCodec { return (i - off); } } - } // end class UlawCodecStream + @Override + public long skip(final long n) throws IOException { + // Implementation of this method assumes that we support + // encoding/decoding from/to 8/16 bits only + return encode ? super.skip(n * 2) / 2 : super.skip(n / 2) * 2; + } + } // end class UlawCodecStream } // end class ULAW diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java index b238e9da66e..240c6d27c58 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -124,7 +124,6 @@ public final class WaveExtensibleFileReader extends SunFileReader { return false; return true; } - } private static final String[] channelnames = { "FL", "FR", "FC", "LF", @@ -196,9 +195,9 @@ public final class WaveExtensibleFileReader extends SunFileReader { fmt_found = true; int format = chunk.readUnsignedShort(); - if (format != 0xFFFE) - throw new UnsupportedAudioFileException(); // WAVE_FORMAT_EXTENSIBLE - // only + if (format != WaveFileFormat.WAVE_FORMAT_EXTENSIBLE) { + throw new UnsupportedAudioFileException(); + } channels = chunk.readUnsignedShort(); samplerate = chunk.readUnsignedInt(); /* framerate = */chunk.readUnsignedInt(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileFormat.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileFormat.java index af9c7160e7e..9bf8c9200ad 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileFormat.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,13 +28,11 @@ package com.sun.media.sound; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; - /** * WAVE file format class. * * @author Jan Borgersen */ - final class WaveFileFormat extends AudioFileFormat { /** @@ -53,15 +51,16 @@ final class WaveFileFormat extends AudioFileFormat { private static final int STANDARD_FMT_CHUNK_SIZE = 16; // magic numbers - static final int RIFF_MAGIC = 1380533830; - static final int WAVE_MAGIC = 1463899717; - static final int FMT_MAGIC = 0x666d7420; // "fmt " - static final int DATA_MAGIC = 0x64617461; // "data" + static final int RIFF_MAGIC = 1380533830; + static final int WAVE_MAGIC = 1463899717; + static final int FMT_MAGIC = 0x666d7420; // "fmt " + static final int DATA_MAGIC = 0x64617461; // "data" // encodings static final int WAVE_FORMAT_UNKNOWN = 0x0000; static final int WAVE_FORMAT_PCM = 0x0001; static final int WAVE_FORMAT_ADPCM = 0x0002; + static final int WAVE_FORMAT_IEEE_FLOAT= 0x0003; static final int WAVE_FORMAT_ALAW = 0x0006; static final int WAVE_FORMAT_MULAW = 0x0007; static final int WAVE_FORMAT_OKI_ADPCM = 0x0010; @@ -72,12 +71,7 @@ final class WaveFileFormat extends AudioFileFormat { static final int WAVE_IBM_FORMAT_ADPCM = 0x0103; static final int WAVE_FORMAT_DVI_ADPCM = 0x0011; static final int WAVE_FORMAT_SX7383 = 0x1C07; - - - WaveFileFormat( AudioFileFormat aff ) { - - this( aff.getType(), aff.getByteLength(), aff.getFormat(), aff.getFrameLength() ); - } + static final int WAVE_FORMAT_EXTENSIBLE= 0xFFFE; WaveFileFormat(AudioFileFormat.Type type, int lengthInBytes, AudioFormat format, int lengthInFrames) { @@ -98,7 +92,6 @@ final class WaveFileFormat extends AudioFileFormat { } int getWaveType() { - return waveType; } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileWriter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileWriter.java index 199364c94f4..752afc512c9 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFileWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,23 +25,22 @@ package com.sun.media.sound; -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - import java.io.BufferedOutputStream; -import java.io.DataOutputStream; -import java.io.FileOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.RandomAccessFile; import java.io.SequenceInputStream; import java.util.Objects; import javax.sound.sampled.AudioFileFormat; -import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; //$$fb this class is buggy. Should be replaced in future. @@ -53,27 +52,6 @@ import javax.sound.sampled.AudioSystem; */ public final class WaveFileWriter extends SunFileWriter { - // magic numbers - static final int RIFF_MAGIC = 1380533830; - static final int WAVE_MAGIC = 1463899717; - static final int FMT_MAGIC = 0x666d7420; // "fmt " - static final int DATA_MAGIC = 0x64617461; // "data" - - // encodings - static final int WAVE_FORMAT_UNKNOWN = 0x0000; - static final int WAVE_FORMAT_PCM = 0x0001; - static final int WAVE_FORMAT_ADPCM = 0x0002; - static final int WAVE_FORMAT_ALAW = 0x0006; - static final int WAVE_FORMAT_MULAW = 0x0007; - static final int WAVE_FORMAT_OKI_ADPCM = 0x0010; - static final int WAVE_FORMAT_DIGISTD = 0x0015; - static final int WAVE_FORMAT_DIGIFIX = 0x0016; - static final int WAVE_IBM_FORMAT_MULAW = 0x0101; - static final int WAVE_IBM_FORMAT_ALAW = 0x0102; - static final int WAVE_IBM_FORMAT_ADPCM = 0x0103; - static final int WAVE_FORMAT_DVI_ADPCM = 0x0011; - static final int WAVE_FORMAT_SX7383 = 0x1C07; - /** * Constructs a new WaveFileWriter object. */ @@ -81,10 +59,7 @@ public final class WaveFileWriter extends SunFileWriter { super(new AudioFileFormat.Type[]{AudioFileFormat.Type.WAVE}); } - - // METHODS TO IMPLEMENT AudioFileWriter - - + @Override public AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream) { AudioFileFormat.Type[] filetypes = new AudioFileFormat.Type[types.length]; @@ -106,6 +81,7 @@ public final class WaveFileWriter extends SunFileWriter { } + @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException { Objects.requireNonNull(stream); Objects.requireNonNull(fileType); @@ -125,11 +101,11 @@ public final class WaveFileWriter extends SunFileWriter { throw new IOException("stream length not specified"); } - int bytesWritten = writeWaveFile(stream, waveFileFormat, out); - return bytesWritten; + return writeWaveFile(stream, waveFileFormat, out); } + @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException { Objects.requireNonNull(stream); Objects.requireNonNull(fileType); @@ -173,6 +149,9 @@ public final class WaveFileWriter extends SunFileWriter { * Throws IllegalArgumentException if not supported. */ private AudioFileFormat getAudioFileFormat(AudioFileFormat.Type type, AudioInputStream stream) { + if (!isFileTypeSupported(type, stream)) { + throw new IllegalArgumentException("File type " + type + " not supported."); + } AudioFormat format = null; WaveFileFormat fileFormat = null; AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED; @@ -187,9 +166,6 @@ public final class WaveFileWriter extends SunFileWriter { float frameRate; int fileSize; - if (!types[0].equals(type)) { - throw new IllegalArgumentException("File type " + type + " not supported."); - } int waveType = WaveFileFormat.WAVE_FORMAT_PCM; if( AudioFormat.Encoding.ALAW.equals(streamEncoding) || @@ -198,9 +174,9 @@ public final class WaveFileWriter extends SunFileWriter { encoding = streamEncoding; sampleSizeInBits = streamFormat.getSampleSizeInBits(); if (streamEncoding.equals(AudioFormat.Encoding.ALAW)) { - waveType = WAVE_FORMAT_ALAW; + waveType = WaveFileFormat.WAVE_FORMAT_ALAW; } else { - waveType = WAVE_FORMAT_MULAW; + waveType = WaveFileFormat.WAVE_FORMAT_MULAW; } } else if ( streamFormat.getSampleSizeInBits()==8 ) { encoding = AudioFormat.Encoding.PCM_UNSIGNED; diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java index 3fe278fc70c..afecd0e34be 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,8 +67,9 @@ public final class WaveFloatFileReader extends SunFileReader { fmt_found = true; int format = chunk.readUnsignedShort(); - if (format != 3) // WAVE_FORMAT_IEEE_FLOAT only + if (format != WaveFileFormat.WAVE_FORMAT_IEEE_FLOAT) { throw new UnsupportedAudioFileException(); + } channels = chunk.readUnsignedShort(); samplerate = chunk.readUnsignedInt(); /* framerate = */chunk.readUnsignedInt(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileWriter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileWriter.java index 2845083384a..b2529f48f5c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,18 +22,20 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package com.sun.media.sound; import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.util.Objects; import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFileFormat.Type; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioFormat.Encoding; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.AudioFileFormat.Type; import javax.sound.sampled.spi.AudioFileWriter; /** @@ -43,10 +45,12 @@ import javax.sound.sampled.spi.AudioFileWriter; */ public final class WaveFloatFileWriter extends AudioFileWriter { + @Override public Type[] getAudioFileTypes() { - return new Type[] { Type.WAVE }; + return new Type[]{Type.WAVE}; } + @Override public Type[] getAudioFileTypes(AudioInputStream stream) { if (!stream.getFormat().getEncoding().equals(Encoding.PCM_FLOAT)) @@ -92,18 +96,22 @@ public final class WaveFloatFileWriter extends AudioFileWriter { this.out = out; } + @Override public void write(int b) throws IOException { out.write(b); } + @Override public void flush() throws IOException { out.flush(); } + @Override public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); } + @Override public void write(byte[] b) throws IOException { out.write(b); } @@ -118,8 +126,12 @@ public final class WaveFloatFileWriter extends AudioFileWriter { return AudioSystem.getAudioInputStream(targetFormat, ais); } + @Override public int write(AudioInputStream stream, Type fileType, OutputStream out) throws IOException { + Objects.requireNonNull(stream); + Objects.requireNonNull(fileType); + Objects.requireNonNull(out); checkFormat(fileType, stream); if (stream.getFormat().isBigEndian()) @@ -131,8 +143,13 @@ public final class WaveFloatFileWriter extends AudioFileWriter { return fpointer; } + @Override public int write(AudioInputStream stream, Type fileType, File out) throws IOException { + Objects.requireNonNull(stream); + Objects.requireNonNull(fileType); + Objects.requireNonNull(out); + checkFormat(fileType, stream); if (stream.getFormat().isBigEndian()) stream = toLittleEndian(stream); @@ -142,5 +159,4 @@ public final class WaveFloatFileWriter extends AudioFileWriter { writer.close(); return fpointer; } - } diff --git a/jdk/src/java.desktop/share/classes/java/applet/Applet.java b/jdk/src/java.desktop/share/classes/java/applet/Applet.java index aed6eae421b..0e02c9cb054 100644 --- a/jdk/src/java.desktop/share/classes/java/applet/Applet.java +++ b/jdk/src/java.desktop/share/classes/java/applet/Applet.java @@ -38,9 +38,9 @@ import javax.accessibility.*; * An applet is a small program that is intended not to be run on * its own, but rather to be embedded inside another application. *

- * The Applet class must be the superclass of any + * The {@code Applet} class must be the superclass of any * applet that is to be embedded in a Web page or viewed by the Java - * Applet Viewer. The Applet class provides a standard + * Applet Viewer. The {@code Applet} class provides a standard * interface between applets and their environment. * * @author Arthur van Hoff @@ -52,10 +52,10 @@ public class Applet extends Panel { /** * Constructs a new Applet. *

- * Note: Many methods in java.applet.Applet + * Note: Many methods in {@code java.applet.Applet} * may be invoked by the applet only after the applet is * fully constructed; applet should avoid calling methods - * in java.applet.Applet in the constructor. + * in {@code java.applet.Applet} in the constructor. * * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. @@ -88,8 +88,8 @@ public class Applet extends Panel { * Read an applet from an object input stream. * @param s an object input stream. * @exception HeadlessException if - * GraphicsEnvironment.isHeadless() returns - * true + * {@code GraphicsEnvironment.isHeadless()} returns + * {@code true} * @serial * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.4 @@ -104,9 +104,9 @@ public class Applet extends Panel { /** * Sets this applet's stub. This is done automatically by the system. - *

If there is a security manager, its checkPermission + *

If there is a security manager, its {@code checkPermission} * method is called with the - * AWTPermission("setAppletStub") + * {@code AWTPermission("setAppletStub")} * permission if a stub has already been set. * @param stub the new stub. * @exception SecurityException if the caller cannot set the stub @@ -123,11 +123,11 @@ public class Applet extends Panel { /** * Determines if this applet is active. An applet is marked active - * just before its start method is called. It becomes - * inactive just before its stop method is called. + * just before its {@code start} method is called. It becomes + * inactive just before its {@code stop} method is called. * - * @return true if the applet is active; - * false otherwise. + * @return {@code true} if the applet is active; + * {@code false} otherwise. * @see java.applet.Applet#start() * @see java.applet.Applet#stop() */ @@ -179,14 +179,14 @@ public class Applet extends Panel { * </applet> * *

- * then a call to getParameter("Color") returns the - * value "blue". + * then a call to {@code getParameter("Color")} returns the + * value {@code "blue"}. *

- * The name argument is case insensitive. + * The {@code name} argument is case insensitive. * * @param name a parameter name. * @return the value of the named parameter, - * or null if not set. + * or {@code null} if not set. */ public String getParameter(String name) { return stub.getParameter(name); @@ -260,8 +260,8 @@ public class Applet extends Panel { } /** - * Returns an Image object that can then be painted on - * the screen. The url that is passed as an argument + * Returns an {@code Image} object that can then be painted on + * the screen. The {@code url} that is passed as an argument * must specify an absolute URL. *

* This method always returns immediately, whether or not the image @@ -278,10 +278,10 @@ public class Applet extends Panel { } /** - * Returns an Image object that can then be painted on - * the screen. The url argument must specify an absolute - * URL. The name argument is a specifier that is - * relative to the url argument. + * Returns an {@code Image} object that can then be painted on + * the screen. The {@code url} argument must specify an absolute + * URL. The {@code name} argument is a specifier that is + * relative to the {@code url} argument. *

* This method always returns immediately, whether or not the image * exists. When this applet attempts to draw the image on the screen, @@ -290,7 +290,7 @@ public class Applet extends Panel { * * @param url an absolute URL giving the base location of the image. * @param name the location of the image, relative to the - * url argument. + * {@code url} argument. * @return the image at the specified URL. * @see java.awt.Image */ @@ -315,8 +315,8 @@ public class Applet extends Panel { } /** - * Returns the AudioClip object specified by the - * URL argument. + * Returns the {@code AudioClip} object specified by the + * {@code URL} argument. *

* This method always returns immediately, whether or not the audio * clip exists. When this applet attempts to play the audio clip, the @@ -331,8 +331,8 @@ public class Applet extends Panel { } /** - * Returns the AudioClip object specified by the - * URL and name arguments. + * Returns the {@code AudioClip} object specified by the + * {@code URL} and {@code name} arguments. *

* This method always returns immediately, whether or not the audio * clip exists. When this applet attempts to play the audio clip, the @@ -341,7 +341,7 @@ public class Applet extends Panel { * @param url an absolute URL giving the base location of the * audio clip. * @param name the location of the audio clip, relative to the - * url argument. + * {@code url} argument. * @return the audio clip at the specified URL. * @see java.applet.AudioClip */ @@ -355,11 +355,11 @@ public class Applet extends Panel { /** * Returns information about this applet. An applet should override - * this method to return a String containing information + * this method to return a {@code String} containing information * about the author, version, and copyright of the applet. *

* The implementation of this method provided by the - * Applet class returns null. + * {@code Applet} class returns {@code null}. * * @return a string containing information about the author, version, and * copyright of the applet. @@ -388,10 +388,10 @@ public class Applet extends Panel { /** * Returns information about the parameters that are understood by * this applet. An applet should override this method to return an - * array of Strings describing these parameters. + * array of {@code Strings} describing these parameters. *

* Each element of the array should be a set of three - * Strings containing the name, the type, and a + * {@code Strings} containing the name, the type, and a * description. For example: *

      * String pinfo[][] = {
@@ -402,7 +402,7 @@ public class Applet extends Panel {
      * 
*

* The implementation of this method provided by the - * Applet class returns null. + * {@code Applet} class returns {@code null}. * * @return an array describing the parameters this applet looks for. */ @@ -430,7 +430,7 @@ public class Applet extends Panel { * @param url an absolute URL giving the base location of the * audio clip. * @param name the location of the audio clip, relative to the - * url argument. + * {@code url} argument. */ public void play(URL url, String name) { AudioClip clip = getAudioClip(url, name); @@ -442,16 +442,16 @@ public class Applet extends Panel { /** * Called by the browser or applet viewer to inform * this applet that it has been loaded into the system. It is always - * called before the first time that the start method is + * called before the first time that the {@code start} method is * called. *

- * A subclass of Applet should override this method if + * A subclass of {@code Applet} should override this method if * it has initialization to perform. For example, an applet with - * threads would use the init method to create the - * threads and the destroy method to kill them. + * threads would use the {@code init} method to create the + * threads and the {@code destroy} method to kill them. *

* The implementation of this method provided by the - * Applet class does nothing. + * {@code Applet} class does nothing. * * @see java.applet.Applet#destroy() * @see java.applet.Applet#start() @@ -463,25 +463,25 @@ public class Applet extends Panel { /** * Called by the browser or applet viewer to inform * this applet that it should start its execution. It is called after - * the init method and each time the applet is revisited + * the {@code init} method and each time the applet is revisited * in a Web page. *

- * A subclass of Applet should override this method if + * A subclass of {@code Applet} should override this method if * it has any operation that it wants to perform each time the Web * page containing it is visited. For example, an applet with - * animation might want to use the start method to - * resume animation, and the stop method to suspend the + * animation might want to use the {@code start} method to + * resume animation, and the {@code stop} method to suspend the * animation. *

- * Note: some methods, such as getLocationOnScreen, can only + * Note: some methods, such as {@code getLocationOnScreen}, can only * provide meaningful results if the applet is showing. Because - * isShowing returns false when the applet's - * start is first called, methods requiring - * isShowing to return true should be called from - * a ComponentListener. + * {@code isShowing} returns {@code false} when the applet's + * {@code start} is first called, methods requiring + * {@code isShowing} to return {@code true} should be called from + * a {@code ComponentListener}. *

* The implementation of this method provided by the - * Applet class does nothing. + * {@code Applet} class does nothing. * * @see java.applet.Applet#destroy() * @see java.applet.Applet#init() @@ -498,15 +498,15 @@ public class Applet extends Panel { * the Web page that contains this applet has been replaced by * another page, and also just before the applet is to be destroyed. *

- * A subclass of Applet should override this method if + * A subclass of {@code Applet} should override this method if * it has any operation that it wants to perform each time the Web * page containing it is no longer visible. For example, an applet - * with animation might want to use the start method to - * resume animation, and the stop method to suspend the + * with animation might want to use the {@code start} method to + * resume animation, and the {@code stop} method to suspend the * animation. *

* The implementation of this method provided by the - * Applet class does nothing. + * {@code Applet} class does nothing. * * @see java.applet.Applet#destroy() * @see java.applet.Applet#init() @@ -517,17 +517,17 @@ public class Applet extends Panel { /** * Called by the browser or applet viewer to inform * this applet that it is being reclaimed and that it should destroy - * any resources that it has allocated. The stop method - * will always be called before destroy. + * any resources that it has allocated. The {@code stop} method + * will always be called before {@code destroy}. *

- * A subclass of Applet should override this method if + * A subclass of {@code Applet} should override this method if * it has any operation that it wants to perform before it is * destroyed. For example, an applet with threads would use the - * init method to create the threads and the - * destroy method to kill them. + * {@code init} method to create the threads and the + * {@code destroy} method to kill them. *

* The implementation of this method provided by the - * Applet class does nothing. + * {@code Applet} class does nothing. * * @see java.applet.Applet#init() * @see java.applet.Applet#start() @@ -561,7 +561,7 @@ public class Applet extends Panel { /** * This class implements accessibility support for the - * Applet class. It provides an implementation of the + * {@code Applet} class. It provides an implementation of the * Java Accessibility API appropriate to applet user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/applet/AudioClip.java b/jdk/src/java.desktop/share/classes/java/applet/AudioClip.java index 8356e492e49..f935fa4965b 100644 --- a/jdk/src/java.desktop/share/classes/java/applet/AudioClip.java +++ b/jdk/src/java.desktop/share/classes/java/applet/AudioClip.java @@ -26,8 +26,8 @@ package java.applet; /** - * The AudioClip interface is a simple abstraction for - * playing a sound clip. Multiple AudioClip items can be + * The {@code AudioClip} interface is a simple abstraction for + * playing a sound clip. Multiple {@code AudioClip} items can be * playing at the same time, and the resulting sound is mixed * together to produce a composite. * diff --git a/jdk/src/java.desktop/share/classes/java/awt/AWTError.java b/jdk/src/java.desktop/share/classes/java/awt/AWTError.java index 1110a6450c0..6ea6a2adb97 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/AWTError.java +++ b/jdk/src/java.desktop/share/classes/java/awt/AWTError.java @@ -38,7 +38,7 @@ public class AWTError extends Error { private static final long serialVersionUID = -1819846354050686206L; /** - * Constructs an instance of AWTError with the specified + * Constructs an instance of {@code AWTError} with the specified * detail message. * @param msg the detail message. * @since 1.0 diff --git a/jdk/src/java.desktop/share/classes/java/awt/AWTEvent.java b/jdk/src/java.desktop/share/classes/java/awt/AWTEvent.java index 04c4effeafa..1c723aeb133 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/AWTEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/AWTEvent.java @@ -410,11 +410,11 @@ public abstract class AWTEvent extends EventObject { } /** - * Returns a string representing the state of this Event. + * Returns a string representing the state of this {@code Event}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return a string representation of this event */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java b/jdk/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java index 8297188f1f9..a9f102643f4 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java +++ b/jdk/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java @@ -122,9 +122,9 @@ public class AWTEventMulticaster implements /** * Creates an event multicaster instance which chains listener-a - * with listener-b. Input parameters a and b - * should not be null, though implementations may vary in - * choosing whether or not to throw NullPointerException + * with listener-b. Input parameters {@code a} and {@code b} + * should not be {@code null}, though implementations may vary in + * choosing whether or not to throw {@code NullPointerException} * in that case. * @param a listener-a * @param b listener-b @@ -1078,30 +1078,30 @@ public class AWTEventMulticaster implements /** * Returns an array of all the objects chained as * FooListeners by the specified - * java.util.EventListener. + * {@code java.util.EventListener}. * FooListeners are chained by the - * AWTEventMulticaster using the + * {@code AWTEventMulticaster} using the * addFooListener method. - * If a null listener is specified, this method returns an + * If a {@code null} listener is specified, this method returns an * empty array. If the specified listener is not an instance of - * AWTEventMulticaster, this method returns an array which + * {@code AWTEventMulticaster}, this method returns an array which * contains only the specified listener. If no such listeners are chained, * this method returns an empty array. * * @param the listener type - * @param l the specified java.util.EventListener + * @param l the specified {@code java.util.EventListener} * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects chained as * FooListeners by the specified multicast * listener, or an empty array if no such listeners have been * chained by the specified multicast listener * @exception NullPointerException if the specified * {@code listenertype} parameter is {@code null} - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @since 1.4 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/AWTException.java b/jdk/src/java.desktop/share/classes/java/awt/AWTException.java index 0ffe52cd00a..5518643b3f5 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/AWTException.java +++ b/jdk/src/java.desktop/share/classes/java/awt/AWTException.java @@ -38,9 +38,9 @@ public class AWTException extends Exception { private static final long serialVersionUID = -1900414231151323879L; /** - * Constructs an instance of AWTException with the + * Constructs an instance of {@code AWTException} with the * specified detail message. A detail message is an - * instance of String that describes this particular + * instance of {@code String} that describes this particular * exception. * @param msg the detail message * @since 1.0 diff --git a/jdk/src/java.desktop/share/classes/java/awt/AWTKeyStroke.java b/jdk/src/java.desktop/share/classes/java/awt/AWTKeyStroke.java index f49b16badd2..6e85f2b1bbf 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/AWTKeyStroke.java +++ b/jdk/src/java.desktop/share/classes/java/awt/AWTKeyStroke.java @@ -37,22 +37,22 @@ import java.lang.reflect.Field; import sun.swing.SwingAccessor; /** - * An AWTKeyStroke represents a key action on the - * keyboard, or equivalent input device. AWTKeyStrokes + * An {@code AWTKeyStroke} represents a key action on the + * keyboard, or equivalent input device. {@code AWTKeyStroke}s * can correspond to only a press or release of a - * particular key, just as KEY_PRESSED and - * KEY_RELEASED KeyEvents do; + * particular key, just as {@code KEY_PRESSED} and + * {@code KEY_RELEASED KeyEvent}s do; * alternately, they can correspond to typing a specific Java character, just - * as KEY_TYPED KeyEvents do. - * In all cases, AWTKeyStrokes can specify modifiers + * as {@code KEY_TYPED KeyEvent}s do. + * In all cases, {@code AWTKeyStroke}s can specify modifiers * (alt, shift, control, meta, altGraph, or a combination thereof) which must be present * during the action for an exact match. *

- * AWTKeyStrokes are immutable, and are intended + * {@code AWTKeyStrokes} are immutable, and are intended * to be unique. Client code should never create an - * AWTKeyStroke on its own, but should instead use - * a variant of getAWTKeyStroke. Client use of these factory - * methods allows the AWTKeyStroke implementation + * {@code AWTKeyStroke} on its own, but should instead use + * a variant of {@code getAWTKeyStroke}. Client use of these factory + * methods allows the {@code AWTKeyStroke} implementation * to cache and share instances efficiently. * * @see #getAWTKeyStroke @@ -88,17 +88,17 @@ public class AWTKeyStroke implements Serializable { } /** - * Constructs an AWTKeyStroke with default values. + * Constructs an {@code AWTKeyStroke} with default values. * The default values used are: * * * * - * + * * * * - * + * * * * @@ -106,12 +106,12 @@ public class AWTKeyStroke implements Serializable { * * * - * + * * *
PropertyDefault Value
Key CharKeyEvent.CHAR_UNDEFINED{@code KeyEvent.CHAR_UNDEFINED}
Key CodeKeyEvent.VK_UNDEFINED{@code KeyEvent.VK_UNDEFINED}
Modifiers
On key release?false{@code false}
* - * AWTKeyStrokes should not be constructed - * by client code. Use a variant of getAWTKeyStroke + * {@code AWTKeyStroke}s should not be constructed + * by client code. Use a variant of {@code getAWTKeyStroke} * instead. * * @see #getAWTKeyStroke @@ -120,17 +120,17 @@ public class AWTKeyStroke implements Serializable { } /** - * Constructs an AWTKeyStroke with the specified - * values. AWTKeyStrokes should not be constructed - * by client code. Use a variant of getAWTKeyStroke + * Constructs an {@code AWTKeyStroke} with the specified + * values. {@code AWTKeyStroke}s should not be constructed + * by client code. Use a variant of {@code getAWTKeyStroke} * instead. * * @param keyChar the character value for a keyboard key - * @param keyCode the key code for this AWTKeyStroke + * @param keyCode the key code for this {@code AWTKeyStroke} * @param modifiers a bitwise-ored combination of any modifiers - * @param onKeyRelease true if this - * AWTKeyStroke corresponds - * to a key release; false otherwise + * @param onKeyRelease {@code true} if this + * {@code AWTKeyStroke} corresponds + * to a key release; {@code false} otherwise * @see #getAWTKeyStroke */ protected AWTKeyStroke(char keyChar, int keyCode, int modifiers, @@ -185,12 +185,12 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns a shared instance of an AWTKeyStroke - * that represents a KEY_TYPED event for the + * Returns a shared instance of an {@code AWTKeyStroke} + * that represents a {@code KEY_TYPED} event for the * specified character. * * @param keyChar the character value for a keyboard key - * @return an AWTKeyStroke object for that key + * @return an {@code AWTKeyStroke} object for that key */ public static AWTKeyStroke getAWTKeyStroke(char keyChar) { return getCachedStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false); @@ -202,7 +202,7 @@ public class AWTKeyStroke implements Serializable { * specified Character object and a set of modifiers. Note * that the first parameter is of type Character rather than * char. This is to avoid inadvertent clashes with - * calls to getAWTKeyStroke(int keyCode, int modifiers). + * calls to {@code getAWTKeyStroke(int keyCode, int modifiers)}. * * The modifiers consist of any combination of following:

    *
  • java.awt.event.InputEvent.SHIFT_DOWN_MASK @@ -227,9 +227,9 @@ public class AWTKeyStroke implements Serializable { * * @param keyChar the Character object for a keyboard character * @param modifiers a bitwise-ored combination of any modifiers - * @return an AWTKeyStroke object for that key - * @throws IllegalArgumentException if keyChar is - * null + * @return an {@code AWTKeyStroke} object for that key + * @throws IllegalArgumentException if {@code keyChar} is + * {@code null} * * @see java.awt.event.InputEvent */ @@ -243,19 +243,19 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns a shared instance of an AWTKeyStroke, + * Returns a shared instance of an {@code AWTKeyStroke}, * given a numeric key code and a set of modifiers, specifying * whether the key is activated when it is pressed or released. *

    * The "virtual key" constants defined in - * java.awt.event.KeyEvent can be + * {@code java.awt.event.KeyEvent} can be * used to specify the key code. For example:

      - *
    • java.awt.event.KeyEvent.VK_ENTER - *
    • java.awt.event.KeyEvent.VK_TAB - *
    • java.awt.event.KeyEvent.VK_SPACE + *
    • {@code java.awt.event.KeyEvent.VK_ENTER} + *
    • {@code java.awt.event.KeyEvent.VK_TAB} + *
    • {@code java.awt.event.KeyEvent.VK_SPACE} *
    * Alternatively, the key code may be obtained by calling - * java.awt.event.KeyEvent.getExtendedKeyCodeForChar. + * {@code java.awt.event.KeyEvent.getExtendedKeyCodeForChar}. * * The modifiers consist of any combination of:
      *
    • java.awt.event.InputEvent.SHIFT_DOWN_MASK @@ -279,8 +279,8 @@ public class AWTKeyStroke implements Serializable { * * @param keyCode an int specifying the numeric code for a keyboard key * @param modifiers a bitwise-ored combination of any modifiers - * @param onKeyRelease true if the AWTKeyStroke - * should represent a key release; false otherwise + * @param onKeyRelease {@code true} if the {@code AWTKeyStroke} + * should represent a key release; {@code false} otherwise * @return an AWTKeyStroke object for that key * * @see java.awt.event.KeyEvent @@ -293,16 +293,16 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns a shared instance of an AWTKeyStroke, + * Returns a shared instance of an {@code AWTKeyStroke}, * given a numeric key code and a set of modifiers. The returned - * AWTKeyStroke will correspond to a key press. + * {@code AWTKeyStroke} will correspond to a key press. *

      * The "virtual key" constants defined in - * java.awt.event.KeyEvent can be + * {@code java.awt.event.KeyEvent} can be * used to specify the key code. For example:

        - *
      • java.awt.event.KeyEvent.VK_ENTER - *
      • java.awt.event.KeyEvent.VK_TAB - *
      • java.awt.event.KeyEvent.VK_SPACE + *
      • {@code java.awt.event.KeyEvent.VK_ENTER} + *
      • {@code java.awt.event.KeyEvent.VK_TAB} + *
      • {@code java.awt.event.KeyEvent.VK_SPACE} *
      * The modifiers consist of any combination of:
        *
      • java.awt.event.InputEvent.SHIFT_DOWN_MASK @@ -326,7 +326,7 @@ public class AWTKeyStroke implements Serializable { * * @param keyCode an int specifying the numeric code for a keyboard key * @param modifiers a bitwise-ored combination of any modifiers - * @return an AWTKeyStroke object for that key + * @return an {@code AWTKeyStroke} object for that key * * @see java.awt.event.KeyEvent * @see java.awt.event.InputEvent @@ -337,18 +337,18 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns an AWTKeyStroke which represents the - * stroke which generated a given KeyEvent. + * Returns an {@code AWTKeyStroke} which represents the + * stroke which generated a given {@code KeyEvent}. *

        - * This method obtains the keyChar from a KeyTyped - * event, and the keyCode from a KeyPressed or - * KeyReleased event. The KeyEvent modifiers are - * obtained for all three types of KeyEvent. + * This method obtains the keyChar from a {@code KeyTyped} + * event, and the keyCode from a {@code KeyPressed} or + * {@code KeyReleased} event. The {@code KeyEvent} modifiers are + * obtained for all three types of {@code KeyEvent}. * - * @param anEvent the KeyEvent from which to - * obtain the AWTKeyStroke - * @throws NullPointerException if anEvent is null - * @return the AWTKeyStroke that precipitated the event + * @param anEvent the {@code KeyEvent} from which to + * obtain the {@code AWTKeyStroke} + * @throws NullPointerException if {@code anEvent} is null + * @return the {@code AWTKeyStroke} that precipitated the event */ public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) { int id = anEvent.getID(); @@ -371,7 +371,7 @@ public class AWTKeyStroke implements Serializable { } /** - * Parses a string and returns an AWTKeyStroke. + * Parses a string and returns an {@code AWTKeyStroke}. * The string must have the following syntax: *

              *    <modifiers>* (<typedID> | <pressedReleasedID>)
        @@ -393,8 +393,8 @@ public class AWTKeyStroke implements Serializable {
              * 
        * * @param s a String formatted as described above - * @return an AWTKeyStroke object for that String - * @throws IllegalArgumentException if s is null, + * @return an {@code AWTKeyStroke} object for that String + * @throws IllegalArgumentException if {@code s} is {@code null}, * or is formatted incorrectly */ public static AWTKeyStroke getAWTKeyStroke(String s) { @@ -500,8 +500,8 @@ public class AWTKeyStroke implements Serializable { } /** * Returns the integer constant for the KeyEvent.VK field named - * key. This will throw an - * IllegalArgumentException if key is + * {@code key}. This will throw an + * {@code IllegalArgumentException} if {@code key} is * not a valid constant. */ private static int getVKValue(String key) { @@ -527,7 +527,7 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns the character for this AWTKeyStroke. + * Returns the character for this {@code AWTKeyStroke}. * * @return a char value * @see #getAWTKeyStroke(char) @@ -538,7 +538,7 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns the numeric key code for this AWTKeyStroke. + * Returns the numeric key code for this {@code AWTKeyStroke}. * * @return an int containing the key code value * @see #getAWTKeyStroke(int,int) @@ -549,7 +549,7 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns the modifier keys for this AWTKeyStroke. + * Returns the modifier keys for this {@code AWTKeyStroke}. * * @return an int containing the modifiers * @see #getAWTKeyStroke(int,int) @@ -559,10 +559,10 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns whether this AWTKeyStroke represents a key release. + * Returns whether this {@code AWTKeyStroke} represents a key release. * - * @return true if this AWTKeyStroke - * represents a key release; false otherwise + * @return {@code true} if this {@code AWTKeyStroke} + * represents a key release; {@code false} otherwise * @see #getAWTKeyStroke(int,int,boolean) */ public final boolean isOnKeyRelease() { @@ -570,12 +570,12 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns the type of KeyEvent which corresponds to - * this AWTKeyStroke. + * Returns the type of {@code KeyEvent} which corresponds to + * this {@code AWTKeyStroke}. * - * @return KeyEvent.KEY_PRESSED, - * KeyEvent.KEY_TYPED, - * or KeyEvent.KEY_RELEASED + * @return {@code KeyEvent.KEY_PRESSED}, + * {@code KeyEvent.KEY_TYPED}, + * or {@code KeyEvent.KEY_RELEASED} * @see java.awt.event.KeyEvent */ public final int getKeyEventType() { @@ -617,8 +617,8 @@ public class AWTKeyStroke implements Serializable { /** * Returns a string that displays and identifies this object's properties. - * The String returned by this method can be passed - * as a parameter to getAWTKeyStroke(String) to produce + * The {@code String} returned by this method can be passed + * as a parameter to {@code getAWTKeyStroke(String)} to produce * a key stroke equal to this key stroke. * * @return a String representation of this object @@ -695,8 +695,8 @@ public class AWTKeyStroke implements Serializable { } /** - * Returns a cached instance of AWTKeyStroke (or a subclass of - * AWTKeyStroke) which is equal to this instance. + * Returns a cached instance of {@code AWTKeyStroke} (or a subclass of + * {@code AWTKeyStroke}) which is equal to this instance. * * @return a cached instance which is equal to this instance * @throws java.io.ObjectStreamException if a serialization problem occurs diff --git a/jdk/src/java.desktop/share/classes/java/awt/AWTPermission.java b/jdk/src/java.desktop/share/classes/java/awt/AWTPermission.java index a201670bec8..5eedadb383b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/AWTPermission.java +++ b/jdk/src/java.desktop/share/classes/java/awt/AWTPermission.java @@ -29,7 +29,7 @@ import java.security.BasicPermission; /** * This class is for AWT permissions. - * An AWTPermission contains a target name but + * An {@code AWTPermission} contains a target name but * no actions list; you either have the named permission * or you don't. * @@ -39,7 +39,7 @@ import java.security.BasicPermission; * Also, an asterisk could be used to represent all AWT permissions. * *

        - * The following table lists all the possible AWTPermission + * The following table lists all the possible {@code AWTPermission} * target names, and for each provides a description of what the * permission allows and a discussion of the risks of granting code * the permission. @@ -125,12 +125,12 @@ import java.security.BasicPermission; * * * replaceKeyboardFocusManager - * Sets the KeyboardFocusManager for + * Sets the {@code KeyboardFocusManager} for * a particular thread. - * When SecurityManager is installed, the invoking + * When {@code SecurityManager} is installed, the invoking * thread must be granted this permission in order to replace - * the current KeyboardFocusManager. If permission - * is not granted, a SecurityException will be thrown. + * the current {@code KeyboardFocusManager}. If permission + * is not granted, a {@code SecurityException} will be thrown. * * * @@ -201,15 +201,15 @@ public final class AWTPermission extends BasicPermission { private static final long serialVersionUID = 8890392402588814465L; /** - * Creates a new AWTPermission with the specified name. - * The name is the symbolic name of the AWTPermission, + * Creates a new {@code AWTPermission} with the specified name. + * The name is the symbolic name of the {@code AWTPermission}, * such as "topLevelWindow", "systemClipboard", etc. An asterisk * may be used to indicate all AWT permissions. * * @param name the name of the AWTPermission * - * @throws NullPointerException if name is null. - * @throws IllegalArgumentException if name is empty. + * @throws NullPointerException if {@code name} is {@code null}. + * @throws IllegalArgumentException if {@code name} is empty. */ public AWTPermission(String name) @@ -218,15 +218,15 @@ public final class AWTPermission extends BasicPermission { } /** - * Creates a new AWTPermission object with the specified name. - * The name is the symbolic name of the AWTPermission, and the - * actions string is currently unused and should be null. + * Creates a new {@code AWTPermission} object with the specified name. + * The name is the symbolic name of the {@code AWTPermission}, and the + * actions string is currently unused and should be {@code null}. * - * @param name the name of the AWTPermission - * @param actions should be null + * @param name the name of the {@code AWTPermission} + * @param actions should be {@code null} * - * @throws NullPointerException if name is null. - * @throws IllegalArgumentException if name is empty. + * @throws NullPointerException if {@code name} is {@code null}. + * @throws IllegalArgumentException if {@code name} is empty. */ public AWTPermission(String name, String actions) diff --git a/jdk/src/java.desktop/share/classes/java/awt/ActiveEvent.java b/jdk/src/java.desktop/share/classes/java/awt/ActiveEvent.java index e7dbd875938..857eea54668 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ActiveEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ActiveEvent.java @@ -28,19 +28,19 @@ package java.awt; /** * An interface for events that know how to dispatch themselves. * By implementing this interface an event can be placed upon the event - * queue and its dispatch() method will be called when the event - * is dispatched, using the EventDispatchThread. + * queue and its {@code dispatch()} method will be called when the event + * is dispatched, using the {@code EventDispatchThread}. *

        * This is a very useful mechanism for avoiding deadlocks. If * a thread is executing in a critical section (i.e., it has entered * one or more monitors), calling other synchronized code may * cause deadlocks. To avoid the potential deadlocks, an - * ActiveEvent can be created to run the second section of + * {@code ActiveEvent} can be created to run the second section of * code at later time. If there is contention on the monitor, * the second thread will simply block until the first thread * has finished its work and exited its monitors. *

        - * For security reasons, it is often desirable to use an ActiveEvent + * For security reasons, it is often desirable to use an {@code ActiveEvent} * to avoid calling untrusted code from a critical thread. For * instance, peer implementations can use this facility to avoid * making calls into user code from a system thread. Doing so avoids diff --git a/jdk/src/java.desktop/share/classes/java/awt/Adjustable.java b/jdk/src/java.desktop/share/classes/java/awt/Adjustable.java index 6193a07c965..916dbf0b28f 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Adjustable.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Adjustable.java @@ -39,25 +39,25 @@ import java.lang.annotation.Native; public interface Adjustable { /** - * Indicates that the Adjustable has horizontal orientation. + * Indicates that the {@code Adjustable} has horizontal orientation. */ @Native public static final int HORIZONTAL = 0; /** - * Indicates that the Adjustable has vertical orientation. + * Indicates that the {@code Adjustable} has vertical orientation. */ @Native public static final int VERTICAL = 1; /** - * Indicates that the Adjustable has no orientation. + * Indicates that the {@code Adjustable} has no orientation. */ @Native public static final int NO_ORIENTATION = 2; /** * Gets the orientation of the adjustable object. * @return the orientation of the adjustable object; - * either HORIZONTAL, VERTICAL, - * or NO_ORIENTATION + * either {@code HORIZONTAL}, {@code VERTICAL}, + * or {@code NO_ORIENTATION} */ int getOrientation(); @@ -124,15 +124,15 @@ public interface Adjustable { /** * Sets the current value of the adjustable object. If - * the value supplied is less than minimum - * or greater than maximum - visibleAmount, + * the value supplied is less than {@code minimum} + * or greater than {@code maximum} - {@code visibleAmount}, * then one of those values is substituted, as appropriate. *

        * Calling this method does not fire an - * AdjustmentEvent. + * {@code AdjustmentEvent}. * - * @param v the current value, between minimum - * and maximum - visibleAmount + * @param v the current value, between {@code minimum} + * and {@code maximum} - {@code visibleAmount} */ void setValue(int v); diff --git a/jdk/src/java.desktop/share/classes/java/awt/AlphaComposite.java b/jdk/src/java.desktop/share/classes/java/awt/AlphaComposite.java index 1c5b7426986..dc650632d08 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/AlphaComposite.java +++ b/jdk/src/java.desktop/share/classes/java/awt/AlphaComposite.java @@ -30,7 +30,7 @@ import java.lang.annotation.Native; import sun.java2d.SunCompositeContext; /** - * The AlphaComposite class implements basic alpha + * The {@code AlphaComposite} class implements basic alpha * compositing rules for combining source and destination colors * to achieve blending and transparency effects with graphics and * images. @@ -44,7 +44,7 @@ import sun.java2d.SunCompositeContext; *

        * This class extends the standard equations defined by Porter and * Duff to include one additional factor. - * An instance of the AlphaComposite class can contain + * An instance of the {@code AlphaComposite} class can contain * an alpha value that is used to modify the opacity or coverage of * every source pixel before it is used in the blending equations. * @@ -52,7 +52,7 @@ import sun.java2d.SunCompositeContext; * It is important to note that the equations defined by the Porter * and Duff paper are all defined to operate on color components * that are premultiplied by their corresponding alpha components. - * Since the ColorModel and Raster classes + * Since the {@code ColorModel} and {@code Raster} classes * allow the storage of pixel data in either premultiplied or * non-premultiplied form, all input data must be normalized into * premultiplied form before applying the equations and all results @@ -96,7 +96,7 @@ import sun.java2d.SunCompositeContext; * that specify visual effects. * For example, * the description for - * SRC_OVER + * {@code SRC_OVER} * specifies that Fs = 1 and Fd = (1-As). * Once a set of equations for determining the blending factors is * known they can then be applied to each pixel to produce a result @@ -128,12 +128,12 @@ import sun.java2d.SunCompositeContext; *

        Preparing Inputs

        * *

        - * The AlphaComposite class defines an additional alpha + * The {@code AlphaComposite} class defines an additional alpha * value that is applied to the source alpha. * This value is applied as if an implicit SRC_IN rule were first * applied to the source pixel against a pixel with the indicated * alpha by multiplying both the raw source alpha and the raw - * source colors by the alpha in the AlphaComposite. + * source colors by the alpha in the {@code AlphaComposite}. * This leads to the following equation for producing the alpha * used in the Porter and Duff blending equation: * @@ -141,7 +141,7 @@ import sun.java2d.SunCompositeContext; * As = Asr * Aac * * All of the raw source color components need to be multiplied - * by the alpha in the AlphaComposite instance. + * by the alpha in the {@code AlphaComposite} instance. * Additionally, if the source was not in premultiplied form * then the color components also need to be multiplied by the * source alpha. @@ -196,11 +196,11 @@ import sun.java2d.SunCompositeContext; * *

        * For performance reasons, it is preferable that - * Raster objects passed to the compose + * {@code Raster} objects passed to the {@code compose} * method of a {@link CompositeContext} object created by the - * AlphaComposite class have premultiplied data. - * If either the source Raster - * or the destination Raster + * {@code AlphaComposite} class have premultiplied data. + * If either the source {@code Raster} + * or the destination {@code Raster} * is not premultiplied, however, * appropriate conversions are performed before and after the compositing * operation. @@ -210,7 +210,7 @@ import sun.java2d.SunCompositeContext; *

          *
        • * Many sources, such as some of the opaque image types listed - * in the BufferedImage class, do not store alpha values + * in the {@code BufferedImage} class, do not store alpha values * for their pixels. Such sources supply an alpha of 1.0 for * all of their pixels. * @@ -237,7 +237,7 @@ import sun.java2d.SunCompositeContext; * that does not separately store * color components is not a * good candidate for any type of translucent blending. - * For example, BufferedImage.TYPE_BYTE_INDEXED + * For example, {@code BufferedImage.TYPE_BYTE_INDEXED} * should not be used as a destination for a blending operation * because every operation * can introduce large errors, due to @@ -277,7 +277,7 @@ import sun.java2d.SunCompositeContext; *

          * If integer math were being used and this value were being * composited in - * SRC + * {@code SRC} * mode with no extra alpha, then the math would * indicate that the results were (in integer format): * @@ -510,21 +510,21 @@ public final class AlphaComposite implements Composite { @Native public static final int XOR = 12; /** - * AlphaComposite object that implements the opaque CLEAR rule + * {@code AlphaComposite} object that implements the opaque CLEAR rule * with an alpha of 1.0f. * @see #CLEAR */ public static final AlphaComposite Clear = new AlphaComposite(CLEAR); /** - * AlphaComposite object that implements the opaque SRC rule + * {@code AlphaComposite} object that implements the opaque SRC rule * with an alpha of 1.0f. * @see #SRC */ public static final AlphaComposite Src = new AlphaComposite(SRC); /** - * AlphaComposite object that implements the opaque DST rule + * {@code AlphaComposite} object that implements the opaque DST rule * with an alpha of 1.0f. * @see #DST * @since 1.4 @@ -532,49 +532,49 @@ public final class AlphaComposite implements Composite { public static final AlphaComposite Dst = new AlphaComposite(DST); /** - * AlphaComposite object that implements the opaque SRC_OVER rule + * {@code AlphaComposite} object that implements the opaque SRC_OVER rule * with an alpha of 1.0f. * @see #SRC_OVER */ public static final AlphaComposite SrcOver = new AlphaComposite(SRC_OVER); /** - * AlphaComposite object that implements the opaque DST_OVER rule + * {@code AlphaComposite} object that implements the opaque DST_OVER rule * with an alpha of 1.0f. * @see #DST_OVER */ public static final AlphaComposite DstOver = new AlphaComposite(DST_OVER); /** - * AlphaComposite object that implements the opaque SRC_IN rule + * {@code AlphaComposite} object that implements the opaque SRC_IN rule * with an alpha of 1.0f. * @see #SRC_IN */ public static final AlphaComposite SrcIn = new AlphaComposite(SRC_IN); /** - * AlphaComposite object that implements the opaque DST_IN rule + * {@code AlphaComposite} object that implements the opaque DST_IN rule * with an alpha of 1.0f. * @see #DST_IN */ public static final AlphaComposite DstIn = new AlphaComposite(DST_IN); /** - * AlphaComposite object that implements the opaque SRC_OUT rule + * {@code AlphaComposite} object that implements the opaque SRC_OUT rule * with an alpha of 1.0f. * @see #SRC_OUT */ public static final AlphaComposite SrcOut = new AlphaComposite(SRC_OUT); /** - * AlphaComposite object that implements the opaque DST_OUT rule + * {@code AlphaComposite} object that implements the opaque DST_OUT rule * with an alpha of 1.0f. * @see #DST_OUT */ public static final AlphaComposite DstOut = new AlphaComposite(DST_OUT); /** - * AlphaComposite object that implements the opaque SRC_ATOP rule + * {@code AlphaComposite} object that implements the opaque SRC_ATOP rule * with an alpha of 1.0f. * @see #SRC_ATOP * @since 1.4 @@ -582,7 +582,7 @@ public final class AlphaComposite implements Composite { public static final AlphaComposite SrcAtop = new AlphaComposite(SRC_ATOP); /** - * AlphaComposite object that implements the opaque DST_ATOP rule + * {@code AlphaComposite} object that implements the opaque DST_ATOP rule * with an alpha of 1.0f. * @see #DST_ATOP * @since 1.4 @@ -590,7 +590,7 @@ public final class AlphaComposite implements Composite { public static final AlphaComposite DstAtop = new AlphaComposite(DST_ATOP); /** - * AlphaComposite object that implements the opaque XOR rule + * {@code AlphaComposite} object that implements the opaque XOR rule * with an alpha of 1.0f. * @see #XOR * @since 1.4 @@ -620,11 +620,11 @@ public final class AlphaComposite implements Composite { } /** - * Creates an AlphaComposite object with the specified rule. + * Creates an {@code AlphaComposite} object with the specified rule. * * @param rule the compositing rule * @return the {@code AlphaComposite} object created - * @throws IllegalArgumentException if rule is not one of + * @throws IllegalArgumentException if {@code rule} is not one of * the following: {@link #CLEAR}, {@link #SRC}, {@link #DST}, * {@link #SRC_OVER}, {@link #DST_OVER}, {@link #SRC_IN}, * {@link #DST_IN}, {@link #SRC_OUT}, {@link #DST_OUT}, @@ -662,19 +662,19 @@ public final class AlphaComposite implements Composite { } /** - * Creates an AlphaComposite object with the specified rule and + * Creates an {@code AlphaComposite} object with the specified rule and * the constant alpha to multiply with the alpha of the source. * The source is multiplied with the specified alpha before being composited * with the destination. * * @param rule the compositing rule * @param alpha the constant alpha to be multiplied with the alpha of - * the source. alpha must be a floating point number in the + * the source. {@code alpha} must be a floating point number in the * inclusive range [0.0, 1.0]. * @return the {@code AlphaComposite} object created * @throws IllegalArgumentException if - * alpha is less than 0.0 or greater than 1.0, or if - * rule is not one of + * {@code alpha} is less than 0.0 or greater than 1.0, or if + * {@code rule} is not one of * the following: {@link #CLEAR}, {@link #SRC}, {@link #DST}, * {@link #SRC_OVER}, {@link #DST_OVER}, {@link #SRC_IN}, * {@link #DST_IN}, {@link #SRC_OUT}, {@link #DST_OUT}, @@ -692,8 +692,8 @@ public final class AlphaComposite implements Composite { * The context contains state that is used in performing * the compositing operation. * @param srcColorModel the {@link ColorModel} of the source - * @param dstColorModel the ColorModel of the destination - * @return the CompositeContext object to be used to perform + * @param dstColorModel the {@code ColorModel} of the destination + * @return the {@code CompositeContext} object to be used to perform * compositing operations. */ public CompositeContext createContext(ColorModel srcColorModel, @@ -703,32 +703,32 @@ public final class AlphaComposite implements Composite { } /** - * Returns the alpha value of this AlphaComposite. If this - * AlphaComposite does not have an alpha value, 1.0 is returned. - * @return the alpha value of this AlphaComposite. + * Returns the alpha value of this {@code AlphaComposite}. If this + * {@code AlphaComposite} does not have an alpha value, 1.0 is returned. + * @return the alpha value of this {@code AlphaComposite}. */ public float getAlpha() { return extraAlpha; } /** - * Returns the compositing rule of this AlphaComposite. - * @return the compositing rule of this AlphaComposite. + * Returns the compositing rule of this {@code AlphaComposite}. + * @return the compositing rule of this {@code AlphaComposite}. */ public int getRule() { return rule; } /** - * Returns a similar AlphaComposite object that uses + * Returns a similar {@code AlphaComposite} object that uses * the specified compositing rule. * If this object already uses the specified compositing rule, * this object is returned. - * @return an AlphaComposite object derived from + * @return an {@code AlphaComposite} object derived from * this object that uses the specified compositing rule. * @param rule the compositing rule * @throws IllegalArgumentException if - * rule is not one of + * {@code rule} is not one of * the following: {@link #CLEAR}, {@link #SRC}, {@link #DST}, * {@link #SRC_OVER}, {@link #DST_OVER}, {@link #SRC_IN}, * {@link #DST_IN}, {@link #SRC_OUT}, {@link #DST_OUT}, @@ -742,17 +742,17 @@ public final class AlphaComposite implements Composite { } /** - * Returns a similar AlphaComposite object that uses + * Returns a similar {@code AlphaComposite} object that uses * the specified alpha value. * If this object already has the specified alpha value, * this object is returned. - * @return an AlphaComposite object derived from + * @return an {@code AlphaComposite} object derived from * this object that uses the specified alpha value. * @param alpha the constant alpha to be multiplied with the alpha of - * the source. alpha must be a floating point number in the + * the source. {@code alpha} must be a floating point number in the * inclusive range [0.0, 1.0]. * @throws IllegalArgumentException if - * alpha is less than 0.0 or greater than 1.0 + * {@code alpha} is less than 0.0 or greater than 1.0 * @since 1.6 */ public AlphaComposite derive(float alpha) { @@ -771,16 +771,16 @@ public final class AlphaComposite implements Composite { /** * Determines whether the specified object is equal to this - * AlphaComposite. + * {@code AlphaComposite}. *

          - * The result is true if and only if - * the argument is not null and is an - * AlphaComposite object that has the same + * The result is {@code true} if and only if + * the argument is not {@code null} and is an + * {@code AlphaComposite} object that has the same * compositing rule and alpha value as this object. * - * @param obj the Object to test for equality - * @return true if obj equals this - * AlphaComposite; false otherwise. + * @param obj the {@code Object} to test for equality + * @return {@code true} if {@code obj} equals this + * {@code AlphaComposite}; {@code false} otherwise. */ public boolean equals(Object obj) { if (!(obj instanceof AlphaComposite)) { diff --git a/jdk/src/java.desktop/share/classes/java/awt/BorderLayout.java b/jdk/src/java.desktop/share/classes/java/awt/BorderLayout.java index 4720e895892..4b23f936ad3 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/BorderLayout.java +++ b/jdk/src/java.desktop/share/classes/java/awt/BorderLayout.java @@ -33,8 +33,8 @@ import java.util.Hashtable; * north, south, east, west, and center. * Each region may contain no more than one component, and * is identified by a corresponding constant: - * NORTH, SOUTH, EAST, - * WEST, and CENTER. When adding a + * {@code NORTH}, {@code SOUTH}, {@code EAST}, + * {@code WEST}, and {@code CENTER}. When adding a * component to a container with a border layout, use one of these * five constants, for example: *

          @@ -42,55 +42,55 @@ import java.util.Hashtable;
            *    p.setLayout(new BorderLayout());
            *    p.add(new Button("Okay"), BorderLayout.SOUTH);
            * 
          - * As a convenience, BorderLayout interprets the + * As a convenience, {@code BorderLayout} interprets the * absence of a string specification the same as the constant - * CENTER: + * {@code CENTER}: *
            *    Panel p2 = new Panel();
            *    p2.setLayout(new BorderLayout());
            *    p2.add(new TextArea());  // Same as p.add(new TextArea(), BorderLayout.CENTER);
            * 
          *

          - * In addition, BorderLayout supports the relative - * positioning constants, PAGE_START, PAGE_END, - * LINE_START, and LINE_END. - * In a container whose ComponentOrientation is set to - * ComponentOrientation.LEFT_TO_RIGHT, these constants map to - * NORTH, SOUTH, WEST, and - * EAST, respectively. + * In addition, {@code BorderLayout} supports the relative + * positioning constants, {@code PAGE_START}, {@code PAGE_END}, + * {@code LINE_START}, and {@code LINE_END}. + * In a container whose {@code ComponentOrientation} is set to + * {@code ComponentOrientation.LEFT_TO_RIGHT}, these constants map to + * {@code NORTH}, {@code SOUTH}, {@code WEST}, and + * {@code EAST}, respectively. *

          - * For compatibility with previous releases, BorderLayout - * also includes the relative positioning constants BEFORE_FIRST_LINE, - * AFTER_LAST_LINE, BEFORE_LINE_BEGINS and - * AFTER_LINE_ENDS. These are equivalent to - * PAGE_START, PAGE_END, LINE_START - * and LINE_END respectively. For + * For compatibility with previous releases, {@code BorderLayout} + * also includes the relative positioning constants {@code BEFORE_FIRST_LINE}, + * {@code AFTER_LAST_LINE}, {@code BEFORE_LINE_BEGINS} and + * {@code AFTER_LINE_ENDS}. These are equivalent to + * {@code PAGE_START}, {@code PAGE_END}, {@code LINE_START} + * and {@code LINE_END} respectively. For * consistency with the relative positioning constants used by other * components, the latter constants are preferred. *

          * Mixing both absolute and relative positioning constants can lead to * unpredictable results. If * you use both types, the relative constants will take precedence. - * For example, if you add components using both the NORTH - * and PAGE_START constants in a container whose - * orientation is LEFT_TO_RIGHT, only the - * PAGE_START will be laid out. + * For example, if you add components using both the {@code NORTH} + * and {@code PAGE_START} constants in a container whose + * orientation is {@code LEFT_TO_RIGHT}, only the + * {@code PAGE_START} will be laid out. *

          * NOTE: Currently (in the Java 2 platform v1.2), - * BorderLayout does not support vertical - * orientations. The isVertical setting on the container's - * ComponentOrientation is not respected. + * {@code BorderLayout} does not support vertical + * orientations. The {@code isVertical} setting on the container's + * {@code ComponentOrientation} is not respected. *

          * The components are laid out according to their * preferred sizes and the constraints of the container's size. - * The NORTH and SOUTH components may - * be stretched horizontally; the EAST and - * WEST components may be stretched vertically; - * the CENTER component may stretch both horizontally + * The {@code NORTH} and {@code SOUTH} components may + * be stretched horizontally; the {@code EAST} and + * {@code WEST} components may be stretched vertically; + * the {@code CENTER} component may stretch both horizontally * and vertically to fill any space left over. *

          * Here is an example of five buttons in an applet laid out using - * the BorderLayout layout manager: + * the {@code BorderLayout} layout manager: *

          * Diagram of an applet demonstrating BorderLayout.
@@ -126,7 +126,7 @@ public class BorderLayout implements LayoutManager2,
     /**
      * Constructs a border layout with the horizontal gaps
      * between components.
-     * The horizontal gap is specified by <code>hgap</code>.
+     * The horizontal gap is specified by {@code hgap}.
      *
      * @see #getHgap()
      * @see #setHgap(int)
@@ -138,7 +138,7 @@ public class BorderLayout implements LayoutManager2,
     /**
      * Constructs a border layout with the vertical gaps
      * between components.
-     * The vertical gap is specified by <code>vgap</code>.
+     * The vertical gap is specified by {@code vgap}.
      *
      * @see #getVgap()
      * @see #setVgap(int)
@@ -208,10 +208,10 @@ public class BorderLayout implements LayoutManager2,
      * north, south, east, west or center.
      * mixing the two types of constants can lead to unpredictable results.  If
      * you use both types, the relative constants will take precedence.
-     * For example, if you add components using both the <code>NORTH</code>
-     * and <code>BEFORE_FIRST_LINE</code> constants in a container whose
-     * orientation is <code>LEFT_TO_RIGHT</code>, only the
-     * <code>BEFORE_FIRST_LINE</code> will be laid out.
+     * For example, if you add components using both the {@code NORTH}
+     * and {@code BEFORE_FIRST_LINE} constants in a container whose
+     * orientation is {@code LEFT_TO_RIGHT}, only the
+     * {@code BEFORE_FIRST_LINE} will be laid out.
      * This will be the same for lastLine, firstItem, lastItem.
      * @serial
      */
@@ -355,8 +355,8 @@ public class BorderLayout implements LayoutManager2,
     /**
      * Constructs a border layout with the specified gaps
      * between components.
-     * The horizontal gap is specified by <code>hgap</code>
-     * and the vertical gap is specified by <code>vgap</code>.
+     * The horizontal gap is specified by {@code hgap}
+     * and the vertical gap is specified by {@code vgap}.
      * @param   hgap   the horizontal gap.
      * @param   vgap   the vertical gap.
      */
@@ -408,13 +408,13 @@ public class BorderLayout implements LayoutManager2,
     /**
      * Adds the specified component to the layout, using the specified
      * constraint object.  For border layouts, the constraint must be
-     * one of the following constants:  <code>NORTH</code>,
-     * <code>SOUTH</code>, <code>EAST</code>,
-     * <code>WEST</code>, or <code>CENTER</code>.
+     * one of the following constants:  {@code NORTH},
+     * {@code SOUTH}, {@code EAST},
+     * {@code WEST}, or {@code CENTER}.
      * <p>
      * Most applications do not call this method directly. This method
      * is called when a component is added to a container using the
-     * <code>Container.add</code> method with the same argument types.
+     * {@code Container.add} method with the same argument types.
      * @param   comp         the component to be added.
      * @param   constraints  an object that specifies how and where
      *                       the component is added to the layout.
@@ -434,7 +434,7 @@ public class BorderLayout implements LayoutManager2,
     }
 
     /**
-     * @deprecated  replaced by <code>addLayoutComponent(Component, Object)</code>.
+     * @deprecated  replaced by {@code addLayoutComponent(Component, Object)}.
      */
     @Deprecated
     public void addLayoutComponent(String name, Component comp) {
@@ -472,8 +472,8 @@ public class BorderLayout implements LayoutManager2,
 
     /**
      * Removes the specified component from this border layout. This
-     * method is called when a container calls its <code>remove</code> or
-     * <code>removeAll</code> methods. Most applications do not call this
+     * method is called when a container calls its {@code remove} or
+     * {@code removeAll} methods. Most applications do not call this
      * method directly.
      * @param   comp   the component to be removed.
      * @see     java.awt.Container#remove(java.awt.Component)
@@ -507,12 +507,12 @@ public class BorderLayout implements LayoutManager2,
     /**
      * Gets the component that was added using the given constraint
      *
-     * @param   constraints  the desired constraint, one of <code>CENTER</code>,
-     *                       <code>NORTH</code>, <code>SOUTH</code>,
-     *                       <code>WEST</code>, <code>EAST</code>,
-     *                       <code>PAGE_START</code>, <code>PAGE_END</code>,
-     *                       <code>LINE_START</code>, <code>LINE_END</code>
-     * @return  the component at the given location, or <code>null</code> if
+     * @param   constraints  the desired constraint, one of {@code CENTER},
+     *                       {@code NORTH}, {@code SOUTH},
+     *                       {@code WEST}, {@code EAST},
+     *                       {@code PAGE_START}, {@code PAGE_END},
+     *                       {@code LINE_START}, {@code LINE_END}
+     * @return  the component at the given location, or {@code null} if
      *          the location is empty
      * @exception   IllegalArgumentException  if the constraint object is
      *              not one of the nine specified constants
@@ -546,21 +546,21 @@ public class BorderLayout implements LayoutManager2,
 
     /**
      * Returns the component that corresponds to the given constraint location
-     * based on the target <code>Container</code>'s component orientation.
-     * Components added with the relative constraints <code>PAGE_START</code>,
-     * <code>PAGE_END</code>, <code>LINE_START</code>, and <code>LINE_END</code>
+     * based on the target {@code Container}'s component orientation.
+     * Components added with the relative constraints {@code PAGE_START},
+     * {@code PAGE_END}, {@code LINE_START}, and {@code LINE_END}
      * take precedence over components added with the explicit constraints
-     * <code>NORTH</code>, <code>SOUTH</code>, <code>WEST</code>, and <code>EAST</code>.
-     * The <code>Container</code>'s component orientation is used to determine the location of components
-     * added with <code>LINE_START</code> and <code>LINE_END</code>.
+     * {@code NORTH}, {@code SOUTH}, {@code WEST}, and {@code EAST}.
+     * The {@code Container}'s component orientation is used to determine the location of components
+     * added with {@code LINE_START} and {@code LINE_END}.
      *
-     * @param   constraints     the desired absolute position, one of <code>CENTER</code>,
-     *                          <code>NORTH</code>, <code>SOUTH</code>,
-     *                          <code>EAST</code>, <code>WEST</code>
+     * @param   constraints     the desired absolute position, one of {@code CENTER},
+     *                          {@code NORTH}, {@code SOUTH},
+     *                          {@code EAST}, {@code WEST}
      * @param   target     the {@code Container} used to obtain
      *                     the constraint location based on the target
      *                     {@code Container}'s component orientation.
-     * @return  the component at the given location, or <code>null</code> if
+     * @return  the component at the given location, or {@code null} if
      *          the location is empty
      * @exception   IllegalArgumentException  if the constraint object is
      *              not one of the five specified constants
@@ -634,11 +634,11 @@ public class BorderLayout implements LayoutManager2,
     }
 
     /**
-     * Determines the minimum size of the <code>target</code> container
+     * Determines the minimum size of the {@code target} container
      * using this layout manager.
      * <p>
      * This method is called when a container calls its
-     * <code>getMinimumSize</code> method. Most applications do not call
+     * {@code getMinimumSize} method. Most applications do not call
      * this method directly.
      * @param   target   the container in which to do the layout.
      * @return  the minimum dimensions needed to lay out the subcomponents
@@ -689,12 +689,12 @@ public class BorderLayout implements LayoutManager2,
     }
 
     /**
-     * Determines the preferred size of the <code>target</code>
+     * Determines the preferred size of the {@code target}
      * container using this layout manager, based on the components
      * in the container.
      * <p>
      * Most applications do not call this method directly. This method
-     * is called when a container calls its <code>getPreferredSize</code>
+     * is called when a container calls its {@code getPreferredSize}
      * method.
      * @param   target   the container in which to do the layout.
      * @return  the preferred dimensions to lay out the subcomponents
@@ -790,16 +790,16 @@ public class BorderLayout implements LayoutManager2,
      * <p>
      * This method actually reshapes the components in the specified
      * container in order to satisfy the constraints of this
-     * <code>BorderLayout</code> object. The <code>NORTH</code>
-     * and <code>SOUTH</code> components, if any, are placed at
+     * {@code BorderLayout} object. The {@code NORTH}
+     * and {@code SOUTH} components, if any, are placed at
      * the top and bottom of the container, respectively. The
-     * <code>WEST</code> and <code>EAST</code> components are
+     * {@code WEST} and {@code EAST} components are
      * then placed on the left and right, respectively. Finally,
-     * the <code>CENTER</code> object is placed in any remaining
+     * the {@code CENTER} object is placed in any remaining
      * space in the middle.
      * <p>
      * Most applications do not call this method directly. This method
-     * is called when a container calls its <code>doLayout</code> method.
+     * is called when a container calls its {@code doLayout} method.
      * @param   target   the container in which to do the layout.
      * @see     java.awt.Container
      * @see     java.awt.Container#doLayout()
diff --git a/jdk/src/java.desktop/share/classes/java/awt/BufferCapabilities.java b/jdk/src/java.desktop/share/classes/java/awt/BufferCapabilities.java
index 2da7ac335bc..1b3b5576d83 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/BufferCapabilities.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/BufferCapabilities.java
@@ -42,13 +42,13 @@ public class BufferCapabilities implements Cloneable {
     /**
      * Creates a new object for specifying buffering capabilities
      * @param frontCaps the capabilities of the front buffer; cannot be
-     * <code>null</code>
+     * {@code null}
      * @param backCaps the capabilities of the back and intermediate buffers;
-     * cannot be <code>null</code>
+     * cannot be {@code null}
      * @param flipContents the contents of the back buffer after page-flipping,
-     * <code>null</code> if page flipping is not used (implies blitting)
+     * {@code null} if page flipping is not used (implies blitting)
      * @exception IllegalArgumentException if frontCaps or backCaps are
-     * <code>null</code>
+     * {@code null}
      */
     public BufferCapabilities(ImageCapabilities frontCaps,
         ImageCapabilities backCaps, FlipContents flipContents) {
@@ -83,8 +83,8 @@ public class BufferCapabilities implements Cloneable {
      * more back buffers by switching the video pointer (or by copying memory
      * internally).  A non-flipping set of
      * buffers uses blitting to copy the contents from one buffer to
-     * another; when this is the case, <code>getFlipContents</code> returns
-     * <code>null</code>
+     * another; when this is the case, {@code getFlipContents} returns
+     * {@code null}
      */
     public boolean isPageFlipping() {
         return (getFlipContents() != null);
@@ -92,12 +92,12 @@ public class BufferCapabilities implements Cloneable {
 
     /**
      * @return the resulting contents of the back buffer after page-flipping.
-     * This value is <code>null</code> when the <code>isPageFlipping</code>
-     * returns <code>false</code>, implying blitting.  It can be one of
-     * <code>FlipContents.UNDEFINED</code>
-     * (the assumed default), <code>FlipContents.BACKGROUND</code>,
-     * <code>FlipContents.PRIOR</code>, or
-     * <code>FlipContents.COPIED</code>.
+     * This value is {@code null} when the {@code isPageFlipping}
+     * returns {@code false}, implying blitting.  It can be one of
+     * {@code FlipContents.UNDEFINED}
+     * (the assumed default), {@code FlipContents.BACKGROUND},
+     * {@code FlipContents.PRIOR}, or
+     * {@code FlipContents.COPIED}.
      * @see #isPageFlipping
      * @see FlipContents#UNDEFINED
      * @see FlipContents#BACKGROUND
@@ -110,7 +110,7 @@ public class BufferCapabilities implements Cloneable {
 
     /**
      * @return whether page flipping is only available in full-screen mode.  If this
-     * is <code>true</code>, full-screen exclusive mode is required for
+     * is {@code true}, full-screen exclusive mode is required for
      * page-flipping.
      * @see #isPageFlipping
      * @see GraphicsDevice#setFullScreenWindow
@@ -158,7 +158,7 @@ public class BufferCapabilities implements Cloneable {
             { UNDEFINED, the + * When flip contents are {@code UNDEFINED}, the * contents of the back buffer are undefined after flipping. * @see #isPageFlipping * @see #getFlipContents @@ -170,7 +170,7 @@ public class BufferCapabilities implements Cloneable { new FlipContents(I_UNDEFINED); /** - * When flip contents are BACKGROUND, the + * When flip contents are {@code BACKGROUND}, the * contents of the back buffer are cleared with the background color after * flipping. * @see #isPageFlipping @@ -183,7 +183,7 @@ public class BufferCapabilities implements Cloneable { new FlipContents(I_BACKGROUND); /** - * When flip contents are PRIOR, the + * When flip contents are {@code PRIOR}, the * contents of the back buffer are the prior contents of the front buffer * (a true page flip). * @see #isPageFlipping @@ -196,7 +196,7 @@ public class BufferCapabilities implements Cloneable { new FlipContents(I_PRIOR); /** - * When flip contents are COPIED, the + * When flip contents are {@code COPIED}, the * contents of the back buffer are copied to the front buffer when * flipping. * @see #isPageFlipping diff --git a/jdk/src/java.desktop/share/classes/java/awt/Button.java b/jdk/src/java.desktop/share/classes/java/awt/Button.java index faa8068cf8c..66cbc8cbbe9 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Button.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Button.java @@ -37,7 +37,7 @@ import javax.accessibility.*; /** * This class creates a labeled button. The application can cause * some action to happen when the button is pushed. This image - * depicts three views of a "Quit" button as it appears + * depicts three views of a "{@code Quit}" button as it appears * under the Solaris operating system: *

          * The following context describes the graphic * The gesture of clicking on a button with the mouse - * is associated with one instance of ActionEvent, + * is associated with one instance of {@code ActionEvent}, * which is sent out when the mouse is both pressed and released * over the button. If an application is interested in knowing * when the button has been pressed but not released, as a separate - * gesture, it can specialize processMouseEvent, + * gesture, it can specialize {@code processMouseEvent}, * or it can register itself as a listener for mouse events by - * calling addMouseListener. Both of these methods are - * defined by Component, the abstract superclass of + * calling {@code addMouseListener}. Both of these methods are + * defined by {@code Component}, the abstract superclass of * all components. *

          * When a button is pressed and released, AWT sends an instance - * of ActionEvent to the button, by calling - * processEvent on the button. The button's - * processEvent method receives all events + * of {@code ActionEvent} to the button, by calling + * {@code processEvent} on the button. The button's + * {@code processEvent} method receives all events * for the button; it passes an action event along by - * calling its own processActionEvent method. + * calling its own {@code processActionEvent} method. * The latter method passes the action event on to any action * listeners that have registered an interest in action * events generated by this button. *

          * If an application wants to perform some action based on * a button being pressed and released, it should implement - * ActionListener and register the new listener + * {@code ActionListener} and register the new listener * to receive events from this button, by calling the button's - * addActionListener method. The application can + * {@code addActionListener} method. The application can * make use of the button's action command as a messaging protocol. * * @author Sami Shaio @@ -144,7 +144,7 @@ public class Button extends Component implements Accessible { * Constructs a button with the specified label. * * @param label a string label for the button, or - * null for no label + * {@code null} for no label * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -182,7 +182,7 @@ public class Button extends Component implements Accessible { /** * Gets the label of this button. * - * @return the button's label, or null + * @return the button's label, or {@code null} * if the button has no label. * @see java.awt.Button#setLabel */ @@ -193,7 +193,7 @@ public class Button extends Component implements Accessible { /** * Sets the button's label to be the specified string. * - * @param label the new label, or null + * @param label the new label, or {@code null} * if the button has no label. * @see java.awt.Button#getLabel */ @@ -225,7 +225,7 @@ public class Button extends Component implements Accessible { * * @param command a string used to set the button's * action command. - * If the string is null then the action command + * If the string is {@code null} then the action command * is set to match the label of the button. * @see java.awt.event.ActionEvent * @since 1.1 @@ -236,7 +236,7 @@ public class Button extends Component implements Accessible { /** * Returns the command name of the action event fired by this button. - * If the command name is null (default) then this method + * If the command name is {@code null} (default) then this method * returns the label of the button. * * @return the action command name (or label) for this button @@ -292,7 +292,7 @@ public class Button extends Component implements Accessible { * Returns an array of all the action listeners * registered on this button. * - * @return all of this button's ActionListeners + * @return all of this button's {@code ActionListener}s * or an empty array if no action * listeners are currently registered * @@ -308,16 +308,16 @@ public class Button extends Component implements Accessible { /** * Returns an array of all the objects currently registered * as FooListeners - * upon this Button. + * upon this {@code Button}. * FooListeners are registered using the * addFooListener method. * *

          - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * Button b + * {@code Button b} * for its action listeners with the following code: * *

          ActionListener[] als = (ActionListener[])(b.getListeners(ActionListener.class));
          @@ -326,14 +326,14 @@ public class Button extends Component implements Accessible { * * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this button, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @see #getActionListeners * @since 1.3 @@ -362,10 +362,10 @@ public class Button extends Component implements Accessible { /** * Processes events on this button. If an event is - * an instance of ActionEvent, this method invokes - * the processActionEvent method. Otherwise, - * it invokes processEvent on the superclass. - *

          Note that if the event parameter is null + * an instance of {@code ActionEvent}, this method invokes + * the {@code processActionEvent} method. Otherwise, + * it invokes {@code processEvent} on the superclass. + *

          Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -385,17 +385,17 @@ public class Button extends Component implements Accessible { /** * Processes action events occurring on this button * by dispatching them to any registered - * ActionListener objects. + * {@code ActionListener} objects. *

          * This method is not called unless action events are * enabled for this button. Action events are enabled * when one of the following occurs: *

            - *
          • An ActionListener object is registered - * via addActionListener. - *
          • Action events are enabled via enableEvents. + *
          • An {@code ActionListener} object is registered + * via {@code addActionListener}. + *
          • Action events are enabled via {@code enableEvents}. *
          - *

          Note that if the event parameter is null + *

          Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -413,11 +413,11 @@ public class Button extends Component implements Accessible { } /** - * Returns a string representing the state of this Button. + * Returns a string representing the state of this {@code Button}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this button */ @@ -437,19 +437,19 @@ public class Button extends Component implements Accessible { /** * Writes default serializable fields to stream. Writes - * a list of serializable ActionListeners + * a list of serializable {@code ActionListeners} * as optional data. The non-serializable - * ActionListeners are detected and + * {@code ActionListeners} are detected and * no attempt is made to serialize them. * - * @serialData null terminated sequence of 0 or - * more pairs: the pair consists of a String - * and an Object; the String + * @serialData {@code null} terminated sequence of 0 or + * more pairs: the pair consists of a {@code String} + * and an {@code Object}; the {@code String} * indicates the type of object and is one of the following: - * actionListenerK indicating an - * ActionListener object + * {@code actionListenerK} indicating an + * {@code ActionListener} object * - * @param s the ObjectOutputStream to write + * @param s the {@code ObjectOutputStream} to write * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) * @see java.awt.Component#actionListenerK * @see #readObject(ObjectInputStream) @@ -464,15 +464,15 @@ public class Button extends Component implements Accessible { } /** - * Reads the ObjectInputStream and if - * it isn't null adds a listener to + * Reads the {@code ObjectInputStream} and if + * it isn't {@code null} adds a listener to * receive action events fired by the button. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns - * true + * {@code GraphicsEnvironment.isHeadless} returns + * {@code true} * @serial * @see #removeActionListener(ActionListener) * @see #addActionListener(ActionListener) @@ -503,15 +503,15 @@ public class Button extends Component implements Accessible { //////////////// /** - * Gets the AccessibleContext associated with - * this Button. For buttons, the - * AccessibleContext takes the form of an - * AccessibleAWTButton. - * A new AccessibleAWTButton instance is + * Gets the {@code AccessibleContext} associated with + * this {@code Button}. For buttons, the + * {@code AccessibleContext} takes the form of an + * {@code AccessibleAWTButton}. + * A new {@code AccessibleAWTButton} instance is * created if necessary. * - * @return an AccessibleAWTButton that serves as the - * AccessibleContext of this Button + * @return an {@code AccessibleAWTButton} that serves as the + * {@code AccessibleContext} of this {@code Button} * @since 1.3 */ @BeanProperty(expert = true, description @@ -525,7 +525,7 @@ public class Button extends Component implements Accessible { /** * This class implements accessibility support for the - * Button class. It provides an implementation of the + * {@code Button} class. It provides an implementation of the * Java Accessibility API appropriate to button user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Canvas.java b/jdk/src/java.desktop/share/classes/java/awt/Canvas.java index 166d664a31b..9d1762f0674 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Canvas.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Canvas.java @@ -29,13 +29,13 @@ import java.awt.peer.CanvasPeer; import javax.accessibility.*; /** - * A Canvas component represents a blank rectangular + * A {@code Canvas} component represents a blank rectangular * area of the screen onto which the application can draw or from * which the application can trap input events from the user. *

          - * An application must subclass the Canvas class in + * An application must subclass the {@code Canvas} class in * order to get useful functionality such as creating a custom - * component. The paint method must be overridden + * component. The {@code paint} method must be overridden * in order to perform custom graphics on the canvas. * * @author Sami Shaio @@ -108,7 +108,7 @@ public class Canvas extends Component implements Accessible { /** * Paints this canvas. *

          - * Most applications that subclass Canvas should + * Most applications that subclass {@code Canvas} should * override this method in order to perform some useful operation * (typically, custom painting of the canvas). * The default operation is simply to clear the canvas. @@ -126,10 +126,10 @@ public class Canvas extends Component implements Accessible { /** * Updates this canvas. *

          - * This method is called in response to a call to repaint. + * This method is called in response to a call to {@code repaint}. * The canvas is first cleared by filling it with the background * color, and then completely redrawn by calling this canvas's - * paint method. + * {@code paint} method. * Note: applications that override this method should either call * super.update(g) or incorporate the functionality described * above into their own code. @@ -151,7 +151,7 @@ public class Canvas extends Component implements Accessible { * Creates a new strategy for multi-buffering on this component. * Multi-buffering is useful for rendering performance. This method * attempts to create the best strategy available with the number of - * buffers supplied. It will always create a BufferStrategy + * buffers supplied. It will always create a {@code BufferStrategy} * with that number of buffers. * A page-flipping strategy is attempted first, then a blitting strategy * using accelerated buffers. Finally, an unaccelerated blitting @@ -180,13 +180,13 @@ public class Canvas extends Component implements Accessible { * is called, the existing buffer strategy for this component is discarded. * @param numBuffers number of buffers to create * @param caps the required capabilities for creating the buffer strategy; - * cannot be null + * cannot be {@code null} * @exception AWTException if the capabilities supplied could not be * supported or met; this may happen, for example, if there is not enough * accelerated memory currently available, or if page flipping is specified * but not possible. * @exception IllegalArgumentException if numBuffers is less than 1, or if - * caps is null + * caps is {@code null} * @see #getBufferStrategy * @since 1.4 */ @@ -196,8 +196,8 @@ public class Canvas extends Component implements Accessible { } /** - * Returns the BufferStrategy used by this component. This - * method will return null if a BufferStrategy has not yet + * Returns the {@code BufferStrategy} used by this component. This + * method will return null if a {@code BufferStrategy} has not yet * been created or has been disposed. * * @return the buffer strategy used by this component @@ -232,7 +232,7 @@ public class Canvas extends Component implements Accessible { /** * This class implements accessibility support for the - * Canvas class. It provides an implementation of the + * {@code Canvas} class. It provides an implementation of the * Java Accessibility API appropriate to canvas user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/CardLayout.java b/jdk/src/java.desktop/share/classes/java/awt/CardLayout.java index 9f14d622a15..e7523e1921e 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/CardLayout.java +++ b/jdk/src/java.desktop/share/classes/java/awt/CardLayout.java @@ -36,15 +36,15 @@ import java.io.ObjectStreamField; import java.io.IOException; /** - * A CardLayout object is a layout manager for a + * A {@code CardLayout} object is a layout manager for a * container. It treats each component in the container as a card. * Only one card is visible at a time, and the container acts as * a stack of cards. The first component added to a - * CardLayout object is the visible component when the + * {@code CardLayout} object is the visible component when the * container is first displayed. *

          * The ordering of cards is determined by the container's own internal - * ordering of its component objects. CardLayout + * ordering of its component objects. {@code CardLayout} * defines a set of methods that allow an application to flip * through these cards sequentially, or to show a specified card. * The {@link CardLayout#addLayoutComponent} @@ -188,10 +188,10 @@ public class CardLayout implements LayoutManager2, /** * Adds the specified component to this card layout's internal - * table of names. The object specified by constraints + * table of names. The object specified by {@code constraints} * must be a string. The card layout stores this string as a key-value * pair that can be used for random access to a particular card. - * By calling the show method, an application can + * By calling the {@code show} method, an application can * display the component with the specified name. * @param comp the component to be added. * @param constraints a tag that identifies a particular @@ -214,7 +214,7 @@ public class CardLayout implements LayoutManager2, /** * @deprecated replaced by - * addLayoutComponent(Component, Object). + * {@code addLayoutComponent(Component, Object)}. */ @Deprecated public void addLayoutComponent(String name, Component comp) { @@ -365,7 +365,7 @@ public class CardLayout implements LayoutManager2, /** * Lays out the specified container using this card layout. *

          - * Each component in the parent container is reshaped + * Each component in the {@code parent} container is reshaped * to be the size of the container, minus space for surrounding * insets, horizontal gaps, and vertical gaps. * @@ -515,7 +515,7 @@ public class CardLayout implements LayoutManager2, /** * Flips to the component that was added to this layout with the - * specified name, using addLayoutComponent. + * specified {@code name}, using {@code addLayoutComponent}. * If no such component exists, then nothing happens. * @param parent the parent container in which to do the layout * @param name the component name diff --git a/jdk/src/java.desktop/share/classes/java/awt/Checkbox.java b/jdk/src/java.desktop/share/classes/java/awt/Checkbox.java index 4604b6262a6..bf7f9406158 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Checkbox.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Checkbox.java @@ -35,7 +35,7 @@ import javax.accessibility.*; /** * A check box is a graphical component that can be in either an - * "on" (true) or "off" (false) state. + * "on" ({@code true}) or "off" ({@code false}) state. * Clicking on a check box changes its state from * "on" to "off," or from "off" to "on." *

          @@ -55,14 +55,14 @@ import javax.accessibility.*; * The following context describes the graphic. *

          - * The button labeled one is in the "on" state, and the + * The button labeled {@code one} is in the "on" state, and the * other two are in the "off" state. In this example, which uses the - * GridLayout class, the states of the three check + * {@code GridLayout} class, the states of the three check * boxes are set independently. *

          * Alternatively, several check boxes can be grouped together under * the control of a single object, using the - * CheckboxGroup class. + * {@code CheckboxGroup} class. * In a check box group, at most one button can be in the "on" * state at any given time. Clicking on a check box to turn it on * forces any other check box in the same group that is on @@ -93,7 +93,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { String label; /** - * The state of the Checkbox. + * The state of the {@code Checkbox}. * @serial * @see #getState() * @see #setState(boolean) @@ -150,10 +150,10 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * any check box group. * * @param label a string label for this check box, - * or null for no label. + * or {@code null} for no label. * @exception HeadlessException if - * GraphicsEnvironment.isHeadless - * returns true + * {@code GraphicsEnvironment.isHeadless} + * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless */ public Checkbox(String label) throws HeadlessException { @@ -166,11 +166,11 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * This check box is not part of any check box group. * * @param label a string label for this check box, - * or null for no label + * or {@code null} for no label * @param state the initial state of this check box * @exception HeadlessException if - * GraphicsEnvironment.isHeadless - * returns true + * {@code GraphicsEnvironment.isHeadless} + * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless */ public Checkbox(String label, boolean state) throws HeadlessException { @@ -182,13 +182,13 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * specified state, and in the specified check box group. * * @param label a string label for this check box, - * or null for no label. + * or {@code null} for no label. * @param state the initial state of this check box. * @param group a check box group for this check box, - * or null for no group. + * or {@code null} for no group. * @exception HeadlessException if - * GraphicsEnvironment.isHeadless - * returns true + * {@code GraphicsEnvironment.isHeadless} + * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.1 */ @@ -208,13 +208,13 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * check box group, and set to the specified state. * * @param label a string label for this check box, - * or null for no label. + * or {@code null} for no label. * @param group a check box group for this check box, - * or null for no group. + * or {@code null} for no group. * @param state the initial state of this check box. * @exception HeadlessException if - * GraphicsEnvironment.isHeadless - * returns true + * {@code GraphicsEnvironment.isHeadless} + * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.1 */ @@ -225,7 +225,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * Constructs a name for this component. Called by - * getName when the name is null. + * {@code getName} when the name is {@code null}. * * @return a name for this component */ @@ -252,7 +252,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * Gets the label of this check box. * - * @return the label of this check box, or null + * @return the label of this check box, or {@code null} * if this check box has no label. * @see #setLabel(String) */ @@ -264,7 +264,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * Sets this check box's label to be the string argument. * * @param label a string to set as the new label, or - * null for no label. + * {@code null} for no label. * @see #getLabel */ public void setLabel(String label) { @@ -290,8 +290,8 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * Determines whether this check box is in the "on" or "off" state. - * The boolean value true indicates the "on" state, - * and false indicates the "off" state. + * The boolean value {@code true} indicates the "on" state, + * and {@code false} indicates the "off" state. * * @return the state of this check box, as a boolean value * @see #setState @@ -302,14 +302,14 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * Sets the state of this check box to the specified state. - * The boolean value true indicates the "on" state, - * and false indicates the "off" state. + * The boolean value {@code true} indicates the "on" state, + * and {@code false} indicates the "off" state. * *

          Note that this method should be primarily used to * initialize the state of the checkbox. Programmatically * setting the state of the checkbox will not trigger - * an ItemEvent. The only way to trigger an - * ItemEvent is by user interaction. + * an {@code ItemEvent}. The only way to trigger an + * {@code ItemEvent} is by user interaction. * * @param state the boolean state of the check box * @see #getState @@ -343,7 +343,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * Determines this check box's group. - * @return this check box's group, or null + * @return this check box's group, or {@code null} * if the check box is not part of a check box group. * @see #setCheckboxGroup(CheckboxGroup) */ @@ -356,14 +356,14 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * If this check box is already in a different check box group, * it is first taken out of that group. *

          - * If the state of this check box is true and the new + * If the state of this check box is {@code true} and the new * group already has a check box selected, this check box's state - * is changed to false. If the state of this check - * box is true and the new group has no check box + * is changed to {@code false}. If the state of this check + * box is {@code true} and the new group has no check box * selected, this check box becomes the selected checkbox for - * the new group and its state is true. + * the new group and its state is {@code true}. * - * @param g the new check box group, or null + * @param g the new check box group, or {@code null} * to remove this check box from any check box group * @see #getCheckboxGroup */ @@ -458,7 +458,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * Returns an array of all the item listeners * registered on this checkbox. * - * @return all of this checkbox's ItemListeners + * @return all of this checkbox's {@code ItemListener}s * or an empty array if no item * listeners are currently registered * @@ -475,16 +475,16 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * Returns an array of all the objects currently registered * as FooListeners - * upon this Checkbox. + * upon this {@code Checkbox}. * FooListeners are registered using the * addFooListener method. * *

          - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * Checkbox c + * {@code Checkbox c} * for its item listeners with the following code: * *

          ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));
          @@ -493,14 +493,14 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this checkbox, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @see #getItemListeners * @since 1.3 @@ -529,10 +529,10 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * Processes events on this check box. - * If the event is an instance of ItemEvent, - * this method invokes the processItemEvent method. - * Otherwise, it calls its superclass's processEvent method. - *

          Note that if the event parameter is null + * If the event is an instance of {@code ItemEvent}, + * this method invokes the {@code processItemEvent} method. + * Otherwise, it calls its superclass's {@code processEvent} method. + *

          Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -552,17 +552,17 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * Processes item events occurring on this check box by * dispatching them to any registered - * ItemListener objects. + * {@code ItemListener} objects. *

          * This method is not called unless item events are * enabled for this component. Item events are enabled * when one of the following occurs: *

            - *
          • An ItemListener object is registered - * via addItemListener. - *
          • Item events are enabled via enableEvents. + *
          • An {@code ItemListener} object is registered + * via {@code addItemListener}. + *
          • Item events are enabled via {@code enableEvents}. *
          - *

          Note that if the event parameter is null + *

          Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -581,11 +581,11 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { } /** - * Returns a string representing the state of this Checkbox. + * Returns a string representing the state of this {@code Checkbox}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this check box */ @@ -610,18 +610,18 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * Writes default serializable fields to stream. Writes - * a list of serializable ItemListeners + * a list of serializable {@code ItemListeners} * as optional data. The non-serializable - * ItemListeners are detected and + * {@code ItemListeners} are detected and * no attempt is made to serialize them. * - * @param s the ObjectOutputStream to write - * @serialData null terminated sequence of 0 - * or more pairs; the pair consists of a String - * and an Object; the String indicates + * @param s the {@code ObjectOutputStream} to write + * @serialData {@code null} terminated sequence of 0 + * or more pairs; the pair consists of a {@code String} + * and an {@code Object}; the {@code String} indicates * the type of object and is one of the following: - * itemListenerK indicating an - * ItemListener object + * {@code itemListenerK} indicating an + * {@code ItemListener} object * * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) * @see java.awt.Component#itemListenerK @@ -637,15 +637,15 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { } /** - * Reads the ObjectInputStream and if it - * isn't null adds a listener to receive - * item events fired by the Checkbox. + * Reads the {@code ObjectInputStream} and if it + * isn't {@code null} adds a listener to receive + * item events fired by the {@code Checkbox}. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns - * true + * {@code GraphicsEnvironment.isHeadless} returns + * {@code true} * @serial * @see #removeItemListener(ItemListener) * @see #addItemListener(ItemListener) @@ -700,7 +700,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { /** * This class implements accessibility support for the - * Checkbox class. It provides an implementation of the + * {@code Checkbox} class. It provides an implementation of the * Java Accessibility API appropriate to checkbox user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java b/jdk/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java index aba3f37798e..470ad9a17d0 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java +++ b/jdk/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java @@ -40,20 +40,20 @@ import sun.awt.AWTAccessor; * "on" to "off" or from "off" to "on." *

          * The following picture depicts a menu which contains an instance - * of CheckBoxMenuItem: + * of {@code CheckBoxMenuItem}: *

          * Menu labeled Examples, containing items Basic, Simple, Check, and More Examples. The Check item is a CheckBoxMenuItem instance, in the off state. *

          - * The item labeled Check shows a check box menu item + * The item labeled {@code Check} shows a check box menu item * in its "off" state. *

          * When a check box menu item is selected, AWT sends an item event to - * the item. Since the event is an instance of ItemEvent, - * the processEvent method examines the event and passes - * it along to processItemEvent. The latter method redirects - * the event to any ItemListener objects that have + * the item. Since the event is an instance of {@code ItemEvent}, + * the {@code processEvent} method examines the event and passes + * it along to {@code processItemEvent}. The latter method redirects + * the event to any {@code ItemListener} objects that have * registered an interest in item events generated by this menu item. * * @author Sami Shaio @@ -113,7 +113,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * The item's state is initially set to "off." * @param label a string label for the check box menu item, - * or null for an unlabeled menu item. + * or {@code null} for an unlabeled menu item. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -125,10 +125,10 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access /** * Create a check box menu item with the specified label and state. * @param label a string label for the check box menu item, - * or null for an unlabeled menu item. + * or {@code null} for an unlabeled menu item. * @param state the initial state of the menu item, where - * true indicates "on" and - * false indicates "off." + * {@code true} indicates "on" and + * {@code false} indicates "off." * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -170,8 +170,8 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * is "on" or "off." * * @return the state of this check box menu item, where - * true indicates "on" and - * false indicates "off" + * {@code true} indicates "on" and + * {@code false} indicates "off" * @see #setState */ public boolean getState() { @@ -180,18 +180,18 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access /** * Sets this check box menu item to the specified state. - * The boolean value true indicates "on" while - * false indicates "off." + * The boolean value {@code true} indicates "on" while + * {@code false} indicates "off." * *

          Note that this method should be primarily used to * initialize the state of the check box menu item. * Programmatically setting the state of the check box * menu item will not trigger - * an ItemEvent. The only way to trigger an - * ItemEvent is by user interaction. + * an {@code ItemEvent}. The only way to trigger an + * {@code ItemEvent} is by user interaction. * - * @param b true if the check box - * menu item is on, otherwise false + * @param b {@code true} if the check box + * menu item is on, otherwise {@code false} * @see #getState */ public synchronized void setState(boolean b) { @@ -265,7 +265,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * Returns an array of all the item listeners * registered on this checkbox menuitem. * - * @return all of this checkbox menuitem's ItemListeners + * @return all of this checkbox menuitem's {@code ItemListener}s * or an empty array if no item * listeners are currently registered * @@ -282,16 +282,16 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access /** * Returns an array of all the objects currently registered * as FooListeners - * upon this CheckboxMenuItem. + * upon this {@code CheckboxMenuItem}. * FooListeners are registered using the * addFooListener method. * *

          - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * CheckboxMenuItem c + * {@code CheckboxMenuItem c} * for its item listeners with the following code: * *

          ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));
          @@ -300,14 +300,14 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this checkbox menuitem, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @see #getItemListeners * @since 1.3 @@ -336,13 +336,13 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access /** * Processes events on this check box menu item. - * If the event is an instance of ItemEvent, - * this method invokes the processItemEvent method. + * If the event is an instance of {@code ItemEvent}, + * this method invokes the {@code processItemEvent} method. * If the event is not an item event, - * it invokes processEvent on the superclass. + * it invokes {@code processEvent} on the superclass. *

          * Check box menu items currently support only item events. - *

          Note that if the event parameter is null + *

          Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -361,17 +361,17 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access /** * Processes item events occurring on this check box menu item by - * dispatching them to any registered ItemListener objects. + * dispatching them to any registered {@code ItemListener} objects. *

          * This method is not called unless item events are * enabled for this menu item. Item events are enabled * when one of the following occurs: *

            - *
          • An ItemListener object is registered - * via addItemListener. - *
          • Item events are enabled via enableEvents. + *
          • An {@code ItemListener} object is registered + * via {@code addItemListener}. + *
          • Item events are enabled via {@code enableEvents}. *
          - *

          Note that if the event parameter is null + *

          Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -403,11 +403,11 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access /** * Returns a string representing the state of this - * CheckBoxMenuItem. This + * {@code CheckBoxMenuItem}. This * method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this check box menu item */ @@ -426,18 +426,18 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access /** * Writes default serializable fields to stream. Writes - * a list of serializable ItemListeners + * a list of serializable {@code ItemListeners} * as optional data. The non-serializable - * ItemListeners are detected and + * {@code ItemListeners} are detected and * no attempt is made to serialize them. * - * @param s the ObjectOutputStream to write - * @serialData null terminated sequence of - * 0 or more pairs; the pair consists of a String - * and an Object; the String indicates + * @param s the {@code ObjectOutputStream} to write + * @serialData {@code null} terminated sequence of + * 0 or more pairs; the pair consists of a {@code String} + * and an {@code Object}; the {@code String} indicates * the type of object and is one of the following: - * itemListenerK indicating an - * ItemListener object + * {@code itemListenerK} indicating an + * {@code ItemListener} object * * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) * @see java.awt.Component#itemListenerK @@ -453,12 +453,12 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access } /* - * Reads the ObjectInputStream and if it - * isn't null adds a listener to receive - * item events fired by the Checkbox menu item. + * Reads the {@code ObjectInputStream} and if it + * isn't {@code null} adds a listener to receive + * item events fired by the {@code Checkbox} menu item. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @serial * @see removeActionListener() * @see addActionListener() @@ -515,7 +515,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * subclassed by menu component developers. *

          * This class implements accessibility support for the - * CheckboxMenuItem class. It provides an implementation + * {@code CheckboxMenuItem} class. It provides an implementation * of the Java Accessibility API appropriate to checkbox menu item * user-interface elements. * @since 1.3 diff --git a/jdk/src/java.desktop/share/classes/java/awt/Choice.java b/jdk/src/java.desktop/share/classes/java/awt/Choice.java index d638e45a7a7..e12beb142c2 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Choice.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Choice.java @@ -36,7 +36,7 @@ import javax.accessibility.*; /** - * The Choice class presents a pop-up menu of choices. + * The {@code Choice} class presents a pop-up menu of choices. * The current choice is displayed as the title of the menu. *

          * The following code example produces a pop-up menu: @@ -54,17 +54,17 @@ import javax.accessibility.*; * The following text describes the graphic *

          - * In the picture, "Green" is the current choice. + * In the picture, {@code "Green"} is the current choice. * Pushing the mouse button down on the object causes a menu to * appear with the current choice highlighted. *

          * Some native platforms do not support arbitrary resizing of - * Choice components and the behavior of - * setSize()/getSize() is bound by + * {@code Choice} components and the behavior of + * {@code setSize()/getSize()} is bound by * such limitations. - * Native GUI Choice components' size are often bound by such + * Native GUI {@code Choice} components' size are often bound by such * attributes as font size and length of items contained within - * the Choice. + * the {@code Choice}. * * @author Sami Shaio * @author Arthur van Hoff @@ -72,8 +72,8 @@ import javax.accessibility.*; */ public class Choice extends Component implements ItemSelectable, Accessible { /** - * The items for the Choice. - * This can be a null value. + * The items for the {@code Choice}. + * This can be a {@code null} value. * @serial * @see #add(String) * @see #addItem(String) @@ -85,7 +85,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { Vector pItems; /** - * The index of the current choice for this Choice + * The index of the current choice for this {@code Choice} * or -1 if nothing is selected. * @serial * @see #getSelectedItem() @@ -117,7 +117,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { *

          * By default, the first item added to the choice menu becomes the * selected item, until a different selection is made by the user - * by calling one of the select methods. + * by calling one of the {@code select} methods. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -131,7 +131,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Constructs a name for this component. Called by - * getName when the name is null. + * {@code getName} when the name is {@code null}. */ String constructComponentName() { synchronized (Choice.class) { @@ -140,9 +140,9 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Creates the Choice's peer. This peer allows us + * Creates the {@code Choice}'s peer. This peer allows us * to change the look - * of the Choice without changing its functionality. + * of the {@code Choice} without changing its functionality. * @see java.awt.Component#getToolkit() */ public void addNotify() { @@ -154,9 +154,9 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Returns the number of items in this Choice menu. + * Returns the number of items in this {@code Choice} menu. * - * @return the number of items in this Choice menu + * @return the number of items in this {@code Choice} menu * @see #getItem * @since 1.1 */ @@ -169,7 +169,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { * * @return the number of items in this {@code Choice} menu * @deprecated As of JDK version 1.1, - * replaced by getItemCount(). + * replaced by {@code getItemCount()}. */ @Deprecated public int countItems() { @@ -178,7 +178,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Gets the string at the specified index in this - * Choice menu. + * {@code Choice} menu. * * @param index the index at which to begin * @return the item at the specified index @@ -197,10 +197,10 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Adds an item to this Choice menu. + * Adds an item to this {@code Choice} menu. * @param item the item to be added * @exception NullPointerException if the item's value is - * null + * {@code null} * @since 1.1 */ public void add(String item) { @@ -209,12 +209,12 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Obsolete as of Java 2 platform v1.1. Please use the - * add method instead. + * {@code add} method instead. *

          - * Adds an item to this Choice menu. + * Adds an item to this {@code Choice} menu. * @param item the item to be added * @exception NullPointerException if the item's value is equal to - * null + * {@code null} */ public void addItem(String item) { synchronized (this) { @@ -226,14 +226,14 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Inserts an item to this Choice, - * but does not invalidate the Choice. + * Inserts an item to this {@code Choice}, + * but does not invalidate the {@code Choice}. * Client methods must provide their own synchronization before * invoking this method. * @param item the item to be added * @param index the new item position * @exception NullPointerException if the item's value is equal to - * null + * {@code null} */ private void insertNoInvalidate(String item, int index) { if (item == null) { @@ -255,10 +255,10 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Inserts the item into this choice at the specified position. * Existing items at an index greater than or equal to - * index are shifted up by one to accommodate - * the new item. If index is greater than or + * {@code index} are shifted up by one to accommodate + * the new item. If {@code index} is greater than or * equal to the number of items in this choice, - * item is added to the end of this choice. + * {@code item} is added to the end of this choice. *

          * If the item is the first one being added to the choice, * then the item becomes selected. Otherwise, if the @@ -266,7 +266,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { * item in the choice becomes the selected item. If the * selected item was no among those shifted, it remains * the selected item. - * @param item the non-null item to be inserted + * @param item the non-{@code null} item to be inserted * @param index the position at which the item should be inserted * @exception IllegalArgumentException if index is less than 0 */ @@ -286,14 +286,14 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Removes the first occurrence of item - * from the Choice menu. If the item + * Removes the first occurrence of {@code item} + * from the {@code Choice} menu. If the item * being removed is the currently selected item, * then the first item in the choice becomes the * selected item. Otherwise, the currently selected * item remains selected (and the selected index is * updated accordingly). - * @param item the item to remove from this Choice menu + * @param item the item to remove from this {@code Choice} menu * @exception IllegalArgumentException if the item doesn't * exist in the choice menu * @since 1.1 @@ -336,8 +336,8 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Removes an item from the Choice at the - * specified position, but does not invalidate the Choice. + * Removes an item from the {@code Choice} at the + * specified position, but does not invalidate the {@code Choice}. * Client methods must provide their * own synchronization before invoking this method. * @param position the position of the item @@ -389,7 +389,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Returns an array (length 1) containing the currently selected - * item. If this choice has no items, returns null. + * item. If this choice has no items, returns {@code null}. * @see ItemSelectable */ public synchronized Object[] getSelectedObjects() { @@ -414,14 +414,14 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Sets the selected item in this Choice menu to be the + * Sets the selected item in this {@code Choice} menu to be the * item at the specified position. * *

          Note that this method should be primarily used to * initially select an item in this component. * Programmatically calling this method will not trigger - * an ItemEvent. The only way to trigger an - * ItemEvent is by user interaction. + * an {@code ItemEvent}. The only way to trigger an + * {@code ItemEvent} is by user interaction. * * @param pos the position of the selected item * @exception IllegalArgumentException if the specified @@ -444,7 +444,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Sets the selected item in this Choice menu + * Sets the selected item in this {@code Choice} menu * to be the item whose name is equal to the specified string. * If more than one item matches (is equal to) the specified string, * the one with the smallest index is selected. @@ -452,8 +452,8 @@ public class Choice extends Component implements ItemSelectable, Accessible { *

          Note that this method should be primarily used to * initially select an item in this component. * Programmatically calling this method will not trigger - * an ItemEvent. The only way to trigger an - * ItemEvent is by user interaction. + * an {@code ItemEvent}. The only way to trigger an + * {@code ItemEvent} is by user interaction. * * @param str the specified string * @see #getSelectedItem @@ -468,9 +468,9 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Adds the specified item listener to receive item events from - * this Choice menu. Item events are sent in response - * to user input, but not in response to calls to select. - * If l is null, no exception is thrown and no action + * this {@code Choice} menu. Item events are sent in response + * to user input, but not in response to calls to {@code select}. + * If l is {@code null}, no exception is thrown and no action * is performed. *

          Refer to AWT Threading Issues for details on AWT's threading model. @@ -492,8 +492,8 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Removes the specified item listener so that it no longer receives - * item events from this Choice menu. - * If l is null, no exception is thrown and no + * item events from this {@code Choice} menu. + * If l is {@code null}, no exception is thrown and no * action is performed. *

          Refer to AWT Threading Issues for details on AWT's threading model. @@ -515,7 +515,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { * Returns an array of all the item listeners * registered on this choice. * - * @return all of this choice's ItemListeners + * @return all of this choice's {@code ItemListener}s * or an empty array if no item * listeners are currently registered * @@ -532,16 +532,16 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Returns an array of all the objects currently registered * as FooListeners - * upon this Choice. + * upon this {@code Choice}. * FooListeners are registered using the * addFooListener method. * *

          - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * Choice c + * {@code Choice c} * for its item listeners with the following code: * *

          ItemListener[] ils = (ItemListener[])(c.getListeners(ItemListener.class));
          @@ -550,14 +550,14 @@ public class Choice extends Component implements ItemSelectable, Accessible { * * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this choice, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @see #getItemListeners * @since 1.3 @@ -586,10 +586,10 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Processes events on this choice. If the event is an - * instance of ItemEvent, it invokes the - * processItemEvent method. Otherwise, it calls its - * superclass's processEvent method. - *

          Note that if the event parameter is null + * instance of {@code ItemEvent}, it invokes the + * {@code processItemEvent} method. Otherwise, it calls its + * superclass's {@code processEvent} method. + *

          Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -607,19 +607,19 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Processes item events occurring on this Choice + * Processes item events occurring on this {@code Choice} * menu by dispatching them to any registered - * ItemListener objects. + * {@code ItemListener} objects. *

          * This method is not called unless item events are * enabled for this component. Item events are enabled * when one of the following occurs: *

            - *
          • An ItemListener object is registered - * via addItemListener. - *
          • Item events are enabled via enableEvents. + *
          • An {@code ItemListener} object is registered + * via {@code addItemListener}. + *
          • Item events are enabled via {@code enableEvents}. *
          - *

          Note that if the event parameter is null + *

          Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -638,13 +638,13 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Returns a string representing the state of this Choice + * Returns a string representing the state of this {@code Choice} * menu. This method is intended to be used only for debugging purposes, * and the content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * - * @return the parameter string of this Choice menu + * @return the parameter string of this {@code Choice} menu */ protected String paramString() { return super.paramString() + ",current=" + getSelectedItem(); @@ -662,18 +662,18 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Writes default serializable fields to stream. Writes - * a list of serializable ItemListeners + * a list of serializable {@code ItemListeners} * as optional data. The non-serializable - * ItemListeners are detected and + * {@code ItemListeners} are detected and * no attempt is made to serialize them. * - * @param s the ObjectOutputStream to write - * @serialData null terminated sequence of 0 - * or more pairs; the pair consists of a String - * and an Object; the String indicates + * @param s the {@code ObjectOutputStream} to write + * @serialData {@code null} terminated sequence of 0 + * or more pairs; the pair consists of a {@code String} + * and an {@code Object}; the {@code String} indicates * the type of object and is one of the following: - * itemListenerK indicating an - * ItemListener object + * {@code itemListenerK} indicating an + * {@code ItemListener} object * * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) * @see java.awt.Component#itemListenerK @@ -689,15 +689,15 @@ public class Choice extends Component implements ItemSelectable, Accessible { } /** - * Reads the ObjectInputStream and if it - * isn't null adds a listener to receive - * item events fired by the Choice item. + * Reads the {@code ObjectInputStream} and if it + * isn't {@code null} adds a listener to receive + * item events fired by the {@code Choice} item. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns - * true + * {@code GraphicsEnvironment.isHeadless} returns + * {@code true} * @serial * @see #removeItemListener(ItemListener) * @see #addItemListener(ItemListener) @@ -733,14 +733,14 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** - * Gets the AccessibleContext associated with this - * Choice. For Choice components, - * the AccessibleContext takes the form of an - * AccessibleAWTChoice. A new AccessibleAWTChoice + * Gets the {@code AccessibleContext} associated with this + * {@code Choice}. For {@code Choice} components, + * the {@code AccessibleContext} takes the form of an + * {@code AccessibleAWTChoice}. A new {@code AccessibleAWTChoice} * instance is created if necessary. * - * @return an AccessibleAWTChoice that serves as the - * AccessibleContext of this Choice + * @return an {@code AccessibleAWTChoice} that serves as the + * {@code AccessibleContext} of this {@code Choice} * @since 1.3 */ public AccessibleContext getAccessibleContext() { @@ -752,7 +752,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * This class implements accessibility support for the - * Choice class. It provides an implementation of the + * {@code Choice} class. It provides an implementation of the * Java Accessibility API appropriate to choice user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Color.java b/jdk/src/java.desktop/share/classes/java/awt/Color.java index da62fc631da..559a429ef22 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Color.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Color.java @@ -32,7 +32,7 @@ import java.awt.geom.Rectangle2D; import java.awt.color.ColorSpace; /** - * The Color class is used to encapsulate colors in the default + * The {@code Color} class is used to encapsulate colors in the default * sRGB color space or colors in arbitrary color spaces identified by a * {@link ColorSpace}. Every color has an implicit alpha value of 1.0 or * an explicit one provided in the constructor. The alpha value @@ -41,8 +41,8 @@ import java.awt.color.ColorSpace; * An alpha value of 1.0 or 255 means that the color is completely * opaque and an alpha value of 0 or 0.0 means that the color is * completely transparent. - * When constructing a Color with an explicit alpha or - * getting the color/alpha components of a Color, the color + * When constructing a {@code Color} with an explicit alpha or + * getting the color/alpha components of a {@code Color}, the color * components are never premultiplied by the alpha component. *

          * The default color space for the Java 2D(tm) API is sRGB, a proposed @@ -210,11 +210,11 @@ public class Color implements Paint, java.io.Serializable { int value; /** - * The color value in the default sRGB ColorSpace as - * float components (no alpha). - * If null after object construction, this must be an + * The color value in the default sRGB {@code ColorSpace} as + * {@code float} components (no alpha). + * If {@code null} after object construction, this must be an * sRGB color constructed with 8-bit precision, so compute from the - * int color value. + * {@code int} color value. * @serial * @see #getRGBColorComponents * @see #getRGBComponents @@ -222,11 +222,11 @@ public class Color implements Paint, java.io.Serializable { private float frgbvalue[] = null; /** - * The color value in the native ColorSpace as - * float components (no alpha). - * If null after object construction, this must be an + * The color value in the native {@code ColorSpace} as + * {@code float} components (no alpha). + * If {@code null} after object construction, this must be an * sRGB color constructed with 8-bit precision, so compute from the - * int color value. + * {@code int} color value. * @serial * @see #getRGBColorComponents * @see #getRGBComponents @@ -234,9 +234,9 @@ public class Color implements Paint, java.io.Serializable { private float fvalue[] = null; /** - * The alpha value as a float component. - * If frgbvalue is null, this is not valid - * data, so compute from the int color value. + * The alpha value as a {@code float} component. + * If {@code frgbvalue} is {@code null}, this is not valid + * data, so compute from the {@code int} color value. * @serial * @see #getRGBComponents * @see #getComponents @@ -244,7 +244,7 @@ public class Color implements Paint, java.io.Serializable { private float falpha = 0.0f; /** - * The ColorSpace. If null, then it's + * The {@code ColorSpace}. If {@code null}, then it's * default is sRGB. * @serial * @see #getColor @@ -313,9 +313,9 @@ public class Color implements Paint, java.io.Serializable { } /** - * Checks the color float components supplied for + * Checks the color {@code float} components supplied for * validity. - * Throws an IllegalArgumentException if the value is out + * Throws an {@code IllegalArgumentException} if the value is out * of range. * @param r the Red component * @param g the Green component @@ -354,8 +354,8 @@ public class Color implements Paint, java.io.Serializable { * available for a given output device. * Alpha is defaulted to 255. * - * @throws IllegalArgumentException if r, g - * or b are outside of the range + * @throws IllegalArgumentException if {@code r}, {@code g} + * or {@code b} are outside of the range * 0 to 255, inclusive * @param r the red component * @param g the green component @@ -373,8 +373,8 @@ public class Color implements Paint, java.io.Serializable { * Creates an sRGB color with the specified red, green, blue, and alpha * values in the range (0 - 255). * - * @throws IllegalArgumentException if r, g, - * b or a are outside of the range + * @throws IllegalArgumentException if {@code r}, {@code g}, + * {@code b} or {@code a} are outside of the range * 0 to 255, inclusive * @param r the red component * @param g the green component @@ -418,12 +418,12 @@ public class Color implements Paint, java.io.Serializable { * Creates an sRGB color with the specified combined RGBA value consisting * of the alpha component in bits 24-31, the red component in bits 16-23, * the green component in bits 8-15, and the blue component in bits 0-7. - * If the hasalpha argument is false, alpha + * If the {@code hasalpha} argument is {@code false}, alpha * is defaulted to 255. * * @param rgba the combined RGBA components - * @param hasalpha true if the alpha bits are valid; - * false otherwise + * @param hasalpha {@code true} if the alpha bits are valid; + * {@code false} otherwise * @see java.awt.image.ColorModel#getRGBdefault * @see #getRed * @see #getGreen @@ -446,8 +446,8 @@ public class Color implements Paint, java.io.Serializable { * match given the color space available for a particular output * device. * - * @throws IllegalArgumentException if r, g - * or b are outside of the range + * @throws IllegalArgumentException if {@code r}, {@code g} + * or {@code b} are outside of the range * 0.0 to 1.0, inclusive * @param r the red component * @param g the green component @@ -473,8 +473,8 @@ public class Color implements Paint, java.io.Serializable { * alpha values in the range (0.0 - 1.0). The actual color * used in rendering depends on finding the best match given the * color space available for a particular output device. - * @throws IllegalArgumentException if r, g - * b or a are outside of the range + * @throws IllegalArgumentException if {@code r}, {@code g} + * {@code b} or {@code a} are outside of the range * 0.0 to 1.0, inclusive * @param r the red component * @param g the green component @@ -497,19 +497,19 @@ public class Color implements Paint, java.io.Serializable { } /** - * Creates a color in the specified ColorSpace - * with the color components specified in the float + * Creates a color in the specified {@code ColorSpace} + * with the color components specified in the {@code float} * array and the specified alpha. The number of components is - * determined by the type of the ColorSpace. For + * determined by the type of the {@code ColorSpace}. For * example, RGB requires 3 components, but CMYK requires 4 * components. - * @param cspace the ColorSpace to be used to + * @param cspace the {@code ColorSpace} to be used to * interpret the components * @param components an arbitrary number of color components - * that is compatible with the ColorSpace + * that is compatible with the {@code ColorSpace} * @param alpha alpha value * @throws IllegalArgumentException if any of the values in the - * components array or alpha is + * {@code components} array or {@code alpha} is * outside of the range 0.0 to 1.0 * @see #getComponents * @see #getColorComponents @@ -592,7 +592,7 @@ public class Color implements Paint, java.io.Serializable { * (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are * blue). * @return the RGB value of the color in the default sRGB - * ColorModel. + * {@code ColorModel}. * @see java.awt.image.ColorModel#getRGBdefault * @see #getRed * @see #getGreen @@ -606,19 +606,19 @@ public class Color implements Paint, java.io.Serializable { private static final double FACTOR = 0.7; /** - * Creates a new Color that is a brighter version of this - * Color. + * Creates a new {@code Color} that is a brighter version of this + * {@code Color}. *

          * This method applies an arbitrary scale factor to each of the three RGB - * components of this Color to create a brighter version - * of this Color. + * components of this {@code Color} to create a brighter version + * of this {@code Color}. * The {@code alpha} value is preserved. - * Although brighter and - * darker are inverse operations, the results of a + * Although {@code brighter} and + * {@code darker} are inverse operations, the results of a * series of invocations of these two methods might be inconsistent * because of rounding errors. - * @return a new Color object that is - * a brighter version of this Color + * @return a new {@code Color} object that is + * a brighter version of this {@code Color} * with the same {@code alpha} value. * @see java.awt.Color#darker * @since 1.0 @@ -649,19 +649,19 @@ public class Color implements Paint, java.io.Serializable { } /** - * Creates a new Color that is a darker version of this - * Color. + * Creates a new {@code Color} that is a darker version of this + * {@code Color}. *

          * This method applies an arbitrary scale factor to each of the three RGB - * components of this Color to create a darker version of - * this Color. + * components of this {@code Color} to create a darker version of + * this {@code Color}. * The {@code alpha} value is preserved. - * Although brighter and - * darker are inverse operations, the results of a series + * Although {@code brighter} and + * {@code darker} are inverse operations, the results of a series * of invocations of these two methods might be inconsistent because * of rounding errors. - * @return a new Color object that is - * a darker version of this Color + * @return a new {@code Color} object that is + * a darker version of this {@code Color} * with the same {@code alpha} value. * @see java.awt.Color#brighter * @since 1.0 @@ -674,7 +674,7 @@ public class Color implements Paint, java.io.Serializable { } /** - * Computes the hash code for this Color. + * Computes the hash code for this {@code Color}. * @return a hash code value for this object. * @since 1.0 */ @@ -684,15 +684,15 @@ public class Color implements Paint, java.io.Serializable { /** * Determines whether another object is equal to this - * Color. + * {@code Color}. *

          - * The result is true if and only if the argument is not - * null and is a Color object that has the same + * The result is {@code true} if and only if the argument is not + * {@code null} and is a {@code Color} object that has the same * red, green, blue, and alpha values as this object. * @param obj the object to test for equality with this - * Color - * @return true if the objects are the same; - * false otherwise. + * {@code Color} + * @return {@code true} if the objects are the same; + * {@code false} otherwise. * @since 1.0 */ public boolean equals(Object obj) { @@ -700,25 +700,25 @@ public class Color implements Paint, java.io.Serializable { } /** - * Returns a string representation of this Color. This + * Returns a string representation of this {@code Color}. This * method is intended to be used only for debugging purposes. The * content and format of the returned string might vary between * implementations. The returned string might be empty but cannot - * be null. + * be {@code null}. * - * @return a string representation of this Color. + * @return a string representation of this {@code Color}. */ public String toString() { return getClass().getName() + "[r=" + getRed() + ",g=" + getGreen() + ",b=" + getBlue() + "]"; } /** - * Converts a String to an integer and returns the - * specified opaque Color. This method handles string + * Converts a {@code String} to an integer and returns the + * specified opaque {@code Color}. This method handles string * formats that are used to represent octal and hexadecimal numbers. - * @param nm a String that represents + * @param nm a {@code String} that represents * an opaque color as a 24-bit integer - * @return the new Color object. + * @return the new {@code Color} object. * @see java.lang.Integer#decode * @exception NumberFormatException if the specified string cannot * be interpreted as a decimal, @@ -736,13 +736,13 @@ public class Color implements Paint, java.io.Serializable { *

          * The argument is treated as the name of a system property to * be obtained. The string value of this property is then interpreted - * as an integer which is then converted to a Color + * as an integer which is then converted to a {@code Color} * object. *

          * If the specified property is not found or could not be parsed as - * an integer then null is returned. + * an integer then {@code null} is returned. * @param nm the name of the color property - * @return the Color converted from the system + * @return the {@code Color} converted from the system * property. * @see java.lang.System#getProperty(java.lang.String) * @see java.lang.Integer#getInteger(java.lang.String) @@ -758,16 +758,16 @@ public class Color implements Paint, java.io.Serializable { *

          * The first argument is treated as the name of a system property to * be obtained. The string value of this property is then interpreted - * as an integer which is then converted to a Color + * as an integer which is then converted to a {@code Color} * object. *

          * If the specified property is not found or cannot be parsed as - * an integer then the Color specified by the second + * an integer then the {@code Color} specified by the second * argument is returned instead. * @param nm the name of the color property - * @param v the default Color - * @return the Color converted from the system - * property, or the specified Color. + * @param v the default {@code Color} + * @return the {@code Color} converted from the system + * property, or the specified {@code Color}. * @see java.lang.System#getProperty(java.lang.String) * @see java.lang.Integer#getInteger(java.lang.String) * @see java.awt.Color#Color(int) @@ -787,16 +787,16 @@ public class Color implements Paint, java.io.Serializable { *

          * The first argument is treated as the name of a system property to * be obtained. The string value of this property is then interpreted - * as an integer which is then converted to a Color + * as an integer which is then converted to a {@code Color} * object. *

          * If the specified property is not found or could not be parsed as - * an integer then the integer value v is used instead, - * and is converted to a Color object. + * an integer then the integer value {@code v} is used instead, + * and is converted to a {@code Color} object. * @param nm the name of the color property * @param v the default color value, as an integer - * @return the Color converted from the system - * property or the Color converted from + * @return the {@code Color} converted from the system + * property or the {@code Color} converted from * the specified integer. * @see java.lang.System#getProperty(java.lang.String) * @see java.lang.Integer#getInteger(java.lang.String) @@ -813,19 +813,19 @@ public class Color implements Paint, java.io.Serializable { * Converts the components of a color, as specified by the HSB * model, to an equivalent set of values for the default RGB model. *

          - * The saturation and brightness components + * The {@code saturation} and {@code brightness} components * should be floating-point values between zero and one - * (numbers in the range 0.0-1.0). The hue component + * (numbers in the range 0.0-1.0). The {@code hue} component * can be any floating-point number. The floor of this number is * subtracted from it to create a fraction between 0 and 1. This * fractional number is then multiplied by 360 to produce the hue * angle in the HSB color model. *

          - * The integer that is returned by HSBtoRGB encodes the + * The integer that is returned by {@code HSBtoRGB} encodes the * value of a color in bits 0-23 of an integer value that is the same * format used by the method {@link #getRGB() getRGB}. * This integer can be supplied as an argument to the - * Color constructor that takes a single integer argument. + * {@code Color} constructor that takes a single integer argument. * @param hue the hue component of the color * @param saturation the saturation of the color * @param brightness the brightness of the color @@ -887,15 +887,15 @@ public class Color implements Paint, java.io.Serializable { * model, to an equivalent set of values for hue, saturation, and * brightness that are the three components of the HSB model. *

          - * If the hsbvals argument is null, then a + * If the {@code hsbvals} argument is {@code null}, then a * new array is allocated to return the result. Otherwise, the method - * returns the array hsbvals, with the values put into + * returns the array {@code hsbvals}, with the values put into * that array. * @param r the red component of the color * @param g the green component of the color * @param b the blue component of the color * @param hsbvals the array used to return the - * three HSB values, or null + * three HSB values, or {@code null} * @return an array of three elements containing the hue, saturation, * and brightness (in that order), of the color with * the indicated red, green, and blue components. @@ -942,12 +942,12 @@ public class Color implements Paint, java.io.Serializable { } /** - * Creates a Color object based on the specified values + * Creates a {@code Color} object based on the specified values * for the HSB color model. *

          - * The s and b components should be + * The {@code s} and {@code b} components should be * floating-point values between zero and one - * (numbers in the range 0.0-1.0). The h component + * (numbers in the range 0.0-1.0). The {@code h} component * can be any floating-point number. The floor of this number is * subtracted from it to create a fraction between 0 and 1. This * fractional number is then multiplied by 360 to produce the hue @@ -955,7 +955,7 @@ public class Color implements Paint, java.io.Serializable { * @param h the hue component * @param s the saturation of the color * @param b the brightness of the color - * @return a Color object with the specified hue, + * @return a {@code Color} object with the specified hue, * saturation, and brightness. * @since 1.0 */ @@ -964,16 +964,16 @@ public class Color implements Paint, java.io.Serializable { } /** - * Returns a float array containing the color and alpha - * components of the Color, as represented in the default + * Returns a {@code float} array containing the color and alpha + * components of the {@code Color}, as represented in the default * sRGB color space. - * If compArray is null, an array of length + * If {@code compArray} is {@code null}, an array of length * 4 is created for the return value. Otherwise, - * compArray must have length 4 or greater, + * {@code compArray} must have length 4 or greater, * and it is filled in with the components and returned. * @param compArray an array that this method fills with * color and alpha components and returns - * @return the RGBA components in a float array. + * @return the RGBA components in a {@code float} array. */ public float[] getRGBComponents(float[] compArray) { float[] f; @@ -997,15 +997,15 @@ public class Color implements Paint, java.io.Serializable { } /** - * Returns a float array containing only the color - * components of the Color, in the default sRGB color - * space. If compArray is null, an array of + * Returns a {@code float} array containing only the color + * components of the {@code Color}, in the default sRGB color + * space. If {@code compArray} is {@code null}, an array of * length 3 is created for the return value. Otherwise, - * compArray must have length 3 or greater, and it is + * {@code compArray} must have length 3 or greater, and it is * filled in with the components and returned. * @param compArray an array that this method fills with color * components and returns - * @return the RGB components in a float array. + * @return the RGB components in a {@code float} array. */ public float[] getRGBColorComponents(float[] compArray) { float[] f; @@ -1027,19 +1027,19 @@ public class Color implements Paint, java.io.Serializable { } /** - * Returns a float array containing the color and alpha - * components of the Color, in the - * ColorSpace of the Color. - * If compArray is null, an array with + * Returns a {@code float} array containing the color and alpha + * components of the {@code Color}, in the + * {@code ColorSpace} of the {@code Color}. + * If {@code compArray} is {@code null}, an array with * length equal to the number of components in the associated - * ColorSpace plus one is created for - * the return value. Otherwise, compArray must have at + * {@code ColorSpace} plus one is created for + * the return value. Otherwise, {@code compArray} must have at * least this length and it is filled in with the components and * returned. * @param compArray an array that this method fills with the color and - * alpha components of this Color in its - * ColorSpace and returns - * @return the color and alpha components in a float + * alpha components of this {@code Color} in its + * {@code ColorSpace} and returns + * @return the color and alpha components in a {@code float} * array. */ public float[] getComponents(float[] compArray) { @@ -1060,19 +1060,19 @@ public class Color implements Paint, java.io.Serializable { } /** - * Returns a float array containing only the color - * components of the Color, in the - * ColorSpace of the Color. - * If compArray is null, an array with + * Returns a {@code float} array containing only the color + * components of the {@code Color}, in the + * {@code ColorSpace} of the {@code Color}. + * If {@code compArray} is {@code null}, an array with * length equal to the number of components in the associated - * ColorSpace is created for - * the return value. Otherwise, compArray must have at + * {@code ColorSpace} is created for + * the return value. Otherwise, {@code compArray} must have at * least this length and it is filled in with the components and * returned. * @param compArray an array that this method fills with the color - * components of this Color in its - * ColorSpace and returns - * @return the color components in a float array. + * components of this {@code Color} in its + * {@code ColorSpace} and returns + * @return the color components in a {@code float} array. */ public float[] getColorComponents(float[] compArray) { if (fvalue == null) @@ -1091,19 +1091,19 @@ public class Color implements Paint, java.io.Serializable { } /** - * Returns a float array containing the color and alpha - * components of the Color, in the - * ColorSpace specified by the cspace - * parameter. If compArray is null, an + * Returns a {@code float} array containing the color and alpha + * components of the {@code Color}, in the + * {@code ColorSpace} specified by the {@code cspace} + * parameter. If {@code compArray} is {@code null}, an * array with length equal to the number of components in - * cspace plus one is created for the return value. - * Otherwise, compArray must have at least this + * {@code cspace} plus one is created for the return value. + * Otherwise, {@code compArray} must have at least this * length, and it is filled in with the components and returned. - * @param cspace a specified ColorSpace + * @param cspace a specified {@code ColorSpace} * @param compArray an array that this method fills with the - * color and alpha components of this Color in - * the specified ColorSpace and returns - * @return the color and alpha components in a float + * color and alpha components of this {@code Color} in + * the specified {@code ColorSpace} and returns + * @return the color and alpha components in a {@code float} * array. */ public float[] getComponents(ColorSpace cspace, float[] compArray) { @@ -1136,19 +1136,19 @@ public class Color implements Paint, java.io.Serializable { } /** - * Returns a float array containing only the color - * components of the Color in the - * ColorSpace specified by the cspace - * parameter. If compArray is null, an array + * Returns a {@code float} array containing only the color + * components of the {@code Color} in the + * {@code ColorSpace} specified by the {@code cspace} + * parameter. If {@code compArray} is {@code null}, an array * with length equal to the number of components in - * cspace is created for the return value. Otherwise, - * compArray must have at least this length, and it is + * {@code cspace} is created for the return value. Otherwise, + * {@code compArray} must have at least this length, and it is * filled in with the components and returned. - * @param cspace a specified ColorSpace + * @param cspace a specified {@code ColorSpace} * @param compArray an array that this method fills with the color - * components of this Color in the specified - * ColorSpace - * @return the color components in a float array. + * components of this {@code Color} in the specified + * {@code ColorSpace} + * @return the color components in a {@code float} array. */ public float[] getColorComponents(ColorSpace cspace, float[] compArray) { if (cs == null) { @@ -1175,8 +1175,8 @@ public class Color implements Paint, java.io.Serializable { } /** - * Returns the ColorSpace of this Color. - * @return this Color object's ColorSpace. + * Returns the {@code ColorSpace} of this {@code Color}. + * @return this {@code Color} object's {@code ColorSpace}. */ public ColorSpace getColorSpace() { if (cs == null) { @@ -1221,9 +1221,9 @@ public class Color implements Paint, java.io.Serializable { } /** - * Returns the transparency mode for this Color. This is - * required to implement the Paint interface. - * @return this Color object's transparency mode. + * Returns the transparency mode for this {@code Color}. This is + * required to implement the {@code Paint} interface. + * @return this {@code Color} object's transparency mode. * @see Paint * @see Transparency * @see #createContext diff --git a/jdk/src/java.desktop/share/classes/java/awt/ColorPaintContext.java b/jdk/src/java.desktop/share/classes/java/awt/ColorPaintContext.java index ae881445a3a..15e296cf525 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ColorPaintContext.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ColorPaintContext.java @@ -50,7 +50,7 @@ class ColorPaintContext implements PaintContext { * (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are * blue). * @return the RGB value of the color in the default sRGB - * ColorModel. + * {@code ColorModel}. * @see java.awt.image.ColorModel#getRGBdefault * @see #getRed * @see #getGreen diff --git a/jdk/src/java.desktop/share/classes/java/awt/Component.java b/jdk/src/java.desktop/share/classes/java/awt/Component.java index 1d80c9e01e0..663c5f909be 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Component.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java @@ -89,9 +89,9 @@ import sun.util.logging.PlatformLogger; * that can be displayed on the screen and that can interact with the * user. Examples of components are the buttons, checkboxes, and scrollbars * of a typical graphical user interface.

          - * The Component class is the abstract superclass of + * The {@code Component} class is the abstract superclass of * the nonmenu-related Abstract Window Toolkit components. Class - * Component can also be extended directly to create a + * {@code Component} can also be extended directly to create a * lightweight component. A lightweight component is a component that is * not associated with a native window. On the contrary, a heavyweight * component is associated with a native window. The {@link #isLightweight()} @@ -107,10 +107,10 @@ import sun.util.logging.PlatformLogger; * *

          Serialization

          * It is important to note that only AWT listeners which conform - * to the Serializable protocol will be saved when + * to the {@code Serializable} protocol will be saved when * the object is stored. If an AWT object has listeners that * aren't marked serializable, they will be dropped at - * writeObject time. Developers will need, as always, + * {@code writeObject} time. Developers will need, as always, * to consider the implications of making an object serializable. * One situation to watch out for is this: *
          @@ -136,12 +136,12 @@ import sun.util.logging.PlatformLogger;
            *        }
            *    }
            * 
          - * In this example, serializing aButton by itself - * will cause MyApp and everything it refers to + * In this example, serializing {@code aButton} by itself + * will cause {@code MyApp} and everything it refers to * to be serialized as well. The problem is that the listener * is serializable by coincidence, not by design. To separate - * the decisions about MyApp and the - * ActionListener being serializable one can use a + * the decisions about {@code MyApp} and the + * {@code ActionListener} being serializable one can use a * nested class, as in the following example: *
            *    import java.awt.*;
          @@ -194,7 +194,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
           
               /**
                * The peer of the component. The peer implements the component's
          -     * behavior. The peer is set when the Component is
          +     * behavior. The peer is set when the {@code Component} is
                * added to a container that also is a peer.
                * @see #addNotify
                * @see #removeNotify
          @@ -202,14 +202,14 @@ public abstract class Component implements ImageObserver, MenuContainer,
               transient volatile ComponentPeer peer;
           
               /**
          -     * The parent of the object. It may be null
          +     * The parent of the object. It may be {@code null}
                * for top-level components.
                * @see #getParent
                */
               transient Container parent;
           
               /**
          -     * The AppContext of the component. Applets/Plugin may
          +     * The {@code AppContext} of the component. Applets/Plugin may
                * change the AppContext.
                */
               transient AppContext appContext;
          @@ -248,7 +248,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
           
               /**
                * The foreground color for this component.
          -     * foreground can be null.
          +     * {@code foreground} can be {@code null}.
                *
                * @serial
                * @see #getForeground
          @@ -258,7 +258,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
           
               /**
                * The background color for this component.
          -     * background can be null.
          +     * {@code background} can be {@code null}.
                *
                * @serial
                * @see #getBackground
          @@ -268,7 +268,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
           
               /**
                * The font used by this component.
          -     * The font can be null.
          +     * The {@code font} can be {@code null}.
                *
                * @serial
                * @see #getFont
          @@ -278,13 +278,13 @@ public abstract class Component implements ImageObserver, MenuContainer,
           
               /**
                * The font which the peer is currently using.
          -     * (null if no peer exists.)
          +     * ({@code null} if no peer exists.)
                */
               Font        peerFont;
           
               /**
                * The cursor displayed when pointer is over this component.
          -     * This value can be null.
          +     * This value can be {@code null}.
                *
                * @serial
                * @see #getCursor
          @@ -302,10 +302,10 @@ public abstract class Component implements ImageObserver, MenuContainer,
               Locale      locale;
           
               /**
          -     * A reference to a GraphicsConfiguration object
          +     * A reference to a {@code GraphicsConfiguration} object
                * used to describe the characteristics of a graphics
                * destination.
          -     * This value can be null.
          +     * This value can be {@code null}.
                *
                * @since 1.3
                * @serial
          @@ -315,7 +315,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
               private transient volatile GraphicsConfiguration graphicsConfig;
           
               /**
          -     * A reference to a BufferStrategy object
          +     * A reference to a {@code BufferStrategy} object
                * used to manipulate the buffers on this component.
                *
                * @since 1.4
          @@ -367,7 +367,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
               private volatile boolean valid = false;
           
               /**
          -     * The DropTarget associated with this component.
          +     * The {@code DropTarget} associated with this component.
                *
                * @since 1.2
                * @serial
          @@ -384,7 +384,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
           
               /**
                * A component's name.
          -     * This field can be null.
          +     * This field can be {@code null}.
                *
                * @serial
                * @see #getName
          @@ -394,7 +394,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
           
               /**
                * A bool to determine whether the name has
          -     * been set explicitly. nameExplicitlySet will
          +     * been set explicitly. {@code nameExplicitlySet} will
                * be false if the name has not been set and
                * true if it has.
                *
          @@ -523,7 +523,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
               = ComponentOrientation.UNKNOWN;
           
               /**
          -     * newEventsOnly will be true if the event is
          +     * {@code newEventsOnly} will be true if the event is
                * one of the event types enabled for the component.
                * It will then allow for normal processing to
                * continue.  If it is false the event is passed
          @@ -565,13 +565,13 @@ public abstract class Component implements ImageObserver, MenuContainer,
               static final String windowFocusListenerK = "windowFocusL";
           
               /**
          -     * The eventMask is ONLY set by subclasses via
          -     * enableEvents.
          +     * The {@code eventMask} is ONLY set by subclasses via
          +     * {@code enableEvents}.
                * The mask should NOT be set when listeners are registered
                * so that we can distinguish the difference between when
                * listeners request events and subclasses request them.
                * One bit is used to indicate whether input methods are
          -     * enabled; this bit is set by enableInputMethods and is
          +     * enabled; this bit is set by {@code enableInputMethods} and is
                * on by default.
                *
                * @serial
          @@ -604,15 +604,15 @@ public abstract class Component implements ImageObserver, MenuContainer,
               }
           
               /**
          -     * Ease-of-use constant for getAlignmentY().
          +     * Ease-of-use constant for {@code getAlignmentY()}.
                * Specifies an alignment to the top of the component.
                * @see     #getAlignmentY
                */
               public static final float TOP_ALIGNMENT = 0.0f;
           
               /**
          -     * Ease-of-use constant for getAlignmentY and
          -     * getAlignmentX. Specifies an alignment to
          +     * Ease-of-use constant for {@code getAlignmentY} and
          +     * {@code getAlignmentX}. Specifies an alignment to
                * the center of the component
                * @see     #getAlignmentX
                * @see     #getAlignmentY
          @@ -620,21 +620,21 @@ public abstract class Component implements ImageObserver, MenuContainer,
               public static final float CENTER_ALIGNMENT = 0.5f;
           
               /**
          -     * Ease-of-use constant for getAlignmentY.
          +     * Ease-of-use constant for {@code getAlignmentY}.
                * Specifies an alignment to the bottom of the component.
                * @see     #getAlignmentY
                */
               public static final float BOTTOM_ALIGNMENT = 1.0f;
           
               /**
          -     * Ease-of-use constant for getAlignmentX.
          +     * Ease-of-use constant for {@code getAlignmentX}.
                * Specifies an alignment to the left side of the component.
                * @see     #getAlignmentX
                */
               public static final float LEFT_ALIGNMENT = 0.0f;
           
               /**
          -     * Ease-of-use constant for getAlignmentX.
          +     * Ease-of-use constant for {@code getAlignmentX}.
                * Specifies an alignment to the right side of the component.
                * @see     #getAlignmentX
                */
          @@ -646,8 +646,8 @@ public abstract class Component implements ImageObserver, MenuContainer,
               private static final long serialVersionUID = -7644114512714619750L;
           
               /**
          -     * If any PropertyChangeListeners have been registered,
          -     * the changeSupport field describes them.
          +     * If any {@code PropertyChangeListeners} have been registered,
          +     * the {@code changeSupport} field describes them.
                *
                * @serial
                * @since 1.2
          @@ -705,8 +705,8 @@ public abstract class Component implements ImageObserver, MenuContainer,
                * size; not a developer specified minimum size).  For sizes
                * smaller than the minimum size the baseline may change in a way
                * other than the baseline resize behavior indicates.  Similarly,
          -     * as the size approaches Integer.MAX_VALUE and/or
          -     * Short.MAX_VALUE the baseline may change in a way
          +     * as the size approaches {@code Integer.MAX_VALUE} and/or
          +     * {@code Short.MAX_VALUE} the baseline may change in a way
                * other than the baseline resize behavior indicates.
                *
                * @see #getBaselineResizeBehavior
          @@ -716,11 +716,11 @@ public abstract class Component implements ImageObserver, MenuContainer,
               public enum BaselineResizeBehavior {
                   /**
                    * Indicates the baseline remains fixed relative to the
          -         * y-origin.  That is, getBaseline returns
          +         * y-origin.  That is, {@code getBaseline} returns
                    * the same value regardless of the height or width.  For example, a
          -         * JLabel containing non-empty text with a
          -         * vertical alignment of TOP should have a
          -         * baseline type of CONSTANT_ASCENT.
          +         * {@code JLabel} containing non-empty text with a
          +         * vertical alignment of {@code TOP} should have a
          +         * baseline type of {@code CONSTANT_ASCENT}.
                    */
                   CONSTANT_ASCENT,
           
          @@ -728,18 +728,18 @@ public abstract class Component implements ImageObserver, MenuContainer,
                    * Indicates the baseline remains fixed relative to the height
                    * and does not change as the width is varied.  That is, for
                    * any height H the difference between H and
          -         * getBaseline(w, H) is the same.  For example, a
          -         * JLabel containing non-empty text with a
          -         * vertical alignment of BOTTOM should have a
          -         * baseline type of CONSTANT_DESCENT.
          +         * {@code getBaseline(w, H)} is the same.  For example, a
          +         * {@code JLabel} containing non-empty text with a
          +         * vertical alignment of {@code BOTTOM} should have a
          +         * baseline type of {@code CONSTANT_DESCENT}.
                    */
                   CONSTANT_DESCENT,
           
                   /**
                    * Indicates the baseline remains a fixed distance from
                    * the center of the component.  That is, for any height H the
          -         * difference between getBaseline(w, H) and
          -         * H / 2 is the same (plus or minus one depending upon
          +         * difference between {@code getBaseline(w, H)} and
          +         * {@code H / 2} is the same (plus or minus one depending upon
                    * rounding error).
                    * 

          * Because of possible rounding errors it is recommended @@ -988,11 +988,11 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Constructs a new component. Class Component can be + * Constructs a new component. Class {@code Component} can be * extended directly to create a lightweight component that does not * utilize an opaque native window. A lightweight component must be * hosted by a native container somewhere higher up in the component - * tree (for example, by a Frame object). + * tree (for example, by a {@code Frame} object). */ protected Component() { appContext = AppContext.getAppContext(); @@ -1004,8 +1004,8 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Constructs a name for this component. Called by getName - * when the name is null. + * Constructs a name for this component. Called by {@code getName} + * when the name is {@code null}. */ String constructComponentName() { return null; // For strict compliance with prior platform versions, a Component @@ -1071,8 +1071,8 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Associate a DropTarget with this component. - * The Component will receive drops only if it + * Associate a {@code DropTarget} with this component. + * The {@code Component} will receive drops only if it * is enabled. * * @see #isEnabled @@ -1119,8 +1119,8 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Gets the DropTarget associated with this - * Component. + * Gets the {@code DropTarget} associated with this + * {@code Component}. * * @return the drop target */ @@ -1128,18 +1128,18 @@ public abstract class Component implements ImageObserver, MenuContainer, public synchronized DropTarget getDropTarget() { return dropTarget; } /** - * Gets the GraphicsConfiguration associated with this - * Component. - * If the Component has not been assigned a specific - * GraphicsConfiguration, - * the GraphicsConfiguration of the - * Component object's top-level container is + * Gets the {@code GraphicsConfiguration} associated with this + * {@code Component}. + * If the {@code Component} has not been assigned a specific + * {@code GraphicsConfiguration}, + * the {@code GraphicsConfiguration} of the + * {@code Component} object's top-level container is * returned. - * If the Component has been created, but not yet added - * to a Container, this method returns null. + * If the {@code Component} has been created, but not yet added + * to a {@code Container}, this method returns {@code null}. * - * @return the GraphicsConfiguration used by this - * Component or null + * @return the {@code GraphicsConfiguration} used by this + * {@code Component} or {@code null} * @since 1.3 */ public GraphicsConfiguration getGraphicsConfiguration() { @@ -1176,8 +1176,8 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Checks that this component's GraphicsDevice - * idString matches the string argument. + * Checks that this component's {@code GraphicsDevice} + * {@code idString} matches the string argument. */ void checkGD(String stringID) { if (graphicsConfig != null) { @@ -1243,7 +1243,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * In order to account for peers' size requirements, components are invalidated * before they are first shown on the screen. By the time the parent container * is fully realized, all its components will be valid. - * @return true if the component is valid, false + * @return {@code true} if the component is valid, {@code false} * otherwise * @see #validate * @see #invalidate @@ -1268,8 +1268,8 @@ public abstract class Component implements ImageObserver, MenuContainer, * is made undisplayable. A containment hierarchy is made * undisplayable when its ancestor window is disposed. * - * @return true if the component is displayable, - * false otherwise + * @return {@code true} if the component is displayable, + * {@code false} otherwise * @see Container#add(Component) * @see Window#pack * @see Window#show @@ -1285,9 +1285,9 @@ public abstract class Component implements ImageObserver, MenuContainer, * Determines whether this component should be visible when its * parent is visible. Components are * initially visible, with the exception of top level components such - * as Frame objects. - * @return true if the component is visible, - * false otherwise + * as {@code Frame} objects. + * @return {@code true} if the component is visible, + * {@code false} otherwise * @see #setVisible * @since 1.0 */ @@ -1301,9 +1301,9 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Determines whether this component will be displayed on the screen. - * @return true if the component and all of its ancestors + * @return {@code true} if the component and all of its ancestors * until a toplevel window or null parent are visible, - * false otherwise + * {@code false} otherwise */ boolean isRecursivelyVisible() { return visible && (parent == null || parent.isRecursivelyVisible()); @@ -1368,30 +1368,30 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Returns the position of the mouse pointer in this Component's - * coordinate space if the Component is directly under the mouse - * pointer, otherwise returns null. - * If the Component is not showing on the screen, this method - * returns null even if the mouse pointer is above the area - * where the Component would be displayed. - * If the Component is partially or fully obscured by other - * Components or native windows, this method returns a non-null + * Returns the position of the mouse pointer in this {@code Component}'s + * coordinate space if the {@code Component} is directly under the mouse + * pointer, otherwise returns {@code null}. + * If the {@code Component} is not showing on the screen, this method + * returns {@code null} even if the mouse pointer is above the area + * where the {@code Component} would be displayed. + * If the {@code Component} is partially or fully obscured by other + * {@code Component}s or native windows, this method returns a non-null * value only if the mouse pointer is located above the unobscured part of the - * Component. + * {@code Component}. *

          - * For Containers it returns a non-null value if the mouse is - * above the Container itself or above any of its descendants. + * For {@code Container}s it returns a non-null value if the mouse is + * above the {@code Container} itself or above any of its descendants. * Use {@link Container#getMousePosition(boolean)} if you need to exclude children. *

          * Sometimes the exact mouse coordinates are not important, and the only thing - * that matters is whether a specific Component is under the mouse - * pointer. If the return value of this method is null, mouse - * pointer is not directly above the Component. + * that matters is whether a specific {@code Component} is under the mouse + * pointer. If the return value of this method is {@code null}, mouse + * pointer is not directly above the {@code Component}. * * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true * @see #isShowing * @see Container#getMousePosition - * @return mouse coordinates relative to this Component, or null + * @return mouse coordinates relative to this {@code Component}, or null * @since 1.5 */ public Point getMousePosition() throws HeadlessException { @@ -1436,8 +1436,8 @@ public abstract class Component implements ImageObserver, MenuContainer, *

        • the {@code Component} is obscured by another {@code Component} or * {@code Container}. *
        - * @return true if the component is showing, - * false otherwise + * @return {@code true} if the component is showing, + * {@code false} otherwise * @see #setVisible * @since 1.0 */ @@ -1453,9 +1453,9 @@ public abstract class Component implements ImageObserver, MenuContainer, * Determines whether this component is enabled. An enabled component * can respond to user input and generate events. Components are * enabled initially by default. A component may be enabled or disabled by - * calling its setEnabled method. - * @return true if the component is enabled, - * false otherwise + * calling its {@code setEnabled} method. + * @return {@code true} if the component is enabled, + * {@code false} otherwise * @see #setEnabled * @since 1.0 */ @@ -1473,7 +1473,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Enables or disables this component, depending on the value of the - * parameter b. An enabled component can respond to user + * parameter {@code b}. An enabled component can respond to user * input and generate events. Components are enabled initially by default. * *

        Note: Disabling a lightweight component does not prevent it from @@ -1482,7 +1482,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * in this container from receiving any input events. But disabling a * lightweight container affects only this container. * - * @param b If true, this component is + * @param b If {@code true}, this component is * enabled; otherwise this component is disabled * @see #isEnabled * @see #isLightweight @@ -1494,7 +1494,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * @deprecated As of JDK version 1.1, - * replaced by setEnabled(boolean). + * replaced by {@code setEnabled(boolean)}. */ @Deprecated public void enable() { @@ -1524,7 +1524,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * otherwise {@code false} * * @deprecated As of JDK version 1.1, - * replaced by setEnabled(boolean). + * replaced by {@code setEnabled(boolean)}. */ @Deprecated public void enable(boolean b) { @@ -1537,7 +1537,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * @deprecated As of JDK version 1.1, - * replaced by setEnabled(boolean). + * replaced by {@code setEnabled(boolean)}. */ @Deprecated public void disable() { @@ -1627,12 +1627,12 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Shows or hides this component depending on the value of parameter - * b. + * {@code b}. *

        * This method changes layout-related information, and therefore, * invalidates the component hierarchy. * - * @param b if true, shows this component; + * @param b if {@code true}, shows this component; * otherwise, hides this component * @see #isVisible * @see #invalidate @@ -1644,7 +1644,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * @deprecated As of JDK version 1.1, - * replaced by setVisible(boolean). + * replaced by {@code setVisible(boolean)}. */ @Deprecated public void show() { @@ -1687,7 +1687,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * otherwise {@code false} * * @deprecated As of JDK version 1.1, - * replaced by setVisible(boolean). + * replaced by {@code setVisible(boolean)}. */ @Deprecated public void show(boolean b) { @@ -1712,7 +1712,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * @deprecated As of JDK version 1.1, - * replaced by setVisible(boolean). + * replaced by {@code setVisible(boolean)}. */ @Deprecated public void hide() { @@ -1775,7 +1775,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Sets the foreground color of this component. * @param c the color to become this component's - * foreground color; if this parameter is null + * foreground color; if this parameter is {@code null} * then this component will inherit * the foreground color of its parent * @see #getForeground @@ -1798,11 +1798,11 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns whether the foreground color has been explicitly set for this - * Component. If this method returns false, this Component is + * Component. If this method returns {@code false}, this Component is * inheriting its foreground color from an ancestor. * - * @return true if the foreground color has been explicitly - * set for this Component; false otherwise. + * @return {@code true} if the foreground color has been explicitly + * set for this Component; {@code false} otherwise. * @since 1.4 */ public boolean isForegroundSet() { @@ -1835,7 +1835,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * may differ between operating systems. * * @param c the color to become this component's color; - * if this parameter is null, then this + * if this parameter is {@code null}, then this * component will inherit the background color of its parent * @see #getBackground * @since 1.0 @@ -1857,11 +1857,11 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns whether the background color has been explicitly set for this - * Component. If this method returns false, this Component is + * Component. If this method returns {@code false}, this Component is * inheriting its background color from an ancestor. * - * @return true if the background color has been explicitly - * set for this Component; false otherwise. + * @return {@code true} if the background color has been explicitly + * set for this Component; {@code false} otherwise. * @since 1.4 */ public boolean isBackgroundSet() { @@ -1900,7 +1900,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * invalidates the component hierarchy. * * @param f the font to become this component's font; - * if this parameter is null then this + * if this parameter is {@code null} then this * component will inherit the font of its parent * @see #getFont * @see #invalidate @@ -1935,11 +1935,11 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns whether the font has been explicitly set for this Component. If - * this method returns false, this Component is inheriting its + * this method returns {@code false}, this Component is inheriting its * font from an ancestor. * - * @return true if the font has been explicitly set for this - * Component; false otherwise. + * @return {@code true} if the font has been explicitly set for this + * Component; {@code false} otherwise. * @since 1.4 */ public boolean isFontSet() { @@ -1951,7 +1951,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @return this component's locale; if this component does not * have a locale, the locale of its parent is returned * @see #setLocale - * @exception IllegalComponentStateException if the Component + * @exception IllegalComponentStateException if the {@code Component} * does not have its own locale and has not yet been added to * a containment hierarchy such that the locale can be determined * from the containing parent @@ -1995,7 +1995,7 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Gets the instance of ColorModel used to display + * Gets the instance of {@code ColorModel} used to display * the component on the output device. * @return the color model used by this component * @see java.awt.image.ColorModel @@ -2020,13 +2020,13 @@ public abstract class Component implements ImageObserver, MenuContainer, *

        * Due to the asynchronous nature of native event handling, this * method can return outdated values (for instance, after several calls - * of setLocation() in rapid succession). For this + * of {@code setLocation()} in rapid succession). For this * reason, the recommended method of obtaining a component's position is - * within java.awt.event.ComponentListener.componentMoved(), + * within {@code java.awt.event.ComponentListener.componentMoved()}, * which is called after the operating system has finished moving the * component. *

        - * @return an instance of Point representing + * @return an instance of {@code Point} representing * the top-left corner of the component's bounds in * the coordinate space of the component's parent * @see #setLocation @@ -2041,7 +2041,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Gets the location of this component in the form of a point * specifying the component's top-left corner in the screen's * coordinate space. - * @return an instance of Point representing + * @return an instance of {@code Point} representing * the top-left corner of the component's bounds in the * coordinate space of the screen * @throws IllegalComponentStateException if the @@ -2087,7 +2087,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * * @return the location of this component's top left corner * @deprecated As of JDK version 1.1, - * replaced by getLocation(). + * replaced by {@code getLocation()}. */ @Deprecated public Point location() { @@ -2100,7 +2100,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Moves this component to a new location. The top-left corner of - * the new location is specified by the x and y + * the new location is specified by the {@code x} and {@code y} * parameters in the coordinate space of this component's parent. *

        * This method changes layout-related information, and therefore, @@ -2128,7 +2128,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * top-left corner in the parent's coordinate space * * @deprecated As of JDK version 1.1, - * replaced by setLocation(int, int). + * replaced by {@code setLocation(int, int)}. */ @Deprecated public void move(int x, int y) { @@ -2140,8 +2140,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Moves this component to a new location. The top-left corner of - * the new location is specified by point p. Point - * p is given in the parent's coordinate space. + * the new location is specified by point {@code p}. Point + * {@code p} is given in the parent's coordinate space. *

        * This method changes layout-related information, and therefore, * invalidates the component hierarchy. @@ -2160,12 +2160,12 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns the size of this component in the form of a - * Dimension object. The height - * field of the Dimension object contains - * this component's height, and the width - * field of the Dimension object contains + * {@code Dimension} object. The {@code height} + * field of the {@code Dimension} object contains + * this component's height, and the {@code width} + * field of the {@code Dimension} object contains * this component's width. - * @return a Dimension object that indicates the + * @return a {@code Dimension} object that indicates the * size of this component * @see #setSize * @since 1.1 @@ -2181,7 +2181,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @return the {@code Dimension} object that indicates the * size of this component * @deprecated As of JDK version 1.1, - * replaced by getSize(). + * replaced by {@code getSize()}. */ @Deprecated public Dimension size() { @@ -2189,8 +2189,8 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Resizes this component so that it has width width - * and height height. + * Resizes this component so that it has width {@code width} + * and height {@code height}. *

        * This method changes layout-related information, and therefore, * invalidates the component hierarchy. @@ -2212,7 +2212,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @param width the new width of the component * @param height the new height of the component * @deprecated As of JDK version 1.1, - * replaced by setSize(int, int). + * replaced by {@code setSize(int, int)}. */ @Deprecated public void resize(int width, int height) { @@ -2223,8 +2223,8 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Resizes this component so that it has width d.width - * and height d.height. + * Resizes this component so that it has width {@code d.width} + * and height {@code d.height}. *

        * This method changes layout-related information, and therefore, * invalidates the component hierarchy. @@ -2247,7 +2247,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * * @param d the new size of this component * @deprecated As of JDK version 1.1, - * replaced by setSize(Dimension). + * replaced by {@code setSize(Dimension)}. */ @Deprecated public void resize(Dimension d) { @@ -2256,7 +2256,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Gets the bounds of this component in the form of a - * Rectangle object. The bounds specify this + * {@code Rectangle} object. The bounds specify this * component's width, height, and location relative to * its parent. * @return a rectangle indicating this component's bounds @@ -2273,7 +2273,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * * @return the bounding rectangle for this component * @deprecated As of JDK version 1.1, - * replaced by getBounds(). + * replaced by {@code getBounds()}. */ @Deprecated public Rectangle bounds() { @@ -2282,16 +2282,16 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Moves and resizes this component. The new location of the top-left - * corner is specified by x and y, and the - * new size is specified by width and height. + * corner is specified by {@code x} and {@code y}, and the + * new size is specified by {@code width} and {@code height}. *

        * This method changes layout-related information, and therefore, * invalidates the component hierarchy. * * @param x the new x-coordinate of this component * @param y the new y-coordinate of this component - * @param width the new width of this component - * @param height the new height of this + * @param width the new {@code width} of this component + * @param height the new {@code height} of this * component * @see #getBounds * @see #setLocation(int, int) @@ -2314,7 +2314,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @param height the height of the rectangle * * @deprecated As of JDK version 1.1, - * replaced by setBounds(int, int, int, int). + * replaced by {@code setBounds(int, int, int, int)}. */ @Deprecated public void reshape(int x, int y, int width, int height) { @@ -2434,10 +2434,10 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Moves and resizes this component to conform to the new - * bounding rectangle r. This component's new - * position is specified by r.x and r.y, - * and its new size is specified by r.width and - * r.height + * bounding rectangle {@code r}. This component's new + * position is specified by {@code r.x} and {@code r.y}, + * and its new size is specified by {@code r.width} and + * {@code r.height} *

        * This method changes layout-related information, and therefore, * invalidates the component hierarchy. @@ -2460,8 +2460,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns the current x coordinate of the components origin. * This method is preferable to writing - * component.getBounds().x, - * or component.getLocation().x because it doesn't + * {@code component.getBounds().x}, + * or {@code component.getLocation().x} because it doesn't * cause any heap allocations. * * @return the current x coordinate of the components origin @@ -2475,8 +2475,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns the current y coordinate of the components origin. * This method is preferable to writing - * component.getBounds().y, - * or component.getLocation().y because it + * {@code component.getBounds().y}, + * or {@code component.getLocation().y} because it * doesn't cause any heap allocations. * * @return the current y coordinate of the components origin @@ -2490,8 +2490,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns the current width of this component. * This method is preferable to writing - * component.getBounds().width, - * or component.getSize().width because it + * {@code component.getBounds().width}, + * or {@code component.getSize().width} because it * doesn't cause any heap allocations. * * @return the current width of this component @@ -2505,8 +2505,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns the current height of this component. * This method is preferable to writing - * component.getBounds().height, - * or component.getSize().height because it + * {@code component.getBounds().height}, + * or {@code component.getSize().height} because it * doesn't cause any heap allocations. * * @return the current height of this component @@ -2518,10 +2518,10 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Stores the bounds of this component into "return value" rv and - * return rv. If rv is null a new - * Rectangle is allocated. - * This version of getBounds is useful if the caller - * wants to avoid allocating a new Rectangle object + * return rv. If rv is {@code null} a new + * {@code Rectangle} is allocated. + * This version of {@code getBounds} is useful if the caller + * wants to avoid allocating a new {@code Rectangle} object * on the heap. * * @param rv the return value, modified to the components bounds @@ -2539,10 +2539,10 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Stores the width/height of this component into "return value" rv - * and return rv. If rv is null a new - * Dimension object is allocated. This version of - * getSize is useful if the caller wants to avoid - * allocating a new Dimension object on the heap. + * and return rv. If rv is {@code null} a new + * {@code Dimension} object is allocated. This version of + * {@code getSize} is useful if the caller wants to avoid + * allocating a new {@code Dimension} object on the heap. * * @param rv the return value, modified to the components size * @return rv @@ -2559,10 +2559,10 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Stores the x,y origin of this component into "return value" rv - * and return rv. If rv is null a new - * Point is allocated. - * This version of getLocation is useful if the - * caller wants to avoid allocating a new Point + * and return rv. If rv is {@code null} a new + * {@code Point} is allocated. + * This version of {@code getLocation} is useful if the + * caller wants to avoid allocating a new {@code Point} * object on the heap. * * @param rv the return value, modified to the components location @@ -2607,12 +2607,12 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * A lightweight component doesn't have a native toolkit peer. - * Subclasses of Component and Container, - * other than the ones defined in this package like Button - * or Scrollbar, are lightweight. + * Subclasses of {@code Component} and {@code Container}, + * other than the ones defined in this package like {@code Button} + * or {@code Scrollbar}, are lightweight. * All of the Swing components are lightweights. *

        - * This method will always return false if this component + * This method will always return {@code false} if this component * is not displayable because it is impossible to determine the * weight of an undisplayable component. * @@ -2628,8 +2628,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Sets the preferred size of this component to a constant - * value. Subsequent calls to getPreferredSize will always - * return this value. Setting the preferred size to null + * value. Subsequent calls to {@code getPreferredSize} will always + * return this value. Setting the preferred size to {@code null} * restores the default behavior. * * @param preferredSize The new preferred size, or null @@ -2656,9 +2656,9 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns true if the preferred size has been set to a - * non-null value otherwise returns false. + * non-{@code null} value otherwise returns false. * - * @return true if setPreferredSize has been invoked + * @return true if {@code setPreferredSize} has been invoked * with a non-null value. * @since 1.5 */ @@ -2683,7 +2683,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * * @return the component's preferred size * @deprecated As of JDK version 1.1, - * replaced by getPreferredSize(). + * replaced by {@code getPreferredSize()}. */ @Deprecated public Dimension preferredSize() { @@ -2704,8 +2704,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Sets the minimum size of this component to a constant - * value. Subsequent calls to getMinimumSize will always - * return this value. Setting the minimum size to null + * value. Subsequent calls to {@code getMinimumSize} will always + * return this value. Setting the minimum size to {@code null} * restores the default behavior. * * @param minimumSize the new minimum size of this component @@ -2730,10 +2730,10 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Returns whether or not setMinimumSize has been + * Returns whether or not {@code setMinimumSize} has been * invoked with a non-null value. * - * @return true if setMinimumSize has been invoked with a + * @return true if {@code setMinimumSize} has been invoked with a * non-null value. * @since 1.5 */ @@ -2756,7 +2756,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * * @return the minimum size of this component * @deprecated As of JDK version 1.1, - * replaced by getMinimumSize(). + * replaced by {@code getMinimumSize()}. */ @Deprecated public Dimension minimumSize() { @@ -2777,11 +2777,11 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Sets the maximum size of this component to a constant - * value. Subsequent calls to getMaximumSize will always - * return this value. Setting the maximum size to null + * value. Subsequent calls to {@code getMaximumSize} will always + * return this value. Setting the maximum size to {@code null} * restores the default behavior. * - * @param maximumSize a Dimension containing the + * @param maximumSize a {@code Dimension} containing the * desired maximum allowable size * @see #getMaximumSize * @see #isMaximumSizeSet @@ -2804,10 +2804,10 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Returns true if the maximum size has been set to a non-null + * Returns true if the maximum size has been set to a non-{@code null} * value otherwise returns false. * - * @return true if maximumSize is non-null, + * @return true if {@code maximumSize} is non-{@code null}, * false otherwise * @since 1.5 */ @@ -2858,16 +2858,16 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns the baseline. The baseline is measured from the top of * the component. This method is primarily meant for - * LayoutManagers to align components along their + * {@code LayoutManager}s to align components along their * baseline. A return value less than 0 indicates this component * does not have a reasonable baseline and that - * LayoutManagers should not align this component on + * {@code LayoutManager}s should not align this component on * its baseline. *

        * The default implementation returns -1. Subclasses that support * baseline should override appropriately. If a value >= 0 is * returned, then the component has a valid baseline for any - * size >= the minimum size and getBaselineResizeBehavior + * size >= the minimum size and {@code getBaselineResizeBehavior} * can be used to determine how the baseline changes with size. * * @param width the width to get the baseline for @@ -2893,15 +2893,15 @@ public abstract class Component implements ImageObserver, MenuContainer, * layout managers and GUI builders. *

        * The default implementation returns - * BaselineResizeBehavior.OTHER. Subclasses that have a + * {@code BaselineResizeBehavior.OTHER}. Subclasses that have a * baseline should override appropriately. Subclasses should - * never return null; if the baseline can not be - * calculated return BaselineResizeBehavior.OTHER. Callers + * never return {@code null}; if the baseline can not be + * calculated return {@code BaselineResizeBehavior.OTHER}. Callers * should first ask for the baseline using - * getBaseline and if a value >= 0 is returned use + * {@code getBaseline} and if a value >= 0 is returned use * this method. It is acceptable for this method to return a - * value other than BaselineResizeBehavior.OTHER even if - * getBaseline returns a value less than 0. + * value other than {@code BaselineResizeBehavior.OTHER} even if + * {@code getBaseline} returns a value less than 0. * * @return an enum indicating how the baseline changes as the component * size changes @@ -2925,7 +2925,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * @deprecated As of JDK version 1.1, - * replaced by doLayout(). + * replaced by {@code doLayout()}. */ @Deprecated public void layout() { @@ -3074,9 +3074,9 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Creates a graphics context for this component. This method will - * return null if this component is currently not + * return {@code null} if this component is currently not * displayable. - * @return a graphics context for this component, or null + * @return a graphics context for this component, or {@code null} * if it has none * @see #paint * @since 1.0 @@ -3138,7 +3138,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * {@link Font Font} class. * @param font the font for which font metrics is to be * obtained - * @return the font metrics for font + * @return the font metrics for {@code font} * @see #getFont * @see java.awt.peer.ComponentPeer#getFontMetrics(Font) * @see Toolkit#getFontMetrics(Font) @@ -3161,19 +3161,19 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Sets the cursor image to the specified cursor. This cursor - * image is displayed when the contains method for + * image is displayed when the {@code contains} method for * this component returns true for the current cursor location, and * this Component is visible, displayable, and enabled. Setting the - * cursor of a Container causes that cursor to be displayed + * cursor of a {@code Container} causes that cursor to be displayed * within all of the container's subcomponents, except for those - * that have a non-null cursor. + * that have a non-{@code null} cursor. *

        * The method may have no visual effect if the Java platform * implementation and/or the native system do not support * changing the mouse cursor shape. * @param cursor One of the constants defined - * by the Cursor class; - * if this parameter is null + * by the {@code Cursor} class; + * if this parameter is {@code null} * then this component will inherit * the cursor of its parent * @see #isEnabled @@ -3213,7 +3213,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Gets the cursor set in the component. If the component does * not have a cursor set, the cursor of its parent is returned. * If no cursor is set in the entire hierarchy, - * Cursor.DEFAULT_CURSOR is returned. + * {@code Cursor.DEFAULT_CURSOR} is returned. * * @return the cursor for this component * @see #setCursor @@ -3238,11 +3238,11 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns whether the cursor has been explicitly set for this Component. - * If this method returns false, this Component is inheriting + * If this method returns {@code false}, this Component is inheriting * its cursor from an ancestor. * - * @return true if the cursor has been explicitly set for this - * Component; false otherwise. + * @return {@code true} if the cursor has been explicitly set for this + * Component; {@code false} otherwise. * @since 1.4 */ public boolean isCursorSet() { @@ -3255,12 +3255,12 @@ public abstract class Component implements ImageObserver, MenuContainer, * This method is called when the contents of the component should * be painted; such as when the component is first being shown or * is damaged and in need of repair. The clip rectangle in the - * Graphics parameter is set to the area + * {@code Graphics} parameter is set to the area * which needs to be painted. - * Subclasses of Component that override this - * method need not call super.paint(g). + * Subclasses of {@code Component} that override this + * method need not call {@code super.paint(g)}. *

        - * For performance reasons, Components with zero width + * For performance reasons, {@code Component}s with zero width * or height aren't considered to need painting when they are first shown, * and also aren't considered to need repair. *

        @@ -3280,21 +3280,21 @@ public abstract class Component implements ImageObserver, MenuContainer, * Updates this component. *

        * If this component is not a lightweight component, the - * AWT calls the update method in response to - * a call to repaint. You can assume that + * AWT calls the {@code update} method in response to + * a call to {@code repaint}. You can assume that * the background is not cleared. *

        - * The update method of Component - * calls this component's paint method to redraw + * The {@code update} method of {@code Component} + * calls this component's {@code paint} method to redraw * this component. This method is commonly overridden by subclasses * which need to do additional work in response to a call to - * repaint. + * {@code repaint}. * Subclasses of Component that override this method should either - * call super.update(g), or call paint(g) - * directly from their update method. + * call {@code super.update(g)}, or call {@code paint(g)} + * directly from their {@code update} method. *

        * The origin of the graphics context, its - * (00) coordinate point, is the + * ({@code 0}, {@code 0}) coordinate point, is the * top-left corner of this component. The clipping region of the * graphics context is the bounding rectangle of this component. * @@ -3317,7 +3317,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Paints this component and all of its subcomponents. *

        * The origin of the graphics context, its - * (00) coordinate point, is the + * ({@code 0}, {@code 0}) coordinate point, is the * top-left corner of this component. The clipping region of the * graphics context is the bounding rectangle of this component. * @@ -3355,9 +3355,9 @@ public abstract class Component implements ImageObserver, MenuContainer, * Repaints this component. *

        * If this component is a lightweight component, this method - * causes a call to this component's paint + * causes a call to this component's {@code paint} * method as soon as possible. Otherwise, this method causes - * a call to this component's update method as soon + * a call to this component's {@code update} method as soon * as possible. *

        * Note: For more information on the paint mechanisms utilitized @@ -3375,8 +3375,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Repaints the component. If this component is a lightweight - * component, this results in a call to paint - * within tm milliseconds. + * component, this results in a call to {@code paint} + * within {@code tm} milliseconds. *

        * Note: For more information on the paint mechanisms utilitized * by AWT and Swing, including information on how to write the most @@ -3396,9 +3396,9 @@ public abstract class Component implements ImageObserver, MenuContainer, * Repaints the specified rectangle of this component. *

        * If this component is a lightweight component, this method - * causes a call to this component's paint method + * causes a call to this component's {@code paint} method * as soon as possible. Otherwise, this method causes a call to - * this component's update method as soon as possible. + * this component's {@code update} method as soon as possible. *

        * Note: For more information on the paint mechanisms utilitized * by AWT and Swing, including information on how to write the most @@ -3418,12 +3418,12 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Repaints the specified rectangle of this component within - * tm milliseconds. + * {@code tm} milliseconds. *

        * If this component is a lightweight component, this method causes - * a call to this component's paint method. + * a call to this component's {@code paint} method. * Otherwise, this method causes a call to this component's - * update method. + * {@code update} method. *

        * Note: For more information on the paint mechanisms utilitized * by AWT and Swing, including information on how to write the most @@ -3481,10 +3481,10 @@ public abstract class Component implements ImageObserver, MenuContainer, * printed or should be printed differently than they are painted. *

        * The default implementation of this method calls the - * paint method. + * {@code paint} method. *

        * The origin of the graphics context, its - * (00) coordinate point, is the + * ({@code 0}, {@code 0}) coordinate point, is the * top-left corner of this component. The clipping region of the * graphics context is the bounding rectangle of this component. * @param g the graphics context to use for printing @@ -3499,7 +3499,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Prints this component and all of its subcomponents. *

        * The origin of the graphics context, its - * (00) coordinate point, is the + * ({@code 0}, {@code 0}) coordinate point, is the * top-left corner of this component. The clipping region of the * graphics context is the bounding rectangle of this component. * @param g the graphics context to use for printing @@ -3542,41 +3542,41 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Repaints the component when the image has changed. - * This imageUpdate method of an ImageObserver + * This {@code imageUpdate} method of an {@code ImageObserver} * is called when more information about an * image which had been previously requested using an asynchronous - * routine such as the drawImage method of - * Graphics becomes available. - * See the definition of imageUpdate for + * routine such as the {@code drawImage} method of + * {@code Graphics} becomes available. + * See the definition of {@code imageUpdate} for * more information on this method and its arguments. *

        - * The imageUpdate method of Component + * The {@code imageUpdate} method of {@code Component} * incrementally draws an image on the component as more of the bits * of the image are available. *

        - * If the system property awt.image.incrementaldraw - * is missing or has the value true, the image is + * If the system property {@code awt.image.incrementaldraw} + * is missing or has the value {@code true}, the image is * incrementally drawn. If the system property has any other value, * then the image is not drawn until it has been completely loaded. *

        * Also, if incremental drawing is in effect, the value of the - * system property awt.image.redrawrate is interpreted + * system property {@code awt.image.redrawrate} is interpreted * as an integer to give the maximum redraw rate, in milliseconds. If * the system property is missing or cannot be interpreted as an * integer, the redraw rate is once every 100ms. *

        - * The interpretation of the x, y, - * width, and height arguments depends on - * the value of the infoflags argument. + * The interpretation of the {@code x}, {@code y}, + * {@code width}, and {@code height} arguments depends on + * the value of the {@code infoflags} argument. * * @param img the image being observed - * @param infoflags see imageUpdate for more information + * @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 false if the infoflags indicate that the - * image is completely loaded; true otherwise. + * @return {@code false} if the infoflags indicate that the + * image is completely loaded; {@code true} otherwise. * * @see java.awt.image.ImageObserver * @see Graphics#drawImage(Image, int, int, Color, java.awt.image.ImageObserver) @@ -3699,12 +3699,12 @@ public abstract class Component implements ImageObserver, MenuContainer, * Prepares an image for rendering on this component. The image * data is downloaded asynchronously in another thread and the * appropriate screen representation of the image is generated. - * @param image the Image for which to + * @param image the {@code Image} for which to * prepare a screen representation - * @param observer the ImageObserver object + * @param observer the {@code ImageObserver} object * to be notified as the image is being prepared - * @return true if the image has already been fully - * prepared; false otherwise + * @return {@code true} if the image has already been fully + * prepared; {@code false} otherwise * @since 1.0 */ public boolean prepareImage(Image image, ImageObserver observer) { @@ -3718,14 +3718,14 @@ public abstract class Component implements ImageObserver, MenuContainer, * The image data is downloaded asynchronously in another thread, * and an appropriately scaled screen representation of the image is * generated. - * @param image the instance of Image + * @param image the instance of {@code Image} * for which to prepare a screen representation * @param width the width of the desired screen representation * @param height the height of the desired screen representation - * @param observer the ImageObserver object + * @param observer the {@code ImageObserver} object * to be notified as the image is being prepared - * @return true if the image has already been fully - * prepared; false otherwise + * @return {@code true} if the image has already been fully + * prepared; {@code false} otherwise * @see java.awt.image.ImageObserver * @since 1.0 */ @@ -3748,17 +3748,17 @@ public abstract class Component implements ImageObserver, MenuContainer, * of the specified image. *

        * This method does not cause the image to begin loading. An - * application must use the prepareImage method + * application must use the {@code prepareImage} method * to force the loading of an image. *

        * Information on the flags returned by this method can be found - * with the discussion of the ImageObserver interface. - * @param image the Image object whose status + * with the discussion of the {@code ImageObserver} interface. + * @param image the {@code Image} object whose status * is being checked - * @param observer the ImageObserver + * @param observer the {@code ImageObserver} * object to be notified as the image is being prepared * @return the bitwise inclusive OR of - * ImageObserver flags indicating what + * {@code ImageObserver} flags indicating what * information about the image is currently available * @see #prepareImage(Image, int, int, java.awt.image.ImageObserver) * @see Toolkit#checkImage(Image, int, int, java.awt.image.ImageObserver) @@ -3774,27 +3774,27 @@ public abstract class Component implements ImageObserver, MenuContainer, * of the specified image. *

        * This method does not cause the image to begin loading. An - * application must use the prepareImage method + * application must use the {@code prepareImage} method * to force the loading of an image. *

        - * The checkImage method of Component - * calls its peer's checkImage method to calculate + * The {@code checkImage} method of {@code Component} + * calls its peer's {@code checkImage} method to calculate * the flags. If this component does not yet have a peer, the - * component's toolkit's checkImage method is called + * component's toolkit's {@code checkImage} method is called * instead. *

        * Information on the flags returned by this method can be found - * with the discussion of the ImageObserver interface. - * @param image the Image object whose status + * with the discussion of the {@code ImageObserver} interface. + * @param image the {@code Image} object whose status * is being checked * @param width the width of the scaled version * whose status is to be checked * @param height the height of the scaled version * whose status is to be checked - * @param observer the ImageObserver object + * @param observer the {@code ImageObserver} object * to be notified as the image is being prepared * @return the bitwise inclusive OR of - * ImageObserver flags indicating what + * {@code ImageObserver} flags indicating what * information about the image is currently available * @see #prepareImage(Image, int, int, java.awt.image.ImageObserver) * @see Toolkit#checkImage(Image, int, int, java.awt.image.ImageObserver) @@ -3819,7 +3819,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Creates a new strategy for multi-buffering on this component. * Multi-buffering is useful for rendering performance. This method * attempts to create the best strategy available with the number of - * buffers supplied. It will always create a BufferStrategy + * buffers supplied. It will always create a {@code BufferStrategy} * with that number of buffers. * A page-flipping strategy is attempted first, then a blitting strategy * using accelerated buffers. Finally, an unaccelerated blitting @@ -3880,17 +3880,17 @@ public abstract class Component implements ImageObserver, MenuContainer, * buffer capabilities). *

        * Each time this method - * is called, dispose will be invoked on the existing - * BufferStrategy. + * is called, {@code dispose} will be invoked on the existing + * {@code BufferStrategy}. * @param numBuffers number of buffers to create * @param caps the required capabilities for creating the buffer strategy; - * cannot be null + * cannot be {@code null} * @exception AWTException if the capabilities supplied could not be * supported or met; this may happen, for example, if there is not enough * accelerated memory currently available, or if page flipping is specified * but not possible. * @exception IllegalArgumentException if numBuffers is less than 1, or if - * caps is null + * caps is {@code null} * @see Window#getBufferStrategy() * @see Canvas#getBufferStrategy() * @since 1.4 @@ -3975,7 +3975,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Inner class for flipping buffers on a component. That component must - * be a Canvas or Window or Applet. + * be a {@code Canvas} or {@code Window} or {@code Applet}. * @see Canvas * @see Window * @see Applet @@ -4026,8 +4026,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Creates a new flipping buffer strategy for this component. - * The component must be a Canvas or Window or - * Applet. + * The component must be a {@code Canvas} or {@code Window} or + * {@code Applet}. * @see Canvas * @see Window * @see Applet @@ -4064,14 +4064,14 @@ public abstract class Component implements ImageObserver, MenuContainer, * @param numBuffers number of buffers to create; must be greater than * one * @param caps the capabilities of the buffers. - * BufferCapabilities.isPageFlipping must be - * true. + * {@code BufferCapabilities.isPageFlipping} must be + * {@code true}. * @exception AWTException if the capabilities supplied could not be * supported or met * @exception IllegalStateException if the component has no peer * @exception IllegalArgumentException if numBuffers is less than two, - * or if BufferCapabilities.isPageFlipping is not - * true. + * or if {@code BufferCapabilities.isPageFlipping} is not + * {@code true}. * @see java.awt.BufferCapabilities#isPageFlipping() */ protected void createBuffers(int numBuffers, BufferCapabilities caps) @@ -4152,7 +4152,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * either by copying or by moving the video pointer. * @param flipAction an integer value describing the flipping action * for the contents of the back buffer. This should be one of the - * values of the BufferCapabilities.FlipContents + * values of the {@code BufferCapabilities.FlipContents} * property. * @exception IllegalStateException if the buffers have not yet * been created @@ -4266,7 +4266,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * @return whether the drawing buffer was lost since the last call to - * getDrawGraphics + * {@code getDrawGraphics} */ public boolean contentsLost() { if (drawVBuffer == null) { @@ -4553,7 +4553,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * @return whether the drawing buffer was lost since the last call to - * getDrawGraphics + * {@code getDrawGraphics} */ public boolean contentsLost() { if (backBuffers == null) { @@ -4632,7 +4632,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Inner class for flipping buffers on a component. That component must - * be a Canvas or Window. + * be a {@code Canvas} or {@code Window}. * @see Canvas * @see Window * @see java.awt.image.BufferStrategy @@ -4700,7 +4700,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Checks whether this component "contains" the specified point, - * where x and y are defined to be + * where {@code x} and {@code y} are defined to be * relative to the coordinate system of this component. * * @param x the x coordinate of the point @@ -4753,15 +4753,15 @@ public abstract class Component implements ImageObserver, MenuContainer, * inside a subcomponent that itself has subcomponents, it does not * go looking down the subcomponent tree. *

        - * The locate method of Component simply + * The {@code locate} method of {@code Component} simply * returns the component itself if the (xy) - * coordinate location is inside its bounding box, and null + * coordinate location is inside its bounding box, and {@code null} * otherwise. * @param x the x coordinate * @param y the y coordinate * @return the component or subcomponent that contains the * (xy) location; - * null if the location + * {@code null} if the location * is outside this component * @see #contains(int, int) * @since 1.0 @@ -4801,7 +4801,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * @param e the event to deliver * @deprecated As of JDK version 1.1, - * replaced by dispatchEvent(AWTEvent e). + * replaced by {@code dispatchEvent(AWTEvent e)}. */ @Deprecated public void deliverEvent(Event e) { @@ -4810,8 +4810,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Dispatches an event to this component or one of its sub components. - * Calls processEvent before returning for 1.1-style - * events which have been enabled for the Component. + * Calls {@code processEvent} before returning for 1.1-style + * events which have been enabled for the {@code Component}. * @param e the event */ public final void dispatchEvent(AWTEvent e) { @@ -5279,7 +5279,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Adds the specified component listener to receive component events from * this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5304,7 +5304,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * receives component events from this component. This method performs * no function, nor does it throw an exception, if the listener * specified by the argument was not previously added to this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5326,7 +5326,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the component listeners * registered on this component. * - * @return all ComponentListeners of this component + * @return all {@code ComponentListener}s of this component * or an empty array if no component * listeners are currently registered * @@ -5341,7 +5341,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Adds the specified focus listener to receive focus events from * this component when this component gains input focus. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5372,7 +5372,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * receives focus events from this component. This method performs * no function, nor does it throw an exception, if the listener * specified by the argument was not previously added to this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5395,7 +5395,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the focus listeners * registered on this component. * - * @return all of this component's FocusListeners + * @return all of this component's {@code FocusListener}s * or an empty array if no component * listeners are currently registered * @@ -5411,7 +5411,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Adds the specified hierarchy listener to receive hierarchy changed * events from this component when the hierarchy to which this container * belongs changes. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5449,7 +5449,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * receives hierarchy changed events from this component. This method * performs no function, nor does it throw an exception, if the listener * specified by the argument was not previously added to this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5486,7 +5486,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the hierarchy listeners * registered on this component. * - * @return all of this component's HierarchyListeners + * @return all of this component's {@code HierarchyListener}s * or an empty array if no hierarchy * listeners are currently registered * @@ -5502,7 +5502,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Adds the specified hierarchy bounds listener to receive hierarchy * bounds events from this component when the hierarchy to which this * container belongs changes. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5542,7 +5542,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * receives hierarchy bounds events from this component. This method * performs no function, nor does it throw an exception, if the listener * specified by the argument was not previously added to this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5648,7 +5648,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the hierarchy bounds listeners * registered on this component. * - * @return all of this component's HierarchyBoundsListeners + * @return all of this component's {@code HierarchyBoundsListener}s * or an empty array if no hierarchy bounds * listeners are currently registered * @@ -5704,7 +5704,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * receives key events from this component. This method performs * no function, nor does it throw an exception, if the listener * specified by the argument was not previously added to this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5727,7 +5727,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the key listeners * registered on this component. * - * @return all of this component's KeyListeners + * @return all of this component's {@code KeyListener}s * or an empty array if no key * listeners are currently registered * @@ -5742,7 +5742,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Adds the specified mouse listener to receive mouse events from * this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5773,7 +5773,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * receives mouse events from this component. This method performs * no function, nor does it throw an exception, if the listener * specified by the argument was not previously added to this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5796,7 +5796,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the mouse listeners * registered on this component. * - * @return all of this component's MouseListeners + * @return all of this component's {@code MouseListener}s * or an empty array if no mouse * listeners are currently registered * @@ -5811,7 +5811,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Adds the specified mouse motion listener to receive mouse motion * events from this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5842,7 +5842,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * receives mouse motion events from this component. This method performs * no function, nor does it throw an exception, if the listener * specified by the argument was not previously added to this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5865,7 +5865,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the mouse motion listeners * registered on this component. * - * @return all of this component's MouseMotionListeners + * @return all of this component's {@code MouseMotionListener}s * or an empty array if no mouse motion * listeners are currently registered * @@ -5885,7 +5885,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * For information on how mouse wheel events are dispatched, see * the class description for {@link MouseWheelEvent}. *

        - * If l is null, no exception is thrown and no + * If l is {@code null}, no exception is thrown and no * action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5938,7 +5938,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the mouse wheel listeners * registered on this component. * - * @return all of this component's MouseWheelListeners + * @return all of this component's {@code MouseWheelListener}s * or an empty array if no mouse wheel * listeners are currently registered * @@ -5954,9 +5954,9 @@ public abstract class Component implements ImageObserver, MenuContainer, * Adds the specified input method listener to receive * input method events from this component. A component will * only receive input method events from input methods - * if it also overrides getInputMethodRequests to return an - * InputMethodRequests instance. - * If listener l is null, + * if it also overrides {@code getInputMethodRequests} to return an + * {@code InputMethodRequests} instance. + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -5982,7 +5982,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * receives input method events from this component. This method performs * no function, nor does it throw an exception, if the listener * specified by the argument was not previously added to this component. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -6005,7 +6005,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the input method listeners * registered on this component. * - * @return all of this component's InputMethodListeners + * @return all of this component's {@code InputMethodListener}s * or an empty array if no input method * listeners are currently registered * @@ -6020,16 +6020,16 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns an array of all the objects currently registered * as FooListeners - * upon this Component. + * upon this {@code Component}. * FooListeners are registered using the * addFooListener method. * *

        - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * Component c + * {@code Component c} * for its mouse listeners with the following code: * *

        MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));
        @@ -6039,13 +6039,13 @@ public abstract class Component implements ImageObserver, MenuContainer, * @param the type of the listeners * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this component, * or an empty array if no such listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * @throws NullPointerException if {@code listenerType} is {@code null} * @see #getComponentListeners * @see #getFocusListeners @@ -6091,11 +6091,11 @@ public abstract class Component implements ImageObserver, MenuContainer, * Gets the input method request handler which supports * requests from input methods for this component. A component * that supports on-the-spot text input must override this - * method to return an InputMethodRequests instance. + * method to return an {@code InputMethodRequests} instance. * At the same time, it also has to handle input method events. * * @return the input method request handler for this component, - * null by default + * {@code null} by default * @see #addInputMethodListener * @since 1.2 */ @@ -6111,7 +6111,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * override this to return a private input context. * * @return the input context used by this component; - * null if no context can be determined + * {@code null} if no context can be determined * @since 1.2 */ public InputContext getInputContext() { @@ -6131,8 +6131,8 @@ public abstract class Component implements ImageObserver, MenuContainer, * that event type is added to the component. *

        * This method only needs to be invoked by subclasses of - * Component which desire to have the specified event - * types delivered to processEvent regardless of whether + * {@code Component} which desire to have the specified event + * types delivered to {@code processEvent} regardless of whether * or not a listener is registered. * @param eventsToEnable the event mask defining the event types * @see #processEvent @@ -6304,28 +6304,28 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Potentially coalesce an event being posted with an existing - * event. This method is called by EventQueue.postEvent + * event. This method is called by {@code EventQueue.postEvent} * if an event with the same ID as the event to be posted is found in * the queue (both events must have this component as their source). * This method either returns a coalesced event which replaces * the existing event (and the new event is then discarded), or - * null to indicate that no combining should be done + * {@code null} to indicate that no combining should be done * (add the second event to the end of the queue). Either event * parameter may be modified and returned, as the other one is discarded - * unless null is returned. + * unless {@code null} is returned. *

        - * This implementation of coalesceEvents coalesces + * This implementation of {@code coalesceEvents} coalesces * two event types: mouse move (and drag) events, * and paint (and update) events. * For mouse move events the last event is always returned, causing * intermediate moves to be discarded. For paint events, the new - * event is coalesced into a complex RepaintArea in the peer. - * The new AWTEvent is always returned. + * event is coalesced into a complex {@code RepaintArea} in the peer. + * The new {@code AWTEvent} is always returned. * - * @param existingEvent the event already on the EventQueue + * @param existingEvent the event already on the {@code EventQueue} * @param newEvent the event being posted to the - * EventQueue - * @return a coalesced event, or null indicating that no + * {@code EventQueue} + * @return a coalesced event, or {@code null} indicating that no * coalescing was done */ protected AWTEvent coalesceEvents(AWTEvent existingEvent, @@ -6338,7 +6338,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * method calls the appropriate * process<event type>Event * method for the given class of event. - *

        Note that if the event parameter is null + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6398,17 +6398,17 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Processes component events occurring on this component by * dispatching them to any registered - * ComponentListener objects. + * {@code ComponentListener} objects. *

        * This method is not called unless component events are * enabled for this component. Component events are enabled * when one of the following occurs: *

          - *
        • A ComponentListener object is registered - * via addComponentListener. - *
        • Component events are enabled via enableEvents. + *
        • A {@code ComponentListener} object is registered + * via {@code addComponentListener}. + *
        • Component events are enabled via {@code enableEvents}. *
        - *

        Note that if the event parameter is null + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6443,33 +6443,33 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Processes focus events occurring on this component by * dispatching them to any registered - * FocusListener objects. + * {@code FocusListener} objects. *

        * This method is not called unless focus events are * enabled for this component. Focus events are enabled * when one of the following occurs: *

          - *
        • A FocusListener object is registered - * via addFocusListener. - *
        • Focus events are enabled via enableEvents. + *
        • A {@code FocusListener} object is registered + * via {@code addFocusListener}. + *
        • Focus events are enabled via {@code enableEvents}. *
        *

        - * If focus events are enabled for a Component, - * the current KeyboardFocusManager determines + * If focus events are enabled for a {@code Component}, + * the current {@code KeyboardFocusManager} determines * whether or not a focus event should be dispatched to - * registered FocusListener objects. If the - * events are to be dispatched, the KeyboardFocusManager - * calls the Component's dispatchEvent - * method, which results in a call to the Component's - * processFocusEvent method. + * registered {@code FocusListener} objects. If the + * events are to be dispatched, the {@code KeyboardFocusManager} + * calls the {@code Component}'s {@code dispatchEvent} + * method, which results in a call to the {@code Component}'s + * {@code processFocusEvent} method. *

        - * If focus events are enabled for a Component, calling - * the Component's dispatchEvent method - * with a FocusEvent as the argument will result in a - * call to the Component's processFocusEvent - * method regardless of the current KeyboardFocusManager. + * If focus events are enabled for a {@code Component}, calling + * the {@code Component}'s {@code dispatchEvent} method + * with a {@code FocusEvent} as the argument will result in a + * call to the {@code Component}'s {@code processFocusEvent} + * method regardless of the current {@code KeyboardFocusManager}. * - *

        Note that if the event parameter is null + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6500,39 +6500,39 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Processes key events occurring on this component by * dispatching them to any registered - * KeyListener objects. + * {@code KeyListener} objects. *

        * This method is not called unless key events are * enabled for this component. Key events are enabled * when one of the following occurs: *

          - *
        • A KeyListener object is registered - * via addKeyListener. - *
        • Key events are enabled via enableEvents. + *
        • A {@code KeyListener} object is registered + * via {@code addKeyListener}. + *
        • Key events are enabled via {@code enableEvents}. *
        * *

        - * If key events are enabled for a Component, - * the current KeyboardFocusManager determines + * If key events are enabled for a {@code Component}, + * the current {@code KeyboardFocusManager} determines * whether or not a key event should be dispatched to - * registered KeyListener objects. The - * DefaultKeyboardFocusManager will not dispatch - * key events to a Component that is not the focus + * registered {@code KeyListener} objects. The + * {@code DefaultKeyboardFocusManager} will not dispatch + * key events to a {@code Component} that is not the focus * owner or is not showing. *

        - * As of J2SE 1.4, KeyEvents are redirected to + * As of J2SE 1.4, {@code KeyEvent}s are redirected to * the focus owner. Please see the * Focus Specification * for further information. *

        - * Calling a Component's dispatchEvent - * method with a KeyEvent as the argument will - * result in a call to the Component's - * processKeyEvent method regardless of the - * current KeyboardFocusManager as long as the + * Calling a {@code Component}'s {@code dispatchEvent} + * method with a {@code KeyEvent} as the argument will + * result in a call to the {@code Component}'s + * {@code processKeyEvent} method regardless of the + * current {@code KeyboardFocusManager} as long as the * component is showing, focused, and enabled, and key events * are enabled on it. - *

        If the event parameter is null + *

        If the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6569,17 +6569,17 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Processes mouse events occurring on this component by * dispatching them to any registered - * MouseListener objects. + * {@code MouseListener} objects. *

        * This method is not called unless mouse events are * enabled for this component. Mouse events are enabled * when one of the following occurs: *

          - *
        • A MouseListener object is registered - * via addMouseListener. - *
        • Mouse events are enabled via enableEvents. + *
        • A {@code MouseListener} object is registered + * via {@code addMouseListener}. + *
        • Mouse events are enabled via {@code enableEvents}. *
        - *

        Note that if the event parameter is null + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6617,17 +6617,17 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Processes mouse motion events occurring on this component by * dispatching them to any registered - * MouseMotionListener objects. + * {@code MouseMotionListener} objects. *

        * This method is not called unless mouse motion events are * enabled for this component. Mouse motion events are enabled * when one of the following occurs: *

          - *
        • A MouseMotionListener object is registered - * via addMouseMotionListener. - *
        • Mouse motion events are enabled via enableEvents. + *
        • A {@code MouseMotionListener} object is registered + * via {@code addMouseMotionListener}. + *
        • Mouse motion events are enabled via {@code enableEvents}. *
        - *

        Note that if the event parameter is null + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6656,21 +6656,21 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Processes mouse wheel events occurring on this component by * dispatching them to any registered - * MouseWheelListener objects. + * {@code MouseWheelListener} objects. *

        * This method is not called unless mouse wheel events are * enabled for this component. Mouse wheel events are enabled * when one of the following occurs: *

          - *
        • A MouseWheelListener object is registered - * via addMouseWheelListener. - *
        • Mouse wheel events are enabled via enableEvents. + *
        • A {@code MouseWheelListener} object is registered + * via {@code addMouseWheelListener}. + *
        • Mouse wheel events are enabled via {@code enableEvents}. *
        *

        * For information on how mouse wheel events are dispatched, see * the class description for {@link MouseWheelEvent}. *

        - * Note that if the event parameter is null + * Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6700,17 +6700,17 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Processes input method events occurring on this component by * dispatching them to any registered - * InputMethodListener objects. + * {@code InputMethodListener} objects. *

        * This method is not called unless input method events * are enabled for this component. Input method events are enabled * when one of the following occurs: *

          - *
        • An InputMethodListener object is registered - * via addInputMethodListener. - *
        • Input method events are enabled via enableEvents. + *
        • An {@code InputMethodListener} object is registered + * via {@code addInputMethodListener}. + *
        • Input method events are enabled via {@code enableEvents}. *
        - *

        Note that if the event parameter is null + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6739,17 +6739,17 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Processes hierarchy events occurring on this component by * dispatching them to any registered - * HierarchyListener objects. + * {@code HierarchyListener} objects. *

        * This method is not called unless hierarchy events * are enabled for this component. Hierarchy events are enabled * when one of the following occurs: *

          - *
        • An HierarchyListener object is registered - * via addHierarchyListener. - *
        • Hierarchy events are enabled via enableEvents. + *
        • An {@code HierarchyListener} object is registered + * via {@code addHierarchyListener}. + *
        • Hierarchy events are enabled via {@code enableEvents}. *
        - *

        Note that if the event parameter is null + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6775,17 +6775,17 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Processes hierarchy bounds events occurring on this component by * dispatching them to any registered - * HierarchyBoundsListener objects. + * {@code HierarchyBoundsListener} objects. *

        * This method is not called unless hierarchy bounds events * are enabled for this component. Hierarchy bounds events are enabled * when one of the following occurs: *

          - *
        • An HierarchyBoundsListener object is registered - * via addHierarchyBoundsListener. - *
        • Hierarchy bounds events are enabled via enableEvents. + *
        • An {@code HierarchyBoundsListener} object is registered + * via {@code addHierarchyBoundsListener}. + *
        • Hierarchy bounds events are enabled via {@code enableEvents}. *
        - *

        Note that if the event parameter is null + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -6972,7 +6972,7 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Makes this Component displayable by connecting it to a + * Makes this {@code Component} displayable by connecting it to a * native screen resource. * This method is called internally by the toolkit and should * not be called directly by programs. @@ -7076,12 +7076,12 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Makes this Component undisplayable by destroying it native + * Makes this {@code Component} undisplayable by destroying it native * screen resource. *

        * This method is called by the toolkit internally and should * not be called directly by programs. Code overriding - * this method should call super.removeNotify as + * this method should call {@code super.removeNotify} as * the first line of the overriding method. * * @see #isDisplayable @@ -7193,14 +7193,14 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Returns whether this Component can become the focus + * Returns whether this {@code Component} can become the focus * owner. * - * @return true if this Component is - * focusable; false otherwise + * @return {@code true} if this {@code Component} is + * focusable; {@code false} otherwise * @see #setFocusable * @since 1.1 - * @deprecated As of 1.4, replaced by isFocusable(). + * @deprecated As of 1.4, replaced by {@code isFocusable()}. */ @Deprecated public boolean isFocusTraversable() { @@ -7213,8 +7213,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns whether this Component can be focused. * - * @return true if this Component is focusable; - * false otherwise. + * @return {@code true} if this Component is focusable; + * {@code false} otherwise. * @see #setFocusable * @since 1.4 */ @@ -7334,7 +7334,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns the Set of focus traversal keys for a given traversal operation * for this Component. (See - * setFocusTraversalKeys for a full description of each key.) + * {@code setFocusTraversalKeys} for a full description of each key.) *

        * If a Set of traversal keys has not been explicitly defined for this * Component, then this Component's parent's Set is returned. If no Set @@ -7434,15 +7434,15 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns whether the Set of focus traversal keys for the given focus * traversal operation has been explicitly defined for this Component. If - * this method returns false, this Component is inheriting the + * this method returns {@code false}, this Component is inheriting the * Set from an ancestor, or from the current KeyboardFocusManager. * * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS - * @return true if the Set of focus traversal keys for the + * @return {@code true} if the Set of focus traversal keys for the * given focus traversal operation has been explicitly defined for - * this Component; false otherwise. + * this Component; {@code false} otherwise. * @throws IllegalArgumentException if id is not one of * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or @@ -7515,12 +7515,12 @@ public abstract class Component implements ImageObserver, MenuContainer, * Window is later focused by the user. *

        * This method cannot be used to set the focus owner to no Component at - * all. Use KeyboardFocusManager.clearGlobalFocusOwner() + * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner()} * instead. *

        * Because the focus behavior of this method is platform-dependent, * developers are strongly encouraged to use - * requestFocusInWindow when possible. + * {@code requestFocusInWindow} when possible. * *

        Note: Not all focus transfers result from invoking this method. As * such, a component may receive focus without this or any of the other @@ -7543,9 +7543,9 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Requests that this Component get the input focus, - * and that this Component's top-level ancestor - * become the focused Window. This component must be + * Requests that this {@code Component} get the input focus, + * and that this {@code Component}'s top-level ancestor + * become the focused {@code Window}. This component must be * displayable, focusable, visible and all of its ancestors (with * the exception of the top-level Window) must be visible for the * request to be granted. Every effort will be made to honor the @@ -7557,29 +7557,29 @@ public abstract class Component implements ImageObserver, MenuContainer, * will be remembered and will be granted when the window is later * focused by the user. *

        - * This method returns a boolean value. If false is returned, - * the request is guaranteed to fail. If true is + * This method returns a boolean value. If {@code false} is returned, + * the request is guaranteed to fail. If {@code true} is * returned, the request will succeed unless it is vetoed, or an * extraordinary event, such as disposal of the component's peer, occurs * before the request can be granted by the native windowing system. Again, - * while a return value of true indicates that the request is + * while a return value of {@code true} indicates that the request is * likely to succeed, developers must never assume that this component is * the focus owner until this component receives a FOCUS_GAINED event. *

        * This method cannot be used to set the focus owner to no component at - * all. Use KeyboardFocusManager.clearGlobalFocusOwner + * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner} * instead. *

        * Because the focus behavior of this method is platform-dependent, * developers are strongly encouraged to use - * requestFocusInWindow when possible. + * {@code requestFocusInWindow} when possible. *

        - * Every effort will be made to ensure that FocusEvents + * Every effort will be made to ensure that {@code FocusEvent}s * generated as a * result of this request will have the specified temporary value. However, * because specifying an arbitrary temporary state may not be implementable * on all native windowing systems, correct behavior for this method can be - * guaranteed only for lightweight Components. + * guaranteed only for lightweight {@code Component}s. * This method is not intended * for general use, but exists instead as a hook for lightweight component * libraries, such as Swing. @@ -7592,8 +7592,8 @@ public abstract class Component implements ImageObserver, MenuContainer, * such as when the window loses the focus; for * more information on temporary focus changes see the *Focus Specification - * @return false if the focus change request is guaranteed to - * fail; true if it is likely to succeed + * @return {@code false} if the focus change request is guaranteed to + * fail; {@code true} if it is likely to succeed * @see java.awt.event.FocusEvent * @see #addFocusListener * @see #isFocusable @@ -7619,31 +7619,31 @@ public abstract class Component implements ImageObserver, MenuContainer, * assume that this Component is the focus owner until this * Component receives a FOCUS_GAINED event. *

        - * This method returns a boolean value. If false is returned, - * the request is guaranteed to fail. If true is + * This method returns a boolean value. If {@code false} is returned, + * the request is guaranteed to fail. If {@code true} is * returned, the request will succeed unless it is vetoed, or an * extraordinary event, such as disposal of the Component's peer, occurs * before the request can be granted by the native windowing system. Again, - * while a return value of true indicates that the request is + * while a return value of {@code true} indicates that the request is * likely to succeed, developers must never assume that this Component is * the focus owner until this Component receives a FOCUS_GAINED event. *

        * This method cannot be used to set the focus owner to no Component at - * all. Use KeyboardFocusManager.clearGlobalFocusOwner() + * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner()} * instead. *

        * The focus behavior of this method can be implemented uniformly across * platforms, and thus developers are strongly encouraged to use this - * method over requestFocus when possible. Code which relies - * on requestFocus may exhibit different focus behavior on + * method over {@code requestFocus} when possible. Code which relies + * on {@code requestFocus} may exhibit different focus behavior on * different platforms. * *

        Note: Not all focus transfers result from invoking this method. As * such, a component may receive focus without this or any of the other * {@code requestFocus} methods of {@code Component} being invoked. * - * @return false if the focus change request is guaranteed to - * fail; true if it is likely to succeed + * @return {@code false} if the focus change request is guaranteed to + * fail; {@code true} if it is likely to succeed * @see #requestFocus * @see java.awt.event.FocusEvent * @see #addFocusListener @@ -7661,9 +7661,9 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Requests that this Component get the input focus, - * if this Component's top-level ancestor is already - * the focused Window. This component must be + * Requests that this {@code Component} get the input focus, + * if this {@code Component}'s top-level ancestor is already + * the focused {@code Window}. This component must be * displayable, focusable, visible and all of its ancestors (with * the exception of the top-level Window) must be visible for the * request to be granted. Every effort will be made to honor the @@ -7671,26 +7671,26 @@ public abstract class Component implements ImageObserver, MenuContainer, * so. Developers must never assume that this component is the * focus owner until this component receives a FOCUS_GAINED event. *

        - * This method returns a boolean value. If false is returned, - * the request is guaranteed to fail. If true is + * This method returns a boolean value. If {@code false} is returned, + * the request is guaranteed to fail. If {@code true} is * returned, the request will succeed unless it is vetoed, or an * extraordinary event, such as disposal of the component's peer, occurs * before the request can be granted by the native windowing system. Again, - * while a return value of true indicates that the request is + * while a return value of {@code true} indicates that the request is * likely to succeed, developers must never assume that this component is * the focus owner until this component receives a FOCUS_GAINED event. *

        * This method cannot be used to set the focus owner to no component at - * all. Use KeyboardFocusManager.clearGlobalFocusOwner + * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner} * instead. *

        * The focus behavior of this method can be implemented uniformly across * platforms, and thus developers are strongly encouraged to use this - * method over requestFocus when possible. Code which relies - * on requestFocus may exhibit different focus behavior on + * method over {@code requestFocus} when possible. Code which relies + * on {@code requestFocus} may exhibit different focus behavior on * different platforms. *

        - * Every effort will be made to ensure that FocusEvents + * Every effort will be made to ensure that {@code FocusEvent}s * generated as a * result of this request will have the specified temporary value. However, * because specifying an arbitrary temporary state may not be implementable @@ -7707,8 +7707,8 @@ public abstract class Component implements ImageObserver, MenuContainer, * such as when the window loses the focus; for * more information on temporary focus changes see the *Focus Specification - * @return false if the focus change request is guaranteed to - * fail; true if it is likely to succeed + * @return {@code false} if the focus change request is guaranteed to + * fail; {@code true} if it is likely to succeed * @see #requestFocus * @see java.awt.event.FocusEvent * @see #addFocusListener @@ -7943,8 +7943,8 @@ public abstract class Component implements ImageObserver, MenuContainer, * belongs to only a single focus traversal cycle. * * @param container the Container to be tested - * @return true if the specified Container is a focus-cycle- - * root of this Component; false otherwise + * @return {@code true} if the specified Container is a focus-cycle- + * root of this Component; {@code false} otherwise * @see Container#isFocusCycleRoot() * @since 1.4 */ @@ -8125,12 +8125,12 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Returns true if this Component is the + * Returns {@code true} if this {@code Component} is the * focus owner. This method is obsolete, and has been replaced by - * isFocusOwner(). + * {@code isFocusOwner()}. * - * @return true if this Component is the - * focus owner; false otherwise + * @return {@code true} if this {@code Component} is the + * focus owner; {@code false} otherwise * @since 1.2 */ public boolean hasFocus() { @@ -8139,11 +8139,11 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Returns true if this Component is the + * Returns {@code true} if this {@code Component} is the * focus owner. * - * @return true if this Component is the - * focus owner; false otherwise + * @return {@code true} if this {@code Component} is the + * focus owner; {@code false} otherwise * @since 1.4 */ public boolean isFocusOwner() { @@ -8222,7 +8222,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return a string representation of this component's state * @since 1.0 @@ -8247,7 +8247,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Prints a listing of this component to the standard system output - * stream System.out. + * stream {@code System.out}. * @see java.lang.System#out * @since 1.0 */ @@ -8342,10 +8342,10 @@ public abstract class Component implements ImageObserver, MenuContainer, *

      • this Component's maximum size ("maximumSize")
      • *
      • this Component's name ("name")
      • *
      - * Note that if this Component is inheriting a bound property, then no + * Note that if this {@code Component} is inheriting a bound property, then no * event will be fired in response to a change in the inherited property. *

      - * If listener is null, + * If {@code listener} is {@code null}, * no exception is thrown and no action is performed. * * @param listener the property change listener to be added @@ -8394,7 +8394,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns an array of all the property change listeners * registered on this component. * - * @return all of this component's PropertyChangeListeners + * @return all of this component's {@code PropertyChangeListener}s * or an empty array if no property change * listeners are currently registered * @@ -8431,10 +8431,10 @@ public abstract class Component implements ImageObserver, MenuContainer, *

    • this Component's Set of UP_CYCLE_TRAVERSAL_KEYS * ("upCycleFocusTraversalKeys")
    • *
    - * Note that if this Component is inheriting a bound property, then no + * Note that if this {@code Component} is inheriting a bound property, then no * event will be fired in response to a change in the inherited property. *

    - * If propertyName or listener is null, + * If {@code propertyName} or {@code listener} is {@code null}, * no exception is thrown and no action is taken. * * @param propertyName one of the property names listed above @@ -8459,12 +8459,12 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Removes a PropertyChangeListener from the listener + * Removes a {@code PropertyChangeListener} from the listener * list for a specific property. This method should be used to remove - * PropertyChangeListeners + * {@code PropertyChangeListener}s * that were registered for a specific bound property. *

    - * If propertyName or listener is null, + * If {@code propertyName} or {@code listener} is {@code null}, * no exception is thrown and no action is taken. * * @param propertyName a valid property name @@ -8490,9 +8490,9 @@ public abstract class Component implements ImageObserver, MenuContainer, * with the named property. * * @param propertyName the property name - * @return all of the PropertyChangeListeners associated with + * @return all of the {@code PropertyChangeListener}s associated with * the named property; if no such listeners have been added or - * if propertyName is null, an empty + * if {@code propertyName} is {@code null}, an empty * array is returned * * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) @@ -8693,7 +8693,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * This hack is for Swing serialization. It will invoke - * the Swing package private method compWriteObjectNotify. + * the Swing package private method {@code compWriteObjectNotify}. */ private void doSwingSerialization() { Package swingPackage = Package.getPackage("javax.swing"); @@ -8747,31 +8747,31 @@ public abstract class Component implements ImageObserver, MenuContainer, * The non-serializable listeners are detected and * no attempt is made to serialize them. * - * @param s the ObjectOutputStream to write - * @serialData null terminated sequence of - * 0 or more pairs; the pair consists of a String - * and an Object; the String indicates + * @param s the {@code ObjectOutputStream} to write + * @serialData {@code null} terminated sequence of + * 0 or more pairs; the pair consists of a {@code String} + * and an {@code Object}; the {@code String} indicates * the type of object and is one of the following (as of 1.4): - * componentListenerK indicating an - * ComponentListener object; - * focusListenerK indicating an - * FocusListener object; - * keyListenerK indicating an - * KeyListener object; - * mouseListenerK indicating an - * MouseListener object; - * mouseMotionListenerK indicating an - * MouseMotionListener object; - * inputMethodListenerK indicating an - * InputMethodListener object; - * hierarchyListenerK indicating an - * HierarchyListener object; - * hierarchyBoundsListenerK indicating an - * HierarchyBoundsListener object; - * mouseWheelListenerK indicating an - * MouseWheelListener object - * @serialData an optional ComponentOrientation - * (after inputMethodListener, as of 1.2) + * {@code componentListenerK} indicating an + * {@code ComponentListener} object; + * {@code focusListenerK} indicating an + * {@code FocusListener} object; + * {@code keyListenerK} indicating an + * {@code KeyListener} object; + * {@code mouseListenerK} indicating an + * {@code MouseListener} object; + * {@code mouseMotionListenerK} indicating an + * {@code MouseMotionListener} object; + * {@code inputMethodListenerK} indicating an + * {@code InputMethodListener} object; + * {@code hierarchyListenerK} indicating an + * {@code HierarchyListener} object; + * {@code hierarchyBoundsListenerK} indicating an + * {@code HierarchyBoundsListener} object; + * {@code mouseWheelListenerK} indicating an + * {@code MouseWheelListener} object + * @serialData an optional {@code ComponentOrientation} + * (after {@code inputMethodListener}, as of 1.2) * * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener) * @see #componentListenerK @@ -8813,12 +8813,12 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Reads the ObjectInputStream and if it isn't - * null adds a listener to receive a variety + * Reads the {@code ObjectInputStream} and if it isn't + * {@code null} adds a listener to receive a variety * of events fired by the component. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @see #writeObject(ObjectOutputStream) */ private void readObject(ObjectInputStream s) @@ -8960,15 +8960,15 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Sets the language-sensitive orientation that is to be used to order * the elements or text within this component. Language-sensitive - * LayoutManager and Component + * {@code LayoutManager} and {@code Component} * subclasses will use this property to * determine how to lay out and draw components. *

    * At construction time, a component's orientation is set to - * ComponentOrientation.UNKNOWN, + * {@code ComponentOrientation.UNKNOWN}, * indicating that it has not been specified * explicitly. The UNKNOWN orientation behaves the same as - * ComponentOrientation.LEFT_TO_RIGHT. + * {@code ComponentOrientation.LEFT_TO_RIGHT}. *

    * To set the orientation of a single component, use this method. * To set the orientation of an entire component @@ -8999,8 +8999,8 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Retrieves the language-sensitive orientation that is to be used to order - * the elements or text within this component. LayoutManager - * and Component + * the elements or text within this component. {@code LayoutManager} + * and {@code Component} * subclasses that wish to respect orientation should call this method to * get the component's orientation before performing layout or drawing. * @@ -9014,7 +9014,7 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Sets the ComponentOrientation property of this component + * Sets the {@code ComponentOrientation} property of this component * and all components contained within it. *

    * This method changes layout-related information, and therefore, @@ -9023,7 +9023,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * * @param orientation the new component orientation of this component and * the components contained within it. - * @exception NullPointerException if orientation is null. + * @exception NullPointerException if {@code orientation} is null. * @see #setComponentOrientation * @see #getComponentOrientation * @see #invalidate @@ -9091,7 +9091,7 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Returns the Window ancestor of the component. + * Returns the {@code Window} ancestor of the component. * @return Window ancestor of the component or component by itself if it is Window; * null, if component is not a part of window hierarchy */ @@ -9118,16 +9118,16 @@ public abstract class Component implements ImageObserver, MenuContainer, protected AccessibleContext accessibleContext = null; /** - * Gets the AccessibleContext associated - * with this Component. + * Gets the {@code AccessibleContext} associated + * with this {@code Component}. * The method implemented by this base - * class returns null. Classes that extend Component + * class returns null. Classes that extend {@code Component} * should implement this method to return the - * AccessibleContext associated with the subclass. + * {@code AccessibleContext} associated with the subclass. * * - * @return the AccessibleContext of this - * Component + * @return the {@code AccessibleContext} of this + * {@code Component} * @since 1.3 */ public AccessibleContext getAccessibleContext() { @@ -9228,7 +9228,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** - * Adds a PropertyChangeListener to the listener list. + * Adds a {@code PropertyChangeListener} to the listener list. * * @param listener the property change listener to be added */ @@ -9265,7 +9265,7 @@ public abstract class Component implements ImageObserver, MenuContainer, // /** * Gets the accessible name of this object. This should almost never - * return java.awt.Component.getName(), + * return {@code java.awt.Component.getName()}, * as that generally isn't a localized name, * and doesn't have meaning for the user. If the * object is fundamentally a text object (e.g. a menu item), the @@ -9274,7 +9274,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * appropriate String to return. * * @return the localized name of the object -- can be - * null if this + * {@code null} if this * object does not have a name * @see javax.accessibility.AccessibleContext#setAccessibleName */ @@ -9294,7 +9294,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * text document" instead). * * @return the localized description of the object -- can be - * null if this object does not have a description + * {@code null} if this object does not have a description * @see javax.accessibility.AccessibleContext#setAccessibleDescription */ public String getAccessibleDescription() { @@ -9304,7 +9304,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Gets the role of this object. * - * @return an instance of AccessibleRole + * @return an instance of {@code AccessibleRole} * describing the role of the object * @see javax.accessibility.AccessibleRole */ @@ -9315,7 +9315,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Gets the state of this object. * - * @return an instance of AccessibleStateSet + * @return an instance of {@code AccessibleStateSet} * containing the current state set of the object * @see javax.accessibility.AccessibleState */ @@ -9324,13 +9324,13 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Gets the Accessible parent of this object. - * If the parent of this object implements Accessible, - * this method should simply return getParent. + * Gets the {@code Accessible} parent of this object. + * If the parent of this object implements {@code Accessible}, + * this method should simply return {@code getParent}. * - * @return the Accessible parent of this - * object -- can be null if this - * object does not have an Accessible parent + * @return the {@code Accessible} parent of this + * object -- can be {@code null} if this + * object does not have an {@code Accessible} parent */ public Accessible getAccessibleParent() { if (accessibleParent != null) { @@ -9357,7 +9357,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns the number of accessible children in the object. If all - * of the children of this object implement Accessible, + * of the children of this object implement {@code Accessible}, * then this method should return the number of children of this object. * * @return the number of accessible children in the object @@ -9367,10 +9367,10 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Returns the nth Accessible child of the object. + * Returns the nth {@code Accessible} child of the object. * * @param i zero-based index of child - * @return the nth Accessible child of the object + * @return the nth {@code Accessible} child of the object */ public Accessible getAccessibleChild(int i) { return null; // Components don't have children @@ -9386,9 +9386,9 @@ public abstract class Component implements ImageObserver, MenuContainer, } /** - * Gets the AccessibleComponent associated + * Gets the {@code AccessibleComponent} associated * with this object if one exists. - * Otherwise return null. + * Otherwise return {@code null}. * * @return the component */ @@ -9403,7 +9403,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Gets the background color of this object. * * @return the background color, if supported, of the object; - * otherwise, null + * otherwise, {@code null} */ public Color getBackground() { return Component.this.getBackground(); @@ -9411,9 +9411,9 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Sets the background color of this object. - * (For transparency, see isOpaque.) + * (For transparency, see {@code isOpaque}.) * - * @param c the new Color for the background + * @param c the new {@code Color} for the background * @see Component#isOpaque */ public void setBackground(Color c) { @@ -9424,7 +9424,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Gets the foreground color of this object. * * @return the foreground color, if supported, of the object; - * otherwise, null + * otherwise, {@code null} */ public Color getForeground() { return Component.this.getForeground(); @@ -9433,59 +9433,59 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Sets the foreground color of this object. * - * @param c the new Color for the foreground + * @param c the new {@code Color} for the foreground */ public void setForeground(Color c) { Component.this.setForeground(c); } /** - * Gets the Cursor of this object. + * Gets the {@code Cursor} of this object. * - * @return the Cursor, if supported, - * of the object; otherwise, null + * @return the {@code Cursor}, if supported, + * of the object; otherwise, {@code null} */ public Cursor getCursor() { return Component.this.getCursor(); } /** - * Sets the Cursor of this object. + * Sets the {@code Cursor} of this object. *

    * The method may have no visual effect if the Java platform * implementation and/or the native system do not support * changing the mouse cursor shape. - * @param cursor the new Cursor for the object + * @param cursor the new {@code Cursor} for the object */ public void setCursor(Cursor cursor) { Component.this.setCursor(cursor); } /** - * Gets the Font of this object. + * Gets the {@code Font} of this object. * - * @return the Font, if supported, - * for the object; otherwise, null + * @return the {@code Font}, if supported, + * for the object; otherwise, {@code null} */ public Font getFont() { return Component.this.getFont(); } /** - * Sets the Font of this object. + * Sets the {@code Font} of this object. * - * @param f the new Font for the object + * @param f the new {@code Font} for the object */ public void setFont(Font f) { Component.this.setFont(f); } /** - * Gets the FontMetrics of this object. + * Gets the {@code FontMetrics} of this object. * - * @param f the Font - * @return the FontMetrics, if supported, - * the object; otherwise, null + * @param f the {@code Font} + * @return the {@code FontMetrics}, if supported, + * the object; otherwise, {@code null} * @see #getFont */ public FontMetrics getFontMetrics(Font f) { @@ -9533,7 +9533,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * object intends to be visible; however, it may not in fact be * showing on the screen because one of the objects that this object * is contained by is not visible. To determine if an object is - * showing on the screen, use isShowing. + * showing on the screen, use {@code isShowing}. * * @return true if object is visible; otherwise, false */ @@ -9582,9 +9582,9 @@ public abstract class Component implements ImageObserver, MenuContainer, * where the point's x and y coordinates are defined to be relative to * the coordinate system of the object. * - * @param p the Point relative to the + * @param p the {@code Point} relative to the * coordinate system of the object - * @return true if object contains Point; otherwise false + * @return true if object contains {@code Point}; otherwise false */ public boolean contains(Point p) { return Component.this.contains(p); @@ -9594,7 +9594,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Returns the location of the object on the screen. * * @return location of object on screen -- can be - * null if this object is not on the screen + * {@code null} if this object is not on the screen */ public Point getLocationOnScreen() { synchronized (Component.this.getTreeLock()) { @@ -9613,7 +9613,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * * @return an instance of Point representing the top-left corner of * the object's bounds in the coordinate space of the screen; - * null if this object or its parent are not on the screen + * {@code null} if this object or its parent are not on the screen */ public Point getLocation() { return Component.this.getLocation(); @@ -9633,7 +9633,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * relative to its parent. * * @return a rectangle indicating this component's bounds; - * null if this object is not on the screen + * {@code null} if this object is not on the screen */ public Rectangle getBounds() { return Component.this.getBounds(); @@ -9641,7 +9641,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Sets the bounds of this object in the form of a - * Rectangle object. + * {@code Rectangle} object. * The bounds specify this object's width, height, and location * relative to its parent. * @@ -9653,13 +9653,13 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Returns the size of this object in the form of a - * Dimension object. The height field of the - * Dimension object contains this object's - * height, and the width field of the Dimension + * {@code Dimension} object. The height field of the + * {@code Dimension} object contains this object's + * height, and the width field of the {@code Dimension} * object contains this object's width. * - * @return a Dimension object that indicates - * the size of this component; null if + * @return a {@code Dimension} object that indicates + * the size of this component; {@code null} if * this object is not on the screen */ public Dimension getSize() { @@ -9669,23 +9669,23 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Resizes this object so that it has width and height. * - * @param d - the dimension specifying the new size of the object + * @param d the dimension specifying the new size of the object */ public void setSize(Dimension d) { Component.this.setSize(d); } /** - * Returns the Accessible child, + * Returns the {@code Accessible} child, * if one exists, contained at the local - * coordinate Point. Otherwise returns - * null. + * coordinate {@code Point}. Otherwise returns + * {@code null}. * * @param p the point defining the top-left corner of - * the Accessible, given in the + * the {@code Accessible}, given in the * coordinate space of the object's parent - * @return the Accessible, if it exists, - * at the specified location; else null + * @return the {@code Accessible}, if it exists, + * at the specified location; else {@code null} */ public Accessible getAccessibleAt(Point p) { return null; // Components don't have children @@ -9759,7 +9759,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Gets the current state set of this object. * - * @return an instance of AccessibleStateSet + * @return an instance of {@code AccessibleStateSet} * containing the current state set of the object * @see AccessibleState */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/ComponentOrientation.java b/jdk/src/java.desktop/share/classes/java/awt/ComponentOrientation.java index 8b67ea0cdde..4df1846a5da 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ComponentOrientation.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ComponentOrientation.java @@ -72,8 +72,8 @@ import java.util.ResourceBundle; *

  • TL - Mongolian *
* Components whose view and controller code depends on orientation - * should use the isLeftToRight() and - * isHorizontal() methods to + * should use the {@code isLeftToRight()} and + * {@code isHorizontal()} methods to * determine their behavior. They should not include switch-like * code that keys off of the constants, such as: *
diff --git a/jdk/src/java.desktop/share/classes/java/awt/Composite.java b/jdk/src/java.desktop/share/classes/java/awt/Composite.java
index 4ce58a06daa..d86b73abac3 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/Composite.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/Composite.java
@@ -28,39 +28,39 @@ package java.awt;
 import java.awt.image.ColorModel;
 
 /**
- * The Composite interface, along with
+ * The {@code Composite} interface, along with
  * {@link CompositeContext}, defines the methods to compose a draw
  * primitive with the underlying graphics area.
- * After the Composite is set in the
+ * After the {@code Composite} is set in the
  * {@link Graphics2D} context, it combines a shape, text, or an image
  * being rendered with the colors that have already been rendered
  * according to pre-defined rules. The classes
  * implementing this interface provide the rules and a method to create
  * the context for a particular operation.
- * CompositeContext is an environment used by the
- * compositing operation, which is created by the Graphics2D
- * prior to the start of the operation.  CompositeContext
+ * {@code CompositeContext} is an environment used by the
+ * compositing operation, which is created by the {@code Graphics2D}
+ * prior to the start of the operation.  {@code CompositeContext}
  * contains private information and resources needed for a compositing
- * operation.  When the CompositeContext is no longer needed,
- * the Graphics2D object disposes of it in order to reclaim
+ * operation.  When the {@code CompositeContext} is no longer needed,
+ * the {@code Graphics2D} object disposes of it in order to reclaim
  * resources allocated for the operation.
  * 

- * Instances of classes implementing Composite must be - * immutable because the Graphics2D does not clone + * Instances of classes implementing {@code Composite} must be + * immutable because the {@code Graphics2D} does not clone * these objects when they are set as an attribute with the - * setComposite method or when the Graphics2D + * {@code setComposite} method or when the {@code Graphics2D} * object is cloned. This is to avoid undefined rendering behavior of - * Graphics2D, resulting from the modification of - * the Composite object after it has been set in the - * Graphics2D context. + * {@code Graphics2D}, resulting from the modification of + * the {@code Composite} object after it has been set in the + * {@code Graphics2D} context. *

* Since this interface must expose the contents of pixels on the * target device or image to potentially arbitrary code, the use of * custom objects which implement this interface when rendering directly - * to a screen device is governed by the readDisplayPixels + * to a screen device is governed by the {@code readDisplayPixels} * {@link AWTPermission}. The permission check will occur when such - * a custom object is passed to the setComposite method - * of a Graphics2D retrieved from a {@link Component}. + * a custom object is passed to the {@code setComposite} method + * of a {@code Graphics2D} retrieved from a {@link Component}. * @see AlphaComposite * @see CompositeContext * @see Graphics2D#setComposite @@ -71,12 +71,12 @@ public interface Composite { * Creates a context containing state that is used to perform * the compositing operation. In a multi-threaded environment, * several contexts can exist simultaneously for a single - * Composite object. + * {@code Composite} object. * @param srcColorModel the {@link ColorModel} of the source - * @param dstColorModel the ColorModel of the destination + * @param dstColorModel the {@code ColorModel} of the destination * @param hints the hint that the context object uses to choose between * rendering alternatives - * @return the CompositeContext object used to perform the + * @return the {@code CompositeContext} object used to perform the * compositing operation. */ public CompositeContext createContext(ColorModel srcColorModel, diff --git a/jdk/src/java.desktop/share/classes/java/awt/CompositeContext.java b/jdk/src/java.desktop/share/classes/java/awt/CompositeContext.java index 60f2ecd3032..525aee73c28 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/CompositeContext.java +++ b/jdk/src/java.desktop/share/classes/java/awt/CompositeContext.java @@ -29,9 +29,9 @@ import java.awt.image.Raster; import java.awt.image.WritableRaster; /** - * The CompositeContext interface defines the encapsulated + * The {@code CompositeContext} interface defines the encapsulated * and optimized environment for a compositing operation. - * CompositeContext objects maintain state for + * {@code CompositeContext} objects maintain state for * compositing operations. In a multi-threaded environment, several * contexts can exist simultaneously for a single {@link Composite} * object. @@ -49,14 +49,14 @@ public interface CompositeContext { * places the result in the destination * {@link WritableRaster}. Note that the destination * can be the same object as either the first or second - * source. Note that dstIn and - * dstOut must be compatible with the - * dstColorModel passed to the + * source. Note that {@code dstIn} and + * {@code dstOut} must be compatible with the + * {@code dstColorModel} passed to the * {@link Composite#createContext(java.awt.image.ColorModel, java.awt.image.ColorModel, java.awt.RenderingHints) createContext} - * method of the Composite interface. + * method of the {@code Composite} interface. * @param src the first source for the compositing operation * @param dstIn the second source for the compositing operation - * @param dstOut the WritableRaster into which the + * @param dstOut the {@code WritableRaster} into which the * result of the operation is stored * @see Composite */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Container.java b/jdk/src/java.desktop/share/classes/java/awt/Container.java index f3e7b3b5d6e..a16c2f55d97 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Container.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Container.java @@ -183,7 +183,7 @@ public class Container extends Component { /** * A constant which toggles one of the controllable behaviors - * of getMouseEventTarget. It is used to specify whether + * of {@code getMouseEventTarget}. It is used to specify whether * the method can return the Container on which it is originally called * in case if none of its children are the current mouse event targets. * @@ -193,7 +193,7 @@ public class Container extends Component { /** * A constant which toggles one of the controllable behaviors - * of getMouseEventTarget. It is used to specify whether + * of {@code getMouseEventTarget}. It is used to specify whether * the method should search only lightweight components. * * @see #getMouseEventTarget(int, int, boolean) @@ -384,7 +384,7 @@ public class Container extends Component { * Determines the insets of this container, which indicate the size * of the container's border. *

- * A Frame object, for example, has a top inset that + * A {@code Frame} object, for example, has a top inset that * corresponds to the height of the frame's title bar. * @return the insets of this container. * @see Insets @@ -399,7 +399,7 @@ public class Container extends Component { * Returns the insets for this container. * * @deprecated As of JDK version 1.1, - * replaced by getInsets(). + * replaced by {@code getInsets()}. * @return the insets for this container */ @Deprecated @@ -439,7 +439,7 @@ public class Container extends Component { * This is a convenience method for {@link #addImpl}. *

* This method is obsolete as of 1.1. Please use the - * method add(Component, Object) instead. + * method {@code add(Component, Object)} instead. *

* This method changes layout-related information, and therefore, * invalidates the component hierarchy. If the container has already been @@ -471,11 +471,11 @@ public class Container extends Component { * * @param comp the component to be added * @param index the position at which to insert the component, - * or -1 to append the component to the end + * or {@code -1} to append the component to the end * @exception NullPointerException if {@code comp} is {@code null} * @exception IllegalArgumentException if {@code index} is invalid (see * {@link #addImpl} for details) - * @return the component comp + * @return the component {@code comp} * @see #addImpl * @see #remove * @see #invalidate @@ -532,7 +532,7 @@ public class Container extends Component { if (comp.parent == this) { if (index == component.size()) { throw new IllegalArgumentException("illegal component position " + - index + " should be less then " + component.size()); + index + " should be less than " + component.size()); } } checkAddToSelf(comp); @@ -734,40 +734,40 @@ public class Container extends Component { * If the component is a child of some other container, it is * removed from that container before being added to this container. * The important difference between this method and - * java.awt.Container.add(Component, int) is that this method - * doesn't call removeNotify on the component while + * {@code java.awt.Container.add(Component, int)} is that this method + * doesn't call {@code removeNotify} on the component while * removing it from its previous container unless necessary and when * allowed by the underlying native windowing system. This way, if the * component has the keyboard focus, it maintains the focus when * moved to the new position. *

* This property is guaranteed to apply only to lightweight - * non-Container components. + * non-{@code Container} components. *

* This method changes layout-related information, and therefore, * invalidates the component hierarchy. *

* Note: Not all platforms support changing the z-order of * heavyweight components from one container into another without - * the call to removeNotify. There is no way to detect + * the call to {@code removeNotify}. There is no way to detect * whether a platform supports this, so developers shouldn't make * any assumptions. * * @param comp the component to be moved * @param index the position in the container's list to - * insert the component, where getComponentCount() + * insert the component, where {@code getComponentCount()} * appends to the end - * @exception NullPointerException if comp is - * null - * @exception IllegalArgumentException if comp is one of the + * @exception NullPointerException if {@code comp} is + * {@code null} + * @exception IllegalArgumentException if {@code comp} is one of the * container's parents - * @exception IllegalArgumentException if index is not in - * the range [0, getComponentCount()] for moving + * @exception IllegalArgumentException if {@code index} is not in + * the range {@code [0, getComponentCount()]} for moving * between containers, or not in the range - * [0, getComponentCount()-1] for moving inside + * {@code [0, getComponentCount()-1]} for moving inside * a container * @exception IllegalArgumentException if adding a container to itself - * @exception IllegalArgumentException if adding a Window + * @exception IllegalArgumentException if adding a {@code Window} * to a container * @see #getComponentZOrder(java.awt.Component) * @see #invalidate @@ -949,7 +949,7 @@ public class Container extends Component { * * @param comp the component being queried * @return the z-order index of the component; otherwise - * returns -1 if the component is null + * returns -1 if the component is {@code null} * or doesn't belong to the container * @see #setComponentZOrder(java.awt.Component, int) * @since 1.5 @@ -1010,7 +1010,7 @@ public class Container extends Component { * @param comp the component to be added * @param constraints an object expressing layout constraints for this * @param index the position in the container's list at which to insert - * the component; -1 means insert at the end + * the component; {@code -1} means insert at the end * component * @exception NullPointerException if {@code comp} is {@code null} * @exception IllegalArgumentException if {@code index} is invalid (see @@ -1030,20 +1030,20 @@ public class Container extends Component { * Adds the specified component to this container at the specified * index. This method also notifies the layout manager to add * the component to this container's layout using the specified - * constraints object via the addLayoutComponent + * constraints object via the {@code addLayoutComponent} * method. *

* The constraints are * defined by the particular layout manager being used. For - * example, the BorderLayout class defines five - * constraints: BorderLayout.NORTH, - * BorderLayout.SOUTH, BorderLayout.EAST, - * BorderLayout.WEST, and BorderLayout.CENTER. + * example, the {@code BorderLayout} class defines five + * constraints: {@code BorderLayout.NORTH}, + * {@code BorderLayout.SOUTH}, {@code BorderLayout.EAST}, + * {@code BorderLayout.WEST}, and {@code BorderLayout.CENTER}. *

- * The GridBagLayout class requires a - * GridBagConstraints object. Failure to pass + * The {@code GridBagLayout} class requires a + * {@code GridBagConstraints} object. Failure to pass * the correct type of constraints object results in an - * IllegalArgumentException. + * {@code IllegalArgumentException}. *

* If the current layout manager implements {@code LayoutManager2}, then * {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on @@ -1061,7 +1061,7 @@ public class Container extends Component { * usually include a call to the superclass's version of the method: * *

- * super.addImpl(comp, constraints, index) + * {@code super.addImpl(comp, constraints, index)} *
*

* This method changes layout-related information, and therefore, @@ -1073,7 +1073,7 @@ public class Container extends Component { * @param constraints an object expressing layout constraints * for this component * @param index the position in the container's list at which to - * insert the component, where -1 + * insert the component, where {@code -1} * means append to the end * @exception IllegalArgumentException if {@code index} is invalid; * if {@code comp} is a child of this container, the valid @@ -1196,11 +1196,11 @@ public class Container extends Component { } /** - * Removes the component, specified by index, + * Removes the component, specified by {@code index}, * from this container. * This method also notifies the layout manager to remove the * component from this container's layout via the - * removeLayoutComponent method. + * {@code removeLayoutComponent} method. *

* This method changes layout-related information, and therefore, * invalidates the component hierarchy. If the container has already been @@ -1263,7 +1263,7 @@ public class Container extends Component { * Removes the specified component from this container. * This method also notifies the layout manager to remove the * component from this container's layout via the - * removeLayoutComponent method. + * {@code removeLayoutComponent} method. *

* This method changes layout-related information, and therefore, * invalidates the component hierarchy. If the container has already been @@ -1292,7 +1292,7 @@ public class Container extends Component { * Removes all the components from this container. * This method also notifies the layout manager to remove the * components from this container's layout via the - * removeLayoutComponent method. + * {@code removeLayoutComponent} method. *

* This method changes layout-related information, and therefore, * invalidates the component hierarchy. If the container has already been @@ -1512,7 +1512,7 @@ public class Container extends Component { /** * Causes this container to lay out its components. Most programs * should not call this method directly, but should invoke - * the validate method instead. + * the {@code validate} method instead. * @see LayoutManager#layoutContainer * @see #setLayout * @see #validate @@ -1524,7 +1524,7 @@ public class Container extends Component { /** * @deprecated As of JDK version 1.1, - * replaced by doLayout(). + * replaced by {@code doLayout()}. */ @Deprecated public void layout() { @@ -1703,7 +1703,7 @@ public class Container extends Component { * Recursively descends the container tree and recomputes the * layout for any subtrees marked as needing it (those marked as * invalid). Synchronization should be provided by the method - * that calls this one: validate. + * that calls this one: {@code validate}. * * @see #doLayout * @see #validate @@ -1791,7 +1791,7 @@ public class Container extends Component { * this method is invoked, rather the {@code LayoutManager} will only * be queried after the {@code Container} becomes invalid. * - * @return an instance of Dimension that represents + * @return an instance of {@code Dimension} that represents * the preferred size of this container. * @see #getMinimumSize * @see #getMaximumSize @@ -1805,7 +1805,7 @@ public class Container extends Component { /** * @deprecated As of JDK version 1.1, - * replaced by getPreferredSize(). + * replaced by {@code getPreferredSize()}. */ @Deprecated public Dimension preferredSize() { @@ -1842,7 +1842,7 @@ public class Container extends Component { * this method is invoked, rather the {@code LayoutManager} will only * be queried after the {@code Container} becomes invalid. * - * @return an instance of Dimension that represents + * @return an instance of {@code Dimension} that represents * the minimum size of this container. * @see #getPreferredSize * @see #getMaximumSize @@ -1857,7 +1857,7 @@ public class Container extends Component { /** * @deprecated As of JDK version 1.1, - * replaced by getMinimumSize(). + * replaced by {@code getMinimumSize()}. */ @Deprecated public Dimension minimumSize() { @@ -1895,7 +1895,7 @@ public class Container extends Component { * this method is invoked, rather the {@code LayoutManager2} will only * be queried after the {@code Container} becomes invalid. * - * @return an instance of Dimension that represents + * @return an instance of {@code Dimension} that represents * the maximum size of this container. * @see #getPreferredSize * @see #getMinimumSize @@ -2169,7 +2169,7 @@ public class Container extends Component { * Returns an array of all the container listeners * registered on this container. * - * @return all of this container's ContainerListeners + * @return all of this container's {@code ContainerListener}s * or an empty array if no container * listeners are currently registered * @@ -2184,16 +2184,16 @@ public class Container extends Component { /** * Returns an array of all the objects currently registered * as FooListeners - * upon this Container. + * upon this {@code Container}. * FooListeners are registered using the * addFooListener method. * *

- * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * Container c + * {@code Container c} * for its container listeners with the following code: * *

ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));
@@ -2202,13 +2202,13 @@ public class Container extends Component { * * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this container, * or an empty array if no such listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * @exception NullPointerException if {@code listenerType} is {@code null} * * @see #getContainerListeners @@ -2242,10 +2242,10 @@ public class Container extends Component { /** * Processes events on this container. If the event is a - * ContainerEvent, it invokes the - * processContainerEvent method, else it invokes - * its superclass's processEvent. - *

Note that if the event parameter is null + * {@code ContainerEvent}, it invokes the + * {@code processContainerEvent} method, else it invokes + * its superclass's {@code processEvent}. + *

Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -2267,10 +2267,10 @@ public class Container extends Component { * following occurs: *

    *
  • A ContainerListener object is registered via - * addContainerListener - *
  • Container events are enabled via enableEvents + * {@code addContainerListener} + *
  • Container events are enabled via {@code enableEvents} *
- *

Note that if the event parameter is null + *

Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -2365,11 +2365,11 @@ public class Container extends Component { * controllable behaviors. This method searches for the top-most * descendant of this container that contains the given coordinates * and is accepted by the given filter. The search will be constrained to - * lightweight descendants if the last argument is false. + * lightweight descendants if the last argument is {@code false}. * * @param filter EventTargetFilter instance to determine whether the * given component is a valid target for this event. - * @param searchHeavyweights if false, the method + * @param searchHeavyweights if {@code false}, the method * will bypass heavyweight components during the search. */ private Component getMouseEventTarget(int x, int y, boolean includeSelf, @@ -2399,17 +2399,17 @@ public class Container extends Component { * descendants of only lightweight children or only heavyweight children * of this container depending on searchHeavyweightChildren. The search will * be constrained to only lightweight descendants of the searched children - * of this container if searchHeavyweightDescendants is false. + * of this container if searchHeavyweightDescendants is {@code false}. * * @param filter EventTargetFilter instance to determine whether the * selected component is a valid target for this event. - * @param searchHeavyweightChildren if true, the method + * @param searchHeavyweightChildren if {@code true}, the method * will bypass immediate lightweight children during the search. - * If false, the methods will bypass immediate + * If {@code false}, the methods will bypass immediate * heavyweight children during the search. - * @param searchHeavyweightDescendants if false, the method + * @param searchHeavyweightDescendants if {@code false}, the method * will bypass heavyweight descendants which are not immediate - * children during the search. If true, the method + * children during the search. If {@code true}, the method * will traverse both lightweight and heavyweight descendants during * the search. */ @@ -2525,7 +2525,7 @@ public class Container extends Component { /** * @deprecated As of JDK version 1.1, - * replaced by dispatchEvent(AWTEvent e) + * replaced by {@code dispatchEvent(AWTEvent e)} */ @Deprecated public void deliverEvent(Event e) { @@ -2562,7 +2562,7 @@ public class Container extends Component { /** * @deprecated As of JDK version 1.1, - * replaced by getComponentAt(int, int). + * replaced by {@code getComponentAt(int, int)}. */ @Deprecated public Component locate(int x, int y) { @@ -2593,7 +2593,7 @@ public class Container extends Component { * Gets the component that contains the specified point. * @param p the point. * @return returns the component that contains the point, - * or null if the component does + * or {@code null} if the component does * not contain the point. * @see Component#contains * @since 1.1 @@ -2603,22 +2603,22 @@ public class Container extends Component { } /** - * Returns the position of the mouse pointer in this Container's - * coordinate space if the Container is under the mouse pointer, - * otherwise returns null. + * Returns the position of the mouse pointer in this {@code Container}'s + * coordinate space if the {@code Container} is under the mouse pointer, + * otherwise returns {@code null}. * This method is similar to {@link Component#getMousePosition()} with the exception - * that it can take the Container's children into account. - * If allowChildren is false, this method will return - * a non-null value only if the mouse pointer is above the Container + * that it can take the {@code Container}'s children into account. + * If {@code allowChildren} is {@code false}, this method will return + * a non-null value only if the mouse pointer is above the {@code Container} * directly, not above the part obscured by children. - * If allowChildren is true, this method returns - * a non-null value if the mouse pointer is above Container or any + * If {@code allowChildren} is {@code true}, this method returns + * a non-null value if the mouse pointer is above {@code Container} or any * of its descendants. * * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true * @param allowChildren true if children should be taken into account * @see Component#getMousePosition - * @return mouse coordinates relative to this Component, or null + * @return mouse coordinates relative to this {@code Component}, or null * @since 1.5 */ public Point getMousePosition(boolean allowChildren) throws HeadlessException { @@ -2848,8 +2848,8 @@ public class Container extends Component { * Checks if the component is contained in the component hierarchy of * this container. * @param c the component - * @return true if it is an ancestor; - * false otherwise. + * @return {@code true} if it is an ancestor; + * {@code false} otherwise. * @since 1.1 */ public boolean isAncestorOf(Component c) { @@ -2983,11 +2983,11 @@ public class Container extends Component { /* End of JOptionPane support code */ /** - * Returns a string representing the state of this Container. + * Returns a string representing the state of this {@code Container}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this container */ @@ -3005,8 +3005,8 @@ public class Container extends Component { * stream. The listing starts at the specified indentation. *

* The immediate children of the container are printed with - * an indentation of indent+1. The children - * of those children are printed at indent+2 + * an indentation of {@code indent+1}. The children + * of those children are printed at {@code indent+2} * and so on. * * @param out a print stream @@ -3032,8 +3032,8 @@ public class Container extends Component { * to the specified print writer. *

* The immediate children of the container are printed with - * an indentation of indent+1. The children - * of those children are printed at indent+2 + * an indentation of {@code indent+1}. The children + * of those children are printed at {@code indent+2} * and so on. * * @param out a print writer @@ -3147,7 +3147,7 @@ public class Container extends Component { /** * Returns the Set of focus traversal keys for a given traversal operation * for this Container. (See - * setFocusTraversalKeys for a full description of each key.) + * {@code setFocusTraversalKeys} for a full description of each key.) *

* If a Set of traversal keys has not been explicitly defined for this * Container, then this Container's parent's Set is returned. If no Set @@ -3186,16 +3186,16 @@ public class Container extends Component { /** * Returns whether the Set of focus traversal keys for the given focus * traversal operation has been explicitly defined for this Container. If - * this method returns false, this Container is inheriting the + * this method returns {@code false}, this Container is inheriting the * Set from an ancestor, or from the current KeyboardFocusManager. * * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS - * @return true if the Set of focus traversal keys for the + * @return {@code true} if the Set of focus traversal keys for the * given focus traversal operation has been explicitly defined for - * this Component; false otherwise. + * this Component; {@code false} otherwise. * @throws IllegalArgumentException if id is not one of * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, @@ -3218,12 +3218,12 @@ public class Container extends Component { * root belongs to only a single focus traversal cycle. Containers which * are focus cycle roots belong to two cycles: one rooted at the Container * itself, and one rooted at the Container's nearest focus-cycle-root - * ancestor. This method will return true for both such + * ancestor. This method will return {@code true} for both such * Containers in this case. * * @param container the Container to be tested - * @return true if the specified Container is a focus-cycle- - * root of this Container; false otherwise + * @return {@code true} if the specified Container is a focus-cycle- + * root of this Container; {@code false} otherwise * @see #isFocusCycleRoot() * @since 1.4 */ @@ -3390,11 +3390,11 @@ public class Container extends Component { /** * Returns whether the focus traversal policy has been explicitly set for - * this Container. If this method returns false, this + * this Container. If this method returns {@code false}, this * Container will inherit its focus traversal policy from an ancestor. * - * @return true if the focus traversal policy has been - * explicitly set for this Container; false otherwise. + * @return {@code true} if the focus traversal policy has been + * explicitly set for this Container; {@code false} otherwise. * @since 1.4 */ public boolean isFocusTraversalPolicySet() { @@ -3458,7 +3458,7 @@ public class Container extends Component { /** * Sets whether this container will be used to provide focus * traversal policy. Container with this property as - * true will be used to acquire focus traversal policy + * {@code true} will be used to acquire focus traversal policy * instead of closest focus cycle root ancestor. * @param provider indicates whether this container will be used to * provide focus traversal policy @@ -3478,7 +3478,7 @@ public class Container extends Component { /** * Returns whether this container provides focus traversal - * policy. If this property is set to true then when + * policy. If this property is set to {@code true} then when * keyboard focus manager searches container hierarchy for focus * traversal policy and encounters this container before any other * container with this property as true or focus cycle roots then @@ -3488,8 +3488,8 @@ public class Container extends Component { * @see #getFocusTraversalPolicy * @see #setFocusCycleRoot * @see #setFocusTraversalPolicyProvider - * @return true if this container provides focus traversal - * policy, false otherwise + * @return {@code true} if this container provides focus traversal + * policy, {@code false} otherwise * @since 1.5 */ public final boolean isFocusTraversalPolicyProvider() { @@ -3539,7 +3539,7 @@ public class Container extends Component { } /** - * Sets the ComponentOrientation property of this container + * Sets the {@code ComponentOrientation} property of this container * and all components contained within it. *

* This method changes layout-related information, and therefore, @@ -3547,7 +3547,7 @@ public class Container extends Component { * * @param o the new component orientation of this container and * the components contained within it. - * @exception NullPointerException if orientation is null. + * @exception NullPointerException if {@code orientation} is null. * @see Component#setComponentOrientation * @see Component#getComponentOrientation * @see #invalidate @@ -3650,26 +3650,26 @@ public class Container extends Component { private int containerSerializedDataVersion = 1; /** - * Serializes this Container to the specified - * ObjectOutputStream. + * Serializes this {@code Container} to the specified + * {@code ObjectOutputStream}. *

    *
  • Writes default serializable fields to the stream.
  • *
  • Writes a list of serializable ContainerListener(s) as optional * data. The non-serializable ContainerListener(s) are detected and * no attempt is made to serialize them.
  • *
  • Write this Container's FocusTraversalPolicy if and only if it - * is Serializable; otherwise, null is written.
  • + * is Serializable; otherwise, {@code null} is written. *
* - * @param s the ObjectOutputStream to write - * @serialData null terminated sequence of 0 or more pairs; - * the pair consists of a String and Object; - * the String indicates the type of object and + * @param s the {@code ObjectOutputStream} to write + * @serialData {@code null} terminated sequence of 0 or more pairs; + * the pair consists of a {@code String} and {@code Object}; + * the {@code String} indicates the type of object and * is one of the following: - * containerListenerK indicating an - * ContainerListener object; - * the Container's FocusTraversalPolicy, - * or null + * {@code containerListenerK} indicating an + * {@code ContainerListener} object; + * the {@code Container}'s {@code FocusTraversalPolicy}, + * or {@code null} * * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener) * @see Container#containerListenerK @@ -3698,8 +3698,8 @@ public class Container extends Component { } /** - * Deserializes this Container from the specified - * ObjectInputStream. + * Deserializes this {@code Container} from the specified + * {@code ObjectInputStream}. *
    *
  • Reads default serializable fields from the stream.
  • *
  • Reads a list of serializable ContainerListener(s) as optional @@ -3708,7 +3708,7 @@ public class Container extends Component { * as optional data.
  • *
* - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @serial * @see #addContainerListener * @see #writeObject(ObjectOutputStream) @@ -3796,7 +3796,7 @@ public class Container extends Component { /** * Returns the number of accessible children in the object. If all - * of the children of this object implement Accessible, + * of the children of this object implement {@code Accessible}, * then this method should return the number of children of this object. * * @return the number of accessible children in the object @@ -3806,24 +3806,24 @@ public class Container extends Component { } /** - * Returns the nth Accessible child of the object. + * Returns the nth {@code Accessible} child of the object. * * @param i zero-based index of child - * @return the nth Accessible child of the object + * @return the nth {@code Accessible} child of the object */ public Accessible getAccessibleChild(int i) { return Container.this.getAccessibleChild(i); } /** - * Returns the Accessible child, if one exists, - * contained at the local coordinate Point. + * Returns the {@code Accessible} child, if one exists, + * contained at the local coordinate {@code Point}. * * @param p the point defining the top-left corner of the - * Accessible, given in the coordinate space + * {@code Accessible}, given in the coordinate space * of the object's parent - * @return the Accessible, if it exists, - * at the specified location; else null + * @return the {@code Accessible}, if it exists, + * at the specified location; else {@code null} */ public Accessible getAccessibleAt(Point p) { return Container.this.getAccessibleAt(p); @@ -3842,7 +3842,7 @@ public class Container extends Component { protected ContainerListener accessibleContainerHandler = null; /** - * Fire PropertyChange listener, if one is registered, + * Fire {@code PropertyChange} listener, if one is registered, * when children are added or removed. * @since 1.3 */ @@ -3898,15 +3898,15 @@ public class Container extends Component { } // inner class AccessibleAWTContainer /** - * Returns the Accessible child contained at the local - * coordinate Point, if one exists. Otherwise - * returns null. + * Returns the {@code Accessible} child contained at the local + * coordinate {@code Point}, if one exists. Otherwise + * returns {@code null}. * * @param p the point defining the top-left corner of the - * Accessible, given in the coordinate space + * {@code Accessible}, given in the coordinate space * of the object's parent - * @return the Accessible at the specified location, - * if it exists; otherwise null + * @return the {@code Accessible} at the specified location, + * if it exists; otherwise {@code null} */ Accessible getAccessibleAt(Point p) { synchronized (getTreeLock()) { @@ -3962,7 +3962,7 @@ public class Container extends Component { /** * Returns the number of accessible children in the object. If all - * of the children of this object implement Accessible, + * of the children of this object implement {@code Accessible}, * then this method should return the number of children of this object. * * @return the number of accessible children in the object @@ -3981,10 +3981,10 @@ public class Container extends Component { } /** - * Returns the nth Accessible child of the object. + * Returns the nth {@code Accessible} child of the object. * * @param i zero-based index of child - * @return the nth Accessible child of the object + * @return the nth {@code Accessible} child of the object */ Accessible getAccessibleChild(int i) { synchronized (getTreeLock()) { diff --git a/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java b/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java index 312149763df..d23e672779c 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java @@ -33,18 +33,18 @@ import sun.util.logging.PlatformLogger; * of child Components in a Container. From a particular focus cycle root, the * policy makes a pre-order traversal of the Component hierarchy, and traverses * a Container's children according to the ordering of the array returned by - * Container.getComponents(). Portions of the hierarchy that are + * {@code Container.getComponents()}. Portions of the hierarchy that are * not visible and displayable will not be searched. *

* By default, ContainerOrderFocusTraversalPolicy implicitly transfers focus * down-cycle. That is, during normal forward focus traversal, the Component * traversed after a focus cycle root will be the focus-cycle-root's default * Component to focus. This behavior can be disabled using the - * setImplicitDownCycleTraversal method. + * {@code setImplicitDownCycleTraversal} method. *

* By default, methods of this class will return a Component only if it is * visible, displayable, enabled, and focusable. Subclasses can modify this - * behavior by overriding the accept method. + * behavior by overriding the {@code accept} method. *

* This policy takes into account focus traversal @@ -193,7 +193,7 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy * focus down-cycle. That is, during normal forward focus traversal, the * Component traversed after a focus cycle root will be the focus-cycle- * root's default Component to focus. This behavior can be disabled using - * the setImplicitDownCycleTraversal method. + * the {@code setImplicitDownCycleTraversal} method. *

* If aContainer is focus * traversal policy provider, the focus is always transferred down-cycle. @@ -519,7 +519,7 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy * Returns the default Component to focus. This Component will be the first * to receive focus when traversing down into a new focus traversal cycle * rooted at aContainer. The default implementation of this method - * returns the same Component as getFirstComponent. + * returns the same Component as {@code getFirstComponent}. * * @param aContainer the focus cycle root or focus traversal policy provider whose default * Component is to be returned @@ -534,12 +534,12 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy /** * Sets whether this ContainerOrderFocusTraversalPolicy transfers focus - * down-cycle implicitly. If true, during normal forward focus + * down-cycle implicitly. If {@code true}, during normal forward focus * traversal, the Component traversed after a focus cycle root will be the - * focus-cycle-root's default Component to focus. If false, + * focus-cycle-root's default Component to focus. If {@code false}, * the next Component in the focus traversal cycle rooted at the specified * focus cycle root will be traversed instead. The default value for this - * property is true. + * property is {@code true}. * * @param implicitDownCycleTraversal whether this * ContainerOrderFocusTraversalPolicy transfers focus down-cycle @@ -553,9 +553,9 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy /** * Returns whether this ContainerOrderFocusTraversalPolicy transfers focus - * down-cycle implicitly. If true, during normal forward focus + * down-cycle implicitly. If {@code true}, during normal forward focus * traversal, the Component traversed after a focus cycle root will be the - * focus-cycle-root's default Component to focus. If false, + * focus-cycle-root's default Component to focus. If {@code false}, * the next Component in the focus traversal cycle rooted at the specified * focus cycle root will be traversed instead. * @@ -575,8 +575,8 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy * * @param aComponent the Component whose fitness as a focus owner is to * be tested - * @return true if aComponent is visible, displayable, - * enabled, and focusable; false otherwise + * @return {@code true} if aComponent is visible, displayable, + * enabled, and focusable; {@code false} otherwise */ protected boolean accept(Component aComponent) { if (!aComponent.canBeFocusOwner()) { diff --git a/jdk/src/java.desktop/share/classes/java/awt/Cursor.java b/jdk/src/java.desktop/share/classes/java/awt/Cursor.java index 0ca5a3060ad..77f5b130b34 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Cursor.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Cursor.java @@ -146,7 +146,7 @@ public class Cursor implements java.io.Serializable { /** * The chosen cursor type initially set to - * the DEFAULT_CURSOR. + * the {@code DEFAULT_CURSOR}. * * @serial * @see #getType() @@ -283,7 +283,7 @@ public class Cursor implements java.io.Serializable { * @param name a string describing the desired system-specific custom cursor * @return the system specific custom cursor named * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns true + * {@code GraphicsEnvironment.isHeadless} returns true * @exception AWTException in case of erroneous retrieving of the cursor */ public static Cursor getSystemCustomCursor(final String name) diff --git a/jdk/src/java.desktop/share/classes/java/awt/DefaultFocusTraversalPolicy.java b/jdk/src/java.desktop/share/classes/java/awt/DefaultFocusTraversalPolicy.java index 508de7d9bc9..a93cbf4d92a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/DefaultFocusTraversalPolicy.java +++ b/jdk/src/java.desktop/share/classes/java/awt/DefaultFocusTraversalPolicy.java @@ -32,13 +32,13 @@ import java.awt.peer.ComponentPeer; * of child Components in a Container. From a particular focus cycle root, the * policy makes a pre-order traversal of the Component hierarchy, and traverses * a Container's children according to the ordering of the array returned by - * Container.getComponents(). Portions of the hierarchy that are + * {@code Container.getComponents()}. Portions of the hierarchy that are * not visible and displayable will not be searched. *

* If client code has explicitly set the focusability of a Component by either - * overriding Component.isFocusTraversable() or - * Component.isFocusable(), or by calling - * Component.setFocusable(), then a DefaultFocusTraversalPolicy + * overriding {@code Component.isFocusTraversable()} or + * {@code Component.isFocusable()}, or by calling + * {@code Component.setFocusable()}, then a DefaultFocusTraversalPolicy * behaves exactly like a ContainerOrderFocusTraversalPolicy. If, however, the * Component is relying on default focusability, then a * DefaultFocusTraversalPolicy will reject all Components with non-focusable @@ -80,9 +80,9 @@ public class DefaultFocusTraversalPolicy * focus owner. The Component must be visible, displayable, and enabled * to be accepted. If client code has explicitly set the focusability * of the Component by either overriding - * Component.isFocusTraversable() or - * Component.isFocusable(), or by calling - * Component.setFocusable(), then the Component will be + * {@code Component.isFocusTraversable()} or + * {@code Component.isFocusable()}, or by calling + * {@code Component.setFocusable()}, then the Component will be * accepted if and only if it is focusable. If, however, the Component is * relying on default focusability, then all Canvases, Labels, Panels, * Scrollbars, ScrollPanes, Windows, and lightweight Components will be @@ -90,8 +90,8 @@ public class DefaultFocusTraversalPolicy * * @param aComponent the Component whose fitness as a focus owner is to * be tested - * @return true if aComponent meets the above requirements; - * false otherwise + * @return {@code true} if aComponent meets the above requirements; + * {@code false} otherwise */ protected boolean accept(Component aComponent) { if (!(aComponent.isVisible() && aComponent.isDisplayable() && diff --git a/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java b/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java index d6ef4d61fdd..b6f1bcfbe4e 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java +++ b/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java @@ -309,12 +309,12 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { * related to focus, and all KeyEvents. These events are dispatched based * on the KeyboardFocusManager's notion of the focus owner and the focused * and active Windows, sometimes overriding the source of the specified - * AWTEvent. If this method returns false, then the AWT event + * AWTEvent. If this method returns {@code false}, then the AWT event * dispatcher will attempt to dispatch the event itself. * * @param e the AWTEvent to be dispatched - * @return true if this method dispatched the event; - * false otherwise + * @return {@code true} if this method dispatched the event; + * {@code false} otherwise */ public boolean dispatchEvent(AWTEvent e) { if (focusLog.isLoggable(PlatformLogger.Level.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) { @@ -778,7 +778,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { } /** - * Called by dispatchEvent if no other + * Called by {@code dispatchEvent} if no other * KeyEventDispatcher in the dispatcher chain dispatched the KeyEvent, or * if no other KeyEventDispatchers are registered. If the event has not * been consumed, its target is enabled, and the focus owner is not null, @@ -787,13 +787,13 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { * KeyEventPostProcessors. After all this operations are finished, * the event is passed to peers for processing. *

- * In all cases, this method returns true, since + * In all cases, this method returns {@code true}, since * DefaultKeyboardFocusManager is designed so that neither - * dispatchEvent, nor the AWT event dispatcher, should take + * {@code dispatchEvent}, nor the AWT event dispatcher, should take * further action on the event in any situation. * * @param e the KeyEvent to be dispatched - * @return true + * @return {@code true} * @see Component#dispatchEvent */ public boolean dispatchKeyEvent(KeyEvent e) { @@ -841,13 +841,13 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { } /** - * This method will be called by dispatchKeyEvent. It will + * This method will be called by {@code dispatchKeyEvent}. It will * handle any unconsumed KeyEvents that map to an AWT - * MenuShortcut by consuming the event and activating the + * {@code MenuShortcut} by consuming the event and activating the * shortcut. * * @param e the KeyEvent to post-process - * @return true + * @return {@code true} * @see #dispatchKeyEvent * @see MenuShortcut */ @@ -998,7 +998,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { } /** - * Returns true if there are some marker associated with component comp + * Returns true if there are some marker associated with component {@code comp} * in a markers' queue * @since 1.5 */ @@ -1201,7 +1201,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { * the focus owner. KeyEvents with timestamps later than the specified * timestamp will be enqueued until the specified Component receives a * FOCUS_GAINED event, or the AWT cancels the delay request by invoking - * dequeueKeyEvents or discardKeyEvents. + * {@code dequeueKeyEvents} or {@code discardKeyEvents}. * * @param after timestamp of current event, or the current, system time if * the current event has no timestamp, or the AWT cannot determine @@ -1241,15 +1241,15 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { /** * Releases for normal dispatching to the current focus owner all * KeyEvents which were enqueued because of a call to - * enqueueKeyEvents with the same timestamp and Component. + * {@code enqueueKeyEvents} with the same timestamp and Component. * If the given timestamp is less than zero, the outstanding enqueue * request for the given Component with the oldest timestamp (if * any) should be cancelled. * * @param after the timestamp specified in the call to - * enqueueKeyEvents, or any value < 0 + * {@code enqueueKeyEvents}, or any value < 0 * @param untilFocused the Component specified in the call to - * enqueueKeyEvents + * {@code enqueueKeyEvents} * @see #enqueueKeyEvents * @see #discardKeyEvents */ @@ -1292,11 +1292,11 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { /** * Discards all KeyEvents which were enqueued because of one or more calls - * to enqueueKeyEvents with the specified Component, or one of + * to {@code enqueueKeyEvents} with the specified Component, or one of * its descendants. * * @param comp the Component specified in one or more calls to - * enqueueKeyEvents, or a parent of such a Component + * {@code enqueueKeyEvents}, or a parent of such a Component * @see #enqueueKeyEvents * @see #dequeueKeyEvents */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Desktop.java b/jdk/src/java.desktop/share/classes/java/awt/Desktop.java index d134a4d218a..96f3d57e235 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Desktop.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Desktop.java @@ -127,7 +127,7 @@ public class Desktop { } /** - * Returns the Desktop instance of the current + * Returns the {@code Desktop} instance of the current * browser context. On some platforms the Desktop API may not be * supported; use the {@link #isDesktopSupported} method to * determine if the current desktop is supported. @@ -162,8 +162,8 @@ public class Desktop { * If it's supported, use {@link #getDesktop()} to retrieve an * instance. * - * @return true if this class is supported on the - * current platform; false otherwise + * @return {@code true} if this class is supported on the + * current platform; {@code false} otherwise * @see #getDesktop() */ public static boolean isDesktopSupported(){ @@ -186,8 +186,8 @@ public class Desktop { * action method will throw an {@link IOException}. * * @param action the specified {@link Action} - * @return true if the specified action is supported on - * the current platform; false otherwise + * @return {@code true} if the specified action is supported on + * the current platform; {@code false} otherwise * @see Desktop.Action */ public boolean isSupported(Action action) { @@ -230,8 +230,8 @@ public class Desktop { /** - * Calls to the security manager's checkPermission method with - * an AWTPermission("showWindowWithoutWarningBanner") + * Calls to the security manager's {@code checkPermission} method with + * an {@code AWTPermission("showWindowWithoutWarningBanner")} * permission. */ private void checkAWTPermission(){ @@ -259,7 +259,7 @@ public class Desktop { * @throws SecurityException if a security manager exists and its * {@link java.lang.SecurityManager#checkRead(java.lang.String)} * method denies read access to the file, or it denies the - * AWTPermission("showWindowWithoutWarningBanner") + * {@code AWTPermission("showWindowWithoutWarningBanner")} * permission, or the calling thread is not allowed to create a * subprocess * @see java.awt.AWTPermission @@ -290,7 +290,7 @@ public class Desktop { * method denies read access to the file, or {@link * java.lang.SecurityManager#checkWrite(java.lang.String)} method * denies write access to the file, or it denies the - * AWTPermission("showWindowWithoutWarningBanner") + * {@code AWTPermission("showWindowWithoutWarningBanner")} * permission, or the calling thread is not allowed to create a * subprocess * @see java.awt.AWTPermission @@ -361,7 +361,7 @@ public class Desktop { * failed to be launched * @throws SecurityException if a security manager exists and it * denies the - * AWTPermission("showWindowWithoutWarningBanner") + * {@code AWTPermission("showWindowWithoutWarningBanner")} * permission, or the calling thread is not allowed to create a * subprocess; and not invoked from within an applet or Java Web Started * application @@ -415,7 +415,7 @@ public class Desktop { * found, or it fails to be launched * @throws SecurityException if a security manager exists and it * denies the - * AWTPermission("showWindowWithoutWarningBanner") + * {@code AWTPermission("showWindowWithoutWarningBanner")} * permission, or the calling thread is not allowed to create a * subprocess * @see java.awt.AWTPermission @@ -438,7 +438,7 @@ public class Desktop { * client, filling the message fields specified by a {@code * mailto:} URI. * - *

A mailto: URI can specify message fields + *

A {@code mailto:} URI can specify message fields * including "to", "cc", "subject", * "body", etc. See The mailto URL @@ -449,14 +449,14 @@ public class Desktop { * @throws NullPointerException if the specified URI is {@code * null} * @throws IllegalArgumentException if the URI scheme is not - * "mailto" + * {@code "mailto"} * @throws UnsupportedOperationException if the current platform * does not support the {@link Desktop.Action#MAIL} action * @throws IOException if the user default mail client is not * found or fails to be launched * @throws SecurityException if a security manager exists and it * denies the - * AWTPermission("showWindowWithoutWarningBanner") + * {@code AWTPermission("showWindowWithoutWarningBanner")} * permission, or the calling thread is not allowed to create a * subprocess * @see java.net.URI diff --git a/jdk/src/java.desktop/share/classes/java/awt/Dialog.java b/jdk/src/java.desktop/share/classes/java/awt/Dialog.java index 84fb5e77e37..79e66b54798 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Dialog.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Dialog.java @@ -46,22 +46,22 @@ import java.security.AccessControlException; * * The size of the dialog includes any area designated for the * border. The dimensions of the border area can be obtained - * using the getInsets method, however, since + * using the {@code getInsets} method, however, since * these dimensions are platform-dependent, a valid insets * value cannot be obtained until the dialog is made displayable - * by either calling pack or show. + * by either calling {@code pack} or {@code show}. * Since the border area is included in the overall size of the * dialog, the border effectively obscures a portion of the dialog, * constraining the area available for rendering and/or displaying * subcomponents to the rectangle which has an upper-left corner - * location of (insets.left, insets.top), and has a size of - * width - (insets.left + insets.right) by - * height - (insets.top + insets.bottom). + * location of {@code (insets.left, insets.top)}, and has a size of + * {@code width - (insets.left + insets.right)} by + * {@code height - (insets.top + insets.bottom)}. *

- * The default layout for a dialog is BorderLayout. + * The default layout for a dialog is {@code BorderLayout}. *

* A dialog may have its native decorations (i.e. Frame & Titlebar) turned off - * with setUndecorated. This can only be done while the dialog + * with {@code setUndecorated}. This can only be done while the dialog * is not {@link Component#isDisplayable() displayable}. *

* A dialog may have another window as its owner when it's constructed. When @@ -69,7 +69,7 @@ import java.security.AccessControlException; * automatically be hidden from the user. When the owner window is subsequently * restored, the dialog is made visible to the user again. *

- * In a multi-screen environment, you can create a Dialog + * In a multi-screen environment, you can create a {@code Dialog} * on a different screen device than its owner. See {@link java.awt.Frame} for * more information. *

@@ -80,11 +80,11 @@ import java.security.AccessControlException; * specification for details. *

* Dialogs are capable of generating the following - * WindowEvents: - * WindowOpened, WindowClosing, - * WindowClosed, WindowActivated, - * WindowDeactivated, WindowGainedFocus, - * WindowLostFocus. + * {@code WindowEvents}: + * {@code WindowOpened}, {@code WindowClosing}, + * {@code WindowClosed}, {@code WindowActivated}, + * {@code WindowDeactivated}, {@code WindowGainedFocus}, + * {@code WindowLostFocus}. * * @see WindowEvent * @see Window#addWindowListener @@ -117,7 +117,7 @@ public class Dialog extends Window { /** * This field indicates whether the dialog is undecorated. * This property can only be changed while the dialog is not displayable. - * undecorated will be true if the dialog is + * {@code undecorated} will be true if the dialog is * undecorated, otherwise it will be false. * * @serial @@ -134,7 +134,7 @@ public class Dialog extends Window { * Modal dialogs block all input to some top-level windows. * Whether a particular window is blocked depends on dialog's type * of modality; this is called the "scope of blocking". The - * ModalityType enum specifies modal types and their + * {@code ModalityType} enum specifies modal types and their * associated scopes. * * @see Dialog#getModalityType @@ -145,11 +145,11 @@ public class Dialog extends Window { */ public static enum ModalityType { /** - * MODELESS dialog doesn't block any top-level windows. + * {@code MODELESS} dialog doesn't block any top-level windows. */ MODELESS, /** - * A DOCUMENT_MODAL dialog blocks input to all top-level windows + * A {@code DOCUMENT_MODAL} dialog blocks input to all top-level windows * from the same document except those from its own child hierarchy. * A document is a top-level window without an owner. It may contain child * windows that, together with the top-level window are treated as a single @@ -158,7 +158,7 @@ public class Dialog extends Window { */ DOCUMENT_MODAL, /** - * An APPLICATION_MODAL dialog blocks all top-level windows + * An {@code APPLICATION_MODAL} dialog blocks all top-level windows * from the same Java application except those from its own child hierarchy. * If there are several applets launched in a browser, they can be * treated either as separate applications or a single one. This behavior @@ -166,18 +166,18 @@ public class Dialog extends Window { */ APPLICATION_MODAL, /** - * A TOOLKIT_MODAL dialog blocks all top-level windows run + * A {@code TOOLKIT_MODAL} dialog blocks all top-level windows run * from the same toolkit except those from its own child hierarchy. If there * are several applets launched in a browser, all of them run with the same * toolkit; thus, a toolkit-modal dialog displayed by an applet may affect * other applets and all windows of the browser instance which embeds the * Java runtime environment for this toolkit. - * Special AWTPermission "toolkitModality" must be granted to use - * toolkit-modal dialogs. If a TOOLKIT_MODAL dialog is being created - * and this permission is not granted, a SecurityException will be + * Special {@code AWTPermission} "toolkitModality" must be granted to use + * toolkit-modal dialogs. If a {@code TOOLKIT_MODAL} dialog is being created + * and this permission is not granted, a {@code SecurityException} will be * thrown, and no dialog will be created. If a modality type is being changed - * to TOOLKIT_MODAL and this permission is not granted, a - * SecurityException will be thrown, and the modality type will + * to {@code TOOLKIT_MODAL} and this permission is not granted, a + * {@code SecurityException} will be thrown, and the modality type will * be left unchanged. */ TOOLKIT_MODAL @@ -185,8 +185,8 @@ public class Dialog extends Window { /** * Default modality type for modal dialogs. The default modality type is - * APPLICATION_MODAL. Calling the oldstyle setModal(true) - * is equal to setModalityType(DEFAULT_MODALITY_TYPE). + * {@code APPLICATION_MODAL}. Calling the oldstyle {@code setModal(true)} + * is equal to {@code setModalityType(DEFAULT_MODALITY_TYPE)}. * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog#setModal @@ -245,20 +245,20 @@ public class Dialog extends Window { */ NO_EXCLUDE, /** - * APPLICATION_EXCLUDE indicates that a top-level window + * {@code APPLICATION_EXCLUDE} indicates that a top-level window * won't be blocked by any application-modal dialogs. Also, it isn't * blocked by document-modal dialogs from outside of its child hierarchy. */ APPLICATION_EXCLUDE, /** - * TOOLKIT_EXCLUDE indicates that a top-level window + * {@code TOOLKIT_EXCLUDE} indicates that a top-level window * won't be blocked by application-modal or toolkit-modal dialogs. Also, * it isn't blocked by document-modal dialogs from outside of its * child hierarchy. - * The "toolkitModality" AWTPermission must be granted + * The "toolkitModality" {@code AWTPermission} must be granted * for this exclusion. If an exclusion property is being changed to - * TOOLKIT_EXCLUDE and this permission is not granted, a - * SecurityException will be thrown, and the exclusion + * {@code TOOLKIT_EXCLUDE} and this permission is not granted, a + * {@code SecurityException} will be thrown, and the exclusion * property will be left unchanged. */ TOOLKIT_EXCLUDE @@ -313,15 +313,15 @@ public class Dialog extends Window { private static final long serialVersionUID = 5920926903803293709L; /** - * Constructs an initially invisible, modeless Dialog with - * the specified owner Frame and an empty title. + * Constructs an initially invisible, modeless {@code Dialog} with + * the specified owner {@code Frame} and an empty title. * - * @param owner the owner of the dialog or null if + * @param owner the owner of the dialog or {@code null} if * this dialog has no owner - * @exception java.lang.IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless * @see Component#setSize @@ -332,19 +332,19 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible Dialog with the specified - * owner Frame and modality and an empty title. + * Constructs an initially invisible {@code Dialog} with the specified + * owner {@code Frame} and modality and an empty title. * - * @param owner the owner of the dialog or null if + * @param owner the owner of the dialog or {@code null} if * this dialog has no owner * @param modal specifies whether dialog blocks user input to other top-level - * windows when shown. If false, the dialog is MODELESS; - * if true, the modality type property is set to - * DEFAULT_MODALITY_TYPE - * @exception java.lang.IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * windows when shown. If {@code false}, the dialog is {@code MODELESS}; + * if {@code true}, the modality type property is set to + * {@code DEFAULT_MODALITY_TYPE} + * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog.ModalityType#MODELESS @@ -358,17 +358,17 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible, modeless Dialog with - * the specified owner Frame and title. + * Constructs an initially invisible, modeless {@code Dialog} with + * the specified owner {@code Frame} and title. * - * @param owner the owner of the dialog or null if + * @param owner the owner of the dialog or {@code null} if * this dialog has no owner - * @param title the title of the dialog or null if this dialog + * @param title the title of the dialog or {@code null} if this dialog * has no title - * @exception IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * @exception IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless * @see Component#setSize @@ -379,21 +379,21 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible Dialog with the - * specified owner Frame, title and modality. + * Constructs an initially invisible {@code Dialog} with the + * specified owner {@code Frame}, title and modality. * - * @param owner the owner of the dialog or null if + * @param owner the owner of the dialog or {@code null} if * this dialog has no owner - * @param title the title of the dialog or null if this dialog + * @param title the title of the dialog or {@code null} if this dialog * has no title * @param modal specifies whether dialog blocks user input to other top-level - * windows when shown. If false, the dialog is MODELESS; - * if true, the modality type property is set to - * DEFAULT_MODALITY_TYPE - * @exception java.lang.IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * windows when shown. If {@code false}, the dialog is {@code MODELESS}; + * if {@code true}, the modality type property is set to + * {@code DEFAULT_MODALITY_TYPE} + * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog.ModalityType#MODELESS @@ -409,23 +409,23 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible Dialog with the specified owner - * Frame, title, modality, and GraphicsConfiguration. - * @param owner the owner of the dialog or null if this dialog + * Constructs an initially invisible {@code Dialog} with the specified owner + * {@code Frame}, title, modality, and {@code GraphicsConfiguration}. + * @param owner the owner of the dialog or {@code null} if this dialog * has no owner - * @param title the title of the dialog or null if this dialog + * @param title the title of the dialog or {@code null} if this dialog * has no title * @param modal specifies whether dialog blocks user input to other top-level - * windows when shown. If false, the dialog is MODELESS; - * if true, the modality type property is set to - * DEFAULT_MODALITY_TYPE - * @param gc the GraphicsConfiguration of the target screen device; - * if null, the default system GraphicsConfiguration + * windows when shown. If {@code false}, the dialog is {@code MODELESS}; + * if {@code true}, the modality type property is set to + * {@code DEFAULT_MODALITY_TYPE} + * @param gc the {@code GraphicsConfiguration} of the target screen device; + * if {@code null}, the default system {@code GraphicsConfiguration} * is assumed - * @exception java.lang.IllegalArgumentException if gc + * @exception java.lang.IllegalArgumentException if {@code gc} * is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog.ModalityType#MODELESS @@ -443,15 +443,15 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible, modeless Dialog with - * the specified owner Dialog and an empty title. + * Constructs an initially invisible, modeless {@code Dialog} with + * the specified owner {@code Dialog} and an empty title. * - * @param owner the owner of the dialog or null if this + * @param owner the owner of the dialog or {@code null} if this * dialog has no owner - * @exception java.lang.IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 */ @@ -460,17 +460,17 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible, modeless Dialog - * with the specified owner Dialog and title. + * Constructs an initially invisible, modeless {@code Dialog} + * with the specified owner {@code Dialog} and title. * - * @param owner the owner of the dialog or null if this + * @param owner the owner of the dialog or {@code null} if this * has no owner - * @param title the title of the dialog or null if this dialog + * @param title the title of the dialog or {@code null} if this dialog * has no title - * @exception java.lang.IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 @@ -480,21 +480,21 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible Dialog with the - * specified owner Dialog, title, and modality. + * Constructs an initially invisible {@code Dialog} with the + * specified owner {@code Dialog}, title, and modality. * - * @param owner the owner of the dialog or null if this + * @param owner the owner of the dialog or {@code null} if this * dialog has no owner - * @param title the title of the dialog or null if this + * @param title the title of the dialog or {@code null} if this * dialog has no title * @param modal specifies whether dialog blocks user input to other top-level - * windows when shown. If false, the dialog is MODELESS; - * if true, the modality type property is set to - * DEFAULT_MODALITY_TYPE - * @exception IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * windows when shown. If {@code false}, the dialog is {@code MODELESS}; + * if {@code true}, the modality type property is set to + * {@code DEFAULT_MODALITY_TYPE} + * @exception IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog.ModalityType#MODELESS @@ -510,25 +510,25 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible Dialog with the - * specified owner Dialog, title, modality and - * GraphicsConfiguration. + * Constructs an initially invisible {@code Dialog} with the + * specified owner {@code Dialog}, title, modality and + * {@code GraphicsConfiguration}. * - * @param owner the owner of the dialog or null if this + * @param owner the owner of the dialog or {@code null} if this * dialog has no owner - * @param title the title of the dialog or null if this + * @param title the title of the dialog or {@code null} if this * dialog has no title * @param modal specifies whether dialog blocks user input to other top-level - * windows when shown. If false, the dialog is MODELESS; - * if true, the modality type property is set to - * DEFAULT_MODALITY_TYPE - * @param gc the GraphicsConfiguration of the target screen device; - * if null, the default system GraphicsConfiguration + * windows when shown. If {@code false}, the dialog is {@code MODELESS}; + * if {@code true}, the modality type property is set to + * {@code DEFAULT_MODALITY_TYPE} + * @param gc the {@code GraphicsConfiguration} of the target screen device; + * if {@code null}, the default system {@code GraphicsConfiguration} * is assumed - * @exception java.lang.IllegalArgumentException if gc + * @exception java.lang.IllegalArgumentException if {@code gc} * is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog.ModalityType#MODELESS @@ -547,20 +547,20 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible, modeless Dialog with the - * specified owner Window and an empty title. + * Constructs an initially invisible, modeless {@code Dialog} with the + * specified owner {@code Window} and an empty title. * * @param owner the owner of the dialog. The owner must be an instance of * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any - * of their descendants or null + * of their descendants or {@code null} * - * @exception java.lang.IllegalArgumentException if the owner + * @exception java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless * @@ -571,22 +571,22 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible, modeless Dialog with - * the specified owner Window and title. + * Constructs an initially invisible, modeless {@code Dialog} with + * the specified owner {@code Window} and title. * * @param owner the owner of the dialog. The owner must be an instance of * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any - * of their descendants or null - * @param title the title of the dialog or null if this dialog + * of their descendants or {@code null} + * @param title the title of the dialog or {@code null} if this dialog * has no title * - * @exception java.lang.IllegalArgumentException if the owner + * @exception java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless * @@ -597,25 +597,25 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible Dialog with the - * specified owner Window and modality and an empty title. + * Constructs an initially invisible {@code Dialog} with the + * specified owner {@code Window} and modality and an empty title. * * @param owner the owner of the dialog. The owner must be an instance of * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any - * of their descendants or null + * of their descendants or {@code null} * @param modalityType specifies whether dialog blocks input to other - * windows when shown. null value and unsupported modality - * types are equivalent to MODELESS + * windows when shown. {@code null} value and unsupported modality + * types are equivalent to {@code MODELESS} * - * @exception java.lang.IllegalArgumentException if the owner + * @exception java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @exception SecurityException if the calling thread does not have permission - * to create modal dialogs with the given modalityType + * to create modal dialogs with the given {@code modalityType} * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog#setModal @@ -630,27 +630,27 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible Dialog with the - * specified owner Window, title and modality. + * Constructs an initially invisible {@code Dialog} with the + * specified owner {@code Window}, title and modality. * * @param owner the owner of the dialog. The owner must be an instance of * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any - * of their descendants or null - * @param title the title of the dialog or null if this dialog + * of their descendants or {@code null} + * @param title the title of the dialog or {@code null} if this dialog * has no title * @param modalityType specifies whether dialog blocks input to other - * windows when shown. null value and unsupported modality - * types are equivalent to MODELESS + * windows when shown. {@code null} value and unsupported modality + * types are equivalent to {@code MODELESS} * - * @exception java.lang.IllegalArgumentException if the owner + * @exception java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if the owner's - * GraphicsConfiguration is not from a screen device + * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * {@code GraphicsConfiguration} is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @exception SecurityException if the calling thread does not have permission - * to create modal dialogs with the given modalityType + * to create modal dialogs with the given {@code modalityType} * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog#setModal @@ -677,31 +677,31 @@ public class Dialog extends Window { } /** - * Constructs an initially invisible Dialog with the - * specified owner Window, title, modality and - * GraphicsConfiguration. + * Constructs an initially invisible {@code Dialog} with the + * specified owner {@code Window}, title, modality and + * {@code GraphicsConfiguration}. * * @param owner the owner of the dialog. The owner must be an instance of * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any - * of their descendants or null - * @param title the title of the dialog or null if this dialog + * of their descendants or {@code null} + * @param title the title of the dialog or {@code null} if this dialog * has no title * @param modalityType specifies whether dialog blocks input to other - * windows when shown. null value and unsupported modality - * types are equivalent to MODELESS - * @param gc the GraphicsConfiguration of the target screen device; - * if null, the default system GraphicsConfiguration + * windows when shown. {@code null} value and unsupported modality + * types are equivalent to {@code MODELESS} + * @param gc the {@code GraphicsConfiguration} of the target screen device; + * if {@code null}, the default system {@code GraphicsConfiguration} * is assumed * - * @exception java.lang.IllegalArgumentException if the owner + * @exception java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if gc + * @exception java.lang.IllegalArgumentException if {@code gc} * is not from a screen device * @exception HeadlessException when - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @exception SecurityException if the calling thread does not have permission - * to create modal dialogs with the given modalityType + * to create modal dialogs with the given {@code modalityType} * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog#setModal @@ -766,8 +766,8 @@ public class Dialog extends Window { * This method is obsolete and is kept for backwards compatibility only. * Use {@link #getModalityType getModalityType()} instead. * - * @return true if this dialog window is modal; - * false otherwise + * @return {@code true} if this dialog window is modal; + * {@code false} otherwise * * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE * @see java.awt.Dialog.ModalityType#MODELESS @@ -792,10 +792,10 @@ public class Dialog extends Window { * until it is hidden and then shown again. * * @param modal specifies whether dialog blocks input to other windows - * when shown; calling to setModal(true) is equivalent to - * setModalityType(Dialog.DEFAULT_MODALITY_TYPE), and - * calling to setModal(false) is equivalent to - * setModalityType(Dialog.ModalityType.MODELESS) + * when shown; calling to {@code setModal(true)} is equivalent to + * {@code setModalityType(Dialog.DEFAULT_MODALITY_TYPE)}, and + * calling to {@code setModal(false)} is equivalent to + * {@code setModalityType(Dialog.ModalityType.MODELESS)} * * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE * @see java.awt.Dialog.ModalityType#MODELESS @@ -827,18 +827,18 @@ public class Dialog extends Window { * Sets the modality type for this dialog. See {@link * java.awt.Dialog.ModalityType ModalityType} for possible modality types. *

- * If the given modality type is not supported, MODELESS - * is used. You may want to call getModalityType() after calling + * If the given modality type is not supported, {@code MODELESS} + * is used. You may want to call {@code getModalityType()} after calling * this method to ensure that the modality type has been set. *

* Note: changing modality of the visible dialog may have no effect * until it is hidden and then shown again. * * @param type specifies whether dialog blocks input to other - * windows when shown. null value and unsupported modality - * types are equivalent to MODELESS + * windows when shown. {@code null} value and unsupported modality + * types are equivalent to {@code MODELESS} * @exception SecurityException if the calling thread does not have permission - * to create modal dialogs with the given modalityType + * to create modal dialogs with the given {@code modalityType} * * @see java.awt.Dialog#getModalityType * @see java.awt.Toolkit#isModalityTypeSupported @@ -866,7 +866,7 @@ public class Dialog extends Window { * Gets the title of the dialog. The title is displayed in the * dialog's border. * @return the title of this dialog window. The title may be - * null. + * {@code null}. * @see java.awt.Dialog#setTitle */ public String getTitle() { @@ -1193,8 +1193,8 @@ public class Dialog extends Window { /** * Indicates whether this dialog is resizable by the user. * By default, all dialogs are initially resizable. - * @return true if the user can resize the dialog; - * false otherwise. + * @return {@code true} if the user can resize the dialog; + * {@code false} otherwise. * @see java.awt.Dialog#setResizable */ public boolean isResizable() { @@ -1203,8 +1203,8 @@ public class Dialog extends Window { /** * Sets whether this dialog is resizable by the user. - * @param resizable true if the user can - * resize this dialog; false otherwise. + * @param resizable {@code true} if the user can + * resize this dialog; {@code false} otherwise. * @see java.awt.Dialog#isResizable */ public void setResizable(boolean resizable) { @@ -1283,8 +1283,8 @@ public class Dialog extends Window { /** * Indicates whether this dialog is undecorated. * By default, all dialogs are initially decorated. - * @return true if dialog is undecorated; - * false otherwise. + * @return {@code true} if dialog is undecorated; + * {@code false} otherwise. * @see java.awt.Dialog#setUndecorated * @since 1.4 */ @@ -1336,7 +1336,7 @@ public class Dialog extends Window { * method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this dialog window. */ @@ -1647,7 +1647,7 @@ public class Dialog extends Window { /** * This class implements accessibility support for the - * Dialog class. It provides an implementation of the + * {@code Dialog} class. It provides an implementation of the * Java Accessibility API appropriate to dialog user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Dimension.java b/jdk/src/java.desktop/share/classes/java/awt/Dimension.java index c368668de5d..9b2b3ff8730 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Dimension.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Dimension.java @@ -29,19 +29,19 @@ import java.awt.geom.Dimension2D; import java.beans.Transient; /** - * The Dimension class encapsulates the width and + * The {@code Dimension} class encapsulates the width and * height of a component (in integer precision) in a single object. * The class is * associated with certain properties of components. Several methods - * defined by the Component class and the - * LayoutManager interface return a - * Dimension object. + * defined by the {@code Component} class and the + * {@code LayoutManager} interface return a + * {@code Dimension} object. *

- * Normally the values of width - * and height are non-negative integers. + * Normally the values of {@code width} + * and {@code height} are non-negative integers. * The constructors that allow you to create a dimension do * not prevent you from setting a negative value for these properties. - * If the value of width or height is + * If the value of {@code width} or {@code height} is * negative, the behavior of some methods defined by other objects is * undefined. * @@ -92,7 +92,7 @@ public class Dimension extends Dimension2D implements java.io.Serializable { } /** - * Creates an instance of Dimension with a width + * Creates an instance of {@code Dimension} with a width * of zero and a height of zero. */ public Dimension() { @@ -100,19 +100,19 @@ public class Dimension extends Dimension2D implements java.io.Serializable { } /** - * Creates an instance of Dimension whose width + * Creates an instance of {@code Dimension} whose width * and height are the same as for the specified dimension. * * @param d the specified dimension for the - * width and - * height values + * {@code width} and + * {@code height} values */ public Dimension(Dimension d) { this(d.width, d.height); } /** - * Constructs a Dimension and initializes + * Constructs a {@code Dimension} and initializes * it to the specified width and specified height. * * @param width the specified width @@ -140,14 +140,14 @@ public class Dimension extends Dimension2D implements java.io.Serializable { } /** - * Sets the size of this Dimension object to + * Sets the size of this {@code Dimension} object to * the specified width and height in double precision. - * Note that if width or height - * are larger than Integer.MAX_VALUE, they will - * be reset to Integer.MAX_VALUE. + * Note that if {@code width} or {@code height} + * are larger than {@code Integer.MAX_VALUE}, they will + * be reset to {@code Integer.MAX_VALUE}. * - * @param width the new width for the Dimension object - * @param height the new height for the Dimension object + * @param width the new width for the {@code Dimension} object + * @param height the new height for the {@code Dimension} object * @since 1.2 */ public void setSize(double width, double height) { @@ -156,12 +156,12 @@ public class Dimension extends Dimension2D implements java.io.Serializable { } /** - * Gets the size of this Dimension object. + * Gets the size of this {@code Dimension} object. * This method is included for completeness, to parallel the - * getSize method defined by Component. + * {@code getSize} method defined by {@code Component}. * * @return the size of this dimension, a new instance of - * Dimension with the same width and height + * {@code Dimension} with the same width and height * @see java.awt.Dimension#setSize * @see java.awt.Component#getSize * @since 1.1 @@ -172,10 +172,10 @@ public class Dimension extends Dimension2D implements java.io.Serializable { } /** - * Sets the size of this Dimension object to the specified size. + * Sets the size of this {@code Dimension} object to the specified size. * This method is included for completeness, to parallel the - * setSize method defined by Component. - * @param d the new size for this Dimension object + * {@code setSize} method defined by {@code Component}. + * @param d the new size for this {@code Dimension} object * @see java.awt.Dimension#getSize * @see java.awt.Component#setSize * @since 1.1 @@ -185,13 +185,13 @@ public class Dimension extends Dimension2D implements java.io.Serializable { } /** - * Sets the size of this Dimension object + * Sets the size of this {@code Dimension} object * to the specified width and height. * This method is included for completeness, to parallel the - * setSize method defined by Component. + * {@code setSize} method defined by {@code Component}. * - * @param width the new width for this Dimension object - * @param height the new height for this Dimension object + * @param width the new width for this {@code Dimension} object + * @param height the new height for this {@code Dimension} object * @see java.awt.Dimension#getSize * @see java.awt.Component#setSize * @since 1.1 @@ -213,9 +213,9 @@ public class Dimension extends Dimension2D implements java.io.Serializable { } /** - * Returns the hash code for this Dimension. + * Returns the hash code for this {@code Dimension}. * - * @return a hash code for this Dimension + * @return a hash code for this {@code Dimension} */ public int hashCode() { int sum = width + height; @@ -224,13 +224,13 @@ public class Dimension extends Dimension2D implements java.io.Serializable { /** * Returns a string representation of the values of this - * Dimension object's height and - * width fields. This method is intended to be used only + * {@code Dimension} object's {@code height} and + * {@code width} fields. This method is intended to be used only * for debugging purposes, and the content and format of the returned * string may vary between implementations. The returned string may be - * empty but may not be null. + * empty but may not be {@code null}. * - * @return a string representation of this Dimension + * @return a string representation of this {@code Dimension} * object */ public String toString() { diff --git a/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java b/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java index 12730fde5f4..3dafedb2be8 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java +++ b/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java @@ -28,8 +28,8 @@ package java.awt; import java.lang.annotation.Native; /** - * The DisplayMode class encapsulates the bit depth, height, - * width, and refresh rate of a GraphicsDevice. The ability to + * The {@code DisplayMode} class encapsulates the bit depth, height, + * width, and refresh rate of a {@code GraphicsDevice}. The ability to * change graphics device's display mode is platform- and * configuration-dependent and may not always be available * (see {@link GraphicsDevice#isDisplayChangeSupported}). @@ -57,10 +57,10 @@ public final class DisplayMode { * @param width the width of the display, in pixels * @param height the height of the display, in pixels * @param bitDepth the bit depth of the display, in bits per - * pixel. This can be BIT_DEPTH_MULTI if multiple + * pixel. This can be {@code BIT_DEPTH_MULTI} if multiple * bit depths are available. * @param refreshRate the refresh rate of the display, in hertz. - * This can be REFRESH_RATE_UNKNOWN if the + * This can be {@code REFRESH_RATE_UNKNOWN} if the * information is not available. * @see #BIT_DEPTH_MULTI * @see #REFRESH_RATE_UNKNOWN @@ -96,7 +96,7 @@ public final class DisplayMode { /** * Returns the bit depth of the display, in bits per pixel. This may be - * BIT_DEPTH_MULTI if multiple bit depths are supported in + * {@code BIT_DEPTH_MULTI} if multiple bit depths are supported in * this display mode. * * @return the bit depth of the display, in bits per pixel. @@ -114,7 +114,7 @@ public final class DisplayMode { /** * Returns the refresh rate of the display, in hertz. This may be - * REFRESH_RATE_UNKNOWN if the information is not available. + * {@code REFRESH_RATE_UNKNOWN} if the information is not available. * * @return the refresh rate of the display, in hertz. * @see #REFRESH_RATE_UNKNOWN diff --git a/jdk/src/java.desktop/share/classes/java/awt/Event.java b/jdk/src/java.desktop/share/classes/java/awt/Event.java index 4235bfaa4dd..b00b09876ea 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Event.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Event.java @@ -28,14 +28,14 @@ import java.awt.event.*; import java.io.*; /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

- * Event is a platform-independent class that + * {@code Event} is a platform-independent class that * encapsulates events from the platform's Graphical User * Interface in the Java 1.0 event model. In Java 1.1 - * and later versions, the Event class is maintained + * and later versions, the {@code Event} class is maintained * only for backwards compatibility. The information in this * class description is provided to assist programmers in * converting Java 1.0 programs to the new event model. @@ -43,18 +43,18 @@ import java.io.*; * In the Java 1.0 event model, an event contains an * {@link Event#id} field * that indicates what type of event it is and which other - * Event variables are relevant for the event. + * {@code Event} variables are relevant for the event. *

* For keyboard events, {@link Event#key} * contains a value indicating which key was activated, and * {@link Event#modifiers} contains the * modifiers for that event. For the KEY_PRESS and KEY_RELEASE - * event ids, the value of key is the unicode + * event ids, the value of {@code key} is the unicode * character code for the key. For KEY_ACTION and - * KEY_ACTION_RELEASE, the value of key is + * KEY_ACTION_RELEASE, the value of {@code key} is * one of the defined action-key identifiers in the - * Event class (PGUP, - * PGDN, F1, F2, etc). + * {@code Event} class ({@code PGUP}, + * {@code PGDN}, {@code F1}, {@code F2}, etc). * * @author Sami Shaio * @since 1.0 @@ -293,7 +293,7 @@ public class Event implements java.io.Serializable { /** * The user has pressed a non-ASCII action key. - * The key field contains a value that indicates + * The {@code key} field contains a value that indicates * that the event occurred on one of the action keys, which * comprise the 12 function keys, the arrow (cursor) keys, * Page Up, Page Down, Home, End, Print Screen, Scroll Lock, @@ -303,7 +303,7 @@ public class Event implements java.io.Serializable { /** * The user has released a non-ASCII action key. - * The key field contains a value that indicates + * The {@code key} field contains a value that indicates * that the event occurred on one of the action keys, which * comprise the 12 function keys, the arrow (cursor) keys, * Page Up, Page Down, Home, End, Print Screen, Scroll Lock, @@ -315,9 +315,9 @@ public class Event implements java.io.Serializable { private static final int MOUSE_EVENT = 500; /** - * The user has pressed the mouse button. The ALT_MASK + * The user has pressed the mouse button. The {@code ALT_MASK} * flag indicates that the middle button has been pressed. - * The META_MASKflag indicates that the + * The {@code META_MASK} flag indicates that the * right button has been pressed. * @see java.awt.Event#ALT_MASK * @see java.awt.Event#META_MASK @@ -325,9 +325,9 @@ public class Event implements java.io.Serializable { public static final int MOUSE_DOWN = 1 + MOUSE_EVENT; /** - * The user has released the mouse button. The ALT_MASK + * The user has released the mouse button. The {@code ALT_MASK} * flag indicates that the middle button has been released. - * The META_MASKflag indicates that the + * The {@code META_MASK} flag indicates that the * right button has been released. * @see java.awt.Event#ALT_MASK * @see java.awt.Event#META_MASK @@ -351,8 +351,8 @@ public class Event implements java.io.Serializable { /** * The user has moved the mouse with a button pressed. The - * ALT_MASK flag indicates that the middle - * button is being pressed. The META_MASK flag indicates + * {@code ALT_MASK} flag indicates that the middle + * button is being pressed. The {@code META_MASK} flag indicates * that the right button is being pressed. * @see java.awt.Event#ALT_MASK * @see java.awt.Event#META_MASK @@ -466,7 +466,7 @@ public class Event implements java.io.Serializable { /** * Indicates which type of event the event is, and which - * other Event variables are relevant for the event. + * other {@code Event} variables are relevant for the event. * This has been replaced by AWTEvent.getID() * * @serial @@ -518,9 +518,9 @@ public class Event implements java.io.Serializable { public int modifiers; /** - * For MOUSE_DOWN events, this field indicates the + * For {@code MOUSE_DOWN} events, this field indicates the * number of consecutive clicks. For other events, its value is - * 0. + * {@code 0}. * This field has been replaced by MouseEvent.getClickCount(). * * @serial @@ -531,7 +531,7 @@ public class Event implements java.io.Serializable { /** * An arbitrary argument of the event. The value of this field * depends on the type of event. - * arg has been replaced by event specific property. + * {@code arg} has been replaced by event specific property. * * @serial */ @@ -608,11 +608,11 @@ public class Event implements java.io.Serializable { private static native void initIDs(); /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

- * Creates an instance of Event with the specified target + * Creates an instance of {@code Event} with the specified target * component, time stamp, event type, x and y * coordinates, keyboard key, state of the modifier keys, and * argument. @@ -659,14 +659,14 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

- * Creates an instance of Event, with the specified target + * Creates an instance of {@code Event}, with the specified target * component, time stamp, event type, x and y * coordinates, keyboard key, state of the modifier keys, and an - * argument set to null. + * argument set to {@code null}. * @param target the target component. * @param when the time stamp. * @param id the event type. @@ -680,11 +680,11 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

- * Creates an instance of Event with the specified + * Creates an instance of {@code Event} with the specified * target component, event type, and argument. * @param target the target component. * @param id the event type. @@ -695,9 +695,9 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

* Translates this event so that its x and y * coordinates are increased by dx and dy, @@ -716,13 +716,13 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

* Checks if the Shift key is down. - * @return true if the key is down; - * false otherwise. + * @return {@code true} if the key is down; + * {@code false} otherwise. * @see java.awt.Event#modifiers * @see java.awt.Event#controlDown * @see java.awt.Event#metaDown @@ -732,13 +732,13 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

* Checks if the Control key is down. - * @return true if the key is down; - * false otherwise. + * @return {@code true} if the key is down; + * {@code false} otherwise. * @see java.awt.Event#modifiers * @see java.awt.Event#shiftDown * @see java.awt.Event#metaDown @@ -748,14 +748,14 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

* Checks if the Meta key is down. * - * @return true if the key is down; - * false otherwise. + * @return {@code true} if the key is down; + * {@code false} otherwise. * @see java.awt.Event#modifiers * @see java.awt.Event#shiftDown * @see java.awt.Event#controlDown @@ -765,9 +765,9 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. */ void consume() { switch(id) { @@ -783,18 +783,18 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. */ boolean isConsumed() { return consumed; } /* - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

* Returns the integer key-code associated with the key in this event, * as described in java.awt.Event. @@ -810,9 +810,9 @@ public class Event implements java.io.Serializable { } /* - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

* Returns a new KeyEvent char which corresponds to the int key * of this old event. @@ -827,15 +827,15 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

- * Returns a string representing the state of this Event. + * Returns a string representing the state of this {@code Event}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this event */ @@ -863,9 +863,9 @@ public class Event implements java.io.Serializable { } /** - * NOTE: The Event class is obsolete and is + * NOTE: The {@code Event} class is obsolete and is * available only for backwards compatibility. It has been replaced - * by the AWTEvent class and its subclasses. + * by the {@code AWTEvent} class and its subclasses. *

* Returns a representation of this event's values as a string. * @return a string that represents the event and the values diff --git a/jdk/src/java.desktop/share/classes/java/awt/EventFilter.java b/jdk/src/java.desktop/share/classes/java/awt/EventFilter.java index 0ee077ad466..d034e1a0aac 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/EventFilter.java +++ b/jdk/src/java.desktop/share/classes/java/awt/EventFilter.java @@ -27,27 +27,27 @@ package java.awt; interface EventFilter { /** - * Enumeration for possible values for acceptEvent(AWTEvent ev) method. + * Enumeration for possible values for {@code acceptEvent(AWTEvent ev)} method. * @see EventDispatchThread#pumpEventsForFilter */ static enum FilterAction { /** * ACCEPT means that this filter do not filter the event and allows other * active filters to proceed it. If all the active filters accept the event, it - * is dispatched by the EventDispatchThread + * is dispatched by the {@code EventDispatchThread} * @see EventDispatchThread#pumpEventsForFilter */ ACCEPT, /** * REJECT means that this filter filter the event. No other filters are queried, - * and the event is not dispatched by the EventDispatchedThread + * and the event is not dispatched by the {@code EventDispatchedThread} * @see EventDispatchThread#pumpEventsForFilter */ REJECT, /** * ACCEPT_IMMEDIATELY means that this filter do not filter the event, no other * filters are queried and to proceed it, and it is dispatched by the - * EventDispatchThread + * {@code EventDispatchThread} * It is not recommended to use ACCEPT_IMMEDIATELY as there may be some active * filters not queried yet that do not accept this event. It is primarily used * by modal filters. diff --git a/jdk/src/java.desktop/share/classes/java/awt/EventQueue.java b/jdk/src/java.desktop/share/classes/java/awt/EventQueue.java index 84bcc5b11fb..6dc5fb44b58 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/EventQueue.java +++ b/jdk/src/java.desktop/share/classes/java/awt/EventQueue.java @@ -51,36 +51,36 @@ import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.JavaSecurityAccess; /** - * EventQueue is a platform-independent class + * {@code EventQueue} is a platform-independent class * that queues events, both from the underlying peer classes * and from trusted application classes. *

* It encapsulates asynchronous event dispatch machinery which * extracts events from the queue and dispatches them by calling * {@link #dispatchEvent(AWTEvent) dispatchEvent(AWTEvent)} method - * on this EventQueue with the event to be dispatched + * on this {@code EventQueue} with the event to be dispatched * as an argument. The particular behavior of this machinery is * implementation-dependent. The only requirements are that events * which were actually enqueued to this queue (note that events - * being posted to the EventQueue can be coalesced) + * being posted to the {@code EventQueue} can be coalesced) * are dispatched: *

*
Sequentially. *
That is, it is not permitted that several events from * this queue are dispatched simultaneously. *
In the same order as they are enqueued. - *
That is, if AWTEvent A is enqueued - * to the EventQueue before - * AWTEvent B then event B will not be + *
That is, if {@code AWTEvent} A is enqueued + * to the {@code EventQueue} before + * {@code AWTEvent} B then event B will not be * dispatched before event A. *
*

* Some browsers partition applets in different code bases into * separate contexts, and establish walls between these contexts. - * In such a scenario, there will be one EventQueue + * In such a scenario, there will be one {@code EventQueue} * per context. Other browsers place all applets into the same * context, implying that there will be only a single, global - * EventQueue for all applets. This behavior is + * {@code EventQueue} for all applets. This behavior is * implementation-dependent. Consult your browser's documentation * for more information. *

@@ -251,14 +251,14 @@ public class EventQueue { } /** - * Posts a 1.1-style event to the EventQueue. + * Posts a 1.1-style event to the {@code EventQueue}. * If there is an existing event on the queue with the same ID - * and event source, the source Component's - * coalesceEvents method will be called. + * and event source, the source {@code Component}'s + * {@code coalesceEvents} method will be called. * - * @param theEvent an instance of java.awt.AWTEvent, + * @param theEvent an instance of {@code java.awt.AWTEvent}, * or a subclass of it - * @throws NullPointerException if theEvent is null + * @throws NullPointerException if {@code theEvent} is {@code null} */ public void postEvent(AWTEvent theEvent) { SunToolkit.flushPendingEvents(appContext); @@ -266,12 +266,12 @@ public class EventQueue { } /** - * Posts a 1.1-style event to the EventQueue. + * Posts a 1.1-style event to the {@code EventQueue}. * If there is an existing event on the queue with the same ID - * and event source, the source Component's - * coalesceEvents method will be called. + * and event source, the source {@code Component}'s + * {@code coalesceEvents} method will be called. * - * @param theEvent an instance of java.awt.AWTEvent, + * @param theEvent an instance of {@code java.awt.AWTEvent}, * or a subclass of it */ private final void postEventPrivate(AWTEvent theEvent) { @@ -320,7 +320,7 @@ public class EventQueue { * Posts the event to the internal Queue of specified priority, * coalescing as appropriate. * - * @param theEvent an instance of java.awt.AWTEvent, + * @param theEvent an instance of {@code java.awt.AWTEvent}, * or a subclass of it * @param priority the desired priority of the event */ @@ -532,10 +532,10 @@ public class EventQueue { } /** - * Removes an event from the EventQueue and + * Removes an event from the {@code EventQueue} and * returns it. This method will block until an event has * been posted by another thread. - * @return the next AWTEvent + * @return the next {@code AWTEvent} * @exception InterruptedException * if any thread has interrupted this thread */ @@ -617,7 +617,7 @@ public class EventQueue { } /** - * Returns the first event on the EventQueue + * Returns the first event on the {@code EventQueue} * without removing it. * @return the first event */ @@ -639,7 +639,7 @@ public class EventQueue { /** * Returns the first event with the specified id, if any. * @param id the id of the type of event desired - * @return the first event of the specified id or null + * @return the first event of the specified id or {@code null} * if there is no such event */ public AWTEvent peekEvent(int id) { @@ -696,9 +696,9 @@ public class EventQueue { * * * - * @param event an instance of java.awt.AWTEvent, + * @param event an instance of {@code java.awt.AWTEvent}, * or a subclass of it - * @throws NullPointerException if event is null + * @throws NullPointerException if {@code event} is {@code null} * @since 1.2 */ protected void dispatchEvent(final AWTEvent event) { @@ -777,23 +777,23 @@ public class EventQueue { /** * Returns the timestamp of the most recent event that had a timestamp, and - * that was dispatched from the EventQueue associated with the + * that was dispatched from the {@code EventQueue} associated with the * calling thread. If an event with a timestamp is currently being * dispatched, its timestamp will be returned. If no events have yet * been dispatched, the EventQueue's initialization time will be * returned instead.In the current version of - * the JDK, only InputEvents, - * ActionEvents, and InvocationEvents have + * the JDK, only {@code InputEvent}s, + * {@code ActionEvent}s, and {@code InvocationEvent}s have * timestamps; however, future versions of the JDK may add timestamps to * additional event types. Note that this method should only be invoked * from an application's {@link #isDispatchThread event dispatching thread}. * If this method is * invoked from another thread, the current system time (as reported by - * System.currentTimeMillis()) will be returned instead. + * {@code System.currentTimeMillis()}) will be returned instead. * - * @return the timestamp of the last InputEvent, - * ActionEvent, or InvocationEvent to be - * dispatched, or System.currentTimeMillis() if this + * @return the timestamp of the last {@code InputEvent}, + * {@code ActionEvent}, or {@code InvocationEvent} to be + * dispatched, or {@code System.currentTimeMillis()} if this * method is invoked on a thread other than an event dispatching * thread * @see java.awt.event.InputEvent#getWhen @@ -831,7 +831,7 @@ public class EventQueue { /** * Returns the event currently being dispatched by the - * EventQueue associated with the calling thread. This is + * {@code EventQueue} associated with the calling thread. This is * useful if a method needs access to the event, but was not designed to * receive a reference to it as an argument. Note that this method should * only be invoked from an application's event dispatching thread. If this @@ -856,14 +856,14 @@ public class EventQueue { } /** - * Replaces the existing EventQueue with the specified one. - * Any pending events are transferred to the new EventQueue + * Replaces the existing {@code EventQueue} with the specified one. + * Any pending events are transferred to the new {@code EventQueue} * for processing by it. * - * @param newEventQueue an EventQueue + * @param newEventQueue an {@code EventQueue} * (or subclass thereof) instance to be use * @see java.awt.EventQueue#pop - * @throws NullPointerException if newEventQueue is null + * @throws NullPointerException if {@code newEventQueue} is {@code null} * @since 1.2 */ public void push(EventQueue newEventQueue) { @@ -921,15 +921,15 @@ public class EventQueue { } /** - * Stops dispatching events using this EventQueue. + * Stops dispatching events using this {@code EventQueue}. * Any pending events are transferred to the previous - * EventQueue for processing. + * {@code EventQueue} for processing. *

* Warning: To avoid deadlock, do not declare this method * synchronized in a subclass. * * @exception EmptyStackException if no previous push was made - * on this EventQueue + * on this {@code EventQueue} * @see java.awt.EventQueue#push * @since 1.2 */ @@ -1122,10 +1122,10 @@ public class EventQueue { } /* - * Gets the EventDispatchThread for this - * EventQueue. + * Gets the {@code EventDispatchThread} for this + * {@code EventQueue}. * @return the event dispatch thread associated with this event queue - * or null if this event queue doesn't have a + * or {@code null} if this event queue doesn't have a * working thread associated with it * @see java.awt.EventQueue#initDispatchThread * @see java.awt.EventQueue#detachDispatchThread @@ -1141,15 +1141,15 @@ public class EventQueue { /* * Removes any pending events for the specified source object. - * If removeAllEvents parameter is true then all + * If removeAllEvents parameter is {@code true} then all * events for the specified source object are removed, if it - * is false then SequencedEvent, SentEvent, - * FocusEvent, WindowEvent, KeyEvent, - * and InputMethodEvent are kept in the queue, but all other + * is {@code false} then {@code SequencedEvent}, {@code SentEvent}, + * {@code FocusEvent}, {@code WindowEvent}, {@code KeyEvent}, + * and {@code InputMethodEvent} are kept in the queue, but all other * events are removed. * * This method is normally called by the source's - * removeNotify method. + * {@code removeNotify} method. */ final void removeSourceEvents(Object source, boolean removeAllEvents) { SunToolkit.flushPendingEvents(appContext); @@ -1249,12 +1249,12 @@ public class EventQueue { } /** - * Causes runnable to have its run + * Causes {@code runnable} to have its {@code run} * method called in the {@link #isDispatchThread dispatch thread} of * {@link Toolkit#getSystemEventQueue the system EventQueue}. * This will happen after all pending events are processed. * - * @param runnable the Runnable whose run + * @param runnable the {@code Runnable} whose {@code run} * method should be executed * asynchronously in the * {@link #isDispatchThread event dispatch thread} @@ -1270,7 +1270,7 @@ public class EventQueue { } /** - * Causes runnable to have its run + * Causes {@code runnable} to have its {@code run} * method called in the {@link #isDispatchThread dispatch thread} of * {@link Toolkit#getSystemEventQueue the system EventQueue}. * This will happen after all pending events are processed. @@ -1278,7 +1278,7 @@ public class EventQueue { * will throw an Error if called from the * {@link #isDispatchThread event dispatcher thread}. * - * @param runnable the Runnable whose run + * @param runnable the {@code Runnable} whose {@code run} * method should be executed * synchronously in the * {@link #isDispatchThread event dispatch thread} @@ -1286,7 +1286,7 @@ public class EventQueue { * @exception InterruptedException if any thread has * interrupted this thread * @exception InvocationTargetException if an throwable is thrown - * when running runnable + * when running {@code runnable} * @see #invokeLater * @see Toolkit#getSystemEventQueue * @see #isDispatchThread diff --git a/jdk/src/java.desktop/share/classes/java/awt/FileDialog.java b/jdk/src/java.desktop/share/classes/java/awt/FileDialog.java index 5b9c17d58ce..197458fa536 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/FileDialog.java +++ b/jdk/src/java.desktop/share/classes/java/awt/FileDialog.java @@ -32,11 +32,11 @@ import java.io.File; import sun.awt.AWTAccessor; /** - * The FileDialog class displays a dialog window + * The {@code FileDialog} class displays a dialog window * from which the user can select a file. *

* Since it is a modal dialog, when the application calls - * its show method to display the dialog, + * its {@code show} method to display the dialog, * it blocks the rest of the application until the user has * chosen a file. * @@ -61,10 +61,10 @@ public class FileDialog extends Dialog { public static final int SAVE = 1; /* - * There are two FileDialog modes: LOAD and - * SAVE. + * There are two {@code FileDialog} modes: {@code LOAD} and + * {@code SAVE}. * This integer will represent one or the other. - * If the mode is not specified it will default to LOAD. + * If the mode is not specified it will default to {@code LOAD}. * * @serial * @see getMode() @@ -76,7 +76,7 @@ public class FileDialog extends Dialog { /* * The string specifying the directory to display - * in the file dialog. This variable may be null. + * in the file dialog. This variable may be {@code null}. * * @serial * @see getDirectory() @@ -87,7 +87,7 @@ public class FileDialog extends Dialog { /* * The string specifying the initial value of the * filename text field in the file dialog. - * This variable may be null. + * This variable may be {@code null}. * * @serial * @see getFile() @@ -118,7 +118,7 @@ public class FileDialog extends Dialog { * The filter used as the file dialog's filename filter. * The file dialog will only be displaying files whose * names are accepted by this filter. - * This variable may be null. + * This variable may be {@code null}. * * @serial * @see #getFilenameFilter() @@ -173,7 +173,7 @@ public class FileDialog extends Dialog { /** * Creates a file dialog for loading a file. The title of the * file dialog is initially empty. This is a convenience method for - * FileDialog(parent, "", LOAD). + * {@code FileDialog(parent, "", LOAD)}. *

* Note: Some platforms may not support * showing the user-specified title in a file dialog. @@ -192,7 +192,7 @@ public class FileDialog extends Dialog { * Creates a file dialog window with the specified title for loading * a file. The files shown are those in the current directory. * This is a convenience method for - * FileDialog(parent, title, LOAD). + * {@code FileDialog(parent, title, LOAD)}. *

* Note: Some platforms may not support * showing the user-specified title in a file dialog. @@ -211,10 +211,10 @@ public class FileDialog extends Dialog { * Creates a file dialog window with the specified title for loading * or saving a file. *

- * If the value of mode is LOAD, then the + * If the value of {@code mode} is {@code LOAD}, then the * file dialog is finding a file to read, and the files shown are those * in the current directory. If the value of - * mode is SAVE, the file dialog is finding + * {@code mode} is {@code SAVE}, the file dialog is finding * a place to write a file. *

* Note: Some platforms may not support @@ -226,7 +226,7 @@ public class FileDialog extends Dialog { * @param parent the owner of the dialog * @param title the title of the dialog * @param mode the mode of the dialog; either - * FileDialog.LOAD or FileDialog.SAVE + * {@code FileDialog.LOAD} or {@code FileDialog.SAVE} * @exception IllegalArgumentException if an illegal file * dialog mode is supplied * @see java.awt.FileDialog#LOAD @@ -241,7 +241,7 @@ public class FileDialog extends Dialog { /** * Creates a file dialog for loading a file. The title of the * file dialog is initially empty. This is a convenience method for - * FileDialog(parent, "", LOAD). + * {@code FileDialog(parent, "", LOAD)}. *

* Note: Some platforms may not support * showing the user-specified title in a file dialog. @@ -250,13 +250,13 @@ public class FileDialog extends Dialog { * displayed. * * @param parent the owner of the dialog - * @exception java.lang.IllegalArgumentException if the parent's - * GraphicsConfiguration + * @exception java.lang.IllegalArgumentException if the {@code parent}'s + * {@code GraphicsConfiguration} * is not from a screen device; - * @exception java.lang.IllegalArgumentException if parent - * is null; this exception is always thrown when - * GraphicsEnvironment.isHeadless - * returns true + * @exception java.lang.IllegalArgumentException if {@code parent} + * is {@code null}; this exception is always thrown when + * {@code GraphicsEnvironment.isHeadless} + * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.5 */ @@ -268,7 +268,7 @@ public class FileDialog extends Dialog { * Creates a file dialog window with the specified title for loading * a file. The files shown are those in the current directory. * This is a convenience method for - * FileDialog(parent, title, LOAD). + * {@code FileDialog(parent, title, LOAD)}. *

* Note: Some platforms may not support * showing the user-specified title in a file dialog. @@ -277,16 +277,16 @@ public class FileDialog extends Dialog { * displayed. * * @param parent the owner of the dialog - * @param title the title of the dialog; a null value + * @param title the title of the dialog; a {@code null} value * will be accepted without causing a - * NullPointerException to be thrown - * @exception java.lang.IllegalArgumentException if the parent's - * GraphicsConfiguration + * {@code NullPointerException} to be thrown + * @exception java.lang.IllegalArgumentException if the {@code parent}'s + * {@code GraphicsConfiguration} * is not from a screen device; - * @exception java.lang.IllegalArgumentException if parent - * is null; this exception is always thrown when - * GraphicsEnvironment.isHeadless - * returns true + * @exception java.lang.IllegalArgumentException if {@code parent} + * is {@code null}; this exception is always thrown when + * {@code GraphicsEnvironment.isHeadless} + * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.5 */ @@ -298,10 +298,10 @@ public class FileDialog extends Dialog { * Creates a file dialog window with the specified title for loading * or saving a file. *

- * If the value of mode is LOAD, then the + * If the value of {@code mode} is {@code LOAD}, then the * file dialog is finding a file to read, and the files shown are those * in the current directory. If the value of - * mode is SAVE, the file dialog is finding + * {@code mode} is {@code SAVE}, the file dialog is finding * a place to write a file. *

* Note: Some platforms may not support @@ -311,20 +311,20 @@ public class FileDialog extends Dialog { * displayed. * * @param parent the owner of the dialog - * @param title the title of the dialog; a null value + * @param title the title of the dialog; a {@code null} value * will be accepted without causing a - * NullPointerException to be thrown + * {@code NullPointerException} to be thrown * @param mode the mode of the dialog; either - * FileDialog.LOAD or FileDialog.SAVE + * {@code FileDialog.LOAD} or {@code FileDialog.SAVE} * @exception java.lang.IllegalArgumentException if an illegal * file dialog mode is supplied; - * @exception java.lang.IllegalArgumentException if the parent's - * GraphicsConfiguration + * @exception java.lang.IllegalArgumentException if the {@code parent}'s + * {@code GraphicsConfiguration} * is not from a screen device; - * @exception java.lang.IllegalArgumentException if parent - * is null; this exception is always thrown when - * GraphicsEnvironment.isHeadless - * returns true + * @exception java.lang.IllegalArgumentException if {@code parent} + * is {@code null}; this exception is always thrown when + * {@code GraphicsEnvironment.isHeadless} + * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @see java.awt.FileDialog#LOAD * @see java.awt.FileDialog#SAVE @@ -353,8 +353,8 @@ public class FileDialog extends Dialog { /** - * Constructs a name for this component. Called by getName() - * when the name is null. + * Constructs a name for this component. Called by {@code getName()} + * when the name is {@code null}. */ String constructComponentName() { synchronized (FileDialog.class) { @@ -382,8 +382,8 @@ public class FileDialog extends Dialog { * or for saving to a file. * * @return the mode of this file dialog window, either - * FileDialog.LOAD or - * FileDialog.SAVE + * {@code FileDialog.LOAD} or + * {@code FileDialog.SAVE} * @see java.awt.FileDialog#LOAD * @see java.awt.FileDialog#SAVE * @see java.awt.FileDialog#setMode @@ -393,13 +393,13 @@ public class FileDialog extends Dialog { } /** - * Sets the mode of the file dialog. If mode is not - * a legal value, an exception will be thrown and mode + * Sets the mode of the file dialog. If {@code mode} is not + * a legal value, an exception will be thrown and {@code mode} * will not be set. * * @param mode the mode for this file dialog, either - * FileDialog.LOAD or - * FileDialog.SAVE + * {@code FileDialog.LOAD} or + * {@code FileDialog.SAVE} * @see java.awt.FileDialog#LOAD * @see java.awt.FileDialog#SAVE * @see java.awt.FileDialog#getMode @@ -421,8 +421,8 @@ public class FileDialog extends Dialog { /** * Gets the directory of this file dialog. * - * @return the (potentially null or invalid) - * directory of this FileDialog + * @return the (potentially {@code null} or invalid) + * directory of this {@code FileDialog} * @see java.awt.FileDialog#setDirectory */ public String getDirectory() { @@ -431,14 +431,14 @@ public class FileDialog extends Dialog { /** * Sets the directory of this file dialog window to be the - * specified directory. Specifying a null or an + * specified directory. Specifying a {@code null} or an * invalid directory implies an implementation-defined default. * This default will not be realized, however, until the user - * has selected a file. Until this point, getDirectory() + * has selected a file. Until this point, {@code getDirectory()} * will return the value passed into this method. *

* Specifying "" as the directory is exactly equivalent to - * specifying null as the directory. + * specifying {@code null} as the directory. * * @param dir the specified directory * @see java.awt.FileDialog#getDirectory @@ -453,10 +453,10 @@ public class FileDialog extends Dialog { /** * Gets the selected file of this file dialog. If the user - * selected CANCEL, the returned file is null. + * selected {@code CANCEL}, the returned file is {@code null}. * * @return the currently selected file of this file dialog window, - * or null if none is selected + * or {@code null} if none is selected * @see java.awt.FileDialog#setFile */ public String getFile() { @@ -592,12 +592,12 @@ public class FileDialog extends Dialog { } /** - * Reads the ObjectInputStream and performs + * Reads the {@code ObjectInputStream} and performs * a backwards compatibility check by converting - * either a dir or a file - * equal to an empty string to null. + * either a {@code dir} or a {@code file} + * equal to an empty string to {@code null}. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read */ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException @@ -614,11 +614,11 @@ public class FileDialog extends Dialog { } /** - * Returns a string representing the state of this FileDialog + * Returns a string representing the state of this {@code FileDialog} * window. This method is intended to be used only for debugging purposes, * and the content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this file dialog window */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/FlowLayout.java b/jdk/src/java.desktop/share/classes/java/awt/FlowLayout.java index 4405620de13..7cdfe67619b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/FlowLayout.java +++ b/jdk/src/java.desktop/share/classes/java/awt/FlowLayout.java @@ -30,16 +30,16 @@ import java.io.IOException; /** * A flow layout arranges components in a directional flow, much * like lines of text in a paragraph. The flow direction is - * determined by the container's componentOrientation + * determined by the container's {@code componentOrientation} * property and may be one of two values: *

    - *
  • ComponentOrientation.LEFT_TO_RIGHT - *
  • ComponentOrientation.RIGHT_TO_LEFT + *
  • {@code ComponentOrientation.LEFT_TO_RIGHT} + *
  • {@code ComponentOrientation.RIGHT_TO_LEFT} *
* Flow layouts are typically used * to arrange buttons in a panel. It arranges buttons * horizontally until no more buttons fit on the same line. - * The line alignment is determined by the align + * The line alignment is determined by the {@code align} * property. The possible values are: *
* * @see Paint @@ -65,19 +65,19 @@ public class GradientPaint implements Paint { boolean cyclic; /** - * Constructs a simple acyclic GradientPaint object. + * Constructs a simple acyclic {@code GradientPaint} object. * @param x1 x coordinate of the first specified - * Point in user space + * {@code Point} in user space * @param y1 y coordinate of the first specified - * Point in user space - * @param color1 Color at the first specified - * Point + * {@code Point} in user space + * @param color1 {@code Color} at the first specified + * {@code Point} * @param x2 x coordinate of the second specified - * Point in user space + * {@code Point} in user space * @param y2 y coordinate of the second specified - * Point in user space - * @param color2 Color at the second specified - * Point + * {@code Point} in user space + * @param color2 {@code Color} at the second specified + * {@code Point} * @throws NullPointerException if either one of colors is null */ public GradientPaint(float x1, @@ -97,13 +97,13 @@ public class GradientPaint implements Paint { } /** - * Constructs a simple acyclic GradientPaint object. - * @param pt1 the first specified Point in user space - * @param color1 Color at the first specified - * Point - * @param pt2 the second specified Point in user space - * @param color2 Color at the second specified - * Point + * Constructs a simple acyclic {@code GradientPaint} object. + * @param pt1 the first specified {@code Point} in user space + * @param color1 {@code Color} at the first specified + * {@code Point} + * @param pt2 the second specified {@code Point} in user space + * @param color2 {@code Color} at the second specified + * {@code Point} * @throws NullPointerException if either one of colors or points * is null */ @@ -123,22 +123,22 @@ public class GradientPaint implements Paint { } /** - * Constructs either a cyclic or acyclic GradientPaint - * object depending on the boolean parameter. + * Constructs either a cyclic or acyclic {@code GradientPaint} + * object depending on the {@code boolean} parameter. * @param x1 x coordinate of the first specified - * Point in user space + * {@code Point} in user space * @param y1 y coordinate of the first specified - * Point in user space - * @param color1 Color at the first specified - * Point + * {@code Point} in user space + * @param color1 {@code Color} at the first specified + * {@code Point} * @param x2 x coordinate of the second specified - * Point in user space + * {@code Point} in user space * @param y2 y coordinate of the second specified - * Point in user space - * @param color2 Color at the second specified - * Point - * @param cyclic true if the gradient pattern should cycle - * repeatedly between the two colors; false otherwise + * {@code Point} in user space + * @param color2 {@code Color} at the second specified + * {@code Point} + * @param cyclic {@code true} if the gradient pattern should cycle + * repeatedly between the two colors; {@code false} otherwise */ public GradientPaint(float x1, float y1, @@ -152,18 +152,18 @@ public class GradientPaint implements Paint { } /** - * Constructs either a cyclic or acyclic GradientPaint - * object depending on the boolean parameter. - * @param pt1 the first specified Point + * Constructs either a cyclic or acyclic {@code GradientPaint} + * object depending on the {@code boolean} parameter. + * @param pt1 the first specified {@code Point} * in user space - * @param color1 Color at the first specified - * Point - * @param pt2 the second specified Point + * @param color1 {@code Color} at the first specified + * {@code Point} + * @param pt2 the second specified {@code Point} * in user space - * @param color2 Color at the second specified - * Point - * @param cyclic true if the gradient pattern should cycle - * repeatedly between the two colors; false otherwise + * @param color2 {@code Color} at the second specified + * {@code Point} + * @param cyclic {@code true} if the gradient pattern should cycle + * repeatedly between the two colors; {@code false} otherwise * @throws NullPointerException if either one of colors or points * is null */ @@ -181,7 +181,7 @@ public class GradientPaint implements Paint { * Returns a copy of the point P1 that anchors the first color. * @return a {@link Point2D} object that is a copy of the point * that anchors the first color of this - * GradientPaint. + * {@code GradientPaint}. */ public Point2D getPoint1() { return new Point2D.Float(p1.x, p1.y); @@ -189,7 +189,7 @@ public class GradientPaint implements Paint { /** * Returns the color C1 anchored by the point P1. - * @return a Color object that is the color + * @return a {@code Color} object that is the color * anchored by P1. */ public Color getColor1() { @@ -200,7 +200,7 @@ public class GradientPaint implements Paint { * Returns a copy of the point P2 which anchors the second color. * @return a {@link Point2D} object that is a copy of the point * that anchors the second color of this - * GradientPaint. + * {@code GradientPaint}. */ public Point2D getPoint2() { return new Point2D.Float(p2.x, p2.y); @@ -208,7 +208,7 @@ public class GradientPaint implements Paint { /** * Returns the color C2 anchored by the point P2. - * @return a Color object that is the color + * @return a {@code Color} object that is the color * anchored by P2. */ public Color getColor2() { @@ -216,10 +216,10 @@ public class GradientPaint implements Paint { } /** - * Returns true if the gradient cycles repeatedly + * Returns {@code true} if the gradient cycles repeatedly * between the two colors C1 and C2. - * @return true if the gradient cycles repeatedly - * between the two colors; false otherwise. + * @return {@code true} if the gradient cycles repeatedly + * between the two colors; {@code false} otherwise. */ public boolean isCyclic() { return cyclic; @@ -264,8 +264,8 @@ public class GradientPaint implements Paint { } /** - * Returns the transparency mode for this GradientPaint. - * @return an integer value representing this GradientPaint + * Returns the transparency mode for this {@code GradientPaint}. + * @return an integer value representing this {@code GradientPaint} * object's transparency mode. * @see Transparency */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Graphics.java b/jdk/src/java.desktop/share/classes/java/awt/Graphics.java index b517cf65390..932a89d5ade 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Graphics.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Graphics.java @@ -31,17 +31,17 @@ import java.awt.image.ImageObserver; import java.text.AttributedCharacterIterator; /** - * The Graphics class is the abstract base class for + * The {@code Graphics} class is the abstract base class for * all graphics contexts that allow an application to draw onto * components that are realized on various devices, as well as * onto off-screen images. *

- * A Graphics object encapsulates state information needed + * A {@code Graphics} object encapsulates state information needed * for the basic rendering operations that Java supports. This * state information includes the following properties: * *

    - *
  • The Component object on which to draw. + *
  • The {@code Component} object on which to draw. *
  • A translation origin for rendering and clipping coordinates. *
  • The current clip. *
  • The current color. @@ -72,21 +72,21 @@ import java.text.AttributedCharacterIterator; * the text, except for any descenders. *

* All coordinates that appear as arguments to the methods of this - * Graphics object are considered relative to the - * translation origin of this Graphics object prior to + * {@code Graphics} object are considered relative to the + * translation origin of this {@code Graphics} object prior to * the invocation of the method. *

* All rendering operations modify only pixels which lie within the * area bounded by the current clip, which is specified by a {@link Shape} * in user space and is controlled by the program using the - * Graphics object. This user clip + * {@code Graphics} object. This user clip * is transformed into device space and combined with the * device clip, which is defined by the visibility of windows and * device extents. The combination of the user clip and device clip * defines the composite clip, which determines the final clipping * region. The user clip cannot be modified by the rendering * system to reflect the resulting composite clip. The user clip can only - * be changed through the setClip or clipRect + * be changed through the {@code setClip} or {@code clipRect} * methods. * All drawing or writing is done in the current color, * using the current paint mode, and in the current font. @@ -104,14 +104,14 @@ import java.text.AttributedCharacterIterator; public abstract class Graphics { /** - * Constructs a new Graphics object. + * Constructs a new {@code Graphics} object. * This constructor is the default constructor for a graphics * context. *

- * Since Graphics is an abstract class, applications + * Since {@code Graphics} is an abstract class, applications * cannot call this constructor directly. Graphics contexts are * obtained from other graphics contexts or are created by calling - * getGraphics on a component. + * {@code getGraphics} on a component. * @see java.awt.Graphics#create() * @see java.awt.Component#getGraphics */ @@ -119,36 +119,36 @@ public abstract class Graphics { } /** - * Creates a new Graphics object that is - * a copy of this Graphics object. + * Creates a new {@code Graphics} object that is + * a copy of this {@code Graphics} object. * @return a new graphics context that is a copy of * this graphics context. */ public abstract Graphics create(); /** - * Creates a new Graphics object based on this - * Graphics object, but with a new translation and clip area. - * The new Graphics object has its origin + * Creates a new {@code Graphics} object based on this + * {@code Graphics} object, but with a new translation and clip area. + * The new {@code Graphics} object has its origin * translated to the specified point (xy). * Its clip area is determined by the intersection of the original * clip area with the specified rectangle. The arguments are all * interpreted in the coordinate system of the original - * Graphics object. The new graphics context is + * {@code Graphics} object. The new graphics context is * identical to the original, except in two respects: * *

    *
  • * The new graphics context is translated by (xy). - * That is to say, the point (00) in the + * That is to say, the point ({@code 0}, {@code 0}) in the * new graphics context is the same as (xy) in * the original graphics context. *
  • * The new graphics context has an additional clipping rectangle, in * addition to whatever (translated) clipping rectangle it inherited * from the original graphics context. The origin of the new clipping - * rectangle is at (00), and its size - * is specified by the width and height + * rectangle is at ({@code 0}, {@code 0}), and its size + * is specified by the {@code width} and {@code height} * arguments. *
* @@ -273,12 +273,12 @@ public abstract class Graphics { * This method refers to the user clip, which is independent of the * clipping associated with device bounds and window visibility. * If no clip has previously been set, or if the clip has been - * cleared using setClip(null), this method returns - * null. + * cleared using {@code setClip(null)}, this method returns + * {@code null}. * The coordinates in the rectangle are relative to the coordinate * system origin of this graphics context. * @return the bounding rectangle of the current clipping area, - * or null if no clip is set. + * or {@code null} if no clip is set. * @see java.awt.Graphics#getClip * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(int, int, int, int) @@ -292,7 +292,7 @@ public abstract class Graphics { * The resulting clipping area is the intersection of the current * clipping area and the specified rectangle. If there is no * current clipping area, either because the clip has never been - * set, or the clip has been cleared using setClip(null), + * set, or the clip has been cleared using {@code setClip(null)}, * the specified rectangle becomes the new clip. * This method sets the user clip, which is independent of the * clipping associated with device bounds and window visibility. @@ -330,10 +330,10 @@ public abstract class Graphics { * This method returns the user clip, which is independent of the * clipping associated with device bounds and window visibility. * If no clip has previously been set, or if the clip has been - * cleared using setClip(null), this method returns - * null. - * @return a Shape object representing the - * current clipping area, or null if + * cleared using {@code setClip(null)}, this method returns + * {@code null}. + * @return a {@code Shape} object representing the + * current clipping area, or {@code null} if * no clip is set. * @see java.awt.Graphics#getClipBounds * @see java.awt.Graphics#clipRect @@ -345,15 +345,15 @@ public abstract class Graphics { /** * Sets the current clipping area to an arbitrary clip shape. - * Not all objects that implement the Shape + * Not all objects that implement the {@code Shape} * interface can be used to set the clip. The only - * Shape objects that are guaranteed to be - * supported are Shape objects that are - * obtained via the getClip method and via - * Rectangle objects. This method sets the + * {@code Shape} objects that are guaranteed to be + * supported are {@code Shape} objects that are + * obtained via the {@code getClip} method and via + * {@code Rectangle} objects. This method sets the * user clip, which is independent of the clipping associated * with device bounds and window visibility. - * @param clip the Shape to use to set the clip + * @param clip the {@code Shape} to use to set the clip * @see java.awt.Graphics#getClip() * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(int, int, int, int) @@ -363,16 +363,16 @@ public abstract class Graphics { /** * Copies an area of the component by a distance specified by - * dx and dy. From the point specified - * by x and y, this method + * {@code dx} and {@code dy}. From the point specified + * by {@code x} and {@code y}, this method * copies downwards and to the right. To copy an area of the * component to the left or upwards, specify a negative value for - * dx or dy. + * {@code dx} or {@code dy}. * If a portion of the source rectangle lies outside the bounds * of the component, or is obscured by another window or component, - * copyArea will be unable to copy the associated + * {@code copyArea} will be unable to copy the associated * pixels. The area that is omitted can be refreshed by calling - * the component's paint method. + * the component's {@code paint} method. * @param x the x coordinate of the source rectangle. * @param y the y coordinate of the source rectangle. * @param width the width of the source rectangle. @@ -397,12 +397,12 @@ public abstract class Graphics { /** * Fills the specified rectangle. * The left and right edges of the rectangle are at - * x and x + width - 1. + * {@code x} and x + width - 1. * The top and bottom edges are at - * y and y + height - 1. + * {@code y} and y + height - 1. * The resulting rectangle covers an area - * width pixels wide by - * height pixels tall. + * {@code width} pixels wide by + * {@code height} pixels tall. * The rectangle is filled using the graphics context's current color. * @param x the x coordinate * of the rectangle to be filled. @@ -418,9 +418,9 @@ public abstract class Graphics { /** * Draws the outline of the specified rectangle. * The left and right edges of the rectangle are at - * x and x + width. + * {@code x} and x + width. * The top and bottom edges are at - * y and y + height. + * {@code y} and y + height. * The rectangle is drawn using the graphics context's current color. * @param x the x coordinate * of the rectangle to be drawn. @@ -453,7 +453,7 @@ public abstract class Graphics { *

* Beginning with Java 1.1, the background color * of offscreen images may be system dependent. Applications should - * use setColor followed by fillRect to + * use {@code setColor} followed by {@code fillRect} to * ensure that an offscreen image is cleared to a specific color. * @param x the x coordinate of the rectangle to clear. * @param y the y coordinate of the rectangle to clear. @@ -470,9 +470,9 @@ public abstract class Graphics { /** * Draws an outlined round-cornered rectangle using this graphics * context's current color. The left and right edges of the rectangle - * are at x and x + width, + * are at {@code x} and x + width, * respectively. The top and bottom edges of the rectangle are at - * y and y + height. + * {@code y} and y + height. * @param x the x coordinate of the rectangle to be drawn. * @param y the y coordinate of the rectangle to be drawn. * @param width the width of the rectangle to be drawn. @@ -489,9 +489,9 @@ public abstract class Graphics { /** * Fills the specified rounded corner rectangle with the current color. * The left and right edges of the rectangle - * are at x and x + width - 1, + * are at {@code x} and x + width - 1, * respectively. The top and bottom edges of the rectangle are at - * y and y + height - 1. + * {@code y} and y + height - 1. * @param x the x coordinate of the rectangle to be filled. * @param y the y coordinate of the rectangle to be filled. * @param width the width of the rectangle to be filled. @@ -576,8 +576,8 @@ public abstract class Graphics { /** * Draws the outline of an oval. * The result is a circle or ellipse that fits within the - * rectangle specified by the x, y, - * width, and height arguments. + * rectangle specified by the {@code x}, {@code y}, + * {@code width}, and {@code height} arguments. *

* The oval covers an area that is * width + 1 pixels wide @@ -609,8 +609,8 @@ public abstract class Graphics { * Draws the outline of a circular or elliptical arc * covering the specified rectangle. *

- * The resulting arc begins at startAngle and extends - * for arcAngle degrees, using the current color. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees, using the current color. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -618,7 +618,7 @@ public abstract class Graphics { *

* The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

* The resulting arc covers an area * width + 1 pixels wide @@ -648,8 +648,8 @@ public abstract class Graphics { /** * Fills a circular or elliptical arc covering the specified rectangle. *

- * The resulting arc begins at startAngle and extends - * for arcAngle degrees. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -657,7 +657,7 @@ public abstract class Graphics { *

* The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

* The resulting arc covers an area * width + 1 pixels wide @@ -704,16 +704,16 @@ public abstract class Graphics { * arrays of x and y coordinates. * Each pair of (xy) coordinates defines a point. *

- * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#fillPolygon * @see java.awt.Graphics#drawPolyline @@ -723,7 +723,7 @@ public abstract class Graphics { /** * Draws the outline of a polygon defined by the specified - * Polygon object. + * {@code Polygon} object. * @param p the polygon to draw. * @see java.awt.Graphics#fillPolygon * @see java.awt.Graphics#drawPolyline @@ -736,19 +736,19 @@ public abstract class Graphics { * Fills a closed polygon defined by * arrays of x and y coordinates. *

- * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. *

* The area inside the polygon is defined using an * even-odd fill rule, also known as the alternating rule. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#drawPolygon(int[], int[], int) */ @@ -776,7 +776,7 @@ public abstract class Graphics { * @param str the string to be drawn. * @param x the x coordinate. * @param y the y coordinate. - * @throws NullPointerException if str is null. + * @throws NullPointerException if {@code str} is {@code null}. * @see java.awt.Graphics#drawBytes * @see java.awt.Graphics#drawChars */ @@ -792,8 +792,8 @@ public abstract class Graphics { * @param iterator the iterator whose text is to be drawn * @param x the x coordinate. * @param y the y coordinate. - * @throws NullPointerException if iterator is - * null. + * @throws NullPointerException if {@code iterator} is + * {@code null}. * @see java.awt.Graphics#drawBytes * @see java.awt.Graphics#drawChars */ @@ -810,11 +810,11 @@ public abstract class Graphics { * @param length the number of characters to be drawn * @param x the x coordinate of the baseline of the text * @param y the y coordinate of the baseline of the text - * @throws NullPointerException if data is null. - * @throws IndexOutOfBoundsException if offset or - * lengthis less than zero, or - * offset+length is greater than the length of the - * data array. + * @throws NullPointerException if {@code data} is {@code null}. + * @throws IndexOutOfBoundsException if {@code offset} or + * {@code length} is less than zero, or + * {@code offset+length} is greater than the length of the + * {@code data} array. * @see java.awt.Graphics#drawBytes * @see java.awt.Graphics#drawString */ @@ -836,10 +836,10 @@ public abstract class Graphics { * @param length the number of bytes that are drawn * @param x the x coordinate of the baseline of the text * @param y the y coordinate of the baseline of the text - * @throws NullPointerException if data is null. - * @throws IndexOutOfBoundsException if offset or - * lengthis less than zero, or offset+length - * is greater than the length of the data array. + * @throws NullPointerException if {@code data} is {@code null}. + * @throws IndexOutOfBoundsException if {@code offset} or + * {@code length} is less than zero, or {@code offset+length} + * is greater than the length of the {@code data} array. * @see java.awt.Graphics#drawChars * @see java.awt.Graphics#drawString */ @@ -861,21 +861,21 @@ public abstract class Graphics { *

* If the image has completely loaded and its pixels are * no longer being changed, then - * drawImage returns true. - * Otherwise, drawImage returns false + * {@code drawImage} returns {@code true}. + * Otherwise, {@code drawImage} returns {@code false} * and as more of * the image becomes available * or it is time to draw another frame of animation, * the process that loads the image notifies * the specified image observer. * @param img the specified image to be drawn. This method does - * nothing if img is null. + * nothing if {@code img} is null. * @param x the x coordinate. * @param y the y coordinate. * @param observer object to be notified as more of * the image is converted. - * @return false if the image pixels are still changing; - * true otherwise. + * @return {@code false} if the image pixels are still changing; + * {@code true} otherwise. * @see java.awt.Image * @see java.awt.image.ImageObserver * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) @@ -896,9 +896,9 @@ public abstract class Graphics { * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that loads the image notifies - * the image observer by calling its imageUpdate method. + * the image observer by calling its {@code imageUpdate} method. *

* A scaled version of an image will not necessarily be * available immediately just because an unscaled version of the @@ -906,15 +906,15 @@ public abstract class Graphics { * the image may be cached separately and generated from the original * data in a separate image production sequence. * @param img the specified image to be drawn. This method does - * nothing if img is null. + * nothing if {@code img} is null. * @param x the x coordinate. * @param y the y coordinate. * @param width the width of the rectangle. * @param height the height of the rectangle. * @param observer object to be notified as more of * the image is converted. - * @return false if the image pixels are still changing; - * true otherwise. + * @return {@code false} if the image pixels are still changing; + * {@code true} otherwise. * @see java.awt.Image * @see java.awt.image.ImageObserver * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) @@ -940,23 +940,23 @@ public abstract class Graphics { *

* If the image has completely loaded and its pixels are * no longer being changed, then - * drawImage returns true. - * Otherwise, drawImage returns false + * {@code drawImage} returns {@code true}. + * Otherwise, {@code drawImage} returns {@code false} * and as more of * the image becomes available * or it is time to draw another frame of animation, * the process that loads the image notifies * the specified image observer. * @param img the specified image to be drawn. This method does - * nothing if img is null. + * nothing if {@code img} is null. * @param x the x coordinate. * @param y the y coordinate. * @param bgcolor the background color to paint under the * non-opaque portions of the image. * @param observer object to be notified as more of * the image is converted. - * @return false if the image pixels are still changing; - * true otherwise. + * @return {@code false} if the image pixels are still changing; + * {@code true} otherwise. * @see java.awt.Image * @see java.awt.image.ImageObserver * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) @@ -981,7 +981,7 @@ public abstract class Graphics { * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that loads the image notifies * the specified image observer. *

@@ -991,7 +991,7 @@ public abstract class Graphics { * the image may be cached separately and generated from the original * data in a separate image production sequence. * @param img the specified image to be drawn. This method does - * nothing if img is null. + * nothing if {@code img} is null. * @param x the x coordinate. * @param y the y coordinate. * @param width the width of the rectangle. @@ -1000,8 +1000,8 @@ public abstract class Graphics { * non-opaque portions of the image. * @param observer object to be notified as more of * the image is converted. - * @return false if the image pixels are still changing; - * true otherwise. + * @return {@code false} if the image pixels are still changing; + * {@code true} otherwise. * @see java.awt.Image * @see java.awt.image.ImageObserver * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) @@ -1021,7 +1021,7 @@ public abstract class Graphics { * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that loads the image notifies * the specified image observer. *

@@ -1035,7 +1035,7 @@ public abstract class Graphics { * mapped to the second destination coordinate. The subimage is * scaled and flipped as needed to preserve those mappings. * @param img the specified image to be drawn. This method does - * nothing if img is null. + * nothing if {@code img} is null. * @param dx1 the x coordinate of the first corner of the * destination rectangle. * @param dy1 the y coordinate of the first corner of the @@ -1054,8 +1054,8 @@ public abstract class Graphics { * source rectangle. * @param observer object to be notified as more of the image is * scaled and converted. - * @return false if the image pixels are still changing; - * true otherwise. + * @return {@code false} if the image pixels are still changing; + * {@code true} otherwise. * @see java.awt.Image * @see java.awt.image.ImageObserver * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) @@ -1080,7 +1080,7 @@ public abstract class Graphics { * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that loads the image notifies * the specified image observer. *

@@ -1094,7 +1094,7 @@ public abstract class Graphics { * mapped to the second destination coordinate. The subimage is * scaled and flipped as needed to preserve those mappings. * @param img the specified image to be drawn. This method does - * nothing if img is null. + * nothing if {@code img} is null. * @param dx1 the x coordinate of the first corner of the * destination rectangle. * @param dy1 the y coordinate of the first corner of the @@ -1115,8 +1115,8 @@ public abstract class Graphics { * non-opaque portions of the image. * @param observer object to be notified as more of the image is * scaled and converted. - * @return false if the image pixels are still changing; - * true otherwise. + * @return {@code false} if the image pixels are still changing; + * {@code true} otherwise. * @see java.awt.Image * @see java.awt.image.ImageObserver * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) @@ -1131,10 +1131,10 @@ public abstract class Graphics { /** * Disposes of this graphics context and releases * any system resources that it is using. - * A Graphics object cannot be used after - * disposehas been called. + * A {@code Graphics} object cannot be used after + * {@code dispose} has been called. *

- * When a Java program runs, a large number of Graphics + * When a Java program runs, a large number of {@code Graphics} * objects can be created within a short time frame. * Although the finalization process of the garbage collector * also disposes of the same system resources, it is preferable @@ -1143,12 +1143,12 @@ public abstract class Graphics { * may not run to completion for a long period of time. *

* Graphics objects which are provided as arguments to the - * paint and update methods + * {@code paint} and {@code update} methods * of components are automatically released by the system when * those methods return. For efficiency, programmers should - * call dispose when finished using - * a Graphics object only if it was created - * directly from a component or another Graphics object. + * call {@code dispose} when finished using + * a {@code Graphics} object only if it was created + * directly from a component or another {@code Graphics} object. * @see java.awt.Graphics#finalize * @see java.awt.Component#paint * @see java.awt.Component#update @@ -1166,8 +1166,8 @@ public abstract class Graphics { } /** - * Returns a String object representing this - * Graphics object's value. + * Returns a {@code String} object representing this + * {@code Graphics} object's value. * @return a string representation of this graphics context. */ public String toString() { @@ -1177,9 +1177,9 @@ public abstract class Graphics { /** * Returns the bounding rectangle of the current clipping area. * @return the bounding rectangle of the current clipping area - * or null if no clip is set. + * or {@code null} if no clip is set. * @deprecated As of JDK version 1.1, - * replaced by getClipBounds(). + * replaced by {@code getClipBounds()}. */ @Deprecated public Rectangle getClipRect() { @@ -1208,8 +1208,8 @@ public abstract class Graphics { * @param y the y coordinate of the rectangle to test against the clip * @param width the width of the rectangle to test against the clip * @param height the height of the rectangle to test against the clip - * @return true if the specified rectangle intersects - * the bounds of the current clip; false + * @return {@code true} if the specified rectangle intersects + * the bounds of the current clip; {@code false} * otherwise. */ public boolean hitClip(int x, int y, int width, int height) { @@ -1232,8 +1232,8 @@ public abstract class Graphics { * This method refers to the user clip, which is independent of the * clipping associated with device bounds and window visibility. * If no clip has previously been set, or if the clip has been - * cleared using setClip(null), this method returns the - * specified Rectangle. + * cleared using {@code setClip(null)}, this method returns the + * specified {@code Rectangle}. * @param r the rectangle where the current clipping area is * copied to. Any current values in this rectangle are * overwritten. diff --git a/jdk/src/java.desktop/share/classes/java/awt/Graphics2D.java b/jdk/src/java.desktop/share/classes/java/awt/Graphics2D.java index 080ac3f7f92..ec5f9bd73bb 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Graphics2D.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Graphics2D.java @@ -39,47 +39,47 @@ import java.text.AttributedCharacterIterator; import java.util.Map; /** - * This Graphics2D class extends the + * This {@code Graphics2D} class extends the * {@link Graphics} class to provide more sophisticated * control over geometry, coordinate transformations, color management, * and text layout. This is the fundamental class for rendering * 2-dimensional shapes, text and images on the Java(tm) platform. * *

Coordinate Spaces

- * All coordinates passed to a Graphics2D object are specified + * All coordinates passed to a {@code Graphics2D} object are specified * in a device-independent coordinate system called User Space, which is - * used by applications. The Graphics2D object contains + * used by applications. The {@code Graphics2D} object contains * an {@link AffineTransform} object as part of its rendering state * that defines how to convert coordinates from user space to * device-dependent coordinates in Device Space. *

* Coordinates in device space usually refer to individual device pixels * and are aligned on the infinitely thin gaps between these pixels. - * Some Graphics2D objects can be used to capture rendering + * Some {@code Graphics2D} objects can be used to capture rendering * operations for storage into a graphics metafile for playback on a * concrete device of unknown physical resolution at a later time. Since * the resolution might not be known when the rendering operations are - * captured, the Graphics2D Transform is set up + * captured, the {@code Graphics2D Transform} is set up * to transform user coordinates to a virtual device space that * approximates the expected resolution of the target device. Further * transformations might need to be applied at playback time if the * estimate is incorrect. *

* Some of the operations performed by the rendering attribute objects - * occur in the device space, but all Graphics2D methods take + * occur in the device space, but all {@code Graphics2D} methods take * user space coordinates. *

- * Every Graphics2D object is associated with a target that + * Every {@code Graphics2D} object is associated with a target that * defines where rendering takes place. A * {@link GraphicsConfiguration} object defines the characteristics * of the rendering target, such as pixel format and resolution. * The same rendering target is used throughout the life of a - * Graphics2D object. + * {@code Graphics2D} object. *

- * When creating a Graphics2D object, the - * GraphicsConfiguration + * When creating a {@code Graphics2D} object, the + * {@code GraphicsConfiguration} * specifies the default transform for - * the target of the Graphics2D (a + * the target of the {@code Graphics2D} (a * {@link Component} or {@link Image}). This default transform maps the * user space coordinate system to screen and printer device coordinates * such that the origin maps to the upper left hand corner of the @@ -90,11 +90,11 @@ import java.util.Map; * The scaling of the default transform is set to approximately 72 user * space coordinates per square inch for high resolution devices, such as * printers. For image buffers, the default transform is the - * Identity transform. + * {@code Identity} transform. * *

Rendering Process

* The Rendering Process can be broken down into four phases that are - * controlled by the Graphics2D rendering attributes. + * controlled by the {@code Graphics2D} rendering attributes. * The renderer can optimize many of these steps, either by caching the * results for future calls, by collapsing multiple virtual steps into * a single operation, or by recognizing various attributes as common @@ -106,13 +106,13 @@ import java.util.Map; *
  • * Determine what to render. *
  • - * Constrain the rendering operation to the current Clip. - * The Clip is specified by a {@link Shape} in user + * Constrain the rendering operation to the current {@code Clip}. + * The {@code Clip} is specified by a {@link Shape} in user * space and is controlled by the program using the various clip - * manipulation methods of Graphics and - * Graphics2D. This user clip + * manipulation methods of {@code Graphics} and + * {@code Graphics2D}. This user clip * is transformed into device space by the current - * Transform and combined with the + * {@code Transform} and combined with the * device clip, which is defined by the visibility of windows and * device extents. The combination of the user clip and device clip * defines the composite clip, which determines the final clipping @@ -122,40 +122,40 @@ import java.util.Map; * Determine what colors to render. *
  • * Apply the colors to the destination drawing surface using the current - * {@link Composite} attribute in the Graphics2D context. + * {@link Composite} attribute in the {@code Graphics2D} context. * *
    * The three types of rendering operations, along with details of each * of their particular rendering processes are: *
      *
    1. - * Shape operations + * {@code Shape} operations *
        *
      1. - * If the operation is a draw(Shape) operation, then + * If the operation is a {@code draw(Shape)} operation, then * the {@link Stroke#createStrokedShape(Shape) createStrokedShape} * method on the current {@link Stroke} attribute in the - * Graphics2D context is used to construct a new - * Shape object that contains the outline of the specified - * Shape. + * {@code Graphics2D} context is used to construct a new + * {@code Shape} object that contains the outline of the specified + * {@code Shape}. *
      2. - * The Shape is transformed from user space to device space - * using the current Transform - * in the Graphics2D context. + * The {@code Shape} is transformed from user space to device space + * using the current {@code Transform} + * in the {@code Graphics2D} context. *
      3. - * The outline of the Shape is extracted using the + * The outline of the {@code Shape} is extracted using the * {@link Shape#getPathIterator(AffineTransform) getPathIterator} method of - * Shape, which returns a + * {@code Shape}, which returns a * {@link java.awt.geom.PathIterator PathIterator} - * object that iterates along the boundary of the Shape. + * object that iterates along the boundary of the {@code Shape}. *
      4. - * If the Graphics2D object cannot handle the curved segments - * that the PathIterator object returns then it can call the + * If the {@code Graphics2D} object cannot handle the curved segments + * that the {@code PathIterator} object returns then it can call the * alternate * {@link Shape#getPathIterator(AffineTransform, double) getPathIterator} - * method of Shape, which flattens the Shape. + * method of {@code Shape}, which flattens the {@code Shape}. *
      5. - * The current {@link Paint} in the Graphics2D context + * The current {@link Paint} in the {@code Graphics2D} context * is queried for a {@link PaintContext}, which specifies the * colors to render in device space. *
      @@ -164,12 +164,12 @@ import java.util.Map; *
        *
      1. * The following steps are used to determine the set of glyphs required - * to render the indicated String: + * to render the indicated {@code String}: *
          *
        1. - * If the argument is a String, then the current - * Font in the Graphics2D context is asked to - * convert the Unicode characters in the String into a set of + * If the argument is a {@code String}, then the current + * {@code Font} in the {@code Graphics2D} context is asked to + * convert the Unicode characters in the {@code String} into a set of * glyphs for presentation with whatever basic layout and shaping * algorithms the font implements. *
        2. @@ -177,75 +177,75 @@ import java.util.Map; * {@link AttributedCharacterIterator}, * the iterator is asked to convert itself to a * {@link java.awt.font.TextLayout TextLayout} - * using its embedded font attributes. The TextLayout + * using its embedded font attributes. The {@code TextLayout} * implements more sophisticated glyph layout algorithms that * perform Unicode bi-directional layout adjustments automatically * for multiple fonts of differing writing directions. *
        3. * If the argument is a * {@link GlyphVector}, then the - * GlyphVector object already contains the appropriate + * {@code GlyphVector} object already contains the appropriate * font-specific glyph codes with explicit coordinates for the position of * each glyph. *
        *
      2. - * The current Font is queried to obtain outlines for the + * The current {@code Font} is queried to obtain outlines for the * indicated glyphs. These outlines are treated as shapes in user space * relative to the position of each glyph that was determined in step 1. *
      3. * The character outlines are filled as indicated above - * under Shape operations. + * under {@code Shape} operations. *
      4. - * The current Paint is queried for a - * PaintContext, which specifies + * The current {@code Paint} is queried for a + * {@code PaintContext}, which specifies * the colors to render in device space. *
      *
    2. - * Image Operations + * {@code Image} Operations *
        *
      1. * The region of interest is defined by the bounding box of the source - * Image. + * {@code Image}. * This bounding box is specified in Image Space, which is the - * Image object's local coordinate system. + * {@code Image} object's local coordinate system. *
      2. - * If an AffineTransform is passed to + * If an {@code AffineTransform} is passed to * {@link #drawImage(java.awt.Image, java.awt.geom.AffineTransform, java.awt.image.ImageObserver) drawImage(Image, AffineTransform, ImageObserver)}, - * the AffineTransform is used to transform the bounding - * box from image space to user space. If no AffineTransform + * the {@code AffineTransform} is used to transform the bounding + * box from image space to user space. If no {@code AffineTransform} * is supplied, the bounding box is treated as if it is already in user space. *
      3. - * The bounding box of the source Image is transformed from user - * space into device space using the current Transform. + * The bounding box of the source {@code Image} is transformed from user + * space into device space using the current {@code Transform}. * Note that the result of transforming the bounding box does not * necessarily result in a rectangular region in device space. *
      4. - * The Image object determines what colors to render, + * The {@code Image} object determines what colors to render, * sampled according to the source to destination - * coordinate mapping specified by the current Transform and the + * coordinate mapping specified by the current {@code Transform} and the * optional image transform. *
      *
    * *

    Default Rendering Attributes

    - * The default values for the Graphics2D rendering attributes are: + * The default values for the {@code Graphics2D} rendering attributes are: *
    - *
    Paint - *
    The color of the Component. - *
    Font - *
    The Font of the Component. - *
    Stroke + *
    {@code Paint} + *
    The color of the {@code Component}. + *
    {@code Font} + *
    The {@code Font} of the {@code Component}. + *
    {@code Stroke} *
    A square pen with a linewidth of 1, no dashing, miter segment joins * and square end caps. - *
    Transform + *
    {@code Transform} *
    The * {@link GraphicsConfiguration#getDefaultTransform() getDefaultTransform} - * for the GraphicsConfiguration of the Component. - *
    Composite + * for the {@code GraphicsConfiguration} of the {@code Component}. + *
    {@code Composite} *
    The {@link AlphaComposite#SRC_OVER} rule. - *
    Clip - *
    No rendering Clip, the output is clipped to the - * Component. + *
    {@code Clip} + *
    No rendering {@code Clip}, the output is clipped to the + * {@code Component}. *
    * *

    Rendering Compatibility Issues

    @@ -291,14 +291,14 @@ import java.util.Map; * Java 2D API maintains compatibility with JDK 1.1 rendering * behavior, such that legacy operations and existing renderer * behavior is unchanged under Java 2D API. Legacy - * methods that map onto general draw and - * fill methods are defined, which clearly indicates - * how Graphics2D extends Graphics based - * on settings of Stroke and Transform + * methods that map onto general {@code draw} and + * {@code fill} methods are defined, which clearly indicates + * how {@code Graphics2D} extends {@code Graphics} based + * on settings of {@code Stroke} and {@code Transform} * attributes and rendering hints. The definition * performs identically under default attribute settings. - * For example, the default Stroke is a - * BasicStroke with a width of 1 and no dashing and the + * For example, the default {@code Stroke} is a + * {@code BasicStroke} with a width of 1 and no dashing and the * default Transform for screen drawing is an Identity transform. *

    * The following two rules provide predictable rendering behavior whether @@ -315,7 +315,7 @@ import java.util.Map; * covered. On the other hand, since coordinates are defined to be * between pixels, a shape like a rectangle would have no half covered * pixels, whether or not it is rendered using antialiasing. - *

  • Lines and paths stroked using the BasicStroke + *
  • Lines and paths stroked using the {@code BasicStroke} * object may be "normalized" to provide consistent rendering of the * outlines when positioned at various points on the drawable and * whether drawn with aliased or antialiased rendering. This @@ -341,11 +341,11 @@ import java.util.Map; * attribute settings: *
      *
    • - * For fill operations, including fillRect, - * fillRoundRect, fillOval, - * fillArc, fillPolygon, and - * clearRect, {@link #fill(Shape) fill} can now be called - * with the desired Shape. For example, when filling a + * For {@code fill} operations, including {@code fillRect}, + * {@code fillRoundRect}, {@code fillOval}, + * {@code fillArc}, {@code fillPolygon}, and + * {@code clearRect}, {@link #fill(Shape) fill} can now be called + * with the desired {@code Shape}. For example, when filling a * rectangle: *
        * fill(new Rectangle(x, y, w, h));
      @@ -353,11 +353,11 @@ import java.util.Map;
        * is called.
        *
        * 
    • - * Similarly, for draw operations, including drawLine, - * drawRect, drawRoundRect, - * drawOval, drawArc, drawPolyline, - * and drawPolygon, {@link #draw(Shape) draw} can now be - * called with the desired Shape. For example, when drawing a + * Similarly, for draw operations, including {@code drawLine}, + * {@code drawRect}, {@code drawRoundRect}, + * {@code drawOval}, {@code drawArc}, {@code drawPolyline}, + * and {@code drawPolygon}, {@link #draw(Shape) draw} can now be + * called with the desired {@code Shape}. For example, when drawing a * rectangle: *
        * draw(new Rectangle(x, y, w, h));
      @@ -365,36 +365,36 @@ import java.util.Map;
        * is called.
        *
        * 
    • - * The draw3DRect and fill3DRect methods were - * implemented in terms of the drawLine and - * fillRect methods in the Graphics class which - * would predicate their behavior upon the current Stroke - * and Paint objects in a Graphics2D context. + * The {@code draw3DRect} and {@code fill3DRect} methods were + * implemented in terms of the {@code drawLine} and + * {@code fillRect} methods in the {@code Graphics} class which + * would predicate their behavior upon the current {@code Stroke} + * and {@code Paint} objects in a {@code Graphics2D} context. * This class overrides those implementations with versions that use - * the current Color exclusively, overriding the current - * Paint and which uses fillRect to describe + * the current {@code Color} exclusively, overriding the current + * {@code Paint} and which uses {@code fillRect} to describe * the exact same behavior as the preexisting methods regardless of the - * setting of the current Stroke. + * setting of the current {@code Stroke}. *
    - * The Graphics class defines only the setColor + * The {@code Graphics} class defines only the {@code setColor} * method to control the color to be painted. Since the Java 2D API extends - * the Color object to implement the new Paint + * the {@code Color} object to implement the new {@code Paint} * interface, the existing - * setColor method is now a convenience method for setting the - * current Paint attribute to a Color object. - * setColor(c) is equivalent to setPaint(c). + * {@code setColor} method is now a convenience method for setting the + * current {@code Paint} attribute to a {@code Color} object. + * {@code setColor(c)} is equivalent to {@code setPaint(c)}. *

    - * The Graphics class defines two methods for controlling + * The {@code Graphics} class defines two methods for controlling * how colors are applied to the destination. *

      *
    1. - * The setPaintMode method is implemented as a convenience - * method to set the default Composite, equivalent to - * setComposite(new AlphaComposite.SrcOver). + * The {@code setPaintMode} method is implemented as a convenience + * method to set the default {@code Composite}, equivalent to + * {@code setComposite(new AlphaComposite.SrcOver)}. *
    2. - * The setXORMode(Color xorcolor) method is implemented - * as a convenience method to set a special Composite object that - * ignores the Alpha components of source colors and sets the + * The {@code setXORMode(Color xorcolor)} method is implemented + * as a convenience method to set a special {@code Composite} object that + * ignores the {@code Alpha} components of source colors and sets the * destination color to the value: *
        * dstpixel = (PixelOf(srccolor) ^ PixelOf(xorcolor) ^ dstpixel);
      @@ -407,13 +407,13 @@ import java.util.Map;
       public abstract class Graphics2D extends Graphics {
       
           /**
      -     * Constructs a new Graphics2D object.  Since
      -     * Graphics2D is an abstract class, and since it must be
      +     * Constructs a new {@code Graphics2D} object.  Since
      +     * {@code Graphics2D} is an abstract class, and since it must be
            * customized by subclasses for different output devices,
      -     * Graphics2D objects cannot be created directly.
      -     * Instead, Graphics2D objects must be obtained from another
      -     * Graphics2D object, created by a
      -     * Component, or obtained from images such as
      +     * {@code Graphics2D} objects cannot be created directly.
      +     * Instead, {@code Graphics2D} objects must be obtained from another
      +     * {@code Graphics2D} object, created by a
      +     * {@code Component}, or obtained from images such as
            * {@link BufferedImage} objects.
            * @see java.awt.Component#getGraphics
            * @see java.awt.Graphics#create
      @@ -431,8 +431,8 @@ public abstract class Graphics2D extends Graphics {
            * The resulting rectangle covers an area that is
            * width + 1 pixels wide
            * by height + 1 pixels tall.  This method
      -     * uses the current Color exclusively and ignores
      -     * the current Paint.
      +     * uses the current {@code Color} exclusively and ignores
      +     * the current {@code Paint}.
            * @param x the x coordinate of the rectangle to be drawn.
            * @param y the y coordinate of the rectangle to be drawn.
            * @param width the width of the rectangle to be drawn.
      @@ -467,9 +467,9 @@ public abstract class Graphics2D extends Graphics {
            * The edges of the rectangle are highlighted so that it appears
            * as if the edges were beveled and lit from the upper left corner.
            * The colors used for the highlighting effect and for filling are
      -     * determined from the current Color.  This method uses
      -     * the current Color exclusively and ignores the current
      -     * Paint.
      +     * determined from the current {@code Color}.  This method uses
      +     * the current {@code Color} exclusively and ignores the current
      +     * {@code Paint}.
            * @param x the x coordinate of the rectangle to be filled.
            * @param y the y coordinate of the rectangle to be filled.
            * @param       width the width of the rectangle to be filled.
      @@ -506,12 +506,12 @@ public abstract class Graphics2D extends Graphics {
           }
       
           /**
      -     * Strokes the outline of a Shape using the settings of the
      -     * current Graphics2D context.  The rendering attributes
      -     * applied include the Clip, Transform,
      -     * Paint, Composite and
      -     * Stroke attributes.
      -     * @param s the Shape to be rendered
      +     * Strokes the outline of a {@code Shape} using the settings of the
      +     * current {@code Graphics2D} context.  The rendering attributes
      +     * applied include the {@code Clip}, {@code Transform},
      +     * {@code Paint}, {@code Composite} and
      +     * {@code Stroke} attributes.
      +     * @param s the {@code Shape} to be rendered
            * @see #setStroke
            * @see #setPaint
            * @see java.awt.Graphics#setColor
      @@ -527,22 +527,22 @@ public abstract class Graphics2D extends Graphics {
            * Renders an image, applying a transform from image space into user space
            * before drawing.
            * The transformation from user space into device space is done with
      -     * the current Transform in the Graphics2D.
      +     * the current {@code Transform} in the {@code Graphics2D}.
            * The specified transformation is applied to the image before the
      -     * transform attribute in the Graphics2D context is applied.
      -     * The rendering attributes applied include the Clip,
      -     * Transform, and Composite attributes.
      +     * transform attribute in the {@code Graphics2D} context is applied.
      +     * The rendering attributes applied include the {@code Clip},
      +     * {@code Transform}, and {@code Composite} attributes.
            * Note that no rendering is done if the specified transform is
            * noninvertible.
            * @param img the specified image to be rendered.
      -     *            This method does nothing if img is null.
      +     *            This method does nothing if {@code img} is null.
            * @param xform the transformation from image space into user space
            * @param obs the {@link ImageObserver}
      -     * to be notified as more of the Image
      +     * to be notified as more of the {@code Image}
            * is converted
      -     * @return true if the Image is
      +     * @return {@code true} if the {@code Image} is
            * fully loaded and completely rendered, or if it's null;
      -     * false if the Image is still being loaded.
      +     * {@code false} if the {@code Image} is still being loaded.
            * @see #transform
            * @see #setTransform
            * @see #setComposite
      @@ -554,19 +554,19 @@ public abstract class Graphics2D extends Graphics {
                                             ImageObserver obs);
       
           /**
      -     * Renders a BufferedImage that is
      +     * Renders a {@code BufferedImage} that is
            * filtered with a
            * {@link BufferedImageOp}.
      -     * The rendering attributes applied include the Clip,
      -     * Transform
      -     * and Composite attributes.  This is equivalent to:
      +     * The rendering attributes applied include the {@code Clip},
      +     * {@code Transform}
      +     * and {@code Composite} attributes.  This is equivalent to:
            * 
            * img1 = op.filter(img, null);
            * drawImage(img1, new AffineTransform(1f,0f,0f,1f,x,y), null);
            * 
      * @param op the filter to be applied to the image before rendering - * @param img the specified BufferedImage to be rendered. - * This method does nothing if img is null. + * @param img the specified {@code BufferedImage} to be rendered. + * This method does nothing if {@code img} is null. * @param x the x coordinate of the location in user space where * the upper left corner of the image is rendered * @param y the y coordinate of the location in user space where @@ -588,15 +588,15 @@ public abstract class Graphics2D extends Graphics { * applying a transform from image * space into user space before drawing. * The transformation from user space into device space is done with - * the current Transform in the Graphics2D. + * the current {@code Transform} in the {@code Graphics2D}. * The specified transformation is applied to the image before the - * transform attribute in the Graphics2D context is applied. - * The rendering attributes applied include the Clip, - * Transform, and Composite attributes. Note + * transform attribute in the {@code Graphics2D} context is applied. + * The rendering attributes applied include the {@code Clip}, + * {@code Transform}, and {@code Composite} attributes. Note * that no rendering is done if the specified transform is * noninvertible. * @param img the image to be rendered. This method does - * nothing if img is null. + * nothing if {@code img} is null. * @param xform the transformation from image space into user space * @see #transform * @see #setTransform @@ -612,24 +612,24 @@ public abstract class Graphics2D extends Graphics { * {@link RenderableImage}, * applying a transform from image space into user space before drawing. * The transformation from user space into device space is done with - * the current Transform in the Graphics2D. + * the current {@code Transform} in the {@code Graphics2D}. * The specified transformation is applied to the image before the - * transform attribute in the Graphics2D context is applied. - * The rendering attributes applied include the Clip, - * Transform, and Composite attributes. Note + * transform attribute in the {@code Graphics2D} context is applied. + * The rendering attributes applied include the {@code Clip}, + * {@code Transform}, and {@code Composite} attributes. Note * that no rendering is done if the specified transform is * noninvertible. *

      - * Rendering hints set on the Graphics2D object might - * be used in rendering the RenderableImage. + * Rendering hints set on the {@code Graphics2D} object might + * be used in rendering the {@code RenderableImage}. * If explicit control is required over specific hints recognized by a - * specific RenderableImage, or if knowledge of which hints - * are used is required, then a RenderedImage should be - * obtained directly from the RenderableImage + * specific {@code RenderableImage}, or if knowledge of which hints + * are used is required, then a {@code RenderedImage} should be + * obtained directly from the {@code RenderableImage} * and rendered using *{@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}. * @param img the image to be rendered. This method does - * nothing if img is null. + * nothing if {@code img} is null. * @param xform the transformation from image space into user space * @see #transform * @see #setTransform @@ -642,24 +642,24 @@ public abstract class Graphics2D extends Graphics { AffineTransform xform); /** - * Renders the text of the specified String, using the - * current text attribute state in the Graphics2D context. + * Renders the text of the specified {@code String}, using the + * current text attribute state in the {@code Graphics2D} context. * The baseline of the * first character is at position (xy) in * the User Space. - * The rendering attributes applied include the Clip, - * Transform, Paint, Font and - * Composite attributes. For characters in script + * The rendering attributes applied include the {@code Clip}, + * {@code Transform}, {@code Paint}, {@code Font} and + * {@code Composite} attributes. For characters in script * systems such as Hebrew and Arabic, the glyphs can be rendered from * right to left, in which case the coordinate supplied is the * location of the leftmost character on the baseline. * @param str the string to be rendered * @param x the x coordinate of the location where the - * String should be rendered + * {@code String} should be rendered * @param y the y coordinate of the location where the - * String should be rendered - * @throws NullPointerException if str is - * null + * {@code String} should be rendered + * @throws NullPointerException if {@code str} is + * {@code null} * @see java.awt.Graphics#drawBytes * @see java.awt.Graphics#drawChars * @since 1.0 @@ -667,23 +667,23 @@ public abstract class Graphics2D extends Graphics { public abstract void drawString(String str, int x, int y); /** - * Renders the text specified by the specified String, - * using the current text attribute state in the Graphics2D context. + * Renders the text specified by the specified {@code String}, + * using the current text attribute state in the {@code Graphics2D} context. * The baseline of the first character is at position * (xy) in the User Space. - * The rendering attributes applied include the Clip, - * Transform, Paint, Font and - * Composite attributes. For characters in script systems + * The rendering attributes applied include the {@code Clip}, + * {@code Transform}, {@code Paint}, {@code Font} and + * {@code Composite} attributes. For characters in script systems * such as Hebrew and Arabic, the glyphs can be rendered from right to * left, in which case the coordinate supplied is the location of the * leftmost character on the baseline. - * @param str the String to be rendered + * @param str the {@code String} to be rendered * @param x the x coordinate of the location where the - * String should be rendered + * {@code String} should be rendered * @param y the y coordinate of the location where the - * String should be rendered - * @throws NullPointerException if str is - * null + * {@code String} should be rendered + * @throws NullPointerException if {@code str} is + * {@code null} * @see #setPaint * @see java.awt.Graphics#setColor * @see java.awt.Graphics#setFont @@ -708,8 +708,8 @@ public abstract class Graphics2D extends Graphics { * rendered * @param y the y coordinate where the iterator's text is to be * rendered - * @throws NullPointerException if iterator is - * null + * @throws NullPointerException if {@code iterator} is + * {@code null} * @see #setPaint * @see java.awt.Graphics#setColor * @see #setTransform @@ -734,8 +734,8 @@ public abstract class Graphics2D extends Graphics { * rendered * @param y the y coordinate where the iterator's text is to be * rendered - * @throws NullPointerException if iterator is - * null + * @throws NullPointerException if {@code iterator} is + * {@code null} * @see #setPaint * @see java.awt.Graphics#setColor * @see #setTransform @@ -748,20 +748,20 @@ public abstract class Graphics2D extends Graphics { /** * Renders the text of the specified * {@link GlyphVector} using - * the Graphics2D context's rendering attributes. - * The rendering attributes applied include the Clip, - * Transform, Paint, and - * Composite attributes. The GlyphVector + * the {@code Graphics2D} context's rendering attributes. + * The rendering attributes applied include the {@code Clip}, + * {@code Transform}, {@code Paint}, and + * {@code Composite} attributes. The {@code GlyphVector} * specifies individual glyphs from a {@link Font}. - * The GlyphVector can also contain the glyph positions. + * The {@code GlyphVector} can also contain the glyph positions. * This is the fastest way to render a set of characters to the * screen. - * @param g the GlyphVector to be rendered + * @param g the {@code GlyphVector} to be rendered * @param x the x position in User Space where the glyphs should * be rendered * @param y the y position in User Space where the glyphs should * be rendered - * @throws NullPointerException if g is null. + * @throws NullPointerException if {@code g} is {@code null}. * * @see java.awt.Font#createGlyphVector * @see java.awt.font.GlyphVector @@ -774,11 +774,11 @@ public abstract class Graphics2D extends Graphics { public abstract void drawGlyphVector(GlyphVector g, float x, float y); /** - * Fills the interior of a Shape using the settings of the - * Graphics2D context. The rendering attributes applied - * include the Clip, Transform, - * Paint, and Composite. - * @param s the Shape to be filled + * Fills the interior of a {@code Shape} using the settings of the + * {@code Graphics2D} context. The rendering attributes applied + * include the {@code Clip}, {@code Transform}, + * {@code Paint}, and {@code Composite}. + * @param s the {@code Shape} to be filled * @see #setPaint * @see java.awt.Graphics#setColor * @see #transform @@ -790,25 +790,25 @@ public abstract class Graphics2D extends Graphics { public abstract void fill(Shape s); /** - * Checks whether or not the specified Shape intersects + * Checks whether or not the specified {@code Shape} intersects * the specified {@link Rectangle}, which is in device - * space. If onStroke is false, this method checks - * whether or not the interior of the specified Shape - * intersects the specified Rectangle. If - * onStroke is true, this method checks - * whether or not the Stroke of the specified - * Shape outline intersects the specified - * Rectangle. + * space. If {@code onStroke} is false, this method checks + * whether or not the interior of the specified {@code Shape} + * intersects the specified {@code Rectangle}. If + * {@code onStroke} is {@code true}, this method checks + * whether or not the {@code Stroke} of the specified + * {@code Shape} outline intersects the specified + * {@code Rectangle}. * The rendering attributes taken into account include the - * Clip, Transform, and Stroke + * {@code Clip}, {@code Transform}, and {@code Stroke} * attributes. * @param rect the area in device space to check for a hit - * @param s the Shape to check for a hit + * @param s the {@code Shape} to check for a hit * @param onStroke flag used to choose between testing the - * stroked or the filled shape. If the flag is true, the - * Stroke outline is tested. If the flag is - * false, the filled Shape is tested. - * @return true if there is a hit; false + * stroked or the filled shape. If the flag is {@code true}, the + * {@code Stroke} outline is tested. If the flag is + * {@code false}, the filled {@code Shape} is tested. + * @return {@code true} if there is a hit; {@code false} * otherwise. * @see #setStroke * @see #fill @@ -824,31 +824,31 @@ public abstract class Graphics2D extends Graphics { /** * Returns the device configuration associated with this - * Graphics2D. - * @return the device configuration of this Graphics2D. + * {@code Graphics2D}. + * @return the device configuration of this {@code Graphics2D}. */ public abstract GraphicsConfiguration getDeviceConfiguration(); /** - * Sets the Composite for the Graphics2D context. - * The Composite is used in all drawing methods such as - * drawImage, drawString, draw, - * and fill. It specifies how new pixels are to be combined + * Sets the {@code Composite} for the {@code Graphics2D} context. + * The {@code Composite} is used in all drawing methods such as + * {@code drawImage}, {@code drawString}, {@code draw}, + * and {@code fill}. It specifies how new pixels are to be combined * with the existing pixels on the graphics device during the rendering * process. - *

      If this Graphics2D context is drawing to a - * Component on the display screen and the - * Composite is a custom object rather than an - * instance of the AlphaComposite class, and if - * there is a security manager, its checkPermission - * method is called with an AWTPermission("readDisplayPixels") + *

      If this {@code Graphics2D} context is drawing to a + * {@code Component} on the display screen and the + * {@code Composite} is a custom object rather than an + * instance of the {@code AlphaComposite} class, and if + * there is a security manager, its {@code checkPermission} + * method is called with an {@code AWTPermission("readDisplayPixels")} * permission. * @throws SecurityException - * if a custom Composite object is being + * if a custom {@code Composite} object is being * used to render to the screen and a security manager - * is set and its checkPermission method + * is set and its {@code checkPermission} method * does not allow the operation. - * @param comp the Composite object to be used for rendering + * @param comp the {@code Composite} object to be used for rendering * @see java.awt.Graphics#setXORMode * @see java.awt.Graphics#setPaintMode * @see #getComposite @@ -859,13 +859,13 @@ public abstract class Graphics2D extends Graphics { public abstract void setComposite(Composite comp); /** - * Sets the Paint attribute for the - * Graphics2D context. Calling this method - * with a null Paint object does - * not have any effect on the current Paint attribute - * of this Graphics2D. - * @param paint the Paint object to be used to generate - * color during the rendering process, or null + * Sets the {@code Paint} attribute for the + * {@code Graphics2D} context. Calling this method + * with a {@code null Paint} object does + * not have any effect on the current {@code Paint} attribute + * of this {@code Graphics2D}. + * @param paint the {@code Paint} object to be used to generate + * color during the rendering process, or {@code null} * @see java.awt.Graphics#setColor * @see #getPaint * @see GradientPaint @@ -874,9 +874,9 @@ public abstract class Graphics2D extends Graphics { public abstract void setPaint( Paint paint ); /** - * Sets the Stroke for the Graphics2D context. - * @param s the Stroke object to be used to stroke a - * Shape during the rendering process + * Sets the {@code Stroke} for the {@code Graphics2D} context. + * @param s the {@code Stroke} object to be used to stroke a + * {@code Shape} during the rendering process * @see BasicStroke * @see #getStroke */ @@ -886,7 +886,7 @@ public abstract class Graphics2D extends Graphics { * Sets the value of a single preference for the rendering algorithms. * Hint categories include controls for rendering quality and overall * time/quality trade-off in the rendering process. Refer to the - * RenderingHints class for definitions of some common + * {@code RenderingHints} class for definitions of some common * keys and values. * @param hintKey the key of the hint to be set. * @param hintValue the value indicating preferences for the specified @@ -900,12 +900,12 @@ public abstract class Graphics2D extends Graphics { * Returns the value of a single preference for the rendering algorithms. * Hint categories include controls for rendering quality and overall * time/quality trade-off in the rendering process. Refer to the - * RenderingHints class for definitions of some common + * {@code RenderingHints} class for definitions of some common * keys and values. * @param hintKey the key corresponding to the hint to get. * @return an object representing the value for the specified hint key. * Some of the keys and their associated values are defined in the - * RenderingHints class. + * {@code RenderingHints} class. * @see RenderingHints * @see #setRenderingHint(RenderingHints.Key, Object) */ @@ -913,13 +913,13 @@ public abstract class Graphics2D extends Graphics { /** * Replaces the values of all preferences for the rendering - * algorithms with the specified hints. + * algorithms with the specified {@code hints}. * The existing values for all rendering hints are discarded and * the new set of known hints and values are initialized from the * specified {@link Map} object. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. - * Refer to the RenderingHints class for definitions of + * Refer to the {@code RenderingHints} class for definitions of * some common keys and values. * @param hints the rendering hints to be set * @see #getRenderingHints @@ -931,12 +931,12 @@ public abstract class Graphics2D extends Graphics { * Sets the values of an arbitrary number of preferences for the * rendering algorithms. * Only values for the rendering hints that are present in the - * specified Map object are modified. + * specified {@code Map} object are modified. * All other preferences not present in the specified * object are left unmodified. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. - * Refer to the RenderingHints class for definitions of + * Refer to the {@code RenderingHints} class for definitions of * some common keys and values. * @param hints the rendering hints to be set * @see RenderingHints @@ -949,9 +949,9 @@ public abstract class Graphics2D extends Graphics { * trade-off in the rendering process. * Returns all of the hint key/value pairs that were ever specified in * one operation. Refer to the - * RenderingHints class for definitions of some common + * {@code RenderingHints} class for definitions of some common * keys and values. - * @return a reference to an instance of RenderingHints + * @return a reference to an instance of {@code RenderingHints} * that contains the current preferences. * @see RenderingHints * @see #setRenderingHints(Map) @@ -959,11 +959,11 @@ public abstract class Graphics2D extends Graphics { public abstract RenderingHints getRenderingHints(); /** - * Translates the origin of the Graphics2D context to the + * Translates the origin of the {@code Graphics2D} context to the * point (xy) in the current coordinate system. - * Modifies the Graphics2D context so that its new origin + * Modifies the {@code Graphics2D} context so that its new origin * corresponds to the point (xy) in the - * Graphics2D context's former coordinate system. All + * {@code Graphics2D} context's former coordinate system. All * coordinates used in subsequent rendering operations on this graphics * context are relative to this new origin. * @param x the specified x coordinate @@ -974,12 +974,12 @@ public abstract class Graphics2D extends Graphics { /** * Concatenates the current - * Graphics2D Transform + * {@code Graphics2D Transform} * with a translation transform. * Subsequent rendering is translated by the specified * distance relative to the previous position. * This is equivalent to calling transform(T), where T is an - * AffineTransform represented by the following matrix: + * {@code AffineTransform} represented by the following matrix: *

            *          [   1    0    tx  ]
            *          [   0    1    ty  ]
      @@ -991,12 +991,12 @@ public abstract class Graphics2D extends Graphics {
           public abstract void translate(double tx, double ty);
       
           /**
      -     * Concatenates the current Graphics2D
      -     * Transform with a rotation transform.
      +     * Concatenates the current {@code Graphics2D}
      +     * {@code Transform} with a rotation transform.
            * Subsequent rendering is rotated by the specified radians relative
            * to the previous origin.
      -     * This is equivalent to calling transform(R), where R is an
      -     * AffineTransform represented by the following matrix:
      +     * This is equivalent to calling {@code transform(R)}, where R is an
      +     * {@code AffineTransform} represented by the following matrix:
            * 
            *          [   cos(theta)    -sin(theta)    0   ]
            *          [   sin(theta)     cos(theta)    0   ]
      @@ -1009,8 +1009,8 @@ public abstract class Graphics2D extends Graphics {
           public abstract void rotate(double theta);
       
           /**
      -     * Concatenates the current Graphics2D
      -     * Transform with a translated rotation
      +     * Concatenates the current {@code Graphics2D}
      +     * {@code Transform} with a translated rotation
            * transform.  Subsequent rendering is transformed by a transform
            * which is constructed by translating to the specified location,
            * rotating by the specified radians, and translating back by the same
      @@ -1030,12 +1030,12 @@ public abstract class Graphics2D extends Graphics {
           public abstract void rotate(double theta, double x, double y);
       
           /**
      -     * Concatenates the current Graphics2D
      -     * Transform with a scaling transformation
      +     * Concatenates the current {@code Graphics2D}
      +     * {@code Transform} with a scaling transformation
            * Subsequent rendering is resized according to the specified scaling
            * factors relative to the previous scaling.
      -     * This is equivalent to calling transform(S), where S is an
      -     * AffineTransform represented by the following matrix:
      +     * This is equivalent to calling {@code transform(S)}, where S is an
      +     * {@code AffineTransform} represented by the following matrix:
            * 
            *          [   sx   0    0   ]
            *          [   0    sy   0   ]
      @@ -1051,12 +1051,12 @@ public abstract class Graphics2D extends Graphics {
           public abstract void scale(double sx, double sy);
       
           /**
      -     * Concatenates the current Graphics2D
      -     * Transform with a shearing transform.
      +     * Concatenates the current {@code Graphics2D}
      +     * {@code Transform} with a shearing transform.
            * Subsequent renderings are sheared by the specified
            * multiplier relative to the previous position.
      -     * This is equivalent to calling transform(SH), where SH
      -     * is an AffineTransform represented by the following
      +     * This is equivalent to calling {@code transform(SH)}, where SH
      +     * is an {@code AffineTransform} represented by the following
            * matrix:
            * 
            *          [   1   shx   0   ]
      @@ -1071,37 +1071,37 @@ public abstract class Graphics2D extends Graphics {
           public abstract void shear(double shx, double shy);
       
           /**
      -     * Composes an AffineTransform object with the
      -     * Transform in this Graphics2D according
      +     * Composes an {@code AffineTransform} object with the
      +     * {@code Transform} in this {@code Graphics2D} according
            * to the rule last-specified-first-applied.  If the current
      -     * Transform is Cx, the result of composition
      -     * with Tx is a new Transform Cx'.  Cx' becomes the
      -     * current Transform for this Graphics2D.
      -     * Transforming a point p by the updated Transform Cx' is
      +     * {@code Transform} is Cx, the result of composition
      +     * with Tx is a new {@code Transform} Cx'.  Cx' becomes the
      +     * current {@code Transform} for this {@code Graphics2D}.
      +     * Transforming a point p by the updated {@code Transform} Cx' is
            * equivalent to first transforming p by Tx and then transforming
      -     * the result by the original Transform Cx.  In other
      +     * the result by the original {@code Transform} Cx.  In other
            * words, Cx'(p) = Cx(Tx(p)).  A copy of the Tx is made, if necessary,
            * so further modifications to Tx do not affect rendering.
      -     * @param Tx the AffineTransform object to be composed with
      -     * the current Transform
      +     * @param Tx the {@code AffineTransform} object to be composed with
      +     * the current {@code Transform}
            * @see #setTransform
            * @see AffineTransform
            */
           public abstract void transform(AffineTransform Tx);
       
           /**
      -     * Overwrites the Transform in the Graphics2D context.
      +     * Overwrites the Transform in the {@code Graphics2D} context.
            * WARNING: This method should never be used to apply a new
            * coordinate transform on top of an existing transform because the
      -     * Graphics2D might already have a transform that is
      +     * {@code Graphics2D} might already have a transform that is
            * needed for other purposes, such as rendering Swing
            * components or applying a scaling transformation to adjust for the
            * resolution of a printer.
            * 

      To add a coordinate transform, use the - * transform, rotate, scale, - * or shear methods. The setTransform + * {@code transform}, {@code rotate}, {@code scale}, + * or {@code shear} methods. The {@code setTransform} * method is intended only for restoring the original - * Graphics2D transform after rendering, as shown in this + * {@code Graphics2D} transform after rendering, as shown in this * example: *

            * // Get the current transform
      @@ -1114,8 +1114,8 @@ public abstract class Graphics2D extends Graphics {
            * g2d.setTransform(saveAT);
            * 
      * - * @param Tx the AffineTransform that was retrieved - * from the getTransform method + * @param Tx the {@code AffineTransform} that was retrieved + * from the {@code getTransform} method * @see #transform * @see #getTransform * @see AffineTransform @@ -1123,19 +1123,19 @@ public abstract class Graphics2D extends Graphics { public abstract void setTransform(AffineTransform Tx); /** - * Returns a copy of the current Transform in the - * Graphics2D context. - * @return the current AffineTransform in the - * Graphics2D context. + * Returns a copy of the current {@code Transform} in the + * {@code Graphics2D} context. + * @return the current {@code AffineTransform} in the + * {@code Graphics2D} context. * @see #transform * @see #setTransform */ public abstract AffineTransform getTransform(); /** - * Returns the current Paint of the - * Graphics2D context. - * @return the current Graphics2D Paint, + * Returns the current {@code Paint} of the + * {@code Graphics2D} context. + * @return the current {@code Graphics2D Paint}, * which defines a color or pattern. * @see #setPaint * @see java.awt.Graphics#setColor @@ -1143,27 +1143,27 @@ public abstract class Graphics2D extends Graphics { public abstract Paint getPaint(); /** - * Returns the current Composite in the - * Graphics2D context. - * @return the current Graphics2D Composite, + * Returns the current {@code Composite} in the + * {@code Graphics2D} context. + * @return the current {@code Graphics2D Composite}, * which defines a compositing style. * @see #setComposite */ public abstract Composite getComposite(); /** - * Sets the background color for the Graphics2D context. + * Sets the background color for the {@code Graphics2D} context. * The background color is used for clearing a region. - * When a Graphics2D is constructed for a - * Component, the background color is - * inherited from the Component. Setting the background color - * in the Graphics2D context only affects the subsequent - * clearRect calls and not the background color of the - * Component. To change the background - * of the Component, use appropriate methods of - * the Component. + * When a {@code Graphics2D} is constructed for a + * {@code Component}, the background color is + * inherited from the {@code Component}. Setting the background color + * in the {@code Graphics2D} context only affects the subsequent + * {@code clearRect} calls and not the background color of the + * {@code Component}. To change the background + * of the {@code Component}, use appropriate methods of + * the {@code Component}. * @param color the background color that is used in - * subsequent calls to clearRect + * subsequent calls to {@code clearRect} * @see #getBackground * @see java.awt.Graphics#clearRect */ @@ -1171,52 +1171,52 @@ public abstract class Graphics2D extends Graphics { /** * Returns the background color used for clearing a region. - * @return the current Graphics2D Color, + * @return the current {@code Graphics2D Color}, * which defines the background color. * @see #setBackground */ public abstract Color getBackground(); /** - * Returns the current Stroke in the - * Graphics2D context. - * @return the current Graphics2D Stroke, + * Returns the current {@code Stroke} in the + * {@code Graphics2D} context. + * @return the current {@code Graphics2D Stroke}, * which defines the line style. * @see #setStroke */ public abstract Stroke getStroke(); /** - * Intersects the current Clip with the interior of the - * specified Shape and sets the Clip to the - * resulting intersection. The specified Shape is - * transformed with the current Graphics2D - * Transform before being intersected with the current - * Clip. This method is used to make the current - * Clip smaller. - * To make the Clip larger, use setClip. + * Intersects the current {@code Clip} with the interior of the + * specified {@code Shape} and sets the {@code Clip} to the + * resulting intersection. The specified {@code Shape} is + * transformed with the current {@code Graphics2D} + * {@code Transform} before being intersected with the current + * {@code Clip}. This method is used to make the current + * {@code Clip} smaller. + * To make the {@code Clip} larger, use {@code setClip}. * The user clip modified by this method is independent of the * clipping associated with device bounds and visibility. If no clip has * previously been set, or if the clip has been cleared using - * {@link Graphics#setClip(Shape) setClip} with a null - * argument, the specified Shape becomes the new + * {@link Graphics#setClip(Shape) setClip} with a {@code null} + * argument, the specified {@code Shape} becomes the new * user clip. - * @param s the Shape to be intersected with the current - * Clip. If s is null, - * this method clears the current Clip. + * @param s the {@code Shape} to be intersected with the current + * {@code Clip}. If {@code s} is {@code null}, + * this method clears the current {@code Clip}. */ public abstract void clip(Shape s); /** - * Get the rendering context of the Font within this - * Graphics2D context. + * Get the rendering context of the {@code Font} within this + * {@code Graphics2D} context. * The {@link FontRenderContext} * encapsulates application hints such as anti-aliasing and * fractional metrics, as well as target device specific information * such as dots-per-inch. This information should be provided by the * application when using objects that perform typographical - * formatting, such as Font and - * TextLayout. This information should also be provided + * formatting, such as {@code Font} and + * {@code TextLayout}. This information should also be provided * by applications that perform their own layout and need accurate * measurements of various characteristics of glyphs such as advance * and line height when various rendering hints have been applied to diff --git a/jdk/src/java.desktop/share/classes/java/awt/GraphicsConfigTemplate.java b/jdk/src/java.desktop/share/classes/java/awt/GraphicsConfigTemplate.java index 7baec878444..d3799b3ef24 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/GraphicsConfigTemplate.java +++ b/jdk/src/java.desktop/share/classes/java/awt/GraphicsConfigTemplate.java @@ -28,14 +28,14 @@ package java.awt; import java.io.*; /** - * The GraphicsConfigTemplate class is used to obtain a valid + * The {@code GraphicsConfigTemplate} class is used to obtain a valid * {@link GraphicsConfiguration}. A user instantiates one of these * objects and then sets all non-default attributes as desired. The * {@link GraphicsDevice#getBestConfiguration} method found in the * {@link GraphicsDevice} class is then called with this - * GraphicsConfigTemplate. A valid - * GraphicsConfiguration is returned that meets or exceeds - * what was requested in the GraphicsConfigTemplate. + * {@code GraphicsConfigTemplate}. A valid + * {@code GraphicsConfiguration} is returned that meets or exceeds + * what was requested in the {@code GraphicsConfigTemplate}. * @see GraphicsDevice * @see GraphicsConfiguration * @@ -56,15 +56,15 @@ public abstract class GraphicsConfigTemplate implements Serializable { /** * Value used for "Enum" (Integer) type. States that this - * feature is required for the GraphicsConfiguration + * feature is required for the {@code GraphicsConfiguration} * object. If this feature is not available, do not select the - * GraphicsConfiguration object. + * {@code GraphicsConfiguration} object. */ public static final int REQUIRED = 1; /** * Value used for "Enum" (Integer) type. States that this - * feature is desired for the GraphicsConfiguration + * feature is desired for the {@code GraphicsConfiguration} * object. A selection with this feature is preferred over a * selection that does not include this feature, although both * selections can be considered valid matches. @@ -74,7 +74,7 @@ public abstract class GraphicsConfigTemplate implements Serializable { /** * Value used for "Enum" (Integer) type. States that this * feature is not necessary for the selection of the - * GraphicsConfiguration object. A selection + * {@code GraphicsConfiguration} object. A selection * without this feature is preferred over a selection that * includes this feature since it is not used. */ @@ -82,10 +82,10 @@ public abstract class GraphicsConfigTemplate implements Serializable { /** * Returns the "best" configuration possible that passes the - * criteria defined in the GraphicsConfigTemplate. - * @param gc the array of GraphicsConfiguration + * criteria defined in the {@code GraphicsConfigTemplate}. + * @param gc the array of {@code GraphicsConfiguration} * objects to choose from. - * @return a GraphicsConfiguration object that is + * @return a {@code GraphicsConfiguration} object that is * the best configuration possible. * @see GraphicsConfiguration */ @@ -93,15 +93,15 @@ public abstract class GraphicsConfigTemplate implements Serializable { getBestConfiguration(GraphicsConfiguration[] gc); /** - * Returns a boolean indicating whether or - * not the specified GraphicsConfiguration can be + * Returns a {@code boolean} indicating whether or + * not the specified {@code GraphicsConfiguration} can be * used to create a drawing surface that supports the indicated * features. - * @param gc the GraphicsConfiguration object to test - * @return true if this - * GraphicsConfiguration object can be used to create + * @param gc the {@code GraphicsConfiguration} object to test + * @return {@code true} if this + * {@code GraphicsConfiguration} object can be used to create * surfaces that support the indicated features; - * false if the GraphicsConfiguration can + * {@code false} if the {@code GraphicsConfiguration} can * not be used to create a drawing surface usable by this Java(tm) * API. */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/GraphicsConfiguration.java b/jdk/src/java.desktop/share/classes/java/awt/GraphicsConfiguration.java index ef0e454a070..3a5640c8f84 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/GraphicsConfiguration.java +++ b/jdk/src/java.desktop/share/classes/java/awt/GraphicsConfiguration.java @@ -34,23 +34,23 @@ import java.awt.image.WritableRaster; import sun.awt.image.SunVolatileImage; /** - * The GraphicsConfiguration class describes the + * The {@code GraphicsConfiguration} class describes the * characteristics of a graphics destination such as a printer or monitor. - * There can be many GraphicsConfiguration objects associated + * There can be many {@code GraphicsConfiguration} objects associated * with a single graphics device, representing different drawing modes or * capabilities. The corresponding native structure will vary from platform * to platform. For example, on X11 windowing systems, - * each visual is a different GraphicsConfiguration. - * On Microsoft Windows, GraphicsConfigurations represent + * each visual is a different {@code GraphicsConfiguration}. + * On Microsoft Windows, {@code GraphicsConfiguration}s represent * PixelFormats available in the current resolution and color depth. *

      * In a virtual device multi-screen environment in which the desktop * area could span multiple physical screen devices, the bounds of the - * GraphicsConfiguration objects are relative to the + * {@code GraphicsConfiguration} objects are relative to the * virtual coordinate system. When setting the location of a * component, use {@link #getBounds() getBounds} to get the bounds of - * the desired GraphicsConfiguration and offset the location - * with the coordinates of the GraphicsConfiguration, + * the desired {@code GraphicsConfiguration} and offset the location + * with the coordinates of the {@code GraphicsConfiguration}, * as the following code sample illustrates: *

      * @@ -61,17 +61,17 @@ import sun.awt.image.SunVolatileImage; * *

      * To determine if your environment is a virtual device - * environment, call getBounds on all of the - * GraphicsConfiguration objects in your system. If + * environment, call {@code getBounds} on all of the + * {@code GraphicsConfiguration} objects in your system. If * any of the origins of the returned bounds is not (0, 0), * your environment is a virtual device environment. * *

      - * You can also use getBounds to determine the bounds - * of the virtual device. To do this, first call getBounds on all - * of the GraphicsConfiguration objects in your + * You can also use {@code getBounds} to determine the bounds + * of the virtual device. To do this, first call {@code getBounds} on all + * of the {@code GraphicsConfiguration} objects in your * system. Then calculate the union of all of the bounds returned - * from the calls to getBounds. The union is the + * from the calls to {@code getBounds}. The union is the * bounds of the virtual device. The following code sample * calculates the bounds of the virtual device. * @@ -125,24 +125,24 @@ public abstract class GraphicsConfiguration { /** * Returns the {@link GraphicsDevice} associated with this - * GraphicsConfiguration. - * @return a GraphicsDevice object that is - * associated with this GraphicsConfiguration. + * {@code GraphicsConfiguration}. + * @return a {@code GraphicsDevice} object that is + * associated with this {@code GraphicsConfiguration}. */ public abstract GraphicsDevice getDevice(); /** * Returns a {@link BufferedImage} with a data layout and color model - * compatible with this GraphicsConfiguration. This + * compatible with this {@code GraphicsConfiguration}. This * method has nothing to do with memory-mapping - * a device. The returned BufferedImage has + * a device. The returned {@code BufferedImage} has * a layout and color model that is closest to this native device * configuration and can therefore be optimally blitted to this * device. - * @param width the width of the returned BufferedImage - * @param height the height of the returned BufferedImage - * @return a BufferedImage whose data layout and color - * model is compatible with this GraphicsConfiguration. + * @param width the width of the returned {@code BufferedImage} + * @param height the height of the returned {@code BufferedImage} + * @return a {@code BufferedImage} whose data layout and color + * model is compatible with this {@code GraphicsConfiguration}. */ public BufferedImage createCompatibleImage(int width, int height) { ColorModel model = getColorModel(); @@ -153,18 +153,18 @@ public abstract class GraphicsConfiguration { } /** - * Returns a BufferedImage that supports the specified + * Returns a {@code BufferedImage} that supports the specified * transparency and has a data layout and color model - * compatible with this GraphicsConfiguration. This + * compatible with this {@code GraphicsConfiguration}. This * method has nothing to do with memory-mapping - * a device. The returned BufferedImage has a layout and + * a device. The returned {@code BufferedImage} has a layout and * color model that can be optimally blitted to a device - * with this GraphicsConfiguration. - * @param width the width of the returned BufferedImage - * @param height the height of the returned BufferedImage + * with this {@code GraphicsConfiguration}. + * @param width the width of the returned {@code BufferedImage} + * @param height the height of the returned {@code BufferedImage} * @param transparency the specified transparency mode - * @return a BufferedImage whose data layout and color - * model is compatible with this GraphicsConfiguration + * @return a {@code BufferedImage} whose data layout and color + * model is compatible with this {@code GraphicsConfiguration} * and also supports the specified transparency. * @throws IllegalArgumentException if the transparency is not a valid value * @see Transparency#OPAQUE @@ -190,15 +190,15 @@ public abstract class GraphicsConfiguration { /** * Returns a {@link VolatileImage} with a data layout and color model - * compatible with this GraphicsConfiguration. - * The returned VolatileImage + * compatible with this {@code GraphicsConfiguration}. + * The returned {@code VolatileImage} * may have data that is stored optimally for the underlying graphics * device and may therefore benefit from platform-specific rendering * acceleration. - * @param width the width of the returned VolatileImage - * @param height the height of the returned VolatileImage - * @return a VolatileImage whose data layout and color - * model is compatible with this GraphicsConfiguration. + * @param width the width of the returned {@code VolatileImage} + * @param height the height of the returned {@code VolatileImage} + * @return a {@code VolatileImage} whose data layout and color + * model is compatible with this {@code GraphicsConfiguration}. * @see Component#createVolatileImage(int, int) * @since 1.4 */ @@ -216,16 +216,16 @@ public abstract class GraphicsConfiguration { /** * Returns a {@link VolatileImage} with a data layout and color model - * compatible with this GraphicsConfiguration. - * The returned VolatileImage + * compatible with this {@code GraphicsConfiguration}. + * The returned {@code VolatileImage} * may have data that is stored optimally for the underlying graphics * device and may therefore benefit from platform-specific rendering * acceleration. - * @param width the width of the returned VolatileImage - * @param height the height of the returned VolatileImage + * @param width the width of the returned {@code VolatileImage} + * @param height the height of the returned {@code VolatileImage} * @param transparency the specified transparency mode - * @return a VolatileImage whose data layout and color - * model is compatible with this GraphicsConfiguration. + * @return a {@code VolatileImage} whose data layout and color + * model is compatible with this {@code GraphicsConfiguration}. * @throws IllegalArgumentException if the transparency is not a valid value * @see Transparency#OPAQUE * @see Transparency#BITMASK @@ -248,20 +248,20 @@ public abstract class GraphicsConfiguration { /** * Returns a {@link VolatileImage} with a data layout and color model - * compatible with this GraphicsConfiguration, using + * compatible with this {@code GraphicsConfiguration}, using * the specified image capabilities. - * If the caps parameter is null, it is effectively ignored + * If the {@code caps} parameter is null, it is effectively ignored * and this method will create a VolatileImage without regard to - * ImageCapabilities constraints. + * {@code ImageCapabilities} constraints. * - * The returned VolatileImage has + * The returned {@code VolatileImage} has * a layout and color model that is closest to this native device * configuration and can therefore be optimally blitted to this * device. - * @return a VolatileImage whose data layout and color - * model is compatible with this GraphicsConfiguration. - * @param width the width of the returned VolatileImage - * @param height the height of the returned VolatileImage + * @return a {@code VolatileImage} whose data layout and color + * model is compatible with this {@code GraphicsConfiguration}. + * @param width the width of the returned {@code VolatileImage} + * @param height the height of the returned {@code VolatileImage} * @param caps the image capabilities * @exception AWTException if the supplied image capabilities could not * be met by this graphics configuration @@ -276,22 +276,22 @@ public abstract class GraphicsConfiguration { /** * Returns a {@link VolatileImage} with a data layout and color model - * compatible with this GraphicsConfiguration, using + * compatible with this {@code GraphicsConfiguration}, using * the specified image capabilities and transparency value. - * If the caps parameter is null, it is effectively ignored + * If the {@code caps} parameter is null, it is effectively ignored * and this method will create a VolatileImage without regard to - * ImageCapabilities constraints. + * {@code ImageCapabilities} constraints. * - * The returned VolatileImage has + * The returned {@code VolatileImage} has * a layout and color model that is closest to this native device * configuration and can therefore be optimally blitted to this * device. - * @param width the width of the returned VolatileImage - * @param height the height of the returned VolatileImage + * @param width the width of the returned {@code VolatileImage} + * @param height the height of the returned {@code VolatileImage} * @param caps the image capabilities * @param transparency the specified transparency mode - * @return a VolatileImage whose data layout and color - * model is compatible with this GraphicsConfiguration. + * @return a {@code VolatileImage} whose data layout and color + * model is compatible with this {@code GraphicsConfiguration}. * @see Transparency#OPAQUE * @see Transparency#BITMASK * @see Transparency#TRANSLUCENT @@ -317,19 +317,19 @@ public abstract class GraphicsConfiguration { /** * Returns the {@link ColorModel} associated with this - * GraphicsConfiguration. - * @return a ColorModel object that is associated with - * this GraphicsConfiguration. + * {@code GraphicsConfiguration}. + * @return a {@code ColorModel} object that is associated with + * this {@code GraphicsConfiguration}. */ public abstract ColorModel getColorModel(); /** - * Returns the ColorModel associated with this - * GraphicsConfiguration that supports the specified + * Returns the {@code ColorModel} associated with this + * {@code GraphicsConfiguration} that supports the specified * transparency. * @param transparency the specified transparency mode - * @return a ColorModel object that is associated with - * this GraphicsConfiguration and supports the + * @return a {@code ColorModel} object that is associated with + * this {@code GraphicsConfiguration} and supports the * specified transparency or null if the transparency is not a valid * value. * @see Transparency#OPAQUE @@ -340,30 +340,30 @@ public abstract class GraphicsConfiguration { /** * Returns the default {@link AffineTransform} for this - * GraphicsConfiguration. This - * AffineTransform is typically the Identity transform - * for most normal screens. The default AffineTransform + * {@code GraphicsConfiguration}. This + * {@code AffineTransform} is typically the Identity transform + * for most normal screens. The default {@code AffineTransform} * maps coordinates onto the device such that 72 user space * coordinate units measure approximately 1 inch in device * space. The normalizing transform can be used to make * this mapping more exact. Coordinates in the coordinate space - * defined by the default AffineTransform for screen and + * defined by the default {@code AffineTransform} for screen and * printer devices have the origin in the upper left-hand corner of * the target region of the device, with X coordinates * increasing to the right and Y coordinates increasing downwards. * For image buffers not associated with a device, such as those not - * created by createCompatibleImage, - * this AffineTransform is the Identity transform. - * @return the default AffineTransform for this - * GraphicsConfiguration. + * created by {@code createCompatibleImage}, + * this {@code AffineTransform} is the Identity transform. + * @return the default {@code AffineTransform} for this + * {@code GraphicsConfiguration}. */ public abstract AffineTransform getDefaultTransform(); /** * - * Returns a AffineTransform that can be concatenated - * with the default AffineTransform - * of a GraphicsConfiguration so that 72 units in user + * Returns a {@code AffineTransform} that can be concatenated + * with the default {@code AffineTransform} + * of a {@code GraphicsConfiguration} so that 72 units in user * space equals 1 inch in device space. *

      * For a particular {@link Graphics2D}, g, one @@ -375,27 +375,27 @@ public abstract class GraphicsConfiguration { * g.setTransform(gc.getDefaultTransform()); * g.transform(gc.getNormalizingTransform()); *

      - * Note that sometimes this AffineTransform is identity, + * Note that sometimes this {@code AffineTransform} is identity, * such as for printers or metafile output, and that this - * AffineTransform is only as accurate as the information + * {@code AffineTransform} is only as accurate as the information * supplied by the underlying system. For image buffers not * associated with a device, such as those not created by - * createCompatibleImage, this - * AffineTransform is the Identity transform + * {@code createCompatibleImage}, this + * {@code AffineTransform} is the Identity transform * since there is no valid distance measurement. - * @return an AffineTransform to concatenate to the - * default AffineTransform so that 72 units in user + * @return an {@code AffineTransform} to concatenate to the + * default {@code AffineTransform} so that 72 units in user * space is mapped to 1 inch in device space. */ public abstract AffineTransform getNormalizingTransform(); /** - * Returns the bounds of the GraphicsConfiguration + * Returns the bounds of the {@code GraphicsConfiguration} * in the device coordinates. In a multi-screen environment * with a virtual device, the bounds can have negative X * or Y origins. * @return the bounds of the area covered by this - * GraphicsConfiguration. + * {@code GraphicsConfiguration}. * @since 1.3 */ public abstract Rectangle getBounds(); @@ -408,7 +408,7 @@ public abstract class GraphicsConfiguration { /** * Returns the buffering capabilities of this - * GraphicsConfiguration. + * {@code GraphicsConfiguration}. * @return the buffering capabilities of this graphics * configuration object * @since 1.4 @@ -423,7 +423,7 @@ public abstract class GraphicsConfiguration { /** * Returns the image capabilities of this - * GraphicsConfiguration. + * {@code GraphicsConfiguration}. * @return the image capabilities of this graphics * configuration object * @since 1.4 diff --git a/jdk/src/java.desktop/share/classes/java/awt/GraphicsDevice.java b/jdk/src/java.desktop/share/classes/java/awt/GraphicsDevice.java index fdc44ca6ab7..b8947148a7e 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/GraphicsDevice.java +++ b/jdk/src/java.desktop/share/classes/java/awt/GraphicsDevice.java @@ -33,19 +33,19 @@ import sun.awt.AppContext; import sun.awt.SunToolkit; /** - * The GraphicsDevice class describes the graphics devices + * The {@code GraphicsDevice} class describes the graphics devices * that might be available in a particular graphics environment. These * include screen and printer devices. Note that there can be many screens * and many printers in an instance of {@link GraphicsEnvironment}. Each * graphics device has one or more {@link GraphicsConfiguration} objects * associated with it. These objects specify the different configurations - * in which the GraphicsDevice can be used. + * in which the {@code GraphicsDevice} can be used. *

      - * In a multi-screen environment, the GraphicsConfiguration + * In a multi-screen environment, the {@code GraphicsConfiguration} * objects can be used to render components on multiple screens. The - * following code sample demonstrates how to create a JFrame - * object for each GraphicsConfiguration on each screen - * device in the GraphicsEnvironment: + * following code sample demonstrates how to create a {@code JFrame} + * object for each {@code GraphicsConfiguration} on each screen + * device in the {@code GraphicsEnvironment}: *

      {@code
        *   GraphicsEnvironment ge = GraphicsEnvironment.
        *   getLocalGraphicsEnvironment();
      @@ -142,8 +142,8 @@ public abstract class GraphicsDevice {
           }
       
           /**
      -     * Returns the type of this GraphicsDevice.
      -     * @return the type of this GraphicsDevice, which can
      +     * Returns the type of this {@code GraphicsDevice}.
      +     * @return the type of this {@code GraphicsDevice}, which can
            * either be TYPE_RASTER_SCREEN, TYPE_PRINTER or TYPE_IMAGE_BUFFER.
            * @see #TYPE_RASTER_SCREEN
            * @see #TYPE_PRINTER
      @@ -153,52 +153,52 @@ public abstract class GraphicsDevice {
       
           /**
            * Returns the identification string associated with this
      -     * GraphicsDevice.
      +     * {@code GraphicsDevice}.
            * 

      * A particular program might use more than one - * GraphicsDevice in a GraphicsEnvironment. - * This method returns a String identifying a - * particular GraphicsDevice in the local - * GraphicsEnvironment. Although there is - * no public method to set this String, a programmer can - * use the String for debugging purposes. Vendors of + * {@code GraphicsDevice} in a {@code GraphicsEnvironment}. + * This method returns a {@code String} identifying a + * particular {@code GraphicsDevice} in the local + * {@code GraphicsEnvironment}. Although there is + * no public method to set this {@code String}, a programmer can + * use the {@code String} for debugging purposes. Vendors of * the Java™ Runtime Environment can - * format the return value of the String. To determine - * how to interpret the value of the String, contact the + * format the return value of the {@code String}. To determine + * how to interpret the value of the {@code String}, contact the * vendor of your Java Runtime. To find out who the vendor is, from * your program, call the * {@link System#getProperty(String) getProperty} method of the * System class with "java.vendor". - * @return a String that is the identification - * of this GraphicsDevice. + * @return a {@code String} that is the identification + * of this {@code GraphicsDevice}. */ public abstract String getIDstring(); /** - * Returns all of the GraphicsConfiguration - * objects associated with this GraphicsDevice. - * @return an array of GraphicsConfiguration + * Returns all of the {@code GraphicsConfiguration} + * objects associated with this {@code GraphicsDevice}. + * @return an array of {@code GraphicsConfiguration} * objects that are associated with this - * GraphicsDevice. + * {@code GraphicsDevice}. */ public abstract GraphicsConfiguration[] getConfigurations(); /** - * Returns the default GraphicsConfiguration - * associated with this GraphicsDevice. - * @return the default GraphicsConfiguration - * of this GraphicsDevice. + * Returns the default {@code GraphicsConfiguration} + * associated with this {@code GraphicsDevice}. + * @return the default {@code GraphicsConfiguration} + * of this {@code GraphicsDevice}. */ public abstract GraphicsConfiguration getDefaultConfiguration(); /** * Returns the "best" configuration possible that passes the * criteria defined in the {@link GraphicsConfigTemplate}. - * @param gct the GraphicsConfigTemplate object - * used to obtain a valid GraphicsConfiguration - * @return a GraphicsConfiguration that passes + * @param gct the {@code GraphicsConfigTemplate} object + * used to obtain a valid {@code GraphicsConfiguration} + * @return a {@code GraphicsConfiguration} that passes * the criteria defined in the specified - * GraphicsConfigTemplate. + * {@code GraphicsConfigTemplate}. * @see GraphicsConfigTemplate */ public GraphicsConfiguration @@ -208,12 +208,12 @@ public abstract class GraphicsDevice { } /** - * Returns true if this GraphicsDevice + * Returns {@code true} if this {@code GraphicsDevice} * supports full-screen exclusive mode. * If a SecurityManager is installed, its - * checkPermission method will be called - * with AWTPermission("fullScreenExclusive"). - * isFullScreenSupported returns true only if + * {@code checkPermission} method will be called + * with {@code AWTPermission("fullScreenExclusive")}. + * {@code isFullScreenSupported} returns true only if * that permission is granted. * @return whether full-screen exclusive mode is available for * this graphics device @@ -227,8 +227,8 @@ public abstract class GraphicsDevice { /** * Enter full-screen mode, or return to windowed mode. The entered * full-screen mode may be either exclusive or simulated. Exclusive - * mode is only available if isFullScreenSupported - * returns true. + * mode is only available if {@code isFullScreenSupported} + * returns {@code true}. *

      * Exclusive mode implies: *

        @@ -239,7 +239,7 @@ public abstract class GraphicsDevice { * will cause the existing full-screen window to * return to windowed mode. *
      • Input method windows are disabled. It is advisable to call - * Component.enableInputMethods(false) to make a component + * {@code Component.enableInputMethods(false)} to make a component * a non-client of the input method framework. *
      *

      @@ -341,10 +341,10 @@ public abstract class GraphicsDevice { } /** - * Returns the Window object representing the + * Returns the {@code Window} object representing the * full-screen window if the device is in full-screen mode. * - * @return the full-screen window, or null if the device is + * @return the full-screen window, or {@code null} if the device is * not in full-screen mode. * @see #setFullScreenWindow(Window) * @since 1.4 @@ -362,7 +362,7 @@ public abstract class GraphicsDevice { } /** - * Returns true if this GraphicsDevice + * Returns {@code true} if this {@code GraphicsDevice} * supports low-level display changes. * On some platforms low-level display changes may only be allowed in * full-screen exclusive mode (i.e., if {@link #isFullScreenSupported()} @@ -420,11 +420,11 @@ public abstract class GraphicsDevice { *

      * * @param dm The new display mode of this graphics device. - * @exception IllegalArgumentException if the DisplayMode - * supplied is null, or is not available in the array returned - * by getDisplayModes + * @exception IllegalArgumentException if the {@code DisplayMode} + * supplied is {@code null}, or is not available in the array returned + * by {@code getDisplayModes} * @exception UnsupportedOperationException if - * isDisplayChangeSupported returns false + * {@code isDisplayChangeSupported} returns {@code false} * @see #getDisplayMode * @see #getDisplayModes * @see #isDisplayChangeSupported @@ -436,7 +436,7 @@ public abstract class GraphicsDevice { /** * Returns the current display mode of this - * GraphicsDevice. + * {@code GraphicsDevice}. * The returned display mode is allowed to have a refresh rate * {@link DisplayMode#REFRESH_RATE_UNKNOWN} if it is indeterminate. * Likewise, the returned display mode is allowed to have a bit depth @@ -455,7 +455,7 @@ public abstract class GraphicsDevice { /** * Returns all display modes available for this - * GraphicsDevice. + * {@code GraphicsDevice}. * The returned display modes are allowed to have a refresh rate * {@link DisplayMode#REFRESH_RATE_UNKNOWN} if it is indeterminate. * Likewise, the returned display modes are allowed to have a bit depth diff --git a/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java b/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java index af6a7383649..ab2a8467e9a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java +++ b/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java @@ -39,16 +39,16 @@ import sun.security.action.GetPropertyAction; /** * - * The GraphicsEnvironment class describes the collection + * The {@code GraphicsEnvironment} class describes the collection * of {@link GraphicsDevice} objects and {@link java.awt.Font} objects * available to a Java(tm) application on a particular platform. - * The resources in this GraphicsEnvironment might be local - * or on a remote machine. GraphicsDevice objects can be + * The resources in this {@code GraphicsEnvironment} might be local + * or on a remote machine. {@code GraphicsDevice} objects can be * screens, printers or image buffers and are the destination of - * {@link Graphics2D} drawing methods. Each GraphicsDevice + * {@link Graphics2D} drawing methods. Each {@code GraphicsDevice} * has a number of {@link GraphicsConfiguration} objects associated with * it. These objects specify the different configurations in which the - * GraphicsDevice can be used. + * {@code GraphicsDevice} can be used. * @see GraphicsDevice * @see GraphicsConfiguration */ @@ -74,8 +74,8 @@ public abstract class GraphicsEnvironment { } /** - * Returns the local GraphicsEnvironment. - * @return the local GraphicsEnvironment + * Returns the local {@code GraphicsEnvironment}. + * @return the local {@code GraphicsEnvironment} */ public static synchronized GraphicsEnvironment getLocalGraphicsEnvironment() { if (localEnv == null) { @@ -132,8 +132,8 @@ public abstract class GraphicsEnvironment { * a HeadlessException is thrown from areas of the Toolkit * and GraphicsEnvironment that are dependent on a display, * keyboard, or mouse. - * @return true if this environment cannot support - * a display, keyboard, and mouse; false + * @return {@code true} if this environment cannot support + * a display, keyboard, and mouse; {@code false} * otherwise * @see java.awt.HeadlessException * @since 1.4 @@ -209,11 +209,11 @@ public abstract class GraphicsEnvironment { /** * Returns whether or not a display, keyboard, and mouse can be * supported in this graphics environment. If this returns true, - * HeadlessException will be thrown from areas of the + * {@code HeadlessException} will be thrown from areas of the * graphics environment that are dependent on a display, keyboard, or * mouse. - * @return true if a display, keyboard, and mouse - * can be supported in this environment; false + * @return {@code true} if a display, keyboard, and mouse + * can be supported in this environment; {@code false} * otherwise * @see java.awt.HeadlessException * @see #isHeadless @@ -226,9 +226,9 @@ public abstract class GraphicsEnvironment { } /** - * Returns an array of all of the screen GraphicsDevice + * Returns an array of all of the screen {@code GraphicsDevice} * objects. - * @return an array containing all the GraphicsDevice + * @return an array containing all the {@code GraphicsDevice} * objects that represent screen devices * @exception HeadlessException if isHeadless() returns true * @see #isHeadless() @@ -237,8 +237,8 @@ public abstract class GraphicsEnvironment { throws HeadlessException; /** - * Returns the default screen GraphicsDevice. - * @return the GraphicsDevice that represents the + * Returns the default screen {@code GraphicsDevice}. + * @return the {@code GraphicsDevice} that represents the * default screen device * @exception HeadlessException if isHeadless() returns true * @see #isHeadless() @@ -247,35 +247,35 @@ public abstract class GraphicsEnvironment { throws HeadlessException; /** - * Returns a Graphics2D object for rendering into the + * Returns a {@code Graphics2D} object for rendering into the * specified {@link BufferedImage}. - * @param img the specified BufferedImage - * @return a Graphics2D to be used for rendering into - * the specified BufferedImage - * @throws NullPointerException if img is null + * @param img the specified {@code BufferedImage} + * @return a {@code Graphics2D} to be used for rendering into + * the specified {@code BufferedImage} + * @throws NullPointerException if {@code img} is null */ public abstract Graphics2D createGraphics(BufferedImage img); /** * Returns an array containing a one-point size instance of all fonts - * available in this GraphicsEnvironment. Typical usage + * available in this {@code GraphicsEnvironment}. Typical usage * would be to allow a user to select a particular font. Then, the * application can size the font and set various font attributes by - * calling the deriveFont method on the chosen instance. + * calling the {@code deriveFont} method on the chosen instance. *

      * This method provides for the application the most precise control - * over which Font instance is used to render text. - * If a font in this GraphicsEnvironment has multiple + * over which {@code Font} instance is used to render text. + * If a font in this {@code GraphicsEnvironment} has multiple * programmable variations, only one - * instance of that Font is returned in the array, and + * instance of that {@code Font} is returned in the array, and * other variations must be derived by the application. *

      * If a font in this environment has multiple programmable variations, * such as Multiple-Master fonts, only one instance of that font is - * returned in the Font array. The other variations + * returned in the {@code Font} array. The other variations * must be derived by the application. * - * @return an array of Font objects + * @return an array of {@code Font} objects * @see #getAvailableFontFamilyNames * @see java.awt.Font * @see java.awt.Font#deriveFont @@ -286,8 +286,8 @@ public abstract class GraphicsEnvironment { /** * Returns an array containing the names of all font families in this - * GraphicsEnvironment localized for the default locale, - * as returned by Locale.getDefault(). + * {@code GraphicsEnvironment} localized for the default locale, + * as returned by {@code Locale.getDefault()}. *

      * Typical usage would be for presentation to a user for selection of * a particular family name. An application can then specify this name @@ -295,7 +295,7 @@ public abstract class GraphicsEnvironment { * italic, giving the font system flexibility in choosing its own best * match among multiple fonts in the same font family. * - * @return an array of String containing font family names + * @return an array of {@code String} containing font family names * localized for the default locale, or a suitable alternative * name if no name exists for this locale. * @see #getAllFonts @@ -307,7 +307,7 @@ public abstract class GraphicsEnvironment { /** * Returns an array containing the names of all font families in this - * GraphicsEnvironment localized for the specified locale. + * {@code GraphicsEnvironment} localized for the specified locale. *

      * Typical usage would be for presentation to a user for selection of * a particular family name. An application can then specify this name @@ -317,10 +317,10 @@ public abstract class GraphicsEnvironment { * * @param l a {@link Locale} object that represents a * particular geographical, political, or cultural region. - * Specifying null is equivalent to - * specifying Locale.getDefault(). - * @return an array of String containing font family names - * localized for the specified Locale, or a + * Specifying {@code null} is equivalent to + * specifying {@code Locale.getDefault()}. + * @return an array of {@code String} containing font family names + * localized for the specified {@code Locale}, or a * suitable alternative name if no name exists for the specified locale. * @see #getAllFonts * @see java.awt.Font @@ -330,24 +330,24 @@ public abstract class GraphicsEnvironment { public abstract String[] getAvailableFontFamilyNames(Locale l); /** - * Registers a created Fontin this - * GraphicsEnvironment. + * Registers a created {@code Font} in this + * {@code GraphicsEnvironment}. * A created font is one that was returned from calling * {@link Font#createFont}, or derived from a created font by * calling {@link Font#deriveFont}. * After calling this method for such a font, it is available to - * be used in constructing new Fonts by name or family name, + * be used in constructing new {@code Font}s by name or family name, * and is enumerated by {@link #getAvailableFontFamilyNames} and * {@link #getAllFonts} within the execution context of this * application or applet. This means applets cannot register fonts in * a way that they are visible to other applets. *

      * Reasons that this method might not register the font and therefore - * return false are: + * return {@code false} are: *

        - *
      • The font is not a created Font. - *
      • The font conflicts with a non-created Font already - * in this GraphicsEnvironment. For example if the name + *
      • The font is not a created {@code Font}. + *
      • The font conflicts with a non-created {@code Font} already + * in this {@code GraphicsEnvironment}. For example if the name * is that of a system font, or a logical font as described in the * documentation of the {@link Font} class. It is implementation dependent * whether a font may also conflict if it has the same family name @@ -357,9 +357,9 @@ public abstract class GraphicsEnvironment { *
      * * @param font the font to be registered - * @return true if the font is successfully - * registered in this GraphicsEnvironment. - * @throws NullPointerException if font is null + * @return true if the {@code font} is successfully + * registered in this {@code GraphicsEnvironment}. + * @throws NullPointerException if {@code font} is null * @since 1.6 */ public boolean registerFont(Font font) { @@ -444,8 +444,8 @@ public abstract class GraphicsEnvironment { * entire display area. *

      * To get the usable bounds of a single display, use - * GraphicsConfiguration.getBounds() and - * Toolkit.getScreenInsets(). + * {@code GraphicsConfiguration.getBounds()} and + * {@code Toolkit.getScreenInsets()}. * @return the maximum bounds for centered Windows * * @exception HeadlessException if isHeadless() returns true diff --git a/jdk/src/java.desktop/share/classes/java/awt/GridBagConstraints.java b/jdk/src/java.desktop/share/classes/java/awt/GridBagConstraints.java index e676e4c74ad..566c50b67dd 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/GridBagConstraints.java +++ b/jdk/src/java.desktop/share/classes/java/awt/GridBagConstraints.java @@ -25,9 +25,9 @@ package java.awt; /** - * The GridBagConstraints class specifies constraints + * The {@code GridBagConstraints} class specifies constraints * for components that are laid out using the - * GridBagLayout class. + * {@code GridBagLayout} class. * * @author Doug Stein * @author Bill Spitzak (orignial NeWS & OLIT implementation) @@ -38,9 +38,9 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { /** * Specifies that this component is the next-to-last component in its - * column or row (gridwidth, gridheight), + * column or row ({@code gridwidth}, {@code gridheight}), * or that this component be placed next to the previously added - * component (gridx, gridy). + * component ({@code gridx}, {@code gridy}). * @see java.awt.GridBagConstraints#gridwidth * @see java.awt.GridBagConstraints#gridheight * @see java.awt.GridBagConstraints#gridx @@ -194,7 +194,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { public static final int LAST_LINE_END = 26; /** - * Possible value for the anchor field. Specifies + * Possible value for the {@code anchor} field. Specifies * that the component should be horizontally centered and * vertically aligned along the baseline of the prevailing row. * If the component does not have a baseline it will be vertically @@ -205,7 +205,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { public static final int BASELINE = 0x100; /** - * Possible value for the anchor field. Specifies + * Possible value for the {@code anchor} field. Specifies * that the component should be horizontally placed along the * leading edge. For components with a left-to-right orientation, * the leading edge is the left edge. Vertically the component is @@ -218,7 +218,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { public static final int BASELINE_LEADING = 0x200; /** - * Possible value for the anchor field. Specifies + * Possible value for the {@code anchor} field. Specifies * that the component should be horizontally placed along the * trailing edge. For components with a left-to-right * orientation, the trailing edge is the right edge. Vertically @@ -231,7 +231,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { public static final int BASELINE_TRAILING = 0x300; /** - * Possible value for the anchor field. Specifies + * Possible value for the {@code anchor} field. Specifies * that the component should be horizontally centered. Vertically * the component is positioned so that its bottom edge touches * the baseline of the starting row. If the starting row does not @@ -242,7 +242,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { public static final int ABOVE_BASELINE = 0x400; /** - * Possible value for the anchor field. Specifies + * Possible value for the {@code anchor} field. Specifies * that the component should be horizontally placed along the * leading edge. For components with a left-to-right orientation, * the leading edge is the left edge. Vertically the component is @@ -255,7 +255,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { public static final int ABOVE_BASELINE_LEADING = 0x500; /** - * Possible value for the anchor field. Specifies + * Possible value for the {@code anchor} field. Specifies * that the component should be horizontally placed along the * trailing edge. For components with a left-to-right * orientation, the trailing edge is the right edge. Vertically @@ -268,7 +268,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { public static final int ABOVE_BASELINE_TRAILING = 0x600; /** - * Possible value for the anchor field. Specifies + * Possible value for the {@code anchor} field. Specifies * that the component should be horizontally centered. Vertically * the component is positioned so that its top edge touches the * baseline of the starting row. If the starting row does not @@ -279,7 +279,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { public static final int BELOW_BASELINE = 0x700; /** - * Possible value for the anchor field. Specifies + * Possible value for the {@code anchor} field. Specifies * that the component should be horizontally placed along the * leading edge. For components with a left-to-right orientation, * the leading edge is the left edge. Vertically the component is @@ -292,7 +292,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { public static final int BELOW_BASELINE_LEADING = 0x800; /** - * Possible value for the anchor field. Specifies + * Possible value for the {@code anchor} field. Specifies * that the component should be horizontally placed along the * trailing edge. For components with a left-to-right * orientation, the trailing edge is the right edge. Vertically @@ -306,17 +306,17 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { /** * Specifies the cell containing the leading edge of the component's - * display area, where the first cell in a row has gridx=0. + * display area, where the first cell in a row has {@code gridx=0}. * The leading edge of a component's display area is its left edge for * a horizontal, left-to-right container and its right edge for a * horizontal, right-to-left container. * The value - * RELATIVE specifies that the component be placed + * {@code RELATIVE} specifies that the component be placed * immediately following the component that was added to the container * just before this component was added. *

      - * The default value is RELATIVE. - * gridx should be a non-negative value. + * The default value is {@code RELATIVE}. + * {@code gridx} should be a non-negative value. * @serial * @see #clone() * @see java.awt.GridBagConstraints#gridy @@ -326,13 +326,13 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { /** * Specifies the cell at the top of the component's display area, - * where the topmost cell has gridy=0. The value - * RELATIVE specifies that the component be placed just + * where the topmost cell has {@code gridy=0}. The value + * {@code RELATIVE} specifies that the component be placed just * below the component that was added to the container just before * this component was added. *

      - * The default value is RELATIVE. - * gridy should be a non-negative value. + * The default value is {@code RELATIVE}. + * {@code gridy} should be a non-negative value. * @serial * @see #clone() * @see java.awt.GridBagConstraints#gridx @@ -343,14 +343,14 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * Specifies the number of cells in a row for the component's * display area. *

      - * Use REMAINDER to specify that the component's - * display area will be from gridx to the last + * Use {@code REMAINDER} to specify that the component's + * display area will be from {@code gridx} to the last * cell in the row. - * Use RELATIVE to specify that the component's - * display area will be from gridx to the next + * Use {@code RELATIVE} to specify that the component's + * display area will be from {@code gridx} to the next * to the last one in its row. *

      - * gridwidth should be non-negative and the default + * {@code gridwidth} should be non-negative and the default * value is 1. * @serial * @see #clone() @@ -362,14 +362,14 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * Specifies the number of cells in a column for the component's * display area. *

      - * Use REMAINDER to specify that the component's - * display area will be from gridy to the last + * Use {@code REMAINDER} to specify that the component's + * display area will be from {@code gridy} to the last * cell in the column. - * Use RELATIVE to specify that the component's - * display area will be from gridy to the next + * Use {@code RELATIVE} to specify that the component's + * display area will be from {@code gridy} to the next * to the last one in its column. *

      - * gridheight should be a non-negative value and the + * {@code gridheight} should be a non-negative value and the * default value is 1. * @serial * @see #clone() @@ -381,7 +381,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * Specifies how to distribute extra horizontal space. *

      * The grid bag layout manager calculates the weight of a column to - * be the maximum weightx of all the components in a + * be the maximum {@code weightx} of all the components in a * column. If the resulting layout is smaller horizontally than the area * it needs to fill, the extra space is distributed to each column in * proportion to its weight. A column that has a weight of zero receives @@ -390,8 +390,8 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * If all the weights are zero, all the extra space appears between * the grids of the cell and the left and right edges. *

      - * The default value of this field is 0. - * weightx should be a non-negative value. + * The default value of this field is {@code 0}. + * {@code weightx} should be a non-negative value. * @serial * @see #clone() * @see java.awt.GridBagConstraints#weighty @@ -402,7 +402,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * Specifies how to distribute extra vertical space. *

      * The grid bag layout manager calculates the weight of a row to be - * the maximum weighty of all the components in a row. + * the maximum {@code weighty} of all the components in a row. * If the resulting layout is smaller vertically than the area it * needs to fill, the extra space is distributed to each row in * proportion to its weight. A row that has a weight of zero receives no @@ -411,8 +411,8 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * If all the weights are zero, all the extra space appears between * the grids of the cell and the top and bottom edges. *

      - * The default value of this field is 0. - * weighty should be a non-negative value. + * The default value of this field is {@code 0}. + * {@code weighty} should be a non-negative value. * @serial * @see #clone() * @see java.awt.GridBagConstraints#weightx @@ -429,22 +429,22 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * orientation property, baseline relative values are interpreted * relative to the baseline and absolute values are not. The * absolute values are: - * CENTER, NORTH, NORTHEAST, - * EAST, SOUTHEAST, SOUTH, - * SOUTHWEST, WEST, and NORTHWEST. - * The orientation relative values are: PAGE_START, - * PAGE_END, - * LINE_START, LINE_END, - * FIRST_LINE_START, FIRST_LINE_END, - * LAST_LINE_START and LAST_LINE_END. The + * {@code CENTER}, {@code NORTH}, {@code NORTHEAST}, + * {@code EAST}, {@code SOUTHEAST}, {@code SOUTH}, + * {@code SOUTHWEST}, {@code WEST}, and {@code NORTHWEST}. + * The orientation relative values are: {@code PAGE_START}, + * {@code PAGE_END}, + * {@code LINE_START}, {@code LINE_END}, + * {@code FIRST_LINE_START}, {@code FIRST_LINE_END}, + * {@code LAST_LINE_START} and {@code LAST_LINE_END}. The * baseline relative values are: - * BASELINE, BASELINE_LEADING, - * BASELINE_TRAILING, - * ABOVE_BASELINE, ABOVE_BASELINE_LEADING, - * ABOVE_BASELINE_TRAILING, - * BELOW_BASELINE, BELOW_BASELINE_LEADING, - * and BELOW_BASELINE_TRAILING. - * The default value is CENTER. + * {@code BASELINE}, {@code BASELINE_LEADING}, + * {@code BASELINE_TRAILING}, + * {@code ABOVE_BASELINE}, {@code ABOVE_BASELINE_LEADING}, + * {@code ABOVE_BASELINE_TRAILING}, + * {@code BELOW_BASELINE}, {@code BELOW_BASELINE_LEADING}, + * and {@code BELOW_BASELINE_TRAILING}. + * The default value is {@code CENTER}. * @serial * @see #clone() * @see java.awt.ComponentOrientation @@ -456,23 +456,23 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * than the component's requested size. It determines whether to * resize the component, and if so, how. *

      - * The following values are valid for fill: + * The following values are valid for {@code fill}: * *

        *
      • - * NONE: Do not resize the component. + * {@code NONE}: Do not resize the component. *
      • - * HORIZONTAL: Make the component wide enough to fill + * {@code HORIZONTAL}: Make the component wide enough to fill * its display area horizontally, but do not change its height. *
      • - * VERTICAL: Make the component tall enough to fill its + * {@code VERTICAL}: Make the component tall enough to fill its * display area vertically, but do not change its width. *
      • - * BOTH: Make the component fill its display area + * {@code BOTH}: Make the component fill its display area * entirely. *
      *

      - * The default value is NONE. + * The default value is {@code NONE}. * @serial * @see #clone() */ @@ -483,7 +483,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * minimum amount of space between the component and the edges of its * display area. *

      - * The default value is new Insets(0, 0, 0, 0). + * The default value is {@code new Insets(0, 0, 0, 0)}. * @serial * @see #clone() */ @@ -493,9 +493,9 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * This field specifies the internal padding of the component, how much * space to add to the minimum width of the component. The width of * the component is at least its minimum width plus - * ipadx pixels. + * {@code ipadx} pixels. *

      - * The default value is 0. + * The default value is {@code 0}. * @serial * @see #clone() * @see java.awt.GridBagConstraints#ipady @@ -506,7 +506,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { * This field specifies the internal padding, that is, how much * space to add to the minimum height of the component. The height of * the component is at least its minimum height plus - * ipady pixels. + * {@code ipady} pixels. *

      * The default value is 0. * @serial @@ -537,14 +537,14 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { int tempHeight; /** * The minimum width of the component. It is used to calculate - * ipady, where the default will be 0. + * {@code ipady}, where the default will be 0. * @serial * @see #ipady */ int minWidth; /** * The minimum height of the component. It is used to calculate - * ipadx, where the default will be 0. + * {@code ipadx}, where the default will be 0. * @serial * @see #ipadx */ @@ -571,7 +571,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { private static final long serialVersionUID = -1000070633030801713L; /** - * Creates a GridBagConstraint object with + * Creates a {@code GridBagConstraint} object with * all of its fields set to their default value. */ public GridBagConstraints () { @@ -591,7 +591,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { } /** - * Creates a GridBagConstraints object with + * Creates a {@code GridBagConstraints} object with * all of its fields set to the passed-in arguments. * * Note: Because the use of this constructor hinders readability diff --git a/jdk/src/java.desktop/share/classes/java/awt/GridBagLayout.java b/jdk/src/java.desktop/share/classes/java/awt/GridBagLayout.java index 7c86dcc1f67..1ecf40840ea 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/GridBagLayout.java +++ b/jdk/src/java.desktop/share/classes/java/awt/GridBagLayout.java @@ -28,18 +28,18 @@ import java.util.Hashtable; import java.util.Arrays; /** - * The GridBagLayout class is a flexible layout + * The {@code GridBagLayout} class is a flexible layout * manager that aligns components vertically, horizontally or along their * baseline without requiring that the components be of the same size. - * Each GridBagLayout object maintains a dynamic, + * Each {@code GridBagLayout} object maintains a dynamic, * rectangular grid of cells, with each component occupying * one or more cells, called its display area. *

      - * Each component managed by a GridBagLayout is associated with + * Each component managed by a {@code GridBagLayout} is associated with * an instance of {@link GridBagConstraints}. The constraints object * specifies where a component's display area should be located on the grid * and how the component should be positioned within its display area. In - * addition to its constraints object, the GridBagLayout also + * addition to its constraints object, the {@code GridBagLayout} also * considers each component's minimum and preferred sizes in order to * determine a component's size. *

      @@ -52,8 +52,8 @@ import java.util.Arrays; * increasing downward. *

      * To use a grid bag layout effectively, you must customize one or more - * of the GridBagConstraints objects that are associated - * with its components. You customize a GridBagConstraints + * of the {@code GridBagConstraints} objects that are associated + * with its components. You customize a {@code GridBagConstraints} * object by setting one or more of its instance variables: * *

      @@ -65,51 +65,51 @@ import java.util.Arrays; * gridy = 0. For horizontal left-to-right layout, * a component's leading corner is its upper left. For horizontal * right-to-left layout, a component's leading corner is its upper right. - * Use GridBagConstraints.RELATIVE (the default value) + * Use {@code GridBagConstraints.RELATIVE} (the default value) * to specify that the component be placed immediately following - * (along the x axis for gridx or the y axis for - * gridy) the component that was added to the container + * (along the x axis for {@code gridx} or the y axis for + * {@code gridy}) the component that was added to the container * just before this component was added. *
      {@link GridBagConstraints#gridwidth}, * {@link GridBagConstraints#gridheight} - *
      Specifies the number of cells in a row (for gridwidth) - * or column (for gridheight) + *
      Specifies the number of cells in a row (for {@code gridwidth}) + * or column (for {@code gridheight}) * in the component's display area. * The default value is 1. - * Use GridBagConstraints.REMAINDER to specify - * that the component's display area will be from gridx - * to the last cell in the row (for gridwidth) - * or from gridy to the last cell in the column - * (for gridheight). + * Use {@code GridBagConstraints.REMAINDER} to specify + * that the component's display area will be from {@code gridx} + * to the last cell in the row (for {@code gridwidth}) + * or from {@code gridy} to the last cell in the column + * (for {@code gridheight}). * - * Use GridBagConstraints.RELATIVE to specify - * that the component's display area will be from gridx - * to the next to the last cell in its row (for gridwidth - * or from gridy to the next to the last cell in its - * column (for gridheight). + * Use {@code GridBagConstraints.RELATIVE} to specify + * that the component's display area will be from {@code gridx} + * to the next to the last cell in its row (for {@code gridwidth} + * or from {@code gridy} to the next to the last cell in its + * column (for {@code gridheight}). * *
      {@link GridBagConstraints#fill} *
      Used when the component's display area * is larger than the component's requested size * to determine whether (and how) to resize the component. * Possible values are - * GridBagConstraints.NONE (the default), - * GridBagConstraints.HORIZONTAL + * {@code GridBagConstraints.NONE} (the default), + * {@code GridBagConstraints.HORIZONTAL} * (make the component wide enough to fill its display area * horizontally, but don't change its height), - * GridBagConstraints.VERTICAL + * {@code GridBagConstraints.VERTICAL} * (make the component tall enough to fill its display area * vertically, but don't change its width), and - * GridBagConstraints.BOTH + * {@code GridBagConstraints.BOTH} * (make the component fill its display area entirely). *
      {@link GridBagConstraints#ipadx}, * {@link GridBagConstraints#ipady} *
      Specifies the component's internal padding within the layout, * how much to add to the minimum size of the component. * The width of the component will be at least its minimum width - * plus ipadx pixels. Similarly, the height of + * plus {@code ipadx} pixels. Similarly, the height of * the component will be at least the minimum height plus - * ipady pixels. + * {@code ipady} pixels. *
      {@link GridBagConstraints#insets} *
      Specifies the component's external padding, the minimum * amount of space between the component and the edges of its display area. @@ -118,7 +118,7 @@ import java.util.Arrays; * There are three kinds of possible values: absolute, orientation-relative, * and baseline-relative * Orientation relative values are interpreted relative to the container's - * ComponentOrientation property while absolute values + * {@code ComponentOrientation} property while absolute values * are not. Baseline relative values are calculated relative to the * baseline. Valid values are: * @@ -132,40 +132,40 @@ import java.util.Arrays; * * *
        - *
      • GridBagConstraints.NORTH
      • - *
      • GridBagConstraints.SOUTH
      • - *
      • GridBagConstraints.WEST
      • - *
      • GridBagConstraints.EAST
      • - *
      • GridBagConstraints.NORTHWEST
      • - *
      • GridBagConstraints.NORTHEAST
      • - *
      • GridBagConstraints.SOUTHWEST
      • - *
      • GridBagConstraints.SOUTHEAST
      • - *
      • GridBagConstraints.CENTER (the default)
      • + *
      • {@code GridBagConstraints.NORTH}
      • + *
      • {@code GridBagConstraints.SOUTH}
      • + *
      • {@code GridBagConstraints.WEST}
      • + *
      • {@code GridBagConstraints.EAST}
      • + *
      • {@code GridBagConstraints.NORTHWEST}
      • + *
      • {@code GridBagConstraints.NORTHEAST}
      • + *
      • {@code GridBagConstraints.SOUTHWEST}
      • + *
      • {@code GridBagConstraints.SOUTHEAST}
      • + *
      • {@code GridBagConstraints.CENTER} (the default)
      • *
      * * *
        - *
      • GridBagConstraints.PAGE_START
      • - *
      • GridBagConstraints.PAGE_END
      • - *
      • GridBagConstraints.LINE_START
      • - *
      • GridBagConstraints.LINE_END
      • - *
      • GridBagConstraints.FIRST_LINE_START
      • - *
      • GridBagConstraints.FIRST_LINE_END
      • - *
      • GridBagConstraints.LAST_LINE_START
      • - *
      • GridBagConstraints.LAST_LINE_END
      • + *
      • {@code GridBagConstraints.PAGE_START}
      • + *
      • {@code GridBagConstraints.PAGE_END}
      • + *
      • {@code GridBagConstraints.LINE_START}
      • + *
      • {@code GridBagConstraints.LINE_END}
      • + *
      • {@code GridBagConstraints.FIRST_LINE_START}
      • + *
      • {@code GridBagConstraints.FIRST_LINE_END}
      • + *
      • {@code GridBagConstraints.LAST_LINE_START}
      • + *
      • {@code GridBagConstraints.LAST_LINE_END}
      • *
      * * *
        - *
      • GridBagConstraints.BASELINE
      • - *
      • GridBagConstraints.BASELINE_LEADING
      • - *
      • GridBagConstraints.BASELINE_TRAILING
      • - *
      • GridBagConstraints.ABOVE_BASELINE
      • - *
      • GridBagConstraints.ABOVE_BASELINE_LEADING
      • - *
      • GridBagConstraints.ABOVE_BASELINE_TRAILING
      • - *
      • GridBagConstraints.BELOW_BASELINE
      • - *
      • GridBagConstraints.BELOW_BASELINE_LEADING
      • - *
      • GridBagConstraints.BELOW_BASELINE_TRAILING
      • + *
      • {@code GridBagConstraints.BASELINE}
      • + *
      • {@code GridBagConstraints.BASELINE_LEADING}
      • + *
      • {@code GridBagConstraints.BASELINE_TRAILING}
      • + *
      • {@code GridBagConstraints.ABOVE_BASELINE}
      • + *
      • {@code GridBagConstraints.ABOVE_BASELINE_LEADING}
      • + *
      • {@code GridBagConstraints.ABOVE_BASELINE_TRAILING}
      • + *
      • {@code GridBagConstraints.BELOW_BASELINE}
      • + *
      • {@code GridBagConstraints.BELOW_BASELINE_LEADING}
      • + *
      • {@code GridBagConstraints.BELOW_BASELINE_TRAILING}
      • *
      * * @@ -175,10 +175,10 @@ import java.util.Arrays; *
      Used to determine how to distribute space, which is * important for specifying resizing behavior. * Unless you specify a weight for at least one component - * in a row (weightx) and column (weighty), + * in a row ({@code weightx}) and column ({@code weighty}), * all the components clump together in the center of their container. * This is because when the weight is zero (the default), - * the GridBagLayout object puts any extra space + * the {@code GridBagLayout} object puts any extra space * between its grid of cells and the edges of the container. *
      *

      @@ -206,12 +206,12 @@ import java.util.Arrays; * * This layout consists of three components: *

      • A panel that starts in row 0 and ends in row 1. The panel - * has a baseline-resize behavior of CONSTANT_DESCENT and has - * an anchor of BASELINE. As the baseline-resize behavior - * is CONSTANT_DESCENT the prevailing row for the panel is + * has a baseline-resize behavior of {@code CONSTANT_DESCENT} and has + * an anchor of {@code BASELINE}. As the baseline-resize behavior + * is {@code CONSTANT_DESCENT} the prevailing row for the panel is * row 1. *
      • Two buttons, each with a baseline-resize behavior of - * CENTER_OFFSET and an anchor of BASELINE. + * {@code CENTER_OFFSET} and an anchor of {@code BASELINE}. *
      * Because the second button and the panel share the same prevailing row, * they are both aligned along their baseline. @@ -221,7 +221,7 @@ import java.util.Arrays; * value. How components change is dictated by how the baseline of the * prevailing row changes. The baseline is anchored to the * bottom of the display area if any components with the same prevailing row - * have a baseline-resize behavior of CONSTANT_DESCENT, + * have a baseline-resize behavior of {@code CONSTANT_DESCENT}, * otherwise the baseline is anchored to the top of the display area. * The following rules dictate the resize behavior: *
        @@ -233,12 +233,12 @@ import java.util.Arrays; * only grow as high as the difference between the display height and the * baseline. *
      • Resizable components positioned on the baseline with a - * baseline-resize behavior of OTHER are only resized if + * baseline-resize behavior of {@code OTHER} are only resized if * the baseline at the resized size fits within the display area. If * the baseline is such that it does not fit within the display area * the component is not resized. *
      • Components positioned on the baseline that do not have a - * baseline-resize behavior of OTHER + * baseline-resize behavior of {@code OTHER} * can only grow as tall as {@code display height - baseline + baseline of component}. *
      * If you position a component along the baseline, but the @@ -266,9 +266,9 @@ import java.util.Arrays; * * *

      - * Each of the ten components has the fill field - * of its associated GridBagConstraints object - * set to GridBagConstraints.BOTH. + * Each of the ten components has the {@code fill} field + * of its associated {@code GridBagConstraints} object + * set to {@code GridBagConstraints.BOTH}. * In addition, the components have the following non-default constraints: * *

        @@ -387,8 +387,8 @@ java.io.Serializable { /** * This hashtable maintains the association between * a component and its gridbag constraints. - * The Keys in comptable are the components and the - * values are the instances of GridBagConstraints. + * The Keys in {@code comptable} are the components and the + * values are the instances of {@code GridBagConstraints}. * * @serial * @see java.awt.GridBagConstraints @@ -400,7 +400,7 @@ java.io.Serializable { * containing the default values, so if a component * does not have gridbag constraints associated with * it, then the component will be assigned a - * copy of the defaultConstraints. + * copy of the {@code defaultConstraints}. * * @serial * @see #getConstraints(Component) @@ -414,7 +414,7 @@ java.io.Serializable { * for the gridbag. The information in this field * is based on the most recent validation of the * gridbag. - * If layoutInfo is null + * If {@code layoutInfo} is {@code null} * this indicates that there are no components in * the gridbag or if there are components, they have * not yet been validated. @@ -426,7 +426,7 @@ java.io.Serializable { /** * This field holds the overrides to the column minimum - * width. If this field is non-null the values are + * width. If this field is non-{@code null} the values are * applied to the gridbag after all of the minimum columns * widths have been calculated. * If columnWidths has more elements than the number of @@ -440,12 +440,12 @@ java.io.Serializable { /** * This field holds the overrides to the row minimum - * heights. If this field is non-null the values are + * heights. If this field is non-{@code null} the values are * applied to the gridbag after all of the minimum row * heights have been calculated. - * If rowHeights has more elements than the number of + * If {@code rowHeights} has more elements than the number of * rows, rows are added to the gridbag to match - * the number of elements in rowHeights. + * the number of elements in {@code rowHeights}. * * @serial * @see #getLayoutDimensions() @@ -454,12 +454,12 @@ java.io.Serializable { /** * This field holds the overrides to the column weights. - * If this field is non-null the values are + * If this field is non-{@code null} the values are * applied to the gridbag after all of the columns * weights have been calculated. - * If columnWeights[i] > weight for column i, then - * column i is assigned the weight in columnWeights[i]. - * If columnWeights has more elements than the number + * If {@code columnWeights[i] >} weight for column i, then + * column i is assigned the weight in {@code columnWeights[i]}. + * If {@code columnWeights} has more elements than the number * of columns, the excess elements are ignored - they do * not cause more columns to be created. * @@ -469,12 +469,12 @@ java.io.Serializable { /** * This field holds the overrides to the row weights. - * If this field is non-null the values are + * If this field is non-{@code null} the values are * applied to the gridbag after all of the rows * weights have been calculated. - * If rowWeights[i] > weight for row i, then - * row i is assigned the weight in rowWeights[i]. - * If rowWeights has more elements than the number + * If {@code rowWeights[i] > } weight for row i, then + * row i is assigned the weight in {@code rowWeights[i]}. + * If {@code rowWeights} has more elements than the number * of rows, the excess elements are ignored - they do * not cause more rows to be created. * @@ -484,7 +484,7 @@ java.io.Serializable { /** * The component being positioned. This is set before calling into - * adjustForGravity. + * {@code adjustForGravity}. */ private Component componentAdjusting; @@ -507,7 +507,7 @@ java.io.Serializable { /** * Gets the constraints for the specified component. A copy of - * the actual GridBagConstraints object is returned. + * the actual {@code GridBagConstraints} object is returned. * @param comp the component to be queried * @return the constraint for the specified component in this * grid bag layout; a copy of the actual constraint @@ -525,12 +525,12 @@ java.io.Serializable { /** * Retrieves the constraints for the specified component. * The return value is not a copy, but is the actual - * GridBagConstraints object used by the layout mechanism. + * {@code GridBagConstraints} object used by the layout mechanism. *

        - * If comp is not in the GridBagLayout, - * a set of default GridBagConstraints are returned. - * A comp value of null is invalid - * and returns null. + * If {@code comp} is not in the {@code GridBagLayout}, + * a set of default {@code GridBagConstraints} are returned. + * A {@code comp} value of {@code null} is invalid + * and returns {@code null}. * * @param comp the component to be queried * @return the constraints for the specified component @@ -556,7 +556,7 @@ java.io.Serializable { * Determines the origin of the layout area, in the graphics coordinate * space of the target container. This value represents the pixel * coordinates of the top-left corner of the layout area regardless of - * the ComponentOrientation value of the container. This + * the {@code ComponentOrientation} value of the container. This * is distinct from the grid origin given by the cell coordinates (0,0). * Most applications do not call this method directly. * @return the graphics origin of the cell in the top-left @@ -631,16 +631,16 @@ java.io.Serializable { *

        * If the (x, y) point lies * outside the grid, the following rules are used. - * The column index is returned as zero if x lies to the + * The column index is returned as zero if {@code x} lies to the * left of the layout for a left-to-right container or to the right of * the layout for a right-to-left container. The column index is returned - * as the number of columns if x lies + * as the number of columns if {@code x} lies * to the right of the layout in a left-to-right container or to the left * in a right-to-left container. - * The row index is returned as zero if y lies above the - * layout, and as the number of rows if y lies + * The row index is returned as zero if {@code y} lies above the + * layout, and as the number of rows if {@code y} lies * below the layout. The orientation of a container is determined by its - * ComponentOrientation property. + * {@code ComponentOrientation} property. * @param x the x coordinate of a point * @param y the y coordinate of a point * @return an ordered pair of indexes that indicate which cell @@ -692,14 +692,14 @@ java.io.Serializable { /** * Adds the specified component to the layout, using the specified - * constraints object. Note that constraints + * {@code constraints} object. Note that constraints * are mutable and are, therefore, cloned when cached. * * @param comp the component to be added * @param constraints an object that determines how * the component is added to the layout - * @exception IllegalArgumentException if constraints - * is not a GridBagConstraint + * @exception IllegalArgumentException if {@code constraints} + * is not a {@code GridBagConstraint} */ public void addLayoutComponent(Component comp, Object constraints) { if (constraints instanceof GridBagConstraints) { @@ -722,14 +722,14 @@ java.io.Serializable { } /** - * Determines the preferred size of the parent + * Determines the preferred size of the {@code parent} * container using this grid bag layout. *

        * Most applications do not call this method directly. * * @param parent the container in which to do the layout * @see java.awt.Container#getPreferredSize - * @return the preferred size of the parent + * @return the preferred size of the {@code parent} * container */ public Dimension preferredLayoutSize(Container parent) { @@ -738,13 +738,13 @@ java.io.Serializable { } /** - * Determines the minimum size of the parent container + * Determines the minimum size of the {@code parent} container * using this grid bag layout. *

        * Most applications do not call this method directly. * @param parent the container in which to do the layout * @see java.awt.Container#doLayout - * @return the minimum size of the parent container + * @return the minimum size of the {@code parent} container */ public Dimension minimumLayoutSize(Container parent) { GridBagLayoutInfo info = getLayoutInfo(parent, MINSIZE); @@ -771,7 +771,7 @@ java.io.Serializable { * where 0 represents alignment along the origin, 1 is aligned * the furthest away from the origin, 0.5 is centered, etc. * - * @return the value 0.5f to indicate centered + * @return the value {@code 0.5f} to indicate centered */ public float getLayoutAlignmentX(Container parent) { return 0.5f; @@ -784,7 +784,7 @@ java.io.Serializable { * where 0 represents alignment along the origin, 1 is aligned * the furthest away from the origin, 0.5 is centered, etc. * - * @return the value 0.5f to indicate centered + * @return the value {@code 0.5f} to indicate centered */ public float getLayoutAlignmentY(Container parent) { return 0.5f; @@ -800,7 +800,7 @@ java.io.Serializable { /** * Lays out the specified container using this grid bag layout. * This method reshapes components in the specified container in - * order to satisfy the constraints of this GridBagLayout + * order to satisfy the constraints of this {@code GridBagLayout} * object. *

        * Most applications do not call this method directly. @@ -890,7 +890,7 @@ java.io.Serializable { */ /** - * Fills in an instance of GridBagLayoutInfo for the + * Fills in an instance of {@code GridBagLayoutInfo} for the * current set of managed children. This requires three passes through the * set of children: * @@ -904,12 +904,12 @@ java.io.Serializable { * first encountered (so subsequent loops don't need to ask again). *

        * This method should only be used internally by - * GridBagLayout. + * {@code GridBagLayout}. * * @param parent the layout container - * @param sizeflag either PREFERREDSIZE or - * MINSIZE - * @return the GridBagLayoutInfo for the set of children + * @param sizeflag either {@code PREFERREDSIZE} or + * {@code MINSIZE} + * @return the {@code GridBagLayoutInfo} for the set of children * @since 1.4 */ protected GridBagLayoutInfo getLayoutInfo(Container parent, int sizeflag) { @@ -1605,10 +1605,10 @@ java.io.Serializable { * Adjusts the x, y, width, and height fields to the correct * values depending on the constraint geometry and pads. * This method should only be used internally by - * GridBagLayout. + * {@code GridBagLayout}. * * @param constraints the constraints to be applied - * @param r the Rectangle to be adjusted + * @param r the {@code Rectangle} to be adjusted * @since 1.4 */ protected void adjustForGravity(GridBagConstraints constraints, @@ -1624,7 +1624,7 @@ java.io.Serializable { * compatibility only; new code should call {@link * #adjustForGravity(java.awt.GridBagConstraints, java.awt.Rectangle) * adjustForGravity} instead. - * This method is the same as adjustForGravity + * This method is the same as {@code adjustForGravity} * * @param constraints the constraints to be applied * @param r the {@code Rectangle} to be adjusted @@ -1987,13 +1987,13 @@ java.io.Serializable { /** * Figures out the minimum size of the - * master based on the information from getLayoutInfo. + * master based on the information from {@code getLayoutInfo}. * This method should only be used internally by - * GridBagLayout. + * {@code GridBagLayout}. * * @param parent the layout container * @param info the layout info for this parent - * @return a Dimension object containing the + * @return a {@code Dimension} object containing the * minimum size * @since 1.4 */ @@ -2005,11 +2005,11 @@ java.io.Serializable { * This method is obsolete and supplied for backwards * compatibility only; new code should call {@link * #getMinSize(java.awt.Container, GridBagLayoutInfo) getMinSize} instead. - * This method is the same as getMinSize + * This method is the same as {@code getMinSize} * * @param parent the layout container * @param info the layout info for this parent - * @return a Dimension object containing the + * @return a {@code Dimension} object containing the * minimum size */ protected Dimension GetMinSize(Container parent, GridBagLayoutInfo info) { @@ -2035,7 +2035,7 @@ java.io.Serializable { /** * Lays out the grid. * This method should only be used internally by - * GridBagLayout. + * {@code GridBagLayout}. * * @param parent the layout container * @since 1.4 @@ -2048,7 +2048,7 @@ java.io.Serializable { * This method is obsolete and supplied for backwards * compatibility only; new code should call {@link * #arrangeGrid(Container) arrangeGrid} instead. - * This method is the same as arrangeGrid + * This method is the same as {@code arrangeGrid} * * @param parent the layout container */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Image.java b/jdk/src/java.desktop/share/classes/java/awt/Image.java index d18e02d5147..b2ab082aa2c 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Image.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Image.java @@ -35,7 +35,7 @@ import sun.awt.image.SurfaceManager; /** - * The abstract class Image is the superclass of all + * The abstract class {@code Image} is the superclass of all * classes that represent graphical images. The image must be * obtained in a platform-specific manner. * @@ -57,17 +57,17 @@ public abstract class Image { * Priority for accelerating this image. Subclasses are free to * set different default priorities and applications are free to * set the priority for specific images via the - * setAccelerationPriority(float) method. + * {@code setAccelerationPriority(float)} method. * @since 1.5 */ protected float accelerationPriority = .5f; /** * Determines the width of the image. If the width is not yet known, - * this method returns -1 and the specified - * ImageObserver object is notified later. + * this method returns {@code -1} and the specified + * {@code ImageObserver} object is notified later. * @param observer an object waiting for the image to be loaded. - * @return the width of this image, or -1 + * @return the width of this image, or {@code -1} * if the width is not yet known. * @see java.awt.Image#getHeight * @see java.awt.image.ImageObserver @@ -76,10 +76,10 @@ public abstract class Image { /** * Determines the height of the image. If the height is not yet known, - * this method returns -1 and the specified - * ImageObserver object is notified later. + * this method returns {@code -1} and the specified + * {@code ImageObserver} object is notified later. * @param observer an object waiting for the image to be loaded. - * @return the height of this image, or -1 + * @return the height of this image, or {@code -1} * if the height is not yet known. * @see java.awt.Image#getWidth * @see java.awt.image.ImageObserver @@ -112,13 +112,13 @@ public abstract class Image { *

        * Individual property names are defined by the various image * formats. If a property is not defined for a particular image, this - * method returns the UndefinedProperty object. + * method returns the {@code UndefinedProperty} object. *

        * If the properties for this image are not yet known, this method - * returns null, and the ImageObserver + * returns {@code null}, and the {@code ImageObserver} * object is notified later. *

        - * The property name "comment" should be used to store + * The property name {@code "comment"} should be used to store * an optional comment which can be presented to the application as a * description of the image, its source, or its author. * @param name a property name. @@ -131,25 +131,25 @@ public abstract class Image { public abstract Object getProperty(String name, ImageObserver observer); /** - * The UndefinedProperty object should be returned whenever a + * The {@code UndefinedProperty} object should be returned whenever a * property which was not defined for a particular image is fetched. */ public static final Object UndefinedProperty = new Object(); /** * Creates a scaled version of this image. - * A new Image object is returned which will render - * the image at the specified width and - * height by default. The new Image object + * A new {@code Image} object is returned which will render + * the image at the specified {@code width} and + * {@code height} by default. The new {@code Image} object * may be loaded asynchronously even if the original source image * has already been loaded completely. * *

        * - * If either width - * or height is a negative number then a value is + * If either {@code width} + * or {@code height} is a negative number then a value is * substituted to maintain the aspect ratio of the original image - * dimensions. If both width and height + * dimensions. If both {@code width} and {@code height} * are negative, then the original image dimensions are used. * * @param width the width to which to scale the image. @@ -157,8 +157,8 @@ public abstract class Image { * @param hints flags to indicate the type of algorithm to use * for image resampling. * @return a scaled version of the image. - * @exception IllegalArgumentException if width - * or height is zero. + * @exception IllegalArgumentException if {@code width} + * or {@code height} is zero. * @see java.awt.Image#SCALE_DEFAULT * @see java.awt.Image#SCALE_FAST * @see java.awt.Image#SCALE_SMOOTH @@ -200,8 +200,8 @@ public abstract class Image { /** * Use the image scaling algorithm embodied in the - * ReplicateScaleFilter class. - * The Image object is free to substitute a different filter + * {@code ReplicateScaleFilter} class. + * The {@code Image} object is free to substitute a different filter * that performs the same algorithm yet integrates more efficiently * into the imaging infrastructure supplied by the toolkit. * @see java.awt.image.ReplicateScaleFilter @@ -274,11 +274,11 @@ public abstract class Image { * size on the given GraphicsConfiguration, so although the object * may be acceleratable in general, it * does not have that capability on this GraphicsConfiguration. - * @param gc a GraphicsConfiguration object. A value of null + * @param gc a {@code GraphicsConfiguration} object. A value of null * for this parameter will result in getting the image capabilities - * for the default GraphicsConfiguration. - * @return an ImageCapabilities object that contains - * the capabilities of this Image on the specified + * for the default {@code GraphicsConfiguration}. + * @return an {@code ImageCapabilities} object that contains + * the capabilities of this {@code Image} on the specified * GraphicsConfiguration. * @see java.awt.image.VolatileImage#getCapabilities() * VolatileImage.getCapabilities() @@ -313,7 +313,7 @@ public abstract class Image { * means that this Image should never be accelerated. Other values * are used simply to determine acceleration priority relative to other * Images. - * @throws IllegalArgumentException if priority is less + * @throws IllegalArgumentException if {@code priority} is less * than zero or greater than 1. * @since 1.5 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/ImageCapabilities.java b/jdk/src/java.desktop/share/classes/java/awt/ImageCapabilities.java index e02ccacfb77..9d21b924ff8 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ImageCapabilities.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ImageCapabilities.java @@ -43,8 +43,8 @@ public class ImageCapabilities implements Cloneable { } /** - * Returns true if the object whose capabilities are - * encapsulated in this ImageCapabilities can be or is + * Returns {@code true} if the object whose capabilities are + * encapsulated in this {@code ImageCapabilities} can be or is * accelerated. * @return whether or not an image can be, or is, accelerated. There are * various platform-specific ways to accelerate an image, including @@ -56,8 +56,8 @@ public class ImageCapabilities implements Cloneable { } /** - * Returns true if the VolatileImage - * described by this ImageCapabilities can lose + * Returns {@code true} if the {@code VolatileImage} + * described by this {@code ImageCapabilities} can lose * its surfaces. * @return whether or not a volatile image is subject to losing its surfaces * at the whim of the operating system. diff --git a/jdk/src/java.desktop/share/classes/java/awt/Insets.java b/jdk/src/java.desktop/share/classes/java/awt/Insets.java index 66542fcf2a5..edd1473ef39 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Insets.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Insets.java @@ -26,7 +26,7 @@ package java.awt; /** - * An Insets object is a representation of the borders + * An {@code Insets} object is a representation of the borders * of a container. It specifies the space that a container must leave * at each of its edges. The space can be a border, a blank space, or * a title. @@ -93,7 +93,7 @@ public class Insets implements Cloneable, java.io.Serializable { } /** - * Creates and initializes a new Insets object with the + * Creates and initializes a new {@code Insets} object with the * specified top, left, bottom, and right insets. * @param top the inset from the top. * @param left the inset from the left. @@ -125,11 +125,11 @@ public class Insets implements Cloneable, java.io.Serializable { /** * Checks whether two insets objects are equal. Two instances - * of Insets are equal if the four integer values - * of the fields top, left, - * bottom, and right are all equal. - * @return true if the two insets are equal; - * otherwise false. + * of {@code Insets} are equal if the four integer values + * of the fields {@code top}, {@code left}, + * {@code bottom}, and {@code right} are all equal. + * @return {@code true} if the two insets are equal; + * otherwise {@code false}. * @since 1.1 */ public boolean equals(Object obj) { @@ -156,13 +156,13 @@ public class Insets implements Cloneable, java.io.Serializable { } /** - * Returns a string representation of this Insets object. + * Returns a string representation of this {@code Insets} object. * This method is intended to be used only for debugging purposes, and * the content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * - * @return a string representation of this Insets object. + * @return a string representation of this {@code Insets} object. */ public String toString() { return getClass().getName() + "[top=" + top + ",left=" + left + ",bottom=" + bottom + ",right=" + right + "]"; @@ -170,7 +170,7 @@ public class Insets implements Cloneable, java.io.Serializable { /** * Create a copy of this object. - * @return a copy of this Insets object. + * @return a copy of this {@code Insets} object. */ public Object clone() { try { diff --git a/jdk/src/java.desktop/share/classes/java/awt/ItemSelectable.java b/jdk/src/java.desktop/share/classes/java/awt/ItemSelectable.java index e11b70ef48f..2d26112027c 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ItemSelectable.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ItemSelectable.java @@ -37,7 +37,7 @@ import java.awt.event.*; public interface ItemSelectable { /** - * Returns the selected items or null if no + * Returns the selected items or {@code null} if no * items are selected. * * @return the list of selected objects, or {@code null} @@ -47,8 +47,8 @@ public interface ItemSelectable { /** * Adds a listener to receive item events when the state of an item is * changed by the user. Item events are not sent when an item's - * state is set programmatically. If l is - * null, no exception is thrown and no action is performed. + * state is set programmatically. If {@code l} is + * {@code null}, no exception is thrown and no action is performed. * * @param l the listener to receive events * @see ItemEvent @@ -57,7 +57,7 @@ public interface ItemSelectable { /** * Removes an item listener. - * If l is null, + * If {@code l} is {@code null}, * no exception is thrown and no action is performed. * * @param l the listener being removed diff --git a/jdk/src/java.desktop/share/classes/java/awt/JobAttributes.java b/jdk/src/java.desktop/share/classes/java/awt/JobAttributes.java index bbb94e3bb5c..6281d6e1e5e 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/JobAttributes.java +++ b/jdk/src/java.desktop/share/classes/java/awt/JobAttributes.java @@ -72,19 +72,19 @@ public final class JobAttributes implements Cloneable { }; /** - * The DefaultSelectionType instance to use for + * The {@code DefaultSelectionType} instance to use for * specifying that all pages of the job should be printed. */ public static final DefaultSelectionType ALL = new DefaultSelectionType(I_ALL); /** - * The DefaultSelectionType instance to use for + * The {@code DefaultSelectionType} instance to use for * specifying that a range of pages of the job should be printed. */ public static final DefaultSelectionType RANGE = new DefaultSelectionType(I_RANGE); /** - * The DefaultSelectionType instance to use for + * The {@code DefaultSelectionType} instance to use for * specifying that the current selection should be printed. */ public static final DefaultSelectionType SELECTION = @@ -108,13 +108,13 @@ public final class JobAttributes implements Cloneable { }; /** - * The DestinationType instance to use for + * The {@code DestinationType} instance to use for * specifying print to file. */ public static final DestinationType FILE = new DestinationType(I_FILE); /** - * The DestinationType instance to use for + * The {@code DestinationType} instance to use for * specifying print to printer. */ public static final DestinationType PRINTER = @@ -139,17 +139,17 @@ public final class JobAttributes implements Cloneable { }; /** - * The DialogType instance to use for + * The {@code DialogType} instance to use for * specifying the cross-platform, pure Java print dialog. */ public static final DialogType COMMON = new DialogType(I_COMMON); /** - * The DialogType instance to use for + * The {@code DialogType} instance to use for * specifying the platform's native print dialog. */ public static final DialogType NATIVE = new DialogType(I_NATIVE); /** - * The DialogType instance to use for + * The {@code DialogType} instance to use for * specifying no print dialog. */ public static final DialogType NONE = new DialogType(I_NONE); @@ -176,7 +176,7 @@ public final class JobAttributes implements Cloneable { }; /** - * The MultipleDocumentHandlingType instance to use for specifying + * The {@code MultipleDocumentHandlingType} instance to use for specifying * that the job should be divided into separate, collated copies. */ public static final MultipleDocumentHandlingType @@ -184,7 +184,7 @@ public final class JobAttributes implements Cloneable { new MultipleDocumentHandlingType( I_SEPARATE_DOCUMENTS_COLLATED_COPIES); /** - * The MultipleDocumentHandlingType instance to use for specifying + * The {@code MultipleDocumentHandlingType} instance to use for specifying * that the job should be divided into separate, uncollated copies. */ public static final MultipleDocumentHandlingType @@ -212,13 +212,13 @@ public final class JobAttributes implements Cloneable { }; /** - * The SidesType instance to use for specifying that + * The {@code SidesType} instance to use for specifying that * consecutive job pages should be printed upon the same side of * consecutive media sheets. */ public static final SidesType ONE_SIDED = new SidesType(I_ONE_SIDED); /** - * The SidesType instance to use for specifying that + * The {@code SidesType} instance to use for specifying that * consecutive job pages should be printed upon front and back sides * of consecutive media sheets, such that the orientation of each pair * of pages on the medium would be correct for the reader as if for @@ -227,7 +227,7 @@ public final class JobAttributes implements Cloneable { public static final SidesType TWO_SIDED_LONG_EDGE = new SidesType(I_TWO_SIDED_LONG_EDGE); /** - * The SidesType instance to use for specifying that + * The {@code SidesType} instance to use for specifying that * consecutive job pages should be printed upon front and back sides * of consecutive media sheets, such that the orientation of each pair * of pages on the medium would be correct for the reader as if for @@ -258,16 +258,16 @@ public final class JobAttributes implements Cloneable { private int toPage; /** - * Constructs a JobAttributes instance with default + * Constructs a {@code JobAttributes} instance with default * values for every attribute. The dialog defaults to - * DialogType.NATIVE. Min page defaults to - * 1. Max page defaults to Integer.MAX_VALUE. - * Destination defaults to DestinationType.PRINTER. - * Selection defaults to DefaultSelectionType.ALL. - * Number of copies defaults to 1. Multiple document handling defaults - * to MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES. - * Sides defaults to SidesType.ONE_SIDED. File name defaults - * to null. + * {@code DialogType.NATIVE}. Min page defaults to + * {@code 1}. Max page defaults to {@code Integer.MAX_VALUE}. + * Destination defaults to {@code DestinationType.PRINTER}. + * Selection defaults to {@code DefaultSelectionType.ALL}. + * Number of copies defaults to {@code 1}. Multiple document handling defaults + * to {@code MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES}. + * Sides defaults to {@code SidesType.ONE_SIDED}. File name defaults + * to {@code null}. */ public JobAttributes() { setCopiesToDefault(); @@ -281,36 +281,36 @@ public final class JobAttributes implements Cloneable { } /** - * Constructs a JobAttributes instance which is a copy - * of the supplied JobAttributes. + * Constructs a {@code JobAttributes} instance which is a copy + * of the supplied {@code JobAttributes}. * - * @param obj the JobAttributes to copy + * @param obj the {@code JobAttributes} to copy */ public JobAttributes(JobAttributes obj) { set(obj); } /** - * Constructs a JobAttributes instance with the + * Constructs a {@code JobAttributes} instance with the * specified values for every attribute. * * @param copies an integer greater than 0 - * @param defaultSelection DefaultSelectionType.ALL, - * DefaultSelectionType.RANGE, or - * DefaultSelectionType.SELECTION - * @param destination DestinationType.FILE or - * DestinationType.PRINTER - * @param dialog DialogType.COMMON, - * DialogType.NATIVE, or - * DialogType.NONE - * @param fileName the possibly null file name + * @param defaultSelection {@code DefaultSelectionType.ALL}, + * {@code DefaultSelectionType.RANGE}, or + * {@code DefaultSelectionType.SELECTION} + * @param destination {@code DestinationType.FILE} or + * {@code DestinationType.PRINTER} + * @param dialog {@code DialogType.COMMON}, + * {@code DialogType.NATIVE}, or + * {@code DialogType.NONE} + * @param fileName the possibly {@code null} file name * @param maxPage an integer greater than zero and greater than or equal * to minPage * @param minPage an integer greater than zero and less than or equal * to maxPage * @param multipleDocumentHandling - * MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_COLLATED_COPIES or - * MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES + * {@code MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_COLLATED_COPIES} or + * {@code MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES} * @param pageRanges an array of integer arrays of two elements; an array * is interpreted as a range spanning all pages including and * between the specified pages; ranges must be in ascending @@ -322,13 +322,13 @@ public final class JobAttributes implements Cloneable { * new int[] { 15, 19 } }), *

      * specifies pages 1, 2, 3, 5, 15, 16, 17, 18, and 19. Note that - * (new int[][] { new int[] { 1, 1 }, new int[] { 1, 2 } }), + * ({@code new int[][] { new int[] { 1, 1 }, new int[] { 1, 2 } }}), * is an invalid set of page ranges because the two ranges * overlap - * @param printer the possibly null printer name - * @param sides SidesType.ONE_SIDED, - * SidesType.TWO_SIDED_LONG_EDGE, or - * SidesType.TWO_SIDED_SHORT_EDGE + * @param printer the possibly {@code null} printer name + * @param sides {@code SidesType.ONE_SIDED}, + * {@code SidesType.TWO_SIDED_LONG_EDGE}, or + * {@code SidesType.TWO_SIDED_SHORT_EDGE} * @throws IllegalArgumentException if one or more of the above * conditions is violated */ @@ -351,10 +351,10 @@ public final class JobAttributes implements Cloneable { } /** - * Creates and returns a copy of this JobAttributes. + * Creates and returns a copy of this {@code JobAttributes}. * * @return the newly created copy; it is safe to cast this Object into - * a JobAttributes + * a {@code JobAttributes} */ public Object clone() { try { @@ -366,10 +366,10 @@ public final class JobAttributes implements Cloneable { } /** - * Sets all of the attributes of this JobAttributes to + * Sets all of the attributes of this {@code JobAttributes} to * the same values as the attributes of obj. * - * @param obj the JobAttributes to copy + * @param obj the {@code JobAttributes} to copy */ public void set(JobAttributes obj) { copies = obj.copies; @@ -404,10 +404,10 @@ public final class JobAttributes implements Cloneable { /** * Specifies the number of copies the application should render for jobs * using these attributes. Not specifying this attribute is equivalent to - * specifying 1. + * specifying {@code 1}. * * @param copies an integer greater than 0 - * @throws IllegalArgumentException if copies is less than + * @throws IllegalArgumentException if {@code copies} is less than * or equal to 0 */ public void setCopies(int copies) { @@ -429,7 +429,7 @@ public final class JobAttributes implements Cloneable { /** * Specifies whether, for jobs using these attributes, the application * should print all pages, the range specified by the return value of - * getPageRanges, or the current selection. This attribute + * {@code getPageRanges}, or the current selection. This attribute * is updated to the value chosen by the user. * * @return DefaultSelectionType.ALL, DefaultSelectionType.RANGE, or @@ -442,12 +442,12 @@ public final class JobAttributes implements Cloneable { /** * Specifies whether, for jobs using these attributes, the application * should print all pages, the range specified by the return value of - * getPageRanges, or the current selection. Not specifying + * {@code getPageRanges}, or the current selection. Not specifying * this attribute is equivalent to specifying DefaultSelectionType.ALL. * * @param defaultSelection DefaultSelectionType.ALL, * DefaultSelectionType.RANGE, or DefaultSelectionType.SELECTION. - * @throws IllegalArgumentException if defaultSelection is null + * @throws IllegalArgumentException if defaultSelection is {@code null} */ public void setDefaultSelection(DefaultSelectionType defaultSelection) { if (defaultSelection == null) { @@ -495,8 +495,8 @@ public final class JobAttributes implements Cloneable { * This attribute cannot be modified by, and is not subject to any * limitations of, the implementation or the target printer. * - * @return DialogType.COMMON, DialogType.NATIVE, or - * DialogType.NONE + * @return {@code DialogType.COMMON}, {@code DialogType.NATIVE}, or + * {@code DialogType.NONE} */ public DialogType getDialog() { return dialog; @@ -529,7 +529,7 @@ public final class JobAttributes implements Cloneable { * Specifies the file name for the output file for jobs using these * attributes. This attribute is updated to the value chosen by the user. * - * @return the possibly null file name + * @return the possibly {@code null} file name */ public String getFileName() { return fileName; @@ -549,9 +549,9 @@ public final class JobAttributes implements Cloneable { * Returns, for jobs using these attributes, the first page to be * printed, if a range of pages is to be printed. This attribute is * updated to the value chosen by the user. An application should ignore - * this attribute on output, unless the return value of the - * getDefaultSelection method is DefaultSelectionType.RANGE. An - * application should honor the return value of getPageRanges + * this attribute on output, unless the return value of the + * {@code getDefaultSelection} method is DefaultSelectionType.RANGE. An + * application should honor the return value of {@code getPageRanges} * over the return value of this method, if possible. * * @return an integer greater than zero and less than or equal to @@ -612,7 +612,7 @@ public final class JobAttributes implements Cloneable { /** * Specifies the maximum value the user can specify as the last page to * be printed for jobs using these attributes. Not specifying this - * attribute is equivalent to specifying Integer.MAX_VALUE. + * attribute is equivalent to specifying {@code Integer.MAX_VALUE}. * * @param maxPage an integer greater than zero and greater than or equal * to minPage @@ -643,7 +643,7 @@ public final class JobAttributes implements Cloneable { /** * Specifies the minimum value the user can specify as the first page to * be printed for jobs using these attributes. Not specifying this - * attribute is equivalent to specifying 1. + * attribute is equivalent to specifying {@code 1}. * * @param minPage an integer greater than zero and less than or equal * to maxPage. @@ -706,7 +706,7 @@ public final class JobAttributes implements Cloneable { * printed, if a range of pages is to be printed. All range numbers are * inclusive. This attribute is updated to the value chosen by the user. * An application should ignore this attribute on output, unless the - * return value of the getDefaultSelection method is + * return value of the {@code getDefaultSelection} method is * DefaultSelectionType.RANGE. * * @return an array of integer arrays of 2 elements. An array @@ -888,9 +888,9 @@ public final class JobAttributes implements Cloneable { * Returns, for jobs using these attributes, the last page (inclusive) * to be printed, if a range of pages is to be printed. This attribute is * updated to the value chosen by the user. An application should ignore - * this attribute on output, unless the return value of the - * getDefaultSelection method is DefaultSelectionType.RANGE. An - * application should honor the return value of getPageRanges + * this attribute on output, unless the return value of the + * {@code getDefaultSelection} method is DefaultSelectionType.RANGE. An + * application should honor the return value of {@code getPageRanges} * over the return value of this method, if possible. * * @return an integer greater than zero and greater than or equal diff --git a/jdk/src/java.desktop/share/classes/java/awt/KeyEventDispatcher.java b/jdk/src/java.desktop/share/classes/java/awt/KeyEventDispatcher.java index 9970ac586e3..36ef562f3de 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/KeyEventDispatcher.java +++ b/jdk/src/java.desktop/share/classes/java/awt/KeyEventDispatcher.java @@ -62,28 +62,28 @@ public interface KeyEventDispatcher { * used to deliver KeyEvents to Components other than the focus owner. This * can be useful when navigating children of non-focusable Windows in an * accessible environment, for example. Note that if a KeyEventDispatcher - * dispatches the KeyEvent itself, it must use redispatchEvent + * dispatches the KeyEvent itself, it must use {@code redispatchEvent} * to prevent the current KeyboardFocusManager from recursively requesting * that this KeyEventDispatcher dispatch the event again. *

      - * If an implementation of this method returns false, then + * If an implementation of this method returns {@code false}, then * the KeyEvent is passed to the next KeyEventDispatcher in the chain, * ending with the current KeyboardFocusManager. If an implementation - * returns true, the KeyEvent is assumed to have been + * returns {@code true}, the KeyEvent is assumed to have been * dispatched (although this need not be the case), and the current * KeyboardFocusManager will take no further action with regard to the * KeyEvent. In such a case, - * KeyboardFocusManager.dispatchEvent should return - * true as well. If an implementation consumes the KeyEvent, - * but returns false, the consumed event will still be passed + * {@code KeyboardFocusManager.dispatchEvent} should return + * {@code true} as well. If an implementation consumes the KeyEvent, + * but returns {@code false}, the consumed event will still be passed * to the next KeyEventDispatcher in the chain. It is important for * developers to check whether the KeyEvent has been consumed before * dispatching it to a target. By default, the current KeyboardFocusManager * will not dispatch a consumed KeyEvent. * * @param e the KeyEvent to dispatch - * @return true if the KeyboardFocusManager should take no - * further action with regard to the KeyEvent; false + * @return {@code true} if the KeyboardFocusManager should take no + * further action with regard to the KeyEvent; {@code false} * otherwise * @see KeyboardFocusManager#redispatchEvent */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/KeyEventPostProcessor.java b/jdk/src/java.desktop/share/classes/java/awt/KeyEventPostProcessor.java index 5a36b9536b1..15f6cb9dddc 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/KeyEventPostProcessor.java +++ b/jdk/src/java.desktop/share/classes/java/awt/KeyEventPostProcessor.java @@ -68,17 +68,17 @@ public interface KeyEventPostProcessor { * will be used to implement features which require global KeyEvent * post-handling, such as menu shortcuts. Note that if a * KeyEventPostProcessor wishes to dispatch the KeyEvent, it must use - * redispatchEvent to prevent the AWT from recursively + * {@code redispatchEvent} to prevent the AWT from recursively * requesting that this KeyEventPostProcessor perform post-processing * of the event again. *

      - * If an implementation of this method returns false, then the + * If an implementation of this method returns {@code false}, then the * KeyEvent is passed to the next KeyEventPostProcessor in the chain, * ending with the current KeyboardFocusManager. If an implementation - * returns true, the KeyEvent is assumed to have been fully + * returns {@code true}, the KeyEvent is assumed to have been fully * handled (although this need not be the case), and the AWT will take no * further action with regard to the KeyEvent. If an implementation - * consumes the KeyEvent but returns false, the consumed + * consumes the KeyEvent but returns {@code false}, the consumed * event will still be passed to the next KeyEventPostProcessor in the * chain. It is important for developers to check whether the KeyEvent has * been consumed before performing any post-processing of the KeyEvent. By @@ -86,8 +86,8 @@ public interface KeyEventPostProcessor { * processing in response to a consumed KeyEvent. * * @param e the KeyEvent to post-process - * @return true if the AWT should take no further action with - * regard to the KeyEvent; false otherwise + * @return {@code true} if the AWT should take no further action with + * regard to the KeyEvent; {@code false} otherwise * @see KeyboardFocusManager#redispatchEvent */ boolean postProcessKeyEvent(KeyEvent e); diff --git a/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java b/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java index d4d4a92e88c..6b7d779a7db 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java +++ b/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java @@ -356,7 +356,7 @@ public abstract class KeyboardFocusManager /** * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not * include this KeyboardFocusManager unless it was explicitly re-registered - * via a call to addKeyEventDispatcher. If no other + * via a call to {@code addKeyEventDispatcher}. If no other * KeyEventDispatchers are registered, this field may be null or refer to * a List of length 0. */ @@ -365,7 +365,7 @@ public abstract class KeyboardFocusManager /** * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does * not include this KeyboardFocusManager unless it was explicitly - * re-registered via a call to addKeyEventPostProcessor. + * re-registered via a call to {@code addKeyEventPostProcessor}. * If no other KeyEventPostProcessors are registered, this field may be * null or refer to a List of length 0. */ @@ -518,8 +518,8 @@ public abstract class KeyboardFocusManager *

      * This method does not actually set the focus to the specified Component. * It merely stores the value to be subsequently returned by - * getFocusOwner(). Use Component.requestFocus() - * or Component.requestFocusInWindow() to change the focus + * {@code getFocusOwner()}. Use {@code Component.requestFocus()} + * or {@code Component.requestFocusInWindow()} to change the focus * owner, subject to platform limitations. * * @param focusOwner the focus owner @@ -607,7 +607,7 @@ public abstract class KeyboardFocusManager * FOCUS_LOST event. After this operation completes, the native windowing * system will discard all user-generated KeyEvents until the user selects * a new Component to receive focus, or a Component is given focus - * explicitly via a call to requestFocus(). This operation + * explicitly via a call to {@code requestFocus()}. This operation * does not change the focused or active Windows. *

      * If a SecurityManager is installed, the calling thread must be granted @@ -731,9 +731,9 @@ public abstract class KeyboardFocusManager *

      * This method does not actually set the focus to the specified Component. * It merely stores the value to be subsequently returned by - * getPermanentFocusOwner(). Use - * Component.requestFocus() or - * Component.requestFocusInWindow() to change the focus owner, + * {@code getPermanentFocusOwner()}. Use + * {@code Component.requestFocus()} or + * {@code Component.requestFocusInWindow()} to change the focus owner, * subject to platform limitations. * * @param permanentFocusOwner the permanent focus owner @@ -832,9 +832,9 @@ public abstract class KeyboardFocusManager *

      * This method does not actually change the focused Window as far as the * native windowing system is concerned. It merely stores the value to be - * subsequently returned by getFocusedWindow(). Use - * Component.requestFocus() or - * Component.requestFocusInWindow() to change the focused + * subsequently returned by {@code getFocusedWindow()}. Use + * {@code Component.requestFocus()} or + * {@code Component.requestFocusInWindow()} to change the focused * Window, subject to platform limitations. * * @param focusedWindow the focused Window @@ -936,9 +936,9 @@ public abstract class KeyboardFocusManager *

      * This method does not actually change the active Window as far as the * native windowing system is concerned. It merely stores the value to be - * subsequently returned by getActiveWindow(). Use - * Component.requestFocus() or - * Component.requestFocusInWindow()to change the active + * subsequently returned by {@code getActiveWindow()}. Use + * {@code Component.requestFocus()} or + * {@code Component.requestFocusInWindow()} to change the active * Window, subject to platform limitations. * * @param activeWindow the active Window @@ -1160,16 +1160,16 @@ public abstract class KeyboardFocusManager * have no such Set of their own explicitly defined. This Set will also be * inherited, recursively, by any child Component of those Windows that has * no such Set of its own explicitly defined. (See - * setDefaultFocusTraversalKeys for a full description of each + * {@code setDefaultFocusTraversalKeys} for a full description of each * operation.) * * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS - * @return the Set of AWTKeyStrokes - * for the specified operation; the Set - * will be unmodifiable, and may be empty; null + * @return the {@code Set} of {@code AWTKeyStroke}s + * for the specified operation; the {@code Set} + * will be unmodifiable, and may be empty; {@code null} * will never be returned * @see #setDefaultFocusTraversalKeys * @see Component#setFocusTraversalKeys @@ -1359,7 +1359,7 @@ public abstract class KeyboardFocusManager * registered on this keyboard focus manager. * * @return all of this keyboard focus manager's - * PropertyChangeListeners + * {@code PropertyChangeListener}s * or an empty array if no property change * listeners are currently registered * @@ -1446,11 +1446,11 @@ public abstract class KeyboardFocusManager } /** - * Returns an array of all the PropertyChangeListeners + * Returns an array of all the {@code PropertyChangeListener}s * associated with the named property. * * @param propertyName the property name - * @return all of the PropertyChangeListeners associated with + * @return all of the {@code PropertyChangeListener}s associated with * the named property or an empty array if no such listeners have * been added. * @@ -1542,7 +1542,7 @@ public abstract class KeyboardFocusManager * registered on this keyboard focus manager. * * @return all of this keyboard focus manager's - * VetoableChangeListeners + * {@code VetoableChangeListener}s * or an empty array if no vetoable change * listeners are currently registered * @@ -1616,11 +1616,11 @@ public abstract class KeyboardFocusManager } /** - * Returns an array of all the VetoableChangeListeners + * Returns an array of all the {@code VetoableChangeListener}s * associated with the named property. * * @param propertyName the property name - * @return all of the VetoableChangeListeners associated with + * @return all of the {@code VetoableChangeListener}s associated with * the named property or an empty array if no such listeners have * been added. * @@ -1649,8 +1649,8 @@ public abstract class KeyboardFocusManager * @param oldValue the property's previous value * @param newValue the property's new value * @throws java.beans.PropertyVetoException if a - * VetoableChangeListener threw - * PropertyVetoException + * {@code VetoableChangeListener} threw + * {@code PropertyVetoException} */ protected void fireVetoableChange(String propertyName, Object oldValue, Object newValue) @@ -1673,8 +1673,8 @@ public abstract class KeyboardFocusManager * KeyEventDispatcher dispatch KeyEvents generated by the user before * finally dispatching the KeyEvent itself. KeyEventDispatchers will be * notified in the order in which they were added. Notifications will halt - * as soon as one KeyEventDispatcher returns true from its - * dispatchKeyEvent method. There is no limit to the total + * as soon as one KeyEventDispatcher returns {@code true} from its + * {@code dispatchKeyEvent} method. There is no limit to the total * number of KeyEventDispatchers which can be added, nor to the number of * times which a particular KeyEventDispatcher instance can be added. *

      @@ -1704,7 +1704,7 @@ public abstract class KeyboardFocusManager * Removes a KeyEventDispatcher which was previously added to this * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager * cannot itself be removed, unless it was explicitly re-registered via a - * call to addKeyEventDispatcher. + * call to {@code addKeyEventDispatcher}. *

      * If a null dispatcher is specified, if the specified dispatcher is not * in the dispatcher chain, or if this KeyboardFocusManager is specified @@ -1734,7 +1734,7 @@ public abstract class KeyboardFocusManager * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List. * The List will not include this KeyboardFocusManager unless it was * explicitly re-registered via a call to - * addKeyEventDispatcher. If no other KeyEventDispatchers are + * {@code addKeyEventDispatcher}. If no other KeyEventDispatchers are * registered, implementations are free to return null or a List of length * 0. Client code should not assume one behavior over another, nor should * it assume that the behavior, once established, will not change. @@ -1760,8 +1760,8 @@ public abstract class KeyboardFocusManager * of the KeyEvent's final resolution. KeyEventPostProcessors * will be notified in the order in which they were added; the current * KeyboardFocusManager will be notified last. Notifications will halt - * as soon as one KeyEventPostProcessor returns true from its - * postProcessKeyEvent method. There is no limit to the + * as soon as one KeyEventPostProcessor returns {@code true} from its + * {@code postProcessKeyEvent} method. There is no limit to the * total number of KeyEventPostProcessors that can be added, nor to the * number of times that a particular KeyEventPostProcessor instance can be * added. @@ -1794,7 +1794,7 @@ public abstract class KeyboardFocusManager * Removes a previously added KeyEventPostProcessor from this * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager * cannot itself be entirely removed from the chain. Only additional - * references added via addKeyEventPostProcessor can be + * references added via {@code addKeyEventPostProcessor} can be * removed. *

      * If a null post-processor is specified, if the specified post-processor @@ -1825,7 +1825,7 @@ public abstract class KeyboardFocusManager /** * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a * List. The List will not include this KeyboardFocusManager unless it was - * explicitly added via a call to addKeyEventPostProcessor. If + * explicitly added via a call to {@code addKeyEventPostProcessor}. If * no KeyEventPostProcessors are registered, implementations are free to * return null or a List of length 0. Client code should not assume one * behavior over another, nor should it assume that the behavior, once @@ -1914,14 +1914,14 @@ public abstract class KeyboardFocusManager * These events should be dispatched based on the KeyboardFocusManager's * notion of the focus owner and the focused and active Windows, sometimes * overriding the source of the specified AWTEvent. Dispatching must be - * done using redispatchEvent to prevent the AWT event + * done using {@code redispatchEvent} to prevent the AWT event * dispatcher from recursively requesting that the KeyboardFocusManager - * dispatch the event again. If this method returns false, + * dispatch the event again. If this method returns {@code false}, * then the AWT event dispatcher will attempt to dispatch the event itself. * * @param e the AWTEvent to be dispatched - * @return true if this method dispatched the event; - * false otherwise + * @return {@code true} if this method dispatched the event; + * {@code false} otherwise * @see #redispatchEvent * @see #dispatchKeyEvent */ @@ -1931,9 +1931,9 @@ public abstract class KeyboardFocusManager * Redispatches an AWTEvent in such a way that the AWT event dispatcher * will not recursively request that the KeyboardFocusManager, or any * installed KeyEventDispatchers, dispatch the event again. Client - * implementations of dispatchEvent and client-defined - * KeyEventDispatchers must call redispatchEvent(target, e) - * instead of target.dispatchEvent(e) to dispatch an event. + * implementations of {@code dispatchEvent} and client-defined + * KeyEventDispatchers must call {@code redispatchEvent(target, e)} + * instead of {@code target.dispatchEvent(e)} to dispatch an event. *

      * This method is intended to be used only by KeyboardFocusManagers and * KeyEventDispatchers. It is not for general client use. @@ -1950,30 +1950,30 @@ public abstract class KeyboardFocusManager } /** - * Typically this method will be called by dispatchEvent if no + * Typically this method will be called by {@code dispatchEvent} if no * other KeyEventDispatcher in the dispatcher chain dispatched the * KeyEvent, or if no other KeyEventDispatchers are registered. If an - * implementation of this method returns false, - * dispatchEvent may try to dispatch the KeyEvent itself, or - * may simply return false. If true is returned, - * dispatchEvent should return true as well. + * implementation of this method returns {@code false}, + * {@code dispatchEvent} may try to dispatch the KeyEvent itself, or + * may simply return {@code false}. If {@code true} is returned, + * {@code dispatchEvent} should return {@code true} as well. * * @param e the KeyEvent which the current KeyboardFocusManager has * requested that this KeyEventDispatcher dispatch - * @return true if the KeyEvent was dispatched; - * false otherwise + * @return {@code true} if the KeyEvent was dispatched; + * {@code false} otherwise * @see #dispatchEvent */ public abstract boolean dispatchKeyEvent(KeyEvent e); /** - * This method will be called by dispatchKeyEvent. + * This method will be called by {@code dispatchKeyEvent}. * By default, this method will handle any unconsumed KeyEvents that - * map to an AWT MenuShortcut by consuming the event + * map to an AWT {@code MenuShortcut} by consuming the event * and activating the shortcut. * * @param e the KeyEvent to post-process - * @return true to indicate that no other + * @return {@code true} to indicate that no other * KeyEventPostProcessor will be notified of the KeyEvent. * @see #dispatchKeyEvent * @see MenuShortcut @@ -2005,8 +2005,8 @@ public abstract class KeyboardFocusManager * the KeyboardFocusManager to delay dispatching of KeyEvents with * timestamps later than the specified time stamp until the specified * Component receives a FOCUS_GAINED event, or the AWT cancels the delay - * request by invoking dequeueKeyEvents or - * discardKeyEvents. + * request by invoking {@code dequeueKeyEvents} or + * {@code discardKeyEvents}. * * @param after timestamp of current event, or the current, system time if * the current event has no timestamp, or the AWT cannot determine @@ -2022,16 +2022,16 @@ public abstract class KeyboardFocusManager /** * Called by the AWT to notify the KeyboardFocusManager that it should * cancel delayed dispatching of KeyEvents. All KeyEvents which were - * enqueued because of a call to enqueueKeyEvents with the + * enqueued because of a call to {@code enqueueKeyEvents} with the * same timestamp and Component should be released for normal dispatching * to the current focus owner. If the given timestamp is less than zero, * the outstanding enqueue request for the given Component with the * oldest timestamp (if any) should be cancelled. * * @param after the timestamp specified in the call to - * enqueueKeyEvents, or any value < 0 + * {@code enqueueKeyEvents}, or any value < 0 * @param untilFocused the Component specified in the call to - * enqueueKeyEvents + * {@code enqueueKeyEvents} * @see #enqueueKeyEvents * @see #discardKeyEvents */ @@ -2041,11 +2041,11 @@ public abstract class KeyboardFocusManager /** * Called by the AWT to notify the KeyboardFocusManager that it should * cancel delayed dispatching of KeyEvents. All KeyEvents which were - * enqueued because of one or more calls to enqueueKeyEvents + * enqueued because of one or more calls to {@code enqueueKeyEvents} * with the same Component should be discarded. * * @param comp the Component specified in one or more calls to - * enqueueKeyEvents + * {@code enqueueKeyEvents} * @see #enqueueKeyEvents * @see #dequeueKeyEvents */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Label.java b/jdk/src/java.desktop/share/classes/java/awt/Label.java index d0999399e84..32744ee2a60 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Label.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Label.java @@ -30,7 +30,7 @@ import java.io.ObjectInputStream; import javax.accessibility.*; /** - * A Label object is a component for placing text in a + * A {@code Label} object is a component for placing text in a * container. A label displays a single line of read-only text. * The text can be changed by the application, but a user cannot edit it * directly. @@ -107,7 +107,7 @@ public class Label extends Component implements Accessible { /** * Constructs an empty label. - * The text of the label is the empty string "". + * The text of the label is the empty string {@code ""}. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless @@ -120,7 +120,7 @@ public class Label extends Component implements Accessible { * Constructs a new label with the specified string of text, * left justified. * @param text the string that the label presents. - * A null value + * A {@code null} value * will be accepted without causing a NullPointerException * to be thrown. * @exception HeadlessException if GraphicsEnvironment.isHeadless() @@ -134,10 +134,10 @@ public class Label extends Component implements Accessible { /** * Constructs a new label that presents the specified string of * text with the specified alignment. - * Possible values for alignment are Label.LEFT, - * Label.RIGHT, and Label.CENTER. + * Possible values for {@code alignment} are {@code Label.LEFT}, + * {@code Label.RIGHT}, and {@code Label.CENTER}. * @param text the string that the label presents. - * A null value + * A {@code null} value * will be accepted without causing a NullPointerException * to be thrown. * @param alignment the alignment value. @@ -154,8 +154,8 @@ public class Label extends Component implements Accessible { /** * Read a label from an object input stream. * @exception HeadlessException if - * GraphicsEnvironment.isHeadless() returns - * true + * {@code GraphicsEnvironment.isHeadless()} returns + * {@code true} * @serial * @since 1.4 * @see java.awt.GraphicsEnvironment#isHeadless @@ -168,7 +168,7 @@ public class Label extends Component implements Accessible { /** * Construct a name for this component. Called by getName() when the - * name is null. + * name is {@code null}. */ String constructComponentName() { synchronized (Label.class) { @@ -191,8 +191,8 @@ public class Label extends Component implements Accessible { /** * Gets the current alignment of this label. Possible values are - * Label.LEFT, Label.RIGHT, and - * Label.CENTER. + * {@code Label.LEFT}, {@code Label.RIGHT}, and + * {@code Label.CENTER}. * @return the alignment of this label * @see java.awt.Label#setAlignment */ @@ -202,11 +202,11 @@ public class Label extends Component implements Accessible { /** * Sets the alignment for this label to the specified alignment. - * Possible values are Label.LEFT, - * Label.RIGHT, and Label.CENTER. + * Possible values are {@code Label.LEFT}, + * {@code Label.RIGHT}, and {@code Label.CENTER}. * @param alignment the alignment to be set. * @exception IllegalArgumentException if an improper value for - * alignment is given. + * {@code alignment} is given. * @see java.awt.Label#getAlignment */ public synchronized void setAlignment(int alignment) { @@ -226,8 +226,8 @@ public class Label extends Component implements Accessible { /** * Gets the text of this label. - * @return the text of this label, or null if - * the text has been set to null. + * @return the text of this label, or {@code null} if + * the text has been set to {@code null}. * @see java.awt.Label#setText */ public String getText() { @@ -237,9 +237,9 @@ public class Label extends Component implements Accessible { /** * Sets the text for this label to the specified text. * @param text the text that this label displays. If - * text is null, it is + * {@code text} is {@code null}, it is * treated for display purposes like an empty - * string "". + * string {@code ""}. * @see java.awt.Label#getText */ public void setText(String text) { @@ -263,11 +263,11 @@ public class Label extends Component implements Accessible { } /** - * Returns a string representing the state of this Label. + * Returns a string representing the state of this {@code Label}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this label */ @@ -311,7 +311,7 @@ public class Label extends Component implements Accessible { /** * This class implements accessibility support for the - * Label class. It provides an implementation of the + * {@code Label} class. It provides an implementation of the * Java Accessibility API appropriate to label user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/LayoutManager.java b/jdk/src/java.desktop/share/classes/java/awt/LayoutManager.java index d7abfbb1c29..b573ed0b83a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/LayoutManager.java +++ b/jdk/src/java.desktop/share/classes/java/awt/LayoutManager.java @@ -26,13 +26,13 @@ package java.awt; /** * Defines the interface for classes that know how to lay out - * Containers. + * {@code Container}s. *

      * Swing's painting architecture assumes the children of a - * JComponent do not overlap. If a - * JComponent's LayoutManager allows - * children to overlap, the JComponent must override - * isOptimizedDrawingEnabled to return false. + * {@code JComponent} do not overlap. If a + * {@code JComponent}'s {@code LayoutManager} allows + * children to overlap, the {@code JComponent} must override + * {@code isOptimizedDrawingEnabled} to return false. * * @see Container * @see javax.swing.JComponent#isOptimizedDrawingEnabled @@ -43,9 +43,9 @@ package java.awt; public interface LayoutManager { /** * If the layout manager uses a per-component string, - * adds the component comp to the layout, + * adds the component {@code comp} to the layout, * associating it - * with the string specified by name. + * with the string specified by {@code name}. * * @param name the string to be associated with the component * @param comp the component to be added diff --git a/jdk/src/java.desktop/share/classes/java/awt/LinearGradientPaintContext.java b/jdk/src/java.desktop/share/classes/java/awt/LinearGradientPaintContext.java index 635a3cbe45d..16d58af3e55 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/LinearGradientPaintContext.java +++ b/jdk/src/java.desktop/share/classes/java/awt/LinearGradientPaintContext.java @@ -56,7 +56,7 @@ final class LinearGradientPaintContext extends MultipleGradientPaintContext { * @param paint the {@code LinearGradientPaint} from which this context * is created * @param cm {@code ColorModel} that receives - * the Paint data. This is used only as a hint. + * the {@code Paint} data. This is used only as a hint. * @param deviceBounds the device space bounding box of the * graphics primitive being rendered * @param userBounds the user space bounding box of the diff --git a/jdk/src/java.desktop/share/classes/java/awt/List.java b/jdk/src/java.desktop/share/classes/java/awt/List.java index 4112f87fbe2..c0c22d206e8 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/List.java +++ b/jdk/src/java.desktop/share/classes/java/awt/List.java @@ -36,7 +36,7 @@ import javax.accessibility.*; /** - * The List component presents the user with a + * The {@code List} component presents the user with a * scrolling list of text items. The list can be set up so that * the user can choose either one item or multiple items. *

      @@ -57,7 +57,7 @@ import javax.accessibility.*; * cnt.add(lst); *


      *

      - * where cnt is a container, produces the following + * where {@code cnt} is a container, produces the following * scrolling list: *

      * false. If the List does not allow multiple + * list is {@code false}. If the List does not allow multiple * selections, selecting an item causes any other selected item * to be deselected. *

      * Note that the list in the example shown was created with four visible * rows. Once the list has been created, the number of visible rows - * cannot be changed. A default List is created with - * four rows, so that lst = new List() is equivalent to - * list = new List(4, false). + * cannot be changed. A default {@code List} is created with + * four rows, so that {@code lst = new List()} is equivalent to + * {@code list = new List(4, false)}. *

      * Beginning with Java 1.1, the Abstract Window Toolkit - * sends the List object all mouse, keyboard, and focus events + * sends the {@code List} object all mouse, keyboard, and focus events * that occur over it. (The old AWT event model is being maintained * only for backwards compatibility, and its use is discouraged.) *

      * When an item is selected or deselected by the user, AWT sends an instance - * of ItemEvent to the list. + * of {@code ItemEvent} to the list. * When the user double-clicks on an item in a scrolling list, - * AWT sends an instance of ActionEvent to the + * AWT sends an instance of {@code ActionEvent} to the * list following the item event. AWT also generates an action event * when the user presses the return key while an item in the * list is selected. *

      * If an application wants to perform some action based on an item * in this list being selected or activated by the user, it should implement - * ItemListener or ActionListener + * {@code ItemListener} or {@code ActionListener} * as appropriate and register the new listener to receive * events from this list. *

      @@ -119,7 +119,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * This field will represent the number of visible rows in the - * List Component. It is specified only once, and + * {@code List} Component. It is specified only once, and * that is when the list component is actually * created. It will never change. * @@ -129,11 +129,11 @@ public class List extends Component implements ItemSelectable, Accessible { int rows = 0; /** - * multipleMode is a variable that will - * be set to true if a list component is to be set to + * {@code multipleMode} is a variable that will + * be set to {@code true} if a list component is to be set to * multiple selection mode, that is where the user can * select more than one item in a list at one time. - * multipleMode will be set to false if the + * {@code multipleMode} will be set to false if the * list component is set to single selection, that is where * the user can only select one item on the list at any * one time. @@ -145,7 +145,7 @@ public class List extends Component implements ItemSelectable, Accessible { boolean multipleMode = false; /** - * selected is an array that will contain + * {@code selected} is an array that will contain * the indices of items that have been selected. * * @serial @@ -178,7 +178,7 @@ public class List extends Component implements ItemSelectable, Accessible { * Creates a new scrolling list. * By default, there are four visible lines and multiple selections are * not allowed. Note that this is a convenience method for - * List(0, false). Also note that the number of visible + * {@code List(0, false)}. Also note that the number of visible * lines in the list cannot be changed after it has been created. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. @@ -192,7 +192,7 @@ public class List extends Component implements ItemSelectable, Accessible { * Creates a new scrolling list initialized with the specified * number of visible lines. By default, multiple selections are * not allowed. Note that this is a convenience method for - * List(rows, false). Also note that the number + * {@code List(rows, false)}. Also note that the number * of visible rows in the list cannot be changed after it has * been created. * @param rows the number of items to show. @@ -217,12 +217,12 @@ public class List extends Component implements ItemSelectable, Accessible { * the list will be created with a default of four rows. * Also note that the number of visible rows in the list cannot * be changed after it has been created. - * If the value of multipleMode is - * true, then the user can select multiple items from - * the list. If it is false, only one item at a time + * If the value of {@code multipleMode} is + * {@code true}, then the user can select multiple items from + * the list. If it is {@code false}, only one item at a time * can be selected. * @param rows the number of items to show. - * @param multipleMode if true, + * @param multipleMode if {@code true}, * then multiple selections are allowed; * otherwise, only one item can be selected at a time. * @exception HeadlessException if GraphicsEnvironment.isHeadless() @@ -237,7 +237,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Construct a name for this component. Called by - * getName when the name is null. + * {@code getName} when the name is {@code null}. */ String constructComponentName() { synchronized (List.class) { @@ -286,7 +286,7 @@ public class List extends Component implements ItemSelectable, Accessible { * * @return the number of items in the list * @deprecated As of JDK version 1.1, - * replaced by getItemCount(). + * replaced by {@code getItemCount()}. */ @Deprecated public int countItems() { @@ -339,7 +339,7 @@ public class List extends Component implements ItemSelectable, Accessible { * Adds the specified item to the end of the list. * * @param item the item to be added - * @deprecated replaced by add(String). + * @deprecated replaced by {@code add(String)}. */ @Deprecated public void addItem(String item) { @@ -354,8 +354,8 @@ public class List extends Component implements ItemSelectable, Accessible { * the number of items in the list, then the item is added * to the end of the list. * @param item the item to be added; - * if this parameter is null then the item is - * treated as an empty string, "" + * if this parameter is {@code null} then the item is + * treated as an empty string, {@code ""} * @param index the position at which to add the item * @since 1.1 */ @@ -369,7 +369,7 @@ public class List extends Component implements ItemSelectable, Accessible { * * @param item the item to be added * @param index the position at which to add the item - * @deprecated replaced by add(String, int). + * @deprecated replaced by {@code add(String, int)}. */ @Deprecated public synchronized void addItem(String item, int index) { @@ -398,7 +398,7 @@ public class List extends Component implements ItemSelectable, Accessible { * with the new string. * @param newValue a new string to replace an existing item * @param index the position of the item to replace - * @exception ArrayIndexOutOfBoundsException if index + * @exception ArrayIndexOutOfBoundsException if {@code index} * is out of range */ public synchronized void replaceItem(String newValue, int index) { @@ -418,7 +418,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * @deprecated As of JDK version 1.1, - * replaced by removeAll(). + * replaced by {@code removeAll()}. */ @Deprecated public synchronized void clear() { @@ -458,8 +458,8 @@ public class List extends Component implements ItemSelectable, Accessible { * @see #add(String, int) * @since 1.1 * @exception ArrayIndexOutOfBoundsException - * if the position is less than 0 or - * greater than getItemCount()-1 + * if the {@code position} is less than 0 or + * greater than {@code getItemCount()-1} */ public void remove(int position) { delItem(position); @@ -469,8 +469,8 @@ public class List extends Component implements ItemSelectable, Accessible { * Removes the item at the specified position. * * @param position the index of the item to delete - * @deprecated replaced by remove(String) - * and remove(int). + * @deprecated replaced by {@code remove(String)} + * and {@code remove(int)}. */ @Deprecated public void delItem(int position) { @@ -482,7 +482,7 @@ public class List extends Component implements ItemSelectable, Accessible { * * @return the index of the selected item; * if no item is selected, or if multiple items are - * selected, -1 is returned. + * selected, {@code -1} is returned. * @see #select * @see #deselect * @see #isIndexSelected @@ -514,7 +514,7 @@ public class List extends Component implements ItemSelectable, Accessible { * * @return the selected item on the list; * if no item is selected, or if multiple items are - * selected, null is returned. + * selected, {@code null} is returned. * @see #select * @see #deselect * @see #isIndexSelected @@ -544,7 +544,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Gets the selected items on this scrolling list in an array of Objects. - * @return an array of Objects representing the + * @return an array of {@code Object}s representing the * selected items on this scrolling list; * if no item is selected, a zero-length array is returned. * @see #getSelectedItems @@ -563,8 +563,8 @@ public class List extends Component implements ItemSelectable, Accessible { *

      Note that this method should be primarily used to * initially select an item in this component. * Programmatically calling this method will not trigger - * an ItemEvent. The only way to trigger an - * ItemEvent is by user interaction. + * an {@code ItemEvent}. The only way to trigger an + * {@code ItemEvent} is by user interaction. * * @param index the position of the item to select * @see #getSelectedItem @@ -649,8 +649,8 @@ public class List extends Component implements ItemSelectable, Accessible { * Determines if the specified item in this scrolling list is * selected. * @param index the item to be checked - * @return true if the specified item has been - * selected; false otherwise + * @return {@code true} if the specified item has been + * selected; {@code false} otherwise * @see #select * @see #deselect * @since 1.1 @@ -665,7 +665,7 @@ public class List extends Component implements ItemSelectable, Accessible { * @param index specifies the item to be checked * @return {@code true} if the item is selected; otherwise {@code false} * @deprecated As of JDK version 1.1, - * replaced by isIndexSelected(int). + * replaced by {@code isIndexSelected(int)}. */ @Deprecated public boolean isSelected(int index) { @@ -680,7 +680,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Gets the number of visible lines in this list. Note that - * once the List has been created, this number + * once the {@code List} has been created, this number * will never change. * @return the number of visible lines in this scrolling list */ @@ -691,8 +691,8 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Determines whether this list allows multiple selections. * - * @return true if this list allows multiple - * selections; otherwise, false + * @return {@code true} if this list allows multiple + * selections; otherwise, {@code false} * @see #setMultipleMode * @since 1.1 */ @@ -706,7 +706,7 @@ public class List extends Component implements ItemSelectable, Accessible { * @return {@code true} if this list allows multiple * selections; otherwise {@code false} * @deprecated As of JDK version 1.1, - * replaced by isMultipleMode(). + * replaced by {@code isMultipleMode()}. */ @Deprecated public boolean allowsMultipleSelections() { @@ -721,7 +721,7 @@ public class List extends Component implements ItemSelectable, Accessible { * If a selected item has the location cursor, only that * item will remain selected. If no selected item has the * location cursor, all items will be deselected. - * @param b if true then multiple selections + * @param b if {@code true} then multiple selections * are allowed; otherwise, only one item from * the list can be selected at once * @see #isMultipleMode @@ -736,7 +736,7 @@ public class List extends Component implements ItemSelectable, Accessible { * * @param b {@code true} to enable multiple mode, {@code false} otherwise * @deprecated As of JDK version 1.1, - * replaced by setMultipleMode(boolean). + * replaced by {@code setMultipleMode(boolean)}. */ @Deprecated public synchronized void setMultipleSelections(boolean b) { @@ -751,7 +751,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Gets the index of the item that was last made visible by - * the method makeVisible. + * the method {@code makeVisible}. * @return the index of the item that was last made visible * @see #makeVisible */ @@ -792,7 +792,7 @@ public class List extends Component implements ItemSelectable, Accessible { * @param rows the number of rows * @return the preferred dimensions for displaying this list * @deprecated As of JDK version 1.1, - * replaced by getPreferredSize(int). + * replaced by {@code getPreferredSize(int)}. */ @Deprecated public Dimension preferredSize(int rows) { @@ -816,7 +816,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * @deprecated As of JDK version 1.1, - * replaced by getPreferredSize(). + * replaced by {@code getPreferredSize()}. */ @Deprecated public Dimension preferredSize() { @@ -847,7 +847,7 @@ public class List extends Component implements ItemSelectable, Accessible { * @param rows the number of rows in the list * @return the minimum dimensions for displaying this list * @deprecated As of JDK version 1.1, - * replaced by getMinimumSize(int). + * replaced by {@code getMinimumSize(int)}. */ @Deprecated public Dimension minimumSize(int rows) { @@ -872,7 +872,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * @deprecated As of JDK version 1.1, - * replaced by getMinimumSize(). + * replaced by {@code getMinimumSize()}. */ @Deprecated public Dimension minimumSize() { @@ -884,8 +884,8 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Adds the specified item listener to receive item events from * this list. Item events are sent in response to user input, but not - * in response to calls to select or deselect. - * If listener l is null, + * in response to calls to {@code select} or {@code deselect}. + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

      Refer to AWT Threading Issues for details on AWT's threading model. @@ -910,7 +910,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Removes the specified item listener so that it no longer * receives item events from this list. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

      Refer to AWT Threading Issues for details on AWT's threading model. @@ -933,7 +933,7 @@ public class List extends Component implements ItemSelectable, Accessible { * Returns an array of all the item listeners * registered on this list. * - * @return all of this list's ItemListeners + * @return all of this list's {@code ItemListener}s * or an empty array if no item * listeners are currently registered * @@ -953,7 +953,7 @@ public class List extends Component implements ItemSelectable, Accessible { * on a list item or types Enter when the list has the keyboard * focus. *

      - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

      Refer to AWT Threading Issues for details on AWT's threading model. @@ -977,7 +977,7 @@ public class List extends Component implements ItemSelectable, Accessible { * Removes the specified action listener so that it no longer * receives action events from this list. Action events * occur when a user double-clicks on a list item. - * If listener l is null, + * If listener {@code l} is {@code null}, * no exception is thrown and no action is performed. *

      Refer to AWT Threading Issues for details on AWT's threading model. @@ -1000,7 +1000,7 @@ public class List extends Component implements ItemSelectable, Accessible { * Returns an array of all the action listeners * registered on this list. * - * @return all of this list's ActionListeners + * @return all of this list's {@code ActionListener}s * or an empty array if no action * listeners are currently registered * @@ -1017,16 +1017,16 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Returns an array of all the objects currently registered * as FooListeners - * upon this List. + * upon this {@code List}. * FooListeners are registered using the * addFooListener method. * *

      - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * List l + * {@code List l} * for its item listeners with the following code: * *

      ItemListener[] ils = (ItemListener[])(l.getListeners(ItemListener.class));
      @@ -1035,14 +1035,14 @@ public class List extends Component implements ItemSelectable, Accessible { * * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this list, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @see #getItemListeners * @since 1.3 @@ -1082,13 +1082,13 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Processes events on this scrolling list. If an event is - * an instance of ItemEvent, it invokes the - * processItemEvent method. Else, if the - * event is an instance of ActionEvent, - * it invokes processActionEvent. + * an instance of {@code ItemEvent}, it invokes the + * {@code processItemEvent} method. Else, if the + * event is an instance of {@code ActionEvent}, + * it invokes {@code processActionEvent}. * If the event is not an item event or an action event, - * it invokes processEvent on the superclass. - *

      Note that if the event parameter is null + * it invokes {@code processEvent} on the superclass. + *

      Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -1113,17 +1113,17 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Processes item events occurring on this list by * dispatching them to any registered - * ItemListener objects. + * {@code ItemListener} objects. *

      * This method is not called unless item events are * enabled for this component. Item events are enabled * when one of the following occurs: *

        - *
      • An ItemListener object is registered - * via addItemListener. - *
      • Item events are enabled via enableEvents. + *
      • An {@code ItemListener} object is registered + * via {@code addItemListener}. + *
      • Item events are enabled via {@code enableEvents}. *
      - *

      Note that if the event parameter is null + *

      Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -1144,17 +1144,17 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Processes action events occurring on this component * by dispatching them to any registered - * ActionListener objects. + * {@code ActionListener} objects. *

      * This method is not called unless action events are * enabled for this component. Action events are enabled * when one of the following occurs: *

        - *
      • An ActionListener object is registered - * via addActionListener. - *
      • Action events are enabled via enableEvents. + *
      • An {@code ActionListener} object is registered + * via {@code addActionListener}. + *
      • Action events are enabled via {@code enableEvents}. *
      - *

      Note that if the event parameter is null + *

      Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -1209,7 +1209,7 @@ public class List extends Component implements ItemSelectable, Accessible { */ /** - * The List component's + * The {@code List} component's * Serialized Data Version. * * @serial @@ -1218,22 +1218,22 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Writes default serializable fields to stream. Writes - * a list of serializable ItemListeners - * and ActionListeners as optional data. + * a list of serializable {@code ItemListeners} + * and {@code ActionListeners} as optional data. * The non-serializable listeners are detected and * no attempt is made to serialize them. * - * @serialData null terminated sequence of 0 - * or more pairs; the pair consists of a String - * and an Object; the String + * @serialData {@code null} terminated sequence of 0 + * or more pairs; the pair consists of a {@code String} + * and an {@code Object}; the {@code String} * indicates the type of object and is one of the * following: - * itemListenerK indicating an - * ItemListener object; - * actionListenerK indicating an - * ActionListener object + * {@code itemListenerK} indicating an + * {@code ItemListener} object; + * {@code actionListenerK} indicating an + * {@code ActionListener} object * - * @param s the ObjectOutputStream to write + * @param s the {@code ObjectOutputStream} to write * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) * @see java.awt.Component#itemListenerK * @see java.awt.Component#actionListenerK @@ -1256,17 +1256,17 @@ public class List extends Component implements ItemSelectable, Accessible { } /** - * Reads the ObjectInputStream and if it - * isn't null adds a listener to receive + * Reads the {@code ObjectInputStream} and if it + * isn't {@code null} adds a listener to receive * both item events and action events (as specified * by the key stored in the stream) fired by the - * List. + * {@code List}. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to write + * @param s the {@code ObjectInputStream} to write * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns - * true + * {@code GraphicsEnvironment.isHeadless} returns + * {@code true} * @see #removeItemListener(ItemListener) * @see #addItemListener(ItemListener) * @see java.awt.GraphicsEnvironment#isHeadless @@ -1300,13 +1300,13 @@ public class List extends Component implements ItemSelectable, Accessible { /** - * Gets the AccessibleContext associated with this - * List. For lists, the AccessibleContext - * takes the form of an AccessibleAWTList. - * A new AccessibleAWTList instance is created, if necessary. + * Gets the {@code AccessibleContext} associated with this + * {@code List}. For lists, the {@code AccessibleContext} + * takes the form of an {@code AccessibleAWTList}. + * A new {@code AccessibleAWTList} instance is created, if necessary. * - * @return an AccessibleAWTList that serves as the - * AccessibleContext of this List + * @return an {@code AccessibleAWTList} that serves as the + * {@code AccessibleContext} of this {@code List} * @since 1.3 */ public AccessibleContext getAccessibleContext() { @@ -1318,7 +1318,7 @@ public class List extends Component implements ItemSelectable, Accessible { /** * This class implements accessibility support for the - * List class. It provides an implementation of the + * {@code List} class. It provides an implementation of the * Java Accessibility API appropriate to list user-interface elements. * @since 1.3 */ @@ -1930,13 +1930,13 @@ public class List extends Component implements ItemSelectable, Accessible { } /** - * Returns the Accessible child, if one exists, - * contained at the local coordinate Point. + * Returns the {@code Accessible} child, if one exists, + * contained at the local coordinate {@code Point}. * * @param p the point relative to the coordinate system of this * object - * @return the Accessible, if it exists, - * at the specified location; otherwise null + * @return the {@code Accessible}, if it exists, + * at the specified location; otherwise {@code null} */ public Accessible getAccessibleAt(Point p) { return null; // object cannot have children! @@ -1945,8 +1945,8 @@ public class List extends Component implements ItemSelectable, Accessible { /** * Returns whether this object can accept focus or not. Objects * that can accept focus will also have the - * AccessibleState.FOCUSABLE state set in their - * AccessibleStateSet. + * {@code AccessibleState.FOCUSABLE} state set in their + * {@code AccessibleStateSet}. * * @return true if object can accept focus; otherwise false * @see AccessibleContext#getAccessibleStateSet diff --git a/jdk/src/java.desktop/share/classes/java/awt/MediaTracker.java b/jdk/src/java.desktop/share/classes/java/awt/MediaTracker.java index dd8f9e0825f..8af10871768 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MediaTracker.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MediaTracker.java @@ -31,13 +31,13 @@ import java.awt.image.ImageObserver; import sun.awt.image.MultiResolutionToolkitImage; /** - * The MediaTracker class is a utility class to track + * The {@code MediaTracker} class is a utility class to track * the status of a number of media objects. Media objects could * include audio clips as well as images, though currently only * images are supported. *

      * To use a media tracker, create an instance of - * MediaTracker and call its addImage + * {@code MediaTracker} and call its {@code addImage} * method for each image to be tracked. In addition, each image can * be assigned a unique identifier. This identifier controls the * priority order in which the images are fetched. It can also be used @@ -52,20 +52,20 @@ import sun.awt.image.MultiResolutionToolkitImage; * due to the multi-part nature of animated image * loading and painting, * but it is supported. - * MediaTracker treats an animated image + * {@code MediaTracker} treats an animated image * as completely loaded * when the first frame is completely loaded. - * At that point, the MediaTracker + * At that point, the {@code MediaTracker} * signals any waiters * that the image is completely loaded. - * If no ImageObservers are observing the image + * If no {@code ImageObserver}s are observing the image * when the first frame has finished loading, * the image might flush itself * to conserve resources * (see {@link Image#flush()}). * *

      - * Here is an example of using MediaTracker: + * Here is an example of using {@code MediaTracker}: * *


      {@code
        * import java.applet.Applet;
      @@ -169,7 +169,7 @@ import sun.awt.image.MultiResolutionToolkitImage;
       public class MediaTracker implements java.io.Serializable {
       
           /**
      -     * A given Component that will be
      +     * A given {@code Component} that will be
            * tracked by a media tracker where the image will
            * eventually be drawn.
            *
      @@ -178,8 +178,8 @@ public class MediaTracker implements java.io.Serializable {
            */
           Component target;
           /**
      -     * The head of the list of Images that is being
      -     * tracked by the MediaTracker.
      +     * The head of the list of {@code Images} that is being
      +     * tracked by the {@code MediaTracker}.
            *
            * @serial
            * @see #addImage(Image, int)
      @@ -277,11 +277,11 @@ public class MediaTracker implements java.io.Serializable {
            * 

      * If there is an error while loading or scaling an image, then that * image is considered to have finished loading. Use the - * isErrorAny or isErrorID methods to + * {@code isErrorAny} or {@code isErrorID} methods to * check for errors. - * @return true if all images have finished loading, + * @return {@code true} if all images have finished loading, * have been aborted, or have encountered - * an error; false otherwise + * an error; {@code false} otherwise * @see java.awt.MediaTracker#checkAll(boolean) * @see java.awt.MediaTracker#checkID * @see java.awt.MediaTracker#isErrorAny @@ -295,19 +295,19 @@ public class MediaTracker implements java.io.Serializable { * Checks to see if all images being tracked by this media tracker * have finished loading. *

      - * If the value of the load flag is true, + * If the value of the {@code load} flag is {@code true}, * then this method starts loading any images that are not yet * being loaded. *

      * If there is an error while loading or scaling an image, that * image is considered to have finished loading. Use the - * isErrorAny and isErrorID methods to + * {@code isErrorAny} and {@code isErrorID} methods to * check for errors. - * @param load if true, start loading any + * @param load if {@code true}, start loading any * images that are not yet being loaded - * @return true if all images have finished loading, + * @return {@code true} if all images have finished loading, * have been aborted, or have encountered - * an error; false otherwise + * an error; {@code false} otherwise * @see java.awt.MediaTracker#checkID * @see java.awt.MediaTracker#checkAll() * @see java.awt.MediaTracker#isErrorAny() @@ -331,9 +331,9 @@ public class MediaTracker implements java.io.Serializable { /** * Checks the error status of all of the images. - * @return true if any of the images tracked + * @return {@code true} if any of the images tracked * by this media tracker had an error during - * loading; false otherwise + * loading; {@code false} otherwise * @see java.awt.MediaTracker#isErrorID * @see java.awt.MediaTracker#getErrorsAny */ @@ -352,7 +352,7 @@ public class MediaTracker implements java.io.Serializable { * Returns a list of all media that have encountered an error. * @return an array of media objects tracked by this * media tracker that have encountered - * an error, or null if + * an error, or {@code null} if * there are none with errors * @see java.awt.MediaTracker#isErrorAny * @see java.awt.MediaTracker#getErrorsID @@ -388,7 +388,7 @@ public class MediaTracker implements java.io.Serializable { *

      * If there is an error while loading or scaling an image, then that * image is considered to have finished loading. Use the - * isErrorAny or isErrorID methods to + * {@code isErrorAny} or {@code isErrorID} methods to * check for errors. * @see java.awt.MediaTracker#waitForID(int) * @see java.awt.MediaTracker#waitForAll(long) @@ -405,16 +405,16 @@ public class MediaTracker implements java.io.Serializable { * Starts loading all images tracked by this media tracker. This * method waits until all the images being tracked have finished * loading, or until the length of time specified in milliseconds - * by the ms argument has passed. + * by the {@code ms} argument has passed. *

      * If there is an error while loading or scaling an image, then * that image is considered to have finished loading. Use the - * isErrorAny or isErrorID methods to + * {@code isErrorAny} or {@code isErrorID} methods to * check for errors. * @param ms the number of milliseconds to wait * for the loading to complete - * @return true if all images were successfully - * loaded; false otherwise + * @return {@code true} if all images were successfully + * loaded; {@code false} otherwise * @see java.awt.MediaTracker#waitForID(int) * @see java.awt.MediaTracker#waitForAll(long) * @see java.awt.MediaTracker#isErrorAny @@ -451,15 +451,15 @@ public class MediaTracker implements java.io.Serializable { * status of all media that are tracked by this media tracker. *

      * Possible flags defined by the - * MediaTracker class are LOADING, - * ABORTED, ERRORED, and - * COMPLETE. An image that hasn't started + * {@code MediaTracker} class are {@code LOADING}, + * {@code ABORTED}, {@code ERRORED}, and + * {@code COMPLETE}. An image that hasn't started * loading has zero as its status. *

      - * If the value of load is true, then + * If the value of {@code load} is {@code true}, then * this method starts loading any images that are not yet being loaded. * - * @param load if true, start loading + * @param load if {@code true}, start loading * any images that are not yet being loaded * @return the bitwise inclusive OR of the status of * all of the media being tracked @@ -492,12 +492,12 @@ public class MediaTracker implements java.io.Serializable { *

      * If there is an error while loading or scaling an image, then that * image is considered to have finished loading. Use the - * isErrorAny or isErrorID methods to + * {@code isErrorAny} or {@code isErrorID} methods to * check for errors. * @param id the identifier of the images to check - * @return true if all images have finished loading, + * @return {@code true} if all images have finished loading, * have been aborted, or have encountered - * an error; false otherwise + * an error; {@code false} otherwise * @see java.awt.MediaTracker#checkID(int, boolean) * @see java.awt.MediaTracker#checkAll() * @see java.awt.MediaTracker#isErrorAny() @@ -511,20 +511,20 @@ public class MediaTracker implements java.io.Serializable { * Checks to see if all images tracked by this media tracker that * are tagged with the specified identifier have finished loading. *

      - * If the value of the load flag is true, + * If the value of the {@code load} flag is {@code true}, * then this method starts loading any images that are not yet * being loaded. *

      * If there is an error while loading or scaling an image, then that * image is considered to have finished loading. Use the - * isErrorAny or isErrorID methods to + * {@code isErrorAny} or {@code isErrorID} methods to * check for errors. * @param id the identifier of the images to check - * @param load if true, start loading any + * @param load if {@code true}, start loading any * images that are not yet being loaded - * @return true if all images have finished loading, + * @return {@code true} if all images have finished loading, * have been aborted, or have encountered - * an error; false otherwise + * an error; {@code false} otherwise * @see java.awt.MediaTracker#checkID(int, boolean) * @see java.awt.MediaTracker#checkAll() * @see java.awt.MediaTracker#isErrorAny() @@ -553,9 +553,9 @@ public class MediaTracker implements java.io.Serializable { * Checks the error status of all of the images tracked by this * media tracker with the specified identifier. * @param id the identifier of the images to check - * @return true if any of the images with the + * @return {@code true} if any of the images with the * specified identifier had an error during - * loading; false otherwise + * loading; {@code false} otherwise * @see java.awt.MediaTracker#isErrorAny * @see java.awt.MediaTracker#getErrorsID */ @@ -579,7 +579,7 @@ public class MediaTracker implements java.io.Serializable { * @return an array of media objects tracked by this media * tracker with the specified identifier * that have encountered an error, or - * null if there are none with errors + * {@code null} if there are none with errors * @see java.awt.MediaTracker#isErrorID * @see java.awt.MediaTracker#isErrorAny * @see java.awt.MediaTracker#getErrorsAny @@ -619,7 +619,7 @@ public class MediaTracker implements java.io.Serializable { *

      * If there is an error while loading or scaling an image, then that * image is considered to have finished loading. Use the - * isErrorAny and isErrorID methods to + * {@code isErrorAny} and {@code isErrorID} methods to * check for errors. * @param id the identifier of the images to check * @see java.awt.MediaTracker#waitForAll @@ -636,13 +636,13 @@ public class MediaTracker implements java.io.Serializable { * Starts loading all images tracked by this media tracker with the * specified identifier. This method waits until all the images with * the specified identifier have finished loading, or until the - * length of time specified in milliseconds by the ms + * length of time specified in milliseconds by the {@code ms} * argument has passed. *

      * If there is an error while loading or scaling an image, then that * image is considered to have finished loading. Use the - * statusID, isErrorID, and - * isErrorAny methods to check for errors. + * {@code statusID}, {@code isErrorID}, and + * {@code isErrorAny} methods to check for errors. * @param id the identifier of the images to check * @param ms the length of time, in milliseconds, to wait * for the loading to complete @@ -686,15 +686,15 @@ public class MediaTracker implements java.io.Serializable { * tracked by this media tracker. *

      * Possible flags defined by the - * MediaTracker class are LOADING, - * ABORTED, ERRORED, and - * COMPLETE. An image that hasn't started + * {@code MediaTracker} class are {@code LOADING}, + * {@code ABORTED}, {@code ERRORED}, and + * {@code COMPLETE}. An image that hasn't started * loading has zero as its status. *

      - * If the value of load is true, then + * If the value of {@code load} is {@code true}, then * this method starts loading any images that are not yet being loaded. * @param id the identifier of the images to check - * @param load if true, start loading + * @param load if {@code true}, start loading * any images that are not yet being loaded * @return the bitwise inclusive OR of the status of * all of the media with the specified @@ -761,7 +761,7 @@ public class MediaTracker implements java.io.Serializable { /** * Removes the specified image from the specified tracking * ID of this media tracker. - * All instances of Image being tracked + * All instances of {@code Image} being tracked * under the specified ID are removed regardless of scale. * @param image the image to be removed * @param id the tracking ID from which to remove the image diff --git a/jdk/src/java.desktop/share/classes/java/awt/Menu.java b/jdk/src/java.desktop/share/classes/java/awt/Menu.java index af7d4c6b734..70b5ee1f25f 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Menu.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Menu.java @@ -34,7 +34,7 @@ import javax.accessibility.*; import sun.awt.AWTAccessor; /** - * A Menu object is a pull-down menu component + * A {@code Menu} object is a pull-down menu component * that is deployed from a menu bar. *

      * A menu can optionally be a tear-off menu. A tear-off menu @@ -45,10 +45,10 @@ import sun.awt.AWTAccessor; * On platforms that do not support tear-off menus, the tear-off * property is ignored. *

      - * Each item in a menu must belong to the MenuItem - * class. It can be an instance of MenuItem, a submenu - * (an instance of Menu), or a check box (an instance of - * CheckboxMenuItem). + * Each item in a menu must belong to the {@code MenuItem} + * class. It can be an instance of {@code MenuItem}, a submenu + * (an instance of {@code Menu}), or a check box (an instance of + * {@code CheckboxMenuItem}). * * @author Sami Shaio * @see java.awt.MenuItem @@ -83,8 +83,8 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { /** * This field indicates whether the menu has the * tear of property or not. It will be set to - * true if the menu has the tear off - * property and it will be set to false + * {@code true} if the menu has the tear off + * property and it will be set to {@code false} * if it does not. * A torn off menu can be deleted by a user when * it is no longer needed. @@ -95,10 +95,10 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { boolean tearOff; /** - * This field will be set to true + * This field will be set to {@code true} * if the Menu in question is actually a help - * menu. Otherwise it will be set to - * false. + * menu. Otherwise it will be set to + * {@code false}. * * @serial */ @@ -146,7 +146,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * support tear-off menus, this value is silently ignored. * @param label the menu's label in the menu bar, or in * another menu of which this menu is a submenu. - * @param tearOff if true, the menu + * @param tearOff if {@code true}, the menu * is a tear-off menu. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. @@ -204,8 +204,8 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * Tear-off functionality may not be supported by all * implementations of AWT. If a particular implementation doesn't * support tear-off menus, this value is silently ignored. - * @return true if this is a tear-off menu; - * false otherwise. + * @return {@code true} if this is a tear-off menu; + * {@code false} otherwise. */ public boolean isTearOff() { return tearOff; @@ -225,7 +225,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * * @return the number of items in this menu * @deprecated As of JDK version 1.1, - * replaced by getItemCount(). + * replaced by {@code getItemCount()}. */ @Deprecated public int countItems() { @@ -304,7 +304,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * @see java.awt.Menu#add(java.lang.String) * @see java.awt.Menu#add(java.awt.MenuItem) * @exception IllegalArgumentException if the value of - * index is less than zero + * {@code index} is less than zero * @since 1.1 */ @@ -340,7 +340,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { /** * Inserts a menu item with the specified label into this menu * at the specified position. This is a convenience method for - * insert(menuItem, index). + * {@code insert(menuItem, index)}. * * @param label the text on the item * @param index the position at which the menu item @@ -348,7 +348,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * @see java.awt.Menu#add(java.lang.String) * @see java.awt.Menu#add(java.awt.MenuItem) * @exception IllegalArgumentException if the value of - * index is less than zero + * {@code index} is less than zero * @since 1.1 */ @@ -369,7 +369,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * @param index the position at which the * menu separator should be inserted. * @exception IllegalArgumentException if the value of - * index is less than 0. + * {@code index} is less than 0. * @see java.awt.Menu#addSeparator * @since 1.1 */ @@ -423,7 +423,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { /** * Removes the specified menu item from this menu. * @param item the item to be removed from the menu. - * If item is null + * If {@code item} is {@code null} * or is not in this menu, this method does * nothing. */ @@ -519,7 +519,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { /** * Writes default serializable fields to stream. * - * @param s the ObjectOutputStream to write + * @param s the {@code ObjectOutputStream} to write * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) * @see #readObject(ObjectInputStream) */ @@ -530,13 +530,13 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { } /** - * Reads the ObjectInputStream. + * Reads the {@code ObjectInputStream}. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns - * true + * {@code GraphicsEnvironment.isHeadless} returns + * {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @see #writeObject(ObjectOutputStream) */ @@ -552,11 +552,11 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { } /** - * Returns a string representing the state of this Menu. + * Returns a string representing the state of this {@code Menu}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this menu */ @@ -606,7 +606,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * subclassed by menu component developers. *

      * This class implements accessibility support for the - * Menu class. It provides an implementation of the + * {@code Menu} class. It provides an implementation of the * Java Accessibility API appropriate to menu user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java b/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java index b8bb64d8efb..4a57b0dbf2c 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java @@ -34,10 +34,10 @@ import java.awt.event.KeyEvent; import javax.accessibility.*; /** - * The MenuBar class encapsulates the platform's + * The {@code MenuBar} class encapsulates the platform's * concept of a menu bar bound to a frame. In order to associate - * the menu bar with a Frame object, call the - * frame's setMenuBar method. + * the menu bar with a {@code Frame} object, call the + * frame's {@code setMenuBar} method. *

      * * This is what a menu bar might look like: @@ -52,8 +52,8 @@ import javax.accessibility.*; * (Keyboard shortcuts, which are optional, provide the user with * an alternative to the mouse for invoking a menu item and the * action that is associated with it.) - * Each menu item can maintain an instance of MenuShortcut. - * The MenuBar class defines several methods, + * Each menu item can maintain an instance of {@code MenuShortcut}. + * The {@code MenuBar} class defines several methods, * {@link MenuBar#shortcuts} and * {@link MenuBar#getShortcutMenuItem} * that retrieve information about the shortcuts a given @@ -289,7 +289,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * * @return the number of menus on the menu bar. * @deprecated As of JDK version 1.1, - * replaced by getMenuCount(). + * replaced by {@code getMenuCount()}. */ @Deprecated public int countMenus() { @@ -342,9 +342,9 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible } /** - * Gets the instance of MenuItem associated - * with the specified MenuShortcut object, - * or null if none of the menu items being managed + * Gets the instance of {@code MenuItem} associated + * with the specified {@code MenuShortcut} object, + * or {@code null} if none of the menu items being managed * by this menu bar is associated with the specified menu * shortcut. * @param s the specified menu shortcut. @@ -420,7 +420,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible /** * Writes default serializable fields to stream. * - * @param s the ObjectOutputStream to write + * @param s the {@code ObjectOutputStream} to write * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) * @see #readObject(java.io.ObjectInputStream) */ @@ -432,13 +432,13 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible } /** - * Reads the ObjectInputStream. + * Reads the {@code ObjectInputStream}. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns - * true + * {@code GraphicsEnvironment.isHeadless} returns + * {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @see #writeObject(java.io.ObjectOutputStream) */ @@ -494,7 +494,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * subclassed by menu component developers. *

      * This class implements accessibility support for the - * MenuBar class. It provides an implementation of the + * {@code MenuBar} class. It provides an implementation of the * Java Accessibility API appropriate to menu bar user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java b/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java index fca144ac0f8..c6097397c98 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java @@ -38,13 +38,13 @@ import java.security.AccessControlContext; import java.security.AccessController; /** - * The abstract class MenuComponent is the superclass + * The abstract class {@code MenuComponent} is the superclass * of all menu-related components. In this respect, the class - * MenuComponent is analogous to the abstract superclass - * Component for AWT components. + * {@code MenuComponent} is analogous to the abstract superclass + * {@code Component} for AWT components. *

      * Menu components receive and process AWT events, just as components do, - * through the method processEvent. + * through the method {@code processEvent}. * * @author Arthur van Hoff * @since 1.0 @@ -63,15 +63,15 @@ public abstract class MenuComponent implements java.io.Serializable { transient MenuContainer parent; /** - * The AppContext of the MenuComponent. + * The {@code AppContext} of the {@code MenuComponent}. * This is set in the constructor and never changes. */ transient AppContext appContext; /** * The menu component's font. This value can be - * null at which point a default will be used. - * This defaults to null. + * {@code null} at which point a default will be used. + * This defaults to {@code null}. * * @serial * @see #setFont(Font) @@ -80,7 +80,7 @@ public abstract class MenuComponent implements java.io.Serializable { volatile Font font; /** - * The menu component's name, which defaults to null. + * The menu component's name, which defaults to {@code null}. * @serial * @see #getName() * @see #setName(String) @@ -89,15 +89,15 @@ public abstract class MenuComponent implements java.io.Serializable { /** * A variable to indicate whether a name is explicitly set. - * If true the name will be set explicitly. - * This defaults to false. + * If {@code true} the name will be set explicitly. + * This defaults to {@code false}. * @serial * @see #setName(String) */ private boolean nameExplicitlySet = false; /** - * Defaults to false. + * Defaults to {@code false}. * @serial * @see #dispatchEvent(AWTEvent) */ @@ -164,10 +164,10 @@ public abstract class MenuComponent implements java.io.Serializable { } /** - * Creates a MenuComponent. + * Creates a {@code MenuComponent}. * @exception HeadlessException if - * GraphicsEnvironment.isHeadless - * returns true + * {@code GraphicsEnvironment.isHeadless} + * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless */ public MenuComponent() throws HeadlessException { @@ -176,9 +176,9 @@ public abstract class MenuComponent implements java.io.Serializable { } /** - * Constructs a name for this MenuComponent. - * Called by getName when the name is null. - * @return a name for this MenuComponent + * Constructs a name for this {@code MenuComponent}. + * Called by {@code getName} when the name is {@code null}. + * @return a name for this {@code MenuComponent} */ String constructComponentName() { return null; // For strict compliance with prior platform versions, a MenuComponent @@ -226,7 +226,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Returns the parent container for this menu component. * @return the menu component containing this menu component, - * or null if this menu component + * or {@code null} if this menu component * is the outermost component, the menu bar itself */ public MenuContainer getParent() { @@ -243,7 +243,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Gets the font used for this menu component. * @return the font used in this menu component, if there is one; - * null otherwise + * {@code null} otherwise * @see java.awt.MenuComponent#setFont */ public Font getFont() { @@ -290,7 +290,7 @@ public abstract class MenuComponent implements java.io.Serializable { * component, unless those subcomponents specify a different font. *

      * Some platforms may not support setting of all font attributes - * of a menu component; in such cases, calling setFont + * of a menu component; in such cases, calling {@code setFont} * will have no effect on the unsupported font attributes of this * menu component. Unless subcomponents of this menu component * specify a different font, this font will be used by those @@ -385,7 +385,7 @@ public abstract class MenuComponent implements java.io.Serializable { } /** * Processes events occurring on this menu component. - *

      Note that if the event parameter is null + *

      Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -397,10 +397,10 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Returns a string representing the state of this - * MenuComponent. This method is intended to be used + * {@code MenuComponent}. This method is intended to be used * only for debugging purposes, and the content and format of the * returned string may vary between implementations. The returned - * string may be empty but may not be null. + * string may be empty but may not be {@code null}. * * @return the parameter string of this menu component */ @@ -430,10 +430,10 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Reads the menu component from an object input stream. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns - * true + * {@code GraphicsEnvironment.isHeadless} returns + * {@code true} * @serial * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -466,16 +466,16 @@ public abstract class MenuComponent implements java.io.Serializable { AccessibleContext accessibleContext = null; /** - * Gets the AccessibleContext associated with - * this MenuComponent. + * Gets the {@code AccessibleContext} associated with + * this {@code MenuComponent}. * - * The method implemented by this base class returns null. - * Classes that extend MenuComponent + * The method implemented by this base class returns {@code null}. + * Classes that extend {@code MenuComponent} * should implement this method to return the - * AccessibleContext associated with the subclass. + * {@code AccessibleContext} associated with the subclass. * - * @return the AccessibleContext of this - * MenuComponent + * @return the {@code AccessibleContext} of this + * {@code MenuComponent} * @since 1.3 */ public AccessibleContext getAccessibleContext() { @@ -483,7 +483,7 @@ public abstract class MenuComponent implements java.io.Serializable { } /** - * Inner class of MenuComponent used to provide + * Inner class of {@code MenuComponent} used to provide * default support for accessibility. This class is not meant * to be used directly by application developers, but is instead * meant only to be subclassed by menu component developers. @@ -512,11 +512,11 @@ public abstract class MenuComponent implements java.io.Serializable { // /** - * Gets the AccessibleSelection associated with this - * object which allows its Accessible children to be selected. + * Gets the {@code AccessibleSelection} associated with this + * object which allows its {@code Accessible} children to be selected. * - * @return AccessibleSelection if supported by object; - * else return null + * @return {@code AccessibleSelection} if supported by object; + * else return {@code null} * @see AccessibleSelection */ public AccessibleSelection getAccessibleSelection() { @@ -525,14 +525,14 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Gets the accessible name of this object. This should almost never - * return java.awt.MenuComponent.getName, as that + * return {@code java.awt.MenuComponent.getName}, as that * generally isn't a localized name, and doesn't have meaning for the * user. If the object is fundamentally a text object (e.g. a menu item), the * accessible name should be the text of the object (e.g. "save"). * If the object has a tooltip, the tooltip text may also be an * appropriate String to return. * - * @return the localized name of the object -- can be null + * @return the localized name of the object -- can be {@code null} * if this object does not have a name * @see AccessibleContext#setAccessibleName */ @@ -552,7 +552,7 @@ public abstract class MenuComponent implements java.io.Serializable { * text document" instead). * * @return the localized description of the object -- can be - * null if this object does not have a description + * {@code null} if this object does not have a description * @see AccessibleContext#setAccessibleDescription */ public String getAccessibleDescription() { @@ -562,7 +562,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Gets the role of this object. * - * @return an instance of AccessibleRole + * @return an instance of {@code AccessibleRole} * describing the role of the object * @see AccessibleRole */ @@ -573,7 +573,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Gets the state of this object. * - * @return an instance of AccessibleStateSet + * @return an instance of {@code AccessibleStateSet} * containing the current state set of the object * @see AccessibleState */ @@ -582,13 +582,13 @@ public abstract class MenuComponent implements java.io.Serializable { } /** - * Gets the Accessible parent of this object. - * If the parent of this object implements Accessible, - * this method should simply return getParent. + * Gets the {@code Accessible} parent of this object. + * If the parent of this object implements {@code Accessible}, + * this method should simply return {@code getParent}. * - * @return the Accessible parent of this object -- can - * be null if this object does not have an - * Accessible parent + * @return the {@code Accessible} parent of this object -- can + * be {@code null} if this object does not have an + * {@code Accessible} parent */ public Accessible getAccessibleParent() { if (accessibleParent != null) { @@ -615,7 +615,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Returns the number of accessible children in the object. If all - * of the children of this object implement Accessible, + * of the children of this object implement {@code Accessible}, * then this method should return the number of children of this object. * * @return the number of accessible children in the object @@ -625,7 +625,7 @@ public abstract class MenuComponent implements java.io.Serializable { } /** - * Returns the nth Accessible child of the object. + * Returns the nth {@code Accessible} child of the object. * * @param i zero-based index of child * @return the nth Accessible child of the object @@ -648,8 +648,8 @@ public abstract class MenuComponent implements java.io.Serializable { } /** - * Gets the AccessibleComponent associated with - * this object if one exists. Otherwise return null. + * Gets the {@code AccessibleComponent} associated with + * this object if one exists. Otherwise return {@code null}. * * @return the component */ @@ -664,7 +664,7 @@ public abstract class MenuComponent implements java.io.Serializable { * Gets the background color of this object. * * @return the background color, if supported, of the object; - * otherwise, null + * otherwise, {@code null} */ public Color getBackground() { return null; // Not supported for MenuComponents @@ -672,9 +672,9 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Sets the background color of this object. - * (For transparency, see isOpaque.) + * (For transparency, see {@code isOpaque}.) * - * @param c the new Color for the background + * @param c the new {@code Color} for the background * @see Component#isOpaque */ public void setBackground(Color c) { @@ -685,7 +685,7 @@ public abstract class MenuComponent implements java.io.Serializable { * Gets the foreground color of this object. * * @return the foreground color, if supported, of the object; - * otherwise, null + * otherwise, {@code null} */ public Color getForeground() { return null; // Not supported for MenuComponents @@ -694,59 +694,59 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Sets the foreground color of this object. * - * @param c the new Color for the foreground + * @param c the new {@code Color} for the foreground */ public void setForeground(Color c) { // Not supported for MenuComponents } /** - * Gets the Cursor of this object. + * Gets the {@code Cursor} of this object. * - * @return the Cursor, if supported, of the object; - * otherwise, null + * @return the {@code Cursor}, if supported, of the object; + * otherwise, {@code null} */ public Cursor getCursor() { return null; // Not supported for MenuComponents } /** - * Sets the Cursor of this object. + * Sets the {@code Cursor} of this object. *

      * The method may have no visual effect if the Java platform * implementation and/or the native system do not support * changing the mouse cursor shape. - * @param cursor the new Cursor for the object + * @param cursor the new {@code Cursor} for the object */ public void setCursor(Cursor cursor) { // Not supported for MenuComponents } /** - * Gets the Font of this object. + * Gets the {@code Font} of this object. * - * @return the Font,if supported, for the object; - * otherwise, null + * @return the {@code Font},if supported, for the object; + * otherwise, {@code null} */ public Font getFont() { return MenuComponent.this.getFont(); } /** - * Sets the Font of this object. + * Sets the {@code Font} of this object. * - * @param f the new Font for the object + * @param f the new {@code Font} for the object */ public void setFont(Font f) { MenuComponent.this.setFont(f); } /** - * Gets the FontMetrics of this object. + * Gets the {@code FontMetrics} of this object. * - * @param f the Font + * @param f the {@code Font} * @return the FontMetrics, if supported, the object; - * otherwise, null + * otherwise, {@code null} * @see #getFont */ public FontMetrics getFontMetrics(Font f) { @@ -776,7 +776,7 @@ public abstract class MenuComponent implements java.io.Serializable { * object intends to be visible; however, it may not in fact be * showing on the screen because one of the objects that this object * is contained by is not visible. To determine if an object is - * showing on the screen, use isShowing. + * showing on the screen, use {@code isShowing}. * * @return true if object is visible; otherwise, false */ @@ -811,9 +811,9 @@ public abstract class MenuComponent implements java.io.Serializable { * where the point's x and y coordinates are defined to be relative to * the coordinate system of the object. * - * @param p the Point relative to the coordinate + * @param p the {@code Point} relative to the coordinate * system of the object - * @return true if object contains Point; otherwise false + * @return true if object contains {@code Point}; otherwise false */ public boolean contains(Point p) { return false; // Not supported for MenuComponents @@ -822,7 +822,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Returns the location of the object on the screen. * - * @return location of object on screen -- can be null + * @return location of object on screen -- can be {@code null} * if this object is not on the screen */ public Point getLocationOnScreen() { @@ -834,9 +834,9 @@ public abstract class MenuComponent implements java.io.Serializable { * of a point specifying the object's top-left corner in the screen's * coordinate space. * - * @return an instance of Point representing the + * @return an instance of {@code Point} representing the * top-left corner of the object's bounds in the coordinate - * space of the screen; null if + * space of the screen; {@code null} if * this object or its parent are not on the screen */ public Point getLocation() { @@ -852,12 +852,12 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Gets the bounds of this object in the form of a - * Rectangle object. + * {@code Rectangle} object. * The bounds specify this object's width, height, and location * relative to its parent. * * @return a rectangle indicating this component's bounds; - * null if this object is not on the screen + * {@code null} if this object is not on the screen */ public Rectangle getBounds() { return null; // Not supported for MenuComponents @@ -865,7 +865,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Sets the bounds of this object in the form of a - * Rectangle object. + * {@code Rectangle} object. * The bounds specify this object's width, height, and location * relative to its parent. * @@ -877,13 +877,13 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Returns the size of this object in the form of a - * Dimension object. The height field of - * the Dimension object contains this object's - * height, and the width field of the Dimension + * {@code Dimension} object. The height field of + * the {@code Dimension} object contains this object's + * height, and the width field of the {@code Dimension} * object contains this object's width. * - * @return a Dimension object that indicates the - * size of this component; null + * @return a {@code Dimension} object that indicates the + * size of this component; {@code null} * if this object is not on the screen */ public Dimension getSize() { @@ -893,7 +893,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Resizes this object. * - * @param d - the Dimension specifying the + * @param d the {@code Dimension} specifying the * new size of the object */ public void setSize(Dimension d) { @@ -901,16 +901,16 @@ public abstract class MenuComponent implements java.io.Serializable { } /** - * Returns the Accessible child, if one exists, - * contained at the local coordinate Point. - * If there is no Accessible child, null + * Returns the {@code Accessible} child, if one exists, + * contained at the local coordinate {@code Point}. + * If there is no {@code Accessible} child, {@code null} * is returned. * * @param p the point defining the top-left corner of the - * Accessible, given in the coordinate space + * {@code Accessible}, given in the coordinate space * of the object's parent - * @return the Accessible, if it exists, - * at the specified location; else null + * @return the {@code Accessible}, if it exists, + * at the specified location; else {@code null} */ public Accessible getAccessibleAt(Point p) { return null; // MenuComponents don't have children @@ -956,7 +956,7 @@ public abstract class MenuComponent implements java.io.Serializable { // /** - * Returns the number of Accessible children currently selected. + * Returns the number of {@code Accessible} children currently selected. * If no children are selected, the return value will be 0. * * @return the number of items currently selected @@ -966,10 +966,10 @@ public abstract class MenuComponent implements java.io.Serializable { } /** - * Returns an Accessible representing the specified + * Returns an {@code Accessible} representing the specified * selected child in the object. If there isn't a selection, or there are * fewer children selected than the integer passed in, the return - * value will be null. + * value will be {@code null}. *

      Note that the index represents the i-th selected child, which * is different from the i-th child. * @@ -987,7 +987,7 @@ public abstract class MenuComponent implements java.io.Serializable { * @return true if the current child of this object is selected; * else false * @param i the zero-based index of the child in this - * Accessible object + * {@code Accessible} object * @see AccessibleContext#getAccessibleChild */ public boolean isAccessibleChildSelected(int i) { @@ -995,7 +995,7 @@ public abstract class MenuComponent implements java.io.Serializable { } /** - * Adds the specified Accessible child of the object + * Adds the specified {@code Accessible} child of the object * to the object's selection. If the object supports multiple selections, * the specified child is added to any existing selection, otherwise * it replaces any existing selection in the object. If the @@ -1068,7 +1068,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Gets the state of this object. * - * @return an instance of AccessibleStateSet + * @return an instance of {@code AccessibleStateSet} * containing the current state set of the object * @see AccessibleState */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java b/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java index 6c289f1ccf5..3a70fe2bee0 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java @@ -35,9 +35,9 @@ import sun.awt.AWTAccessor; /** * All items in a menu must belong to the class - * MenuItem, or one of its subclasses. + * {@code MenuItem}, or one of its subclasses. *

      - * The default MenuItem object embodies + * The default {@code MenuItem} object embodies * a simple labeled menu item. *

      * This picture of a menu bar shows five menu items: @@ -45,24 +45,24 @@ import sun.awt.AWTAccessor; * style="float:center; margin: 7px 10px;"> *
      * The first two items are simple menu items, labeled - * "Basic" and "Simple". + * {@code "Basic"} and {@code "Simple"}. * Following these two items is a separator, which is itself - * a menu item, created with the label "-". - * Next is an instance of CheckboxMenuItem - * labeled "Check". The final menu item is a + * a menu item, created with the label {@code "-"}. + * Next is an instance of {@code CheckboxMenuItem} + * labeled {@code "Check"}. The final menu item is a * submenu labeled "More Examples", - * and this submenu is an instance of Menu. + * and this submenu is an instance of {@code Menu}. *

      * When a menu item is selected, AWT sends an action event to * the menu item. Since the event is an - * instance of ActionEvent, the processEvent + * instance of {@code ActionEvent}, the {@code processEvent} * method examines the event and passes it along to - * processActionEvent. The latter method redirects the - * event to any ActionListener objects that have + * {@code processActionEvent}. The latter method redirects the + * event to any {@code ActionListener} objects that have * registered an interest in action events generated by this * menu item. *

      - * Note that the subclass Menu overrides this behavior and + * Note that the subclass {@code Menu} overrides this behavior and * does not send any event to the frame until one of its subitems is * selected. * @@ -103,8 +103,8 @@ public class MenuItem extends MenuComponent implements Accessible { /** * A value to indicate whether a menu item is enabled - * or not. If it is enabled, enabled will - * be set to true. Else enabled will + * or not. If it is enabled, {@code enabled} will + * be set to true. Else {@code enabled} will * be set to false. * * @serial @@ -114,7 +114,7 @@ public class MenuItem extends MenuComponent implements Accessible { boolean enabled = true; /** - * label is the label of a menu item. + * {@code label} is the label of a menu item. * It can be any string. * * @serial @@ -124,9 +124,9 @@ public class MenuItem extends MenuComponent implements Accessible { String label; /** - * This field indicates the command tha has been issued + * This field indicates the command that has been issued * by a particular menu item. - * By default the actionCommand + * By default the {@code actionCommand} * is the label of the menu item, unless it has been * set using setActionCommand. * @@ -204,7 +204,7 @@ public class MenuItem extends MenuComponent implements Accessible { * a separator between menu items. By default, all menu * items except for separators are enabled. * @param label the label for this menu item. - * @param s the instance of MenuShortcut + * @param s the instance of {@code MenuShortcut} * associated with this menu item. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. @@ -239,7 +239,7 @@ public class MenuItem extends MenuComponent implements Accessible { /** * Gets the label for this menu item. - * @return the label of this menu item, or null + * @return the label of this menu item, or {@code null} if this menu item has no label. * @see java.awt.MenuItem#setLabel * @since 1.0 @@ -250,7 +250,7 @@ public class MenuItem extends MenuComponent implements Accessible { /** * Sets the label for this menu item to the specified label. - * @param label the new label, or null for no label. + * @param label the new label, or {@code null} for no label. * @see java.awt.MenuItem#getLabel * @since 1.0 */ @@ -276,8 +276,8 @@ public class MenuItem extends MenuComponent implements Accessible { /** * Sets whether or not this menu item can be chosen. - * @param b if true, enables this menu item; - * if false, disables it. + * @param b if {@code true}, enables this menu item; + * if {@code false}, disables it. * @see java.awt.MenuItem#isEnabled * @since 1.1 */ @@ -287,7 +287,7 @@ public class MenuItem extends MenuComponent implements Accessible { /** * @deprecated As of JDK version 1.1, - * replaced by setEnabled(boolean). + * replaced by {@code setEnabled(boolean)}. */ @Deprecated public synchronized void enable() { @@ -304,7 +304,7 @@ public class MenuItem extends MenuComponent implements Accessible { * @param b if {@code true}, enables this menu item; * otherwise disables * @deprecated As of JDK version 1.1, - * replaced by setEnabled(boolean). + * replaced by {@code setEnabled(boolean)}. */ @Deprecated public void enable(boolean b) { @@ -317,7 +317,7 @@ public class MenuItem extends MenuComponent implements Accessible { /** * @deprecated As of JDK version 1.1, - * replaced by setEnabled(boolean). + * replaced by {@code setEnabled(boolean)}. */ @Deprecated public synchronized void disable() { @@ -329,10 +329,10 @@ public class MenuItem extends MenuComponent implements Accessible { } /** - * Get the MenuShortcut object associated with this + * Get the {@code MenuShortcut} object associated with this * menu item, * @return the menu shortcut associated with this menu item, - * or null if none has been specified. + * or {@code null} if none has been specified. * @see java.awt.MenuItem#setShortcut * @since 1.1 */ @@ -341,7 +341,7 @@ public class MenuItem extends MenuComponent implements Accessible { } /** - * Set the MenuShortcut object associated with this + * Set the {@code MenuShortcut} object associated with this * menu item. If a menu shortcut is already associated with * this menu item, it is replaced. * @param s the menu shortcut to associate @@ -358,7 +358,7 @@ public class MenuItem extends MenuComponent implements Accessible { } /** - * Delete any MenuShortcut object associated + * Delete any {@code MenuShortcut} object associated * with this menu item. * @since 1.1 */ @@ -454,8 +454,8 @@ public class MenuItem extends MenuComponent implements Accessible { *

      * Since event types are automatically enabled when a listener for * that type is added to the menu item, this method only needs - * to be invoked by subclasses of MenuItem which desire to - * have the specified event types delivered to processEvent + * to be invoked by subclasses of {@code MenuItem} which desire to + * have the specified event types delivered to {@code processEvent} * regardless of whether a listener is registered. * * @param eventsToEnable the event mask defining the event types @@ -562,7 +562,7 @@ public class MenuItem extends MenuComponent implements Accessible { * Returns an array of all the action listeners * registered on this menu item. * - * @return all of this menu item's ActionListeners + * @return all of this menu item's {@code ActionListener}s * or an empty array if no action * listeners are currently registered * @@ -579,16 +579,16 @@ public class MenuItem extends MenuComponent implements Accessible { /** * Returns an array of all the objects currently registered * as FooListeners - * upon this MenuItem. + * upon this {@code MenuItem}. * FooListeners are registered using the * addFooListener method. * *

      - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * MenuItem m + * {@code MenuItem m} * for its action listeners with the following code: * *

      ActionListener[] als = (ActionListener[])(m.getListeners(ActionListener.class));
      @@ -598,14 +598,14 @@ public class MenuItem extends MenuComponent implements Accessible { * @param the type of the listeners * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this menu item, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @see #getActionListeners * @since 1.3 @@ -620,12 +620,12 @@ public class MenuItem extends MenuComponent implements Accessible { /** * Processes events on this menu item. If the event is an - * instance of ActionEvent, it invokes - * processActionEvent, another method - * defined by MenuItem. + * instance of {@code ActionEvent}, it invokes + * {@code processActionEvent}, another method + * defined by {@code MenuItem}. *

      * Currently, menu items only support action events. - *

      Note that if the event parameter is null + *

      Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -654,16 +654,16 @@ public class MenuItem extends MenuComponent implements Accessible { /** * Processes action events occurring on this menu item, * by dispatching them to any registered - * ActionListener objects. + * {@code ActionListener} objects. * This method is not called unless action events are * enabled for this component. Action events are enabled * when one of the following occurs: *

        - *
      • An ActionListener object is registered - * via addActionListener. - *
      • Action events are enabled via enableEvents. + *
      • An {@code ActionListener} object is registered + * via {@code addActionListener}. + *
      • Action events are enabled via {@code enableEvents}. *
      - *

      Note that if the event parameter is null + *

      Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -681,11 +681,11 @@ public class MenuItem extends MenuComponent implements Accessible { } /** - * Returns a string representing the state of this MenuItem. + * Returns a string representing the state of this {@code MenuItem}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this menu item */ @@ -710,17 +710,17 @@ public class MenuItem extends MenuComponent implements Accessible { /** * Writes default serializable fields to stream. Writes - * a list of serializable ActionListeners + * a list of serializable {@code ActionListeners} * as optional data. The non-serializable listeners are * detected and no attempt is made to serialize them. * - * @param s the ObjectOutputStream to write - * @serialData null terminated sequence of 0 - * or more pairs; the pair consists of a String - * and an Object; the String + * @param s the {@code ObjectOutputStream} to write + * @serialData {@code null} terminated sequence of 0 + * or more pairs; the pair consists of a {@code String} + * and an {@code Object}; the {@code String} * indicates the type of object and is one of the following: - * actionListenerK indicating an - * ActionListener object + * {@code actionListenerK} indicating an + * {@code ActionListener} object * * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) * @see #readObject(ObjectInputStream) @@ -735,15 +735,15 @@ public class MenuItem extends MenuComponent implements Accessible { } /** - * Reads the ObjectInputStream and if it - * isn't null adds a listener to receive - * action events fired by the Menu Item. + * Reads the {@code ObjectInputStream} and if it + * isn't {@code null} adds a listener to receive + * action events fired by the {@code Menu} Item. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns - * true + * {@code GraphicsEnvironment.isHeadless} returns + * {@code true} * @see #removeActionListener(ActionListener) * @see #addActionListener(ActionListener) * @see #writeObject(ObjectOutputStream) @@ -800,7 +800,7 @@ public class MenuItem extends MenuComponent implements Accessible { * subclassed by menu component developers. *

      * This class implements accessibility support for the - * MenuItem class. It provides an implementation of the + * {@code MenuItem} class. It provides an implementation of the * Java Accessibility API appropriate to menu item user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuShortcut.java b/jdk/src/java.desktop/share/classes/java/awt/MenuShortcut.java index cba251bbf4b..57526ff4e6d 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MenuShortcut.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MenuShortcut.java @@ -27,27 +27,27 @@ package java.awt; import java.awt.event.KeyEvent; /** - * The MenuShortcutclass represents a keyboard accelerator + * The {@code MenuShortcut} class represents a keyboard accelerator * for a MenuItem. *

      * Menu shortcuts are created using virtual keycodes, not characters. * For example, a menu shortcut for Ctrl-a (assuming that Control is * the accelerator key) would be created with code like the following: *

      - * MenuShortcut ms = new MenuShortcut(KeyEvent.VK_A, false); + * {@code MenuShortcut ms = new MenuShortcut(KeyEvent.VK_A, false);} *

      or alternatively *

      - * MenuShortcut ms = new MenuShortcut(KeyEvent.getExtendedKeyCodeForChar('A'), false); + * {@code MenuShortcut ms = new MenuShortcut(KeyEvent.getExtendedKeyCodeForChar('A'), false);} *

      * Menu shortcuts may also be constructed for a wider set of keycodes - * using the java.awt.event.KeyEvent.getExtendedKeyCodeForChar call. + * using the {@code java.awt.event.KeyEvent.getExtendedKeyCodeForChar} call. * For example, a menu shortcut for "Ctrl+cyrillic ef" is created by *

      * MenuShortcut ms = new MenuShortcut(KeyEvent.getExtendedKeyCodeForChar('\u0444'), false); *

      - * Note that shortcuts created with a keycode or an extended keycode defined as a constant in KeyEvent + * Note that shortcuts created with a keycode or an extended keycode defined as a constant in {@code KeyEvent} * work regardless of the current keyboard layout. However, a shortcut made of - * an extended keycode not listed in KeyEvent + * an extended keycode not listed in {@code KeyEvent} * only work if the current keyboard layout produces a corresponding letter. *

      * The accelerator key is platform-dependent and may be obtained @@ -128,8 +128,8 @@ public class MenuShortcut implements java.io.Serializable /** * Returns whether this MenuShortcut must be invoked using the SHIFT key. - * @return true if this MenuShortcut must be invoked using the - * SHIFT key, false otherwise. + * @return {@code true} if this MenuShortcut must be invoked using the + * SHIFT key, {@code false} otherwise. * @since 1.1 */ public boolean usesShiftModifier() { @@ -141,8 +141,8 @@ public class MenuShortcut implements java.io.Serializable * equality is defined to mean that both MenuShortcuts use the same key * and both either use or don't use the SHIFT key. * @param s the MenuShortcut to compare with this. - * @return true if this MenuShortcut is the same as another, - * false otherwise. + * @return {@code true} if this MenuShortcut is the same as another, + * {@code false} otherwise. * @since 1.1 */ public boolean equals(MenuShortcut s) { @@ -155,8 +155,8 @@ public class MenuShortcut implements java.io.Serializable * equality is defined to mean that both MenuShortcuts use the same key * and both either use or don't use the SHIFT key. * @param obj the Object to compare with this. - * @return true if this MenuShortcut is the same as another, - * false otherwise. + * @return {@code true} if this MenuShortcut is the same as another, + * {@code false} otherwise. * @since 1.2 */ public boolean equals(Object obj) { diff --git a/jdk/src/java.desktop/share/classes/java/awt/MouseInfo.java b/jdk/src/java.desktop/share/classes/java/awt/MouseInfo.java index c06e5f12767..60849fc1f5d 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/MouseInfo.java +++ b/jdk/src/java.desktop/share/classes/java/awt/MouseInfo.java @@ -29,7 +29,7 @@ import sun.awt.AWTPermissions; import sun.awt.ComponentFactory; /** - * MouseInfo provides methods for getting information about the mouse, + * {@code MouseInfo} provides methods for getting information about the mouse, * such as mouse pointer location and the number of mouse buttons. * * @author Roman Poborchiy @@ -45,26 +45,26 @@ public class MouseInfo { } /** - * Returns a PointerInfo instance that represents the current + * Returns a {@code PointerInfo} instance that represents the current * location of the mouse pointer. - * The GraphicsDevice stored in this PointerInfo + * The {@code GraphicsDevice} stored in this {@code PointerInfo} * contains the mouse pointer. The coordinate system used for the mouse position - * depends on whether or not the GraphicsDevice is part of a virtual + * depends on whether or not the {@code GraphicsDevice} is part of a virtual * screen device. * For virtual screen devices, the coordinates are given in the virtual * coordinate system, otherwise they are returned in the coordinate system - * of the GraphicsDevice. See {@link GraphicsConfiguration} + * of the {@code GraphicsDevice}. See {@link GraphicsConfiguration} * for more information about the virtual screen devices. - * On systems without a mouse, returns null. + * On systems without a mouse, returns {@code null}. *

      - * If there is a security manager, its checkPermission method - * is called with an AWTPermission("watchMousePointer") - * permission before creating and returning a PointerInfo - * object. This may result in a SecurityException. + * If there is a security manager, its {@code checkPermission} method + * is called with an {@code AWTPermission("watchMousePointer")} + * permission before creating and returning a {@code PointerInfo} + * object. This may result in a {@code SecurityException}. * * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true * @exception SecurityException if a security manager exists and its - * checkPermission method doesn't allow the operation + * {@code checkPermission} method doesn't allow the operation * @see GraphicsConfiguration * @see SecurityManager#checkPermission * @see java.awt.AWTPermission @@ -118,7 +118,7 @@ public class MouseInfo { /** * Returns the number of buttons on the mouse. - * On systems without a mouse, returns -1. + * On systems without a mouse, returns {@code -1}. * The number of buttons is obtained from the AWT Toolkit * by requesting the {@code "awt.mouse.numButtons"} desktop property * which is set by the underlying native platform. diff --git a/jdk/src/java.desktop/share/classes/java/awt/PageAttributes.java b/jdk/src/java.desktop/share/classes/java/awt/PageAttributes.java index d06ea4c562a..6b718f79536 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/PageAttributes.java +++ b/jdk/src/java.desktop/share/classes/java/awt/PageAttributes.java @@ -942,7 +942,7 @@ public final class PageAttributes implements Cloneable { * @param printerResolution an integer array of 3 elements. The first * element must be greater than 0. The second element must be * must be greater than 0. The third element must be either - * 3 or 4. + * {@code 3} or {@code 4}. * @throws IllegalArgumentException if one or more of the above * conditions is violated. */ @@ -1095,14 +1095,14 @@ public final class PageAttributes implements Cloneable { /** * Specifies the print orientation for pages using these attributes. - * Specifying 3 denotes portrait. Specifying 4 + * Specifying {@code 3} denotes portrait. Specifying {@code 4} * denotes landscape. Specifying any other value will generate an * IllegalArgumentException. Not specifying the property is equivalent * to calling setOrientationRequested(OrientationRequestedType.PORTRAIT). * - * @param orientationRequested 3 or 4 + * @param orientationRequested {@code 3} or {@code 4} * @throws IllegalArgumentException if orientationRequested is not - * 3 or 4 + * {@code 3} or {@code 4} */ public void setOrientationRequested(int orientationRequested) { switch (orientationRequested) { @@ -1189,15 +1189,15 @@ public final class PageAttributes implements Cloneable { /** * Specifies the print quality for pages using these attributes. - * Specifying 3 denotes draft. Specifying 4 - * denotes normal. Specifying 5 denotes high. Specifying + * Specifying {@code 3} denotes draft. Specifying {@code 4} + * denotes normal. Specifying {@code 5} denotes high. Specifying * any other value will generate an IllegalArgumentException. Not * specifying the property is equivalent to calling * setPrintQuality(PrintQualityType.NORMAL). * - * @param printQuality 3, 4, or 5 - * @throws IllegalArgumentException if printQuality is not 3 - * , 4, or 5 + * @param printQuality {@code 3}, {@code 4}, or {@code 5} + * @throws IllegalArgumentException if printQuality is not + * {@code 3}, {@code 4}, or {@code 5} */ public void setPrintQuality(int printQuality) { switch (printQuality) { @@ -1231,13 +1231,13 @@ public final class PageAttributes implements Cloneable { * (typically the horizontal resolution). Index 1 of the array specifies * the feed direction resolution (typically the vertical resolution). * Index 2 of the array specifies whether the resolutions are in dots per - * inch or dots per centimeter. 3 denotes dots per inch. - * 4 denotes dots per centimeter. + * inch or dots per centimeter. {@code 3} denotes dots per inch. + * {@code 4} denotes dots per centimeter. * * @return an integer array of 3 elements. The first * element must be greater than 0. The second element must be * must be greater than 0. The third element must be either - * 3 or 4. + * {@code 3} or {@code 4}. */ public int[] getPrinterResolution() { // Return a copy because otherwise client code could circumvent the @@ -1258,7 +1258,7 @@ public final class PageAttributes implements Cloneable { * resolution). Index 1 of the array specifies the feed direction * resolution (typically the vertical resolution). Index 2 of the array * specifies whether the resolutions are in dots per inch or dots per - * centimeter. 3 denotes dots per inch. 4 + * centimeter. {@code 3} denotes dots per inch. {@code 4} * denotes dots per centimeter. Note that the 1.1 printing implementation * (Toolkit.getPrintJob) requires that the feed and cross feed resolutions * be the same. Not specifying the property is equivalent to calling @@ -1267,7 +1267,7 @@ public final class PageAttributes implements Cloneable { * @param printerResolution an integer array of 3 elements. The first * element must be greater than 0. The second element must be * must be greater than 0. The third element must be either - * 3 or 4. + * {@code 3} or {@code 4}. * @throws IllegalArgumentException if one or more of the above * conditions is violated. */ @@ -1295,7 +1295,7 @@ public final class PageAttributes implements Cloneable { * inch for pages using these attributes. The same value is used for both * resolutions. The actual resolutions will be determined by the * limitations of the implementation and the target printer. Not - * specifying the property is equivalent to specifying 72. + * specifying the property is equivalent to specifying {@code 72}. * * @param printerResolution an integer greater than 0. * @throws IllegalArgumentException if printerResolution is less than or diff --git a/jdk/src/java.desktop/share/classes/java/awt/Paint.java b/jdk/src/java.desktop/share/classes/java/awt/Paint.java index b2e0dabb13e..ba4d601769b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Paint.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Paint.java @@ -30,16 +30,16 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; /** - * This Paint interface defines how color patterns + * This {@code Paint} interface defines how color patterns * can be generated for {@link Graphics2D} operations. A class - * implementing the Paint interface is added to the - * Graphics2D context in order to define the color - * pattern used by the draw and fill methods. + * implementing the {@code Paint} interface is added to the + * {@code Graphics2D} context in order to define the color + * pattern used by the {@code draw} and {@code fill} methods. *

      - * Instances of classes implementing Paint must be - * read-only because the Graphics2D does not clone + * Instances of classes implementing {@code Paint} must be + * read-only because the {@code Graphics2D} does not clone * these objects when they are set as an attribute with the - * setPaint method or when the Graphics2D + * {@code setPaint} method or when the {@code Graphics2D} * object is itself cloned. * @see PaintContext * @see Color @@ -74,22 +74,22 @@ public interface Paint extends Transparency { * of the graphics primitive being rendered. * Implementations of the {@code Paint} interface * are allowed to throw {@code NullPointerException} - * for a {@code null} {@code deviceBounds}. + * for a {@code null deviceBounds}. * @param userBounds the user space bounding box * of the graphics primitive being rendered. * Implementations of the {@code Paint} interface * are allowed to throw {@code NullPointerException} - * for a {@code null} {@code userBounds}. + * for a {@code null userBounds}. * @param xform the {@link AffineTransform} from user * space into device space. * Implementations of the {@code Paint} interface * are allowed to throw {@code NullPointerException} - * for a {@code null} {@code xform}. + * for a {@code null xform}. * @param hints the set of hints that the context object can use to * choose between rendering alternatives. * Implementations of the {@code Paint} interface * are allowed to throw {@code NullPointerException} - * for a {@code null} {@code hints}. + * for a {@code null hints}. * @return the {@code PaintContext} for * generating color patterns. * @see PaintContext diff --git a/jdk/src/java.desktop/share/classes/java/awt/PaintContext.java b/jdk/src/java.desktop/share/classes/java/awt/PaintContext.java index 4efafff27d4..faca59d2c8b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/PaintContext.java +++ b/jdk/src/java.desktop/share/classes/java/awt/PaintContext.java @@ -29,13 +29,13 @@ import java.awt.image.Raster; import java.awt.image.ColorModel; /** - * The PaintContext interface defines the encapsulated + * The {@code PaintContext} interface defines the encapsulated * and optimized environment to generate color patterns in device * space for fill or stroke operations on a - * {@link Graphics2D}. The PaintContext provides - * the necessary colors for Graphics2D operations in the + * {@link Graphics2D}. The {@code PaintContext} provides + * the necessary colors for {@code Graphics2D} operations in the * form of a {@link Raster} associated with a {@link ColorModel}. - * The PaintContext maintains state for a particular paint + * The {@code PaintContext} maintains state for a particular paint * operation. In a multi-threaded environment, several * contexts can exist simultaneously for a single {@link Paint} object. * @see Paint @@ -48,20 +48,20 @@ public interface PaintContext { public void dispose(); /** - * Returns the ColorModel of the output. Note that - * this ColorModel might be different from the hint + * Returns the {@code ColorModel} of the output. Note that + * this {@code ColorModel} might be different from the hint * specified in the * {@link Paint#createContext(ColorModel, Rectangle, Rectangle2D, AffineTransform, RenderingHints) createContext} method of - * Paint. Not all PaintContext objects are + * {@code Paint}. Not all {@code PaintContext} objects are * capable of generating color patterns in an arbitrary - * ColorModel. - * @return the ColorModel of the output. + * {@code ColorModel}. + * @return the {@code ColorModel} of the output. */ ColorModel getColorModel(); /** - * Returns a Raster containing the colors generated for + * Returns a {@code Raster} containing the colors generated for * the graphics operation. * @param x the x coordinate of the area in device space * for which colors are generated. @@ -69,7 +69,7 @@ AffineTransform, RenderingHints) createContext} method of * for which colors are generated. * @param w the width of the area in device space * @param h the height of the area in device space - * @return a Raster representing the specified + * @return a {@code Raster} representing the specified * rectangular area and containing the colors generated for * the graphics operation. */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Panel.java b/jdk/src/java.desktop/share/classes/java/awt/Panel.java index db8d2c412ad..345db85f793 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Panel.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Panel.java @@ -27,12 +27,12 @@ package java.awt; import javax.accessibility.*; /** - * Panel is the simplest container class. A panel + * {@code Panel} is the simplest container class. A panel * provides space in which an application can attach any other * component, including other panels. *

      * The default layout manager for a panel is the - * FlowLayout layout manager. + * {@code FlowLayout} layout manager. * * @author Sami Shaio * @see java.awt.FlowLayout @@ -50,7 +50,7 @@ public class Panel extends Container implements Accessible { /** * Creates a new panel using the default layout manager. * The default layout manager for all panels is the - * FlowLayout class. + * {@code FlowLayout} class. */ public Panel() { this(new FlowLayout()); @@ -111,7 +111,7 @@ public class Panel extends Container implements Accessible { /** * This class implements accessibility support for the - * Panel class. It provides an implementation of the + * {@code Panel} class. It provides an implementation of the * Java Accessibility API appropriate to panel user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Point.java b/jdk/src/java.desktop/share/classes/java/awt/Point.java index 03337998cb5..e967d33a035 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Point.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Point.java @@ -37,7 +37,7 @@ import java.beans.Transient; */ public class Point extends Point2D implements java.io.Serializable { /** - * The X coordinate of this Point. + * The X coordinate of this {@code Point}. * If no X coordinate is set it will default to 0. * * @serial @@ -48,7 +48,7 @@ public class Point extends Point2D implements java.io.Serializable { public int x; /** - * The Y coordinate of this Point. + * The Y coordinate of this {@code Point}. * If no Y coordinate is set it will default to 0. * * @serial @@ -74,7 +74,7 @@ public class Point extends Point2D implements java.io.Serializable { /** * Constructs and initializes a point with the same location as - * the specified Point object. + * the specified {@code Point} object. * @param p a point * @since 1.1 */ @@ -85,8 +85,8 @@ public class Point extends Point2D implements java.io.Serializable { /** * Constructs and initializes a point at the specified * {@code (x,y)} location in the coordinate space. - * @param x the X coordinate of the newly constructed Point - * @param y the Y coordinate of the newly constructed Point + * @param x the X coordinate of the newly constructed {@code Point} + * @param y the Y coordinate of the newly constructed {@code Point} * @since 1.0 */ public Point(int x, int y) { @@ -113,7 +113,7 @@ public class Point extends Point2D implements java.io.Serializable { /** * Returns the location of this point. * This method is included for completeness, to parallel the - * getLocation method of Component. + * {@code getLocation} method of {@code Component}. * @return a copy of this point, at the same location * @see java.awt.Component#getLocation * @see java.awt.Point#setLocation(java.awt.Point) @@ -128,7 +128,7 @@ public class Point extends Point2D implements java.io.Serializable { /** * Sets the location of the point to the specified location. * This method is included for completeness, to parallel the - * setLocation method of Component. + * {@code setLocation} method of {@code Component}. * @param p a point, the new location for this point * @see java.awt.Component#setLocation(java.awt.Point) * @see java.awt.Point#getLocation @@ -142,7 +142,7 @@ public class Point extends Point2D implements java.io.Serializable { * Changes the point to have the specified location. *

      * This method is included for completeness, to parallel the - * setLocation method of Component. + * {@code setLocation} method of {@code Component}. * Its behavior is identical with move(int, int). * @param x the X coordinate of the new location * @param y the Y coordinate of the new location @@ -158,10 +158,10 @@ public class Point extends Point2D implements java.io.Serializable { /** * Sets the location of this point to the specified double coordinates. * The double values will be rounded to integer values. - * Any number smaller than Integer.MIN_VALUE - * will be reset to MIN_VALUE, and any number - * larger than Integer.MAX_VALUE will be - * reset to MAX_VALUE. + * Any number smaller than {@code Integer.MIN_VALUE} + * will be reset to {@code MIN_VALUE}, and any number + * larger than {@code Integer.MAX_VALUE} will be + * reset to {@code MAX_VALUE}. * * @param x the X coordinate of the new location * @param y the Y coordinate of the new location @@ -203,13 +203,13 @@ public class Point extends Point2D implements java.io.Serializable { /** * Determines whether or not two points are equal. Two instances of - * Point2D are equal if the values of their - * x and y member fields, representing + * {@code Point2D} are equal if the values of their + * {@code x} and {@code y} member fields, representing * their position in the coordinate space, are the same. - * @param obj an object to be compared with this Point2D - * @return true if the object to be compared is - * an instance of Point2D and has - * the same values; false otherwise. + * @param obj an object to be compared with this {@code Point2D} + * @return {@code true} if the object to be compared is + * an instance of {@code Point2D} and has + * the same values; {@code false} otherwise. */ public boolean equals(Object obj) { if (obj instanceof Point) { @@ -224,7 +224,7 @@ public class Point extends Point2D implements java.io.Serializable { * in the {@code (x,y)} coordinate space. This method is * intended to be used only for debugging purposes, and the content * and format of the returned string may vary between implementations. - * The returned string may be empty but may not be null. + * The returned string may be empty but may not be {@code null}. * * @return a string representation of this point */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Polygon.java b/jdk/src/java.desktop/share/classes/java/awt/Polygon.java index 7a30a958f45..90ae45ad352 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Polygon.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Polygon.java @@ -32,7 +32,7 @@ import sun.awt.geom.Crossings; import java.util.Arrays; /** - * The Polygon class encapsulates a description of a + * The {@code Polygon} class encapsulates a description of a * closed, two-dimensional region within a coordinate space. This * region is bounded by an arbitrary number of line segments, each of * which is one side of the polygon. Internally, a polygon @@ -41,12 +41,12 @@ import java.util.Arrays; * polygon, and two successive pairs are the endpoints of a * line that is a side of the polygon. The first and final * pairs of {@code (x,y)} points are joined by a line segment - * that closes the polygon. This Polygon is defined with + * that closes the polygon. This {@code Polygon} is defined with * an even-odd winding rule. See * {@link java.awt.geom.PathIterator#WIND_EVEN_ODD WIND_EVEN_ODD} * for a definition of the even-odd winding rule. * This class's hit-testing methods, which include the - * contains, intersects and inside + * {@code contains}, {@code intersects} and {@code inside} * methods, use the insideness definition described in the * {@link Shape} class comments. * @@ -58,8 +58,8 @@ import java.util.Arrays; public class Polygon implements Shape, java.io.Serializable { /** - * The total number of points. The value of npoints - * represents the number of valid points in this Polygon + * The total number of points. The value of {@code npoints} + * represents the number of valid points in this {@code Polygon} * and might be less than the number of elements in * {@link #xpoints xpoints} or {@link #ypoints ypoints}. * This value can be NULL. @@ -73,10 +73,10 @@ public class Polygon implements Shape, java.io.Serializable { /** * The array of X coordinates. The number of elements in * this array might be more than the number of X coordinates - * in this Polygon. The extra elements allow new points - * to be added to this Polygon without re-creating this + * in this {@code Polygon}. The extra elements allow new points + * to be added to this {@code Polygon} without re-creating this * array. The value of {@link #npoints npoints} is equal to the - * number of valid points in this Polygon. + * number of valid points in this {@code Polygon}. * * @serial * @see #addPoint(int, int) @@ -87,10 +87,10 @@ public class Polygon implements Shape, java.io.Serializable { /** * The array of Y coordinates. The number of elements in * this array might be more than the number of Y coordinates - * in this Polygon. The extra elements allow new points - * to be added to this Polygon without re-creating this - * array. The value of npoints is equal to the - * number of valid points in this Polygon. + * in this {@code Polygon}. The extra elements allow new points + * to be added to this {@code Polygon} without re-creating this + * array. The value of {@code npoints} is equal to the + * number of valid points in this {@code Polygon}. * * @serial * @see #addPoint(int, int) @@ -129,19 +129,19 @@ public class Polygon implements Shape, java.io.Serializable { } /** - * Constructs and initializes a Polygon from the specified + * Constructs and initializes a {@code Polygon} from the specified * parameters. * @param xpoints an array of X coordinates * @param ypoints an array of Y coordinates * @param npoints the total number of points in the - * Polygon + * {@code Polygon} * @exception NegativeArraySizeException if the value of - * npoints is negative. - * @exception IndexOutOfBoundsException if npoints is - * greater than the length of xpoints - * or the length of ypoints. - * @exception NullPointerException if xpoints or - * ypoints is null. + * {@code npoints} is negative. + * @exception IndexOutOfBoundsException if {@code npoints} is + * greater than the length of {@code xpoints} + * or the length of {@code ypoints}. + * @exception NullPointerException if {@code xpoints} or + * {@code ypoints} is {@code null}. * @since 1.0 */ public Polygon(int xpoints[], int ypoints[], int npoints) { @@ -164,7 +164,7 @@ public class Polygon implements Shape, java.io.Serializable { } /** - * Resets this Polygon object to an empty polygon. + * Resets this {@code Polygon} object to an empty polygon. * The coordinate arrays and the data in them are left untouched * but the number of points is reset to zero to mark the old * vertex data as invalid and to start accumulating new vertex @@ -172,7 +172,7 @@ public class Polygon implements Shape, java.io.Serializable { * All internally-cached data relating to the old vertices * are discarded. * Note that since the coordinate arrays from before the reset - * are reused, creating a new empty Polygon might + * are reused, creating a new empty {@code Polygon} might * be more memory efficient than resetting the current one if * the number of vertices in the new polygon data is significantly * smaller than the number of vertices in the data from before the @@ -187,11 +187,11 @@ public class Polygon implements Shape, java.io.Serializable { /** * Invalidates or flushes any internally-cached data that depends - * on the vertex coordinates of this Polygon. + * on the vertex coordinates of this {@code Polygon}. * This method should be called after any direct manipulation - * of the coordinates in the xpoints or - * ypoints arrays to avoid inconsistent results - * from methods such as getBounds or contains + * of the coordinates in the {@code xpoints} or + * {@code ypoints} arrays to avoid inconsistent results + * from methods such as {@code getBounds} or {@code contains} * that might cache data from earlier computations relating to * the vertex coordinates. * @see java.awt.Polygon#getBounds @@ -202,9 +202,9 @@ public class Polygon implements Shape, java.io.Serializable { } /** - * Translates the vertices of the Polygon by - * deltaX along the x axis and by - * deltaY along the y axis. + * Translates the vertices of the {@code Polygon} by + * {@code deltaX} along the x axis and by + * {@code deltaY} along the y axis. * @param deltaX the amount to translate along the X axis * @param deltaY the amount to translate along the Y axis * @since 1.1 @@ -221,7 +221,7 @@ public class Polygon implements Shape, java.io.Serializable { /* * Calculates the bounding box of the points passed to the constructor. - * Sets bounds to the result. + * Sets {@code bounds} to the result. * @param xpoints[] array of x coordinates * @param ypoints[] array of y coordinates * @param npoints the total number of points @@ -270,11 +270,11 @@ public class Polygon implements Shape, java.io.Serializable { } /** - * Appends the specified coordinates to this Polygon. + * Appends the specified coordinates to this {@code Polygon}. *

      * If an operation that calculates the bounding box of this - * Polygon has already been performed, such as - * getBounds or contains, then this + * {@code Polygon} has already been performed, such as + * {@code getBounds} or {@code contains}, then this * method updates the bounding box. * @param x the specified X coordinate * @param y the specified Y coordinate @@ -305,12 +305,12 @@ public class Polygon implements Shape, java.io.Serializable { } /** - * Gets the bounding box of this Polygon. + * Gets the bounding box of this {@code Polygon}. * The bounding box is the smallest {@link Rectangle} whose * sides are parallel to the x and y axes of the - * coordinate space, and can completely contain the Polygon. - * @return a Rectangle that defines the bounds of this - * Polygon. + * coordinate space, and can completely contain the {@code Polygon}. + * @return a {@code Rectangle} that defines the bounds of this + * {@code Polygon}. * @since 1.1 */ public Rectangle getBounds() { @@ -318,10 +318,10 @@ public class Polygon implements Shape, java.io.Serializable { } /** - * Returns the bounds of this Polygon. - * @return the bounds of this Polygon. + * Returns the bounds of this {@code Polygon}. + * @return the bounds of this {@code Polygon}. * @deprecated As of JDK version 1.1, - * replaced by getBounds(). + * replaced by {@code getBounds()}. * @since 1.0 */ @Deprecated @@ -337,10 +337,10 @@ public class Polygon implements Shape, java.io.Serializable { /** * Determines whether the specified {@link Point} is inside this - * Polygon. - * @param p the specified Point to be tested - * @return true if the Polygon contains the - * Point; false otherwise. + * {@code Polygon}. + * @param p the specified {@code Point} to be tested + * @return {@code true} if the {@code Polygon} contains the + * {@code Point}; {@code false} otherwise. * @see #contains(double, double) * @since 1.0 */ @@ -350,7 +350,7 @@ public class Polygon implements Shape, java.io.Serializable { /** * Determines whether the specified coordinates are inside this - * Polygon. + * {@code Polygon}. * * @param x the specified X coordinate to be tested * @param y the specified Y coordinate to be tested @@ -366,7 +366,7 @@ public class Polygon implements Shape, java.io.Serializable { /** * Determines whether the specified coordinates are contained in this - * Polygon. + * {@code Polygon}. * @param x the specified X coordinate to be tested * @param y the specified Y coordinate to be tested * @return {@code true} if this {@code Polygon} contains @@ -374,7 +374,7 @@ public class Polygon implements Shape, java.io.Serializable { * {@code false} otherwise. * @see #contains(double, double) * @deprecated As of JDK version 1.1, - * replaced by contains(int, int). + * replaced by {@code contains(int, int)}. * @since 1.0 */ @Deprecated @@ -531,15 +531,15 @@ public class Polygon implements Shape, java.io.Serializable { /** * Returns an iterator object that iterates along the boundary of this - * Polygon and provides access to the geometry - * of the outline of this Polygon. An optional + * {@code Polygon} and provides access to the geometry + * of the outline of this {@code Polygon}. An optional * {@link AffineTransform} can be specified so that the coordinates * returned in the iteration are transformed accordingly. - * @param at an optional AffineTransform to be applied to the + * @param at an optional {@code AffineTransform} to be applied to the * coordinates as they are returned in the iteration, or - * null if untransformed coordinates are desired + * {@code null} if untransformed coordinates are desired * @return a {@link PathIterator} object that provides access to the - * geometry of this Polygon. + * geometry of this {@code Polygon}. * @since 1.2 */ public PathIterator getPathIterator(AffineTransform at) { @@ -548,23 +548,23 @@ public class Polygon implements Shape, java.io.Serializable { /** * Returns an iterator object that iterates along the boundary of - * the Shape and provides access to the geometry of the - * outline of the Shape. Only SEG_MOVETO, SEG_LINETO, and + * the {@code Shape} and provides access to the geometry of the + * outline of the {@code Shape}. Only SEG_MOVETO, SEG_LINETO, and * SEG_CLOSE point types are returned by the iterator. - * Since polygons are already flat, the flatness parameter - * is ignored. An optional AffineTransform can be specified + * Since polygons are already flat, the {@code flatness} parameter + * is ignored. An optional {@code AffineTransform} can be specified * in which case the coordinates returned in the iteration are transformed * accordingly. - * @param at an optional AffineTransform to be applied to the + * @param at an optional {@code AffineTransform} to be applied to the * coordinates as they are returned in the iteration, or - * null if untransformed coordinates are desired + * {@code null} if untransformed coordinates are desired * @param flatness the maximum amount that the control points * for a given curve can vary from collinear before a subdivided * curve is replaced by a straight line connecting the * endpoints. Since polygons are already flat the - * flatness parameter is ignored. - * @return a PathIterator object that provides access to the - * Shape object's geometry. + * {@code flatness} parameter is ignored. + * @return a {@code PathIterator} object that provides access to the + * {@code Shape} object's geometry. * @since 1.2 */ public PathIterator getPathIterator(AffineTransform at, double flatness) { @@ -597,8 +597,8 @@ public class Polygon implements Shape, java.io.Serializable { /** * Tests if there are more points to read. - * @return true if there are more points to read; - * false otherwise. + * @return {@code true} if there are more points to read; + * {@code false} otherwise. */ public boolean isDone() { return index > poly.npoints; @@ -618,12 +618,12 @@ public class Polygon implements Shape, java.io.Serializable { * the iteration. * The return value is the path segment type: * SEG_MOVETO, SEG_LINETO, or SEG_CLOSE. - * A float array of length 2 must be passed in and + * A {@code float} array of length 2 must be passed in and * can be used to store the coordinates of the point(s). - * Each point is stored as a pair of float x, y + * Each point is stored as a pair of {@code float} x, y * coordinates. SEG_MOVETO and SEG_LINETO types return one * point, and SEG_CLOSE does not return any points. - * @param coords a float array that specifies the + * @param coords a {@code float} array that specifies the * coordinates of the point(s) * @return an integer representing the type and coordinates of the * current path segment. @@ -648,13 +648,13 @@ public class Polygon implements Shape, java.io.Serializable { * the iteration. * The return value is the path segment type: * SEG_MOVETO, SEG_LINETO, or SEG_CLOSE. - * A double array of length 2 must be passed in and + * A {@code double} array of length 2 must be passed in and * can be used to store the coordinates of the point(s). - * Each point is stored as a pair of double x, y + * Each point is stored as a pair of {@code double} x, y * coordinates. * SEG_MOVETO and SEG_LINETO types return one point, * and SEG_CLOSE does not return any points. - * @param coords a double array that specifies the + * @param coords a {@code double} array that specifies the * coordinates of the point(s) * @return an integer representing the type and coordinates of the * current path segment. diff --git a/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java b/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java index 7e4ffc8cb91..253351f164a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java +++ b/jdk/src/java.desktop/share/classes/java/awt/PopupMenu.java @@ -35,11 +35,11 @@ import sun.awt.AWTAccessor; * A class that implements a menu which can be dynamically popped up * at a specified position within a component. *

      - * As the inheritance hierarchy implies, a PopupMenu - * can be used anywhere a Menu can be used. - * However, if you use a PopupMenu like a Menu - * (e.g., you add it to a MenuBar), then you cannot - * call show on that PopupMenu. + * As the inheritance hierarchy implies, a {@code PopupMenu} + * can be used anywhere a {@code Menu} can be used. + * However, if you use a {@code PopupMenu} like a {@code Menu} + * (e.g., you add it to a {@code MenuBar}), then you cannot + * call {@code show} on that {@code PopupMenu}. * * @author Amy Fowler */ @@ -77,7 +77,7 @@ public class PopupMenu extends Menu { /** * Creates a new popup menu with the specified name. * - * @param label a non-null string specifying + * @param label a non-{@code null} string specifying * the popup menu's label * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. @@ -98,8 +98,8 @@ public class PopupMenu extends Menu { } /** - * Constructs a name for this MenuComponent. - * Called by getName when the name is null. + * Constructs a name for this {@code MenuComponent}. + * Called by {@code getName} when the name is {@code null}. */ String constructComponentName() { synchronized (PopupMenu.class) { @@ -139,16 +139,16 @@ public class PopupMenu extends Menu { * hierarchy of the popup menu's parent. Both the origin and the parent * must be showing on the screen for this method to be valid. *

      - * If this PopupMenu is being used as a Menu - * (i.e., it has a non-Component parent), - * then you cannot call this method on the PopupMenu. + * If this {@code PopupMenu} is being used as a {@code Menu} + * (i.e., it has a non-{@code Component} parent), + * then you cannot call this method on the {@code PopupMenu}. * * @param origin the component which defines the coordinate space * @param x the x coordinate position to popup the menu * @param y the y coordinate position to popup the menu - * @exception NullPointerException if the parent is null - * @exception IllegalArgumentException if this PopupMenu - * has a non-Component parent + * @exception NullPointerException if the parent is {@code null} + * @exception IllegalArgumentException if this {@code PopupMenu} + * has a non-{@code Component} parent * @exception IllegalArgumentException if the origin is not in the * parent's hierarchy * @exception RuntimeException if the parent is not showing on screen @@ -196,11 +196,11 @@ public class PopupMenu extends Menu { //////////////// /** - * Gets the AccessibleContext associated with this - * PopupMenu. + * Gets the {@code AccessibleContext} associated with this + * {@code PopupMenu}. * - * @return the AccessibleContext of this - * PopupMenu + * @return the {@code AccessibleContext} of this + * {@code PopupMenu} * @since 1.3 */ public AccessibleContext getAccessibleContext() { diff --git a/jdk/src/java.desktop/share/classes/java/awt/Rectangle.java b/jdk/src/java.desktop/share/classes/java/awt/Rectangle.java index 04bfc026499..fcc5cf3c729 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Rectangle.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Rectangle.java @@ -29,14 +29,14 @@ import java.awt.geom.Rectangle2D; import java.beans.Transient; /** - * A Rectangle specifies an area in a coordinate space that is - * enclosed by the Rectangle object's upper-left point + * A {@code Rectangle} specifies an area in a coordinate space that is + * enclosed by the {@code Rectangle} object's upper-left point * {@code (x,y)} * in the coordinate space, its width, and its height. *

      - * A Rectangle object's width and - * height are public fields. The constructors - * that create a Rectangle, and the methods that can modify + * A {@code Rectangle} object's {@code width} and + * {@code height} are {@code public} fields. The constructors + * that create a {@code Rectangle}, and the methods that can modify * one, do not prevent setting a negative value for width or height. *

      * @@ -120,7 +120,7 @@ public class Rectangle extends Rectangle2D { /** - * The X coordinate of the upper-left corner of the Rectangle. + * The X coordinate of the upper-left corner of the {@code Rectangle}. * * @serial * @see #setLocation(int, int) @@ -130,7 +130,7 @@ public class Rectangle extends Rectangle2D public int x; /** - * The Y coordinate of the upper-left corner of the Rectangle. + * The Y coordinate of the upper-left corner of the {@code Rectangle}. * * @serial * @see #setLocation(int, int) @@ -140,7 +140,7 @@ public class Rectangle extends Rectangle2D public int y; /** - * The width of the Rectangle. + * The width of the {@code Rectangle}. * @serial * @see #setSize(int, int) * @see #getSize() @@ -149,7 +149,7 @@ public class Rectangle extends Rectangle2D public int width; /** - * The height of the Rectangle. + * The height of the {@code Rectangle}. * * @serial * @see #setSize(int, int) @@ -177,7 +177,7 @@ public class Rectangle extends Rectangle2D } /** - * Constructs a new Rectangle whose upper-left corner + * Constructs a new {@code Rectangle} whose upper-left corner * is at (0, 0) in the coordinate space, and whose width and * height are both zero. */ @@ -186,10 +186,10 @@ public class Rectangle extends Rectangle2D } /** - * Constructs a new Rectangle, initialized to match - * the values of the specified Rectangle. - * @param r the Rectangle from which to copy initial values - * to a newly constructed Rectangle + * Constructs a new {@code Rectangle}, initialized to match + * the values of the specified {@code Rectangle}. + * @param r the {@code Rectangle} from which to copy initial values + * to a newly constructed {@code Rectangle} * @since 1.1 */ public Rectangle(Rectangle r) { @@ -197,14 +197,14 @@ public class Rectangle extends Rectangle2D } /** - * Constructs a new Rectangle whose upper-left corner is + * Constructs a new {@code Rectangle} whose upper-left corner is * specified as * {@code (x,y)} and whose width and height * are specified by the arguments of the same name. * @param x the specified X coordinate * @param y the specified Y coordinate - * @param width the width of the Rectangle - * @param height the height of the Rectangle + * @param width the width of the {@code Rectangle} + * @param height the height of the {@code Rectangle} * @since 1.0 */ public Rectangle(int x, int y, int width, int height) { @@ -215,94 +215,94 @@ public class Rectangle extends Rectangle2D } /** - * Constructs a new Rectangle whose upper-left corner + * Constructs a new {@code Rectangle} whose upper-left corner * is at (0, 0) in the coordinate space, and whose width and * height are specified by the arguments of the same name. - * @param width the width of the Rectangle - * @param height the height of the Rectangle + * @param width the width of the {@code Rectangle} + * @param height the height of the {@code Rectangle} */ public Rectangle(int width, int height) { this(0, 0, width, height); } /** - * Constructs a new Rectangle whose upper-left corner is + * Constructs a new {@code Rectangle} whose upper-left corner is * specified by the {@link Point} argument, and * whose width and height are specified by the * {@link Dimension} argument. - * @param p a Point that is the upper-left corner of - * the Rectangle - * @param d a Dimension, representing the - * width and height of the Rectangle + * @param p a {@code Point} that is the upper-left corner of + * the {@code Rectangle} + * @param d a {@code Dimension}, representing the + * width and height of the {@code Rectangle} */ public Rectangle(Point p, Dimension d) { this(p.x, p.y, d.width, d.height); } /** - * Constructs a new Rectangle whose upper-left corner is the - * specified Point, and whose width and height are both zero. - * @param p a Point that is the top left corner - * of the Rectangle + * Constructs a new {@code Rectangle} whose upper-left corner is the + * specified {@code Point}, and whose width and height are both zero. + * @param p a {@code Point} that is the top left corner + * of the {@code Rectangle} */ public Rectangle(Point p) { this(p.x, p.y, 0, 0); } /** - * Constructs a new Rectangle whose top left corner is + * Constructs a new {@code Rectangle} whose top left corner is * (0, 0) and whose width and height are specified - * by the Dimension argument. - * @param d a Dimension, specifying width and height + * by the {@code Dimension} argument. + * @param d a {@code Dimension}, specifying width and height */ public Rectangle(Dimension d) { this(0, 0, d.width, d.height); } /** - * Returns the X coordinate of the bounding Rectangle in - * double precision. - * @return the X coordinate of the bounding Rectangle. + * Returns the X coordinate of the bounding {@code Rectangle} in + * {@code double} precision. + * @return the X coordinate of the bounding {@code Rectangle}. */ public double getX() { return x; } /** - * Returns the Y coordinate of the bounding Rectangle in - * double precision. - * @return the Y coordinate of the bounding Rectangle. + * Returns the Y coordinate of the bounding {@code Rectangle} in + * {@code double} precision. + * @return the Y coordinate of the bounding {@code Rectangle}. */ public double getY() { return y; } /** - * Returns the width of the bounding Rectangle in - * double precision. - * @return the width of the bounding Rectangle. + * Returns the width of the bounding {@code Rectangle} in + * {@code double} precision. + * @return the width of the bounding {@code Rectangle}. */ public double getWidth() { return width; } /** - * Returns the height of the bounding Rectangle in - * double precision. - * @return the height of the bounding Rectangle. + * Returns the height of the bounding {@code Rectangle} in + * {@code double} precision. + * @return the height of the bounding {@code Rectangle}. */ public double getHeight() { return height; } /** - * Gets the bounding Rectangle of this Rectangle. + * Gets the bounding {@code Rectangle} of this {@code Rectangle}. *

      * This method is included for completeness, to parallel the - * getBounds method of + * {@code getBounds} method of * {@link Component}. - * @return a new Rectangle, equal to the - * bounding Rectangle for this Rectangle. + * @return a new {@code Rectangle}, equal to the + * bounding {@code Rectangle} for this {@code Rectangle}. * @see java.awt.Component#getBounds * @see #setBounds(Rectangle) * @see #setBounds(int, int, int, int) @@ -322,12 +322,12 @@ public class Rectangle extends Rectangle2D } /** - * Sets the bounding Rectangle of this Rectangle - * to match the specified Rectangle. + * Sets the bounding {@code Rectangle} of this {@code Rectangle} + * to match the specified {@code Rectangle}. *

      * This method is included for completeness, to parallel the - * setBounds method of Component. - * @param r the specified Rectangle + * {@code setBounds} method of {@code Component}. + * @param r the specified {@code Rectangle} * @see #getBounds * @see java.awt.Component#setBounds(java.awt.Rectangle) * @since 1.1 @@ -337,19 +337,19 @@ public class Rectangle extends Rectangle2D } /** - * Sets the bounding Rectangle of this - * Rectangle to the specified - * x, y, width, - * and height. + * Sets the bounding {@code Rectangle} of this + * {@code Rectangle} to the specified + * {@code x}, {@code y}, {@code width}, + * and {@code height}. *

      * This method is included for completeness, to parallel the - * setBounds method of Component. + * {@code setBounds} method of {@code Component}. * @param x the new X coordinate for the upper-left - * corner of this Rectangle + * corner of this {@code Rectangle} * @param y the new Y coordinate for the upper-left - * corner of this Rectangle - * @param width the new width for this Rectangle - * @param height the new height for this Rectangle + * corner of this {@code Rectangle} + * @param width the new width for this {@code Rectangle} + * @param height the new height for this {@code Rectangle} * @see #getBounds * @see java.awt.Component#setBounds(int, int, int, int) * @since 1.1 @@ -417,19 +417,19 @@ public class Rectangle extends Rectangle2D } /** - * Sets the bounding Rectangle of this - * Rectangle to the specified - * x, y, width, - * and height. + * Sets the bounding {@code Rectangle} of this + * {@code Rectangle} to the specified + * {@code x}, {@code y}, {@code width}, + * and {@code height}. * * @param x the new X coordinate for the upper-left - * corner of this Rectangle + * corner of this {@code Rectangle} * @param y the new Y coordinate for the upper-left - * corner of this Rectangle - * @param width the new width for this Rectangle - * @param height the new height for this Rectangle + * corner of this {@code Rectangle} + * @param width the new width for this {@code Rectangle} + * @param height the new height for this {@code Rectangle} * @deprecated As of JDK version 1.1, - * replaced by setBounds(int, int, int, int). + * replaced by {@code setBounds(int, int, int, int)}. */ @Deprecated public void reshape(int x, int y, int width, int height) { @@ -440,12 +440,12 @@ public class Rectangle extends Rectangle2D } /** - * Returns the location of this Rectangle. + * Returns the location of this {@code Rectangle}. *

      * This method is included for completeness, to parallel the - * getLocation method of Component. - * @return the Point that is the upper-left corner of - * this Rectangle. + * {@code getLocation} method of {@code Component}. + * @return the {@code Point} that is the upper-left corner of + * this {@code Rectangle}. * @see java.awt.Component#getLocation * @see #setLocation(Point) * @see #setLocation(int, int) @@ -456,12 +456,12 @@ public class Rectangle extends Rectangle2D } /** - * Moves this Rectangle to the specified location. + * Moves this {@code Rectangle} to the specified location. *

      * This method is included for completeness, to parallel the - * setLocation method of Component. - * @param p the Point specifying the new location - * for this Rectangle + * {@code setLocation} method of {@code Component}. + * @param p the {@code Point} specifying the new location + * for this {@code Rectangle} * @see java.awt.Component#setLocation(java.awt.Point) * @see #getLocation * @since 1.1 @@ -471,10 +471,10 @@ public class Rectangle extends Rectangle2D } /** - * Moves this Rectangle to the specified location. + * Moves this {@code Rectangle} to the specified location. *

      * This method is included for completeness, to parallel the - * setLocation method of Component. + * {@code setLocation} method of {@code Component}. * @param x the X coordinate of the new location * @param y the Y coordinate of the new location * @see #getLocation @@ -486,12 +486,12 @@ public class Rectangle extends Rectangle2D } /** - * Moves this Rectangle to the specified location. + * Moves this {@code Rectangle} to the specified location. * * @param x the X coordinate of the new location * @param y the Y coordinate of the new location * @deprecated As of JDK version 1.1, - * replaced by setLocation(int, int). + * replaced by {@code setLocation(int, int)}. */ @Deprecated public void move(int x, int y) { @@ -500,12 +500,12 @@ public class Rectangle extends Rectangle2D } /** - * Translates this Rectangle the indicated distance, + * Translates this {@code Rectangle} the indicated distance, * to the right along the X coordinate axis, and * downward along the Y coordinate axis. - * @param dx the distance to move this Rectangle + * @param dx the distance to move this {@code Rectangle} * along the X axis - * @param dy the distance to move this Rectangle + * @param dy the distance to move this {@code Rectangle} * along the Y axis * @see java.awt.Rectangle#setLocation(int, int) * @see java.awt.Rectangle#setLocation(java.awt.Point) @@ -578,13 +578,13 @@ public class Rectangle extends Rectangle2D } /** - * Gets the size of this Rectangle, represented by - * the returned Dimension. + * Gets the size of this {@code Rectangle}, represented by + * the returned {@code Dimension}. *

      * This method is included for completeness, to parallel the - * getSize method of Component. - * @return a Dimension, representing the size of - * this Rectangle. + * {@code getSize} method of {@code Component}. + * @return a {@code Dimension}, representing the size of + * this {@code Rectangle}. * @see java.awt.Component#getSize * @see #setSize(Dimension) * @see #setSize(int, int) @@ -595,12 +595,12 @@ public class Rectangle extends Rectangle2D } /** - * Sets the size of this Rectangle to match the - * specified Dimension. + * Sets the size of this {@code Rectangle} to match the + * specified {@code Dimension}. *

      * This method is included for completeness, to parallel the - * setSize method of Component. - * @param d the new size for the Dimension object + * {@code setSize} method of {@code Component}. + * @param d the new size for the {@code Dimension} object * @see java.awt.Component#setSize(java.awt.Dimension) * @see #getSize * @since 1.1 @@ -610,13 +610,13 @@ public class Rectangle extends Rectangle2D } /** - * Sets the size of this Rectangle to the specified + * Sets the size of this {@code Rectangle} to the specified * width and height. *

      * This method is included for completeness, to parallel the - * setSize method of Component. - * @param width the new width for this Rectangle - * @param height the new height for this Rectangle + * {@code setSize} method of {@code Component}. + * @param width the new width for this {@code Rectangle} + * @param height the new height for this {@code Rectangle} * @see java.awt.Component#setSize(int, int) * @see #getSize * @since 1.1 @@ -626,13 +626,13 @@ public class Rectangle extends Rectangle2D } /** - * Sets the size of this Rectangle to the specified + * Sets the size of this {@code Rectangle} to the specified * width and height. * - * @param width the new width for this Rectangle - * @param height the new height for this Rectangle + * @param width the new width for this {@code Rectangle} + * @param height the new height for this {@code Rectangle} * @deprecated As of JDK version 1.1, - * replaced by setSize(int, int). + * replaced by {@code setSize(int, int)}. */ @Deprecated public void resize(int width, int height) { @@ -641,12 +641,12 @@ public class Rectangle extends Rectangle2D } /** - * Checks whether or not this Rectangle contains the - * specified Point. - * @param p the Point to test - * @return true if the specified Point - * is inside this Rectangle; - * false otherwise. + * Checks whether or not this {@code Rectangle} contains the + * specified {@code Point}. + * @param p the {@code Point} to test + * @return {@code true} if the specified {@code Point} + * is inside this {@code Rectangle}; + * {@code false} otherwise. * @since 1.1 */ public boolean contains(Point p) { @@ -654,15 +654,15 @@ public class Rectangle extends Rectangle2D } /** - * Checks whether or not this Rectangle contains the + * Checks whether or not this {@code Rectangle} contains the * point at the specified location {@code (x,y)}. * * @param x the specified X coordinate * @param y the specified Y coordinate - * @return true if the point + * @return {@code true} if the point * {@code (x,y)} is inside this - * Rectangle; - * false otherwise. + * {@code Rectangle}; + * {@code false} otherwise. * @since 1.1 */ public boolean contains(int x, int y) { @@ -670,13 +670,13 @@ public class Rectangle extends Rectangle2D } /** - * Checks whether or not this Rectangle entirely contains - * the specified Rectangle. + * Checks whether or not this {@code Rectangle} entirely contains + * the specified {@code Rectangle}. * - * @param r the specified Rectangle - * @return true if the Rectangle - * is contained entirely inside this Rectangle; - * false otherwise + * @param r the specified {@code Rectangle} + * @return {@code true} if the {@code Rectangle} + * is contained entirely inside this {@code Rectangle}; + * {@code false} otherwise * @since 1.2 */ public boolean contains(Rectangle r) { @@ -684,18 +684,18 @@ public class Rectangle extends Rectangle2D } /** - * Checks whether this Rectangle entirely contains - * the Rectangle + * Checks whether this {@code Rectangle} entirely contains + * the {@code Rectangle} * at the specified location {@code (X,Y)} with the * specified dimensions {@code (W,H)}. * @param X the specified X coordinate * @param Y the specified Y coordinate - * @param W the width of the Rectangle - * @param H the height of the Rectangle - * @return true if the Rectangle specified by + * @param W the width of the {@code Rectangle} + * @param H the height of the {@code Rectangle} + * @return {@code true} if the {@code Rectangle} specified by * {@code (X, Y, W, H)} - * is entirely enclosed inside this Rectangle; - * false otherwise. + * is entirely enclosed inside this {@code Rectangle}; + * {@code false} otherwise. * @since 1.1 */ public boolean contains(int X, int Y, int W, int H) { @@ -736,17 +736,17 @@ public class Rectangle extends Rectangle2D } /** - * Checks whether or not this Rectangle contains the + * Checks whether or not this {@code Rectangle} contains the * point at the specified location {@code (X,Y)}. * * @param X the specified X coordinate * @param Y the specified Y coordinate - * @return true if the point + * @return {@code true} if the point * {@code (X,Y)} is inside this - * Rectangle; - * false otherwise. + * {@code Rectangle}; + * {@code false} otherwise. * @deprecated As of JDK version 1.1, - * replaced by contains(int, int). + * replaced by {@code contains(int, int)}. */ @Deprecated public boolean inside(int X, int Y) { @@ -770,14 +770,14 @@ public class Rectangle extends Rectangle2D } /** - * Determines whether or not this Rectangle and the specified - * Rectangle intersect. Two rectangles intersect if + * Determines whether or not this {@code Rectangle} and the specified + * {@code Rectangle} intersect. Two rectangles intersect if * their intersection is nonempty. * - * @param r the specified Rectangle - * @return true if the specified Rectangle - * and this Rectangle intersect; - * false otherwise. + * @param r the specified {@code Rectangle} + * @return {@code true} if the specified {@code Rectangle} + * and this {@code Rectangle} intersect; + * {@code false} otherwise. */ public boolean intersects(Rectangle r) { int tw = this.width; @@ -803,16 +803,16 @@ public class Rectangle extends Rectangle2D } /** - * Computes the intersection of this Rectangle with the - * specified Rectangle. Returns a new Rectangle + * Computes the intersection of this {@code Rectangle} with the + * specified {@code Rectangle}. Returns a new {@code Rectangle} * that represents the intersection of the two rectangles. * If the two rectangles do not intersect, the result will be * an empty rectangle. * - * @param r the specified Rectangle - * @return the largest Rectangle contained in both the - * specified Rectangle and in - * this Rectangle; or if the rectangles + * @param r the specified {@code Rectangle} + * @return the largest {@code Rectangle} contained in both the + * specified {@code Rectangle} and in + * this {@code Rectangle}; or if the rectangles * do not intersect, an empty rectangle. */ public Rectangle intersection(Rectangle r) { @@ -839,9 +839,9 @@ public class Rectangle extends Rectangle2D } /** - * Computes the union of this Rectangle with the - * specified Rectangle. Returns a new - * Rectangle that + * Computes the union of this {@code Rectangle} with the + * specified {@code Rectangle}. Returns a new + * {@code Rectangle} that * represents the union of the two rectangles. *

      * If either {@code Rectangle} has any dimension less than zero @@ -856,10 +856,10 @@ public class Rectangle extends Rectangle2D * too large to be expressed as an {@code int}, the result * will have a dimension of {@code Integer.MAX_VALUE} along * that dimension. - * @param r the specified Rectangle - * @return the smallest Rectangle containing both - * the specified Rectangle and this - * Rectangle. + * @param r the specified {@code Rectangle} + * @return the smallest {@code Rectangle} containing both + * the specified {@code Rectangle} and this + * {@code Rectangle}. */ public Rectangle union(Rectangle r) { long tx2 = this.width; @@ -911,14 +911,14 @@ public class Rectangle extends Rectangle2D * have a location equal to the specified coordinates and * width and height equal to zero. *

      - * After adding a point, a call to contains with the + * After adding a point, a call to {@code contains} with the * added point as an argument does not necessarily return - * true. The contains method does not - * return true for points on the right or bottom - * edges of a Rectangle. Therefore, if the added point + * {@code true}. The {@code contains} method does not + * return {@code true} for points on the right or bottom + * edges of a {@code Rectangle}. Therefore, if the added point * falls on the right or bottom edge of the enlarged - * Rectangle, contains returns - * false for that point. + * {@code Rectangle}, {@code contains} returns + * {@code false} for that point. * If the specified point must be contained within the new * {@code Rectangle}, a 1x1 rectangle should be added instead: *

      @@ -962,29 +962,29 @@ public class Rectangle extends Rectangle2D
            * have a location equal to the coordinates of the specified
            * {@code Point} and width and height equal to zero.
            * 

      - * After adding a Point, a call to contains - * with the added Point as an argument does not - * necessarily return true. The contains - * method does not return true for points on the right - * or bottom edges of a Rectangle. Therefore if the added - * Point falls on the right or bottom edge of the - * enlarged Rectangle, contains returns - * false for that Point. + * After adding a {@code Point}, a call to {@code contains} + * with the added {@code Point} as an argument does not + * necessarily return {@code true}. The {@code contains} + * method does not return {@code true} for points on the right + * or bottom edges of a {@code Rectangle}. Therefore if the added + * {@code Point} falls on the right or bottom edge of the + * enlarged {@code Rectangle}, {@code contains} returns + * {@code false} for that {@code Point}. * If the specified point must be contained within the new * {@code Rectangle}, a 1x1 rectangle should be added instead: *

            *     r.add(pt.x, pt.y, 1, 1);
            * 
      - * @param pt the new Point to add to this - * Rectangle + * @param pt the new {@code Point} to add to this + * {@code Rectangle} */ public void add(Point pt) { add(pt.x, pt.y); } /** - * Adds a Rectangle to this Rectangle. - * The resulting Rectangle is the union of the two + * Adds a {@code Rectangle} to this {@code Rectangle}. + * The resulting {@code Rectangle} is the union of the two * rectangles. *

      * If either {@code Rectangle} has any dimension less than 0, the @@ -1003,7 +1003,7 @@ public class Rectangle extends Rectangle2D * too large to be expressed as an {@code int}, the result * will have a dimension of {@code Integer.MAX_VALUE} along * that dimension. - * @param r the specified Rectangle + * @param r the specified {@code Rectangle} */ public void add(Rectangle r) { long tx2 = this.width; @@ -1039,19 +1039,19 @@ public class Rectangle extends Rectangle2D } /** - * Resizes the Rectangle both horizontally and vertically. + * Resizes the {@code Rectangle} both horizontally and vertically. *

      - * This method modifies the Rectangle so that it is - * h units larger on both the left and right side, - * and v units larger at both the top and bottom. + * This method modifies the {@code Rectangle} so that it is + * {@code h} units larger on both the left and right side, + * and {@code v} units larger at both the top and bottom. *

      - * The new Rectangle has {@code (x - h, y - v)} + * The new {@code Rectangle} has {@code (x - h, y - v)} * as its upper-left corner, * width of {@code (width + 2h)}, * and a height of {@code (height + 2v)}. *

      - * If negative values are supplied for h and - * v, the size of the Rectangle + * If negative values are supplied for {@code h} and + * {@code v}, the size of the {@code Rectangle} * decreases accordingly. * The {@code grow} method will check for integer overflow * and underflow, but does not check whether the resulting @@ -1183,14 +1183,14 @@ public class Rectangle extends Rectangle2D /** * Checks whether two rectangles are equal. *

      - * The result is true if and only if the argument is not - * null and is a Rectangle object that has the + * The result is {@code true} if and only if the argument is not + * {@code null} and is a {@code Rectangle} object that has the * same upper-left corner, width, and height as - * this Rectangle. - * @param obj the Object to compare with - * this Rectangle - * @return true if the objects are equal; - * false otherwise. + * this {@code Rectangle}. + * @param obj the {@code Object} to compare with + * this {@code Rectangle} + * @return {@code true} if the objects are equal; + * {@code false} otherwise. */ public boolean equals(Object obj) { if (obj instanceof Rectangle) { @@ -1204,10 +1204,10 @@ public class Rectangle extends Rectangle2D } /** - * Returns a String representing this - * Rectangle and its values. - * @return a String representing this - * Rectangle object's coordinate and size values. + * Returns a {@code String} representing this + * {@code Rectangle} and its values. + * @return a {@code String} representing this + * {@code Rectangle} object's coordinate and size values. */ public String toString() { return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]"; diff --git a/jdk/src/java.desktop/share/classes/java/awt/RenderingHints.java b/jdk/src/java.desktop/share/classes/java/awt/RenderingHints.java index 524fc999ad1..6403821b66a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/RenderingHints.java +++ b/jdk/src/java.desktop/share/classes/java/awt/RenderingHints.java @@ -161,9 +161,9 @@ public class RenderingHints /** * Returns true if the specified object is a valid value * for this Key. - * @param val the Object to test for validity - * @return true if val is valid; - * false otherwise. + * @param val the {@code Object} to test for validity + * @return {@code true} if {@code val} is valid; + * {@code false} otherwise. */ public abstract boolean isCompatibleValue(Object val); @@ -519,7 +519,7 @@ public class RenderingHints /** * LCD text contrast rendering hint key. - * The value is an Integer object which is used as a text + * The value is an {@code Integer} object which is used as a text * contrast adjustment when used in conjunction with an LCD text * anti-aliasing hint such as * {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}. @@ -1028,7 +1028,7 @@ public class RenderingHints * Constructs a new object with the specified key/value pair. * @param key the key of the particular hint property * @param value the value of the hint property specified with - * key + * {@code key} */ public RenderingHints(Key key, Object value) { hintmap.put(key, value); @@ -1036,21 +1036,21 @@ public class RenderingHints /** * Returns the number of key-value mappings in this - * RenderingHints. + * {@code RenderingHints}. * * @return the number of key-value mappings in this - * RenderingHints. + * {@code RenderingHints}. */ public int size() { return hintmap.size(); } /** - * Returns true if this - * RenderingHints contains no key-value mappings. + * Returns {@code true} if this + * {@code RenderingHints} contains no key-value mappings. * - * @return true if this - * RenderingHints contains no key-value mappings. + * @return {@code true} if this + * {@code RenderingHints} contains no key-value mappings. */ public boolean isEmpty() { return hintmap.isEmpty(); @@ -1074,19 +1074,19 @@ public class RenderingHints /** * Returns true if this RenderingHints maps one or more keys to the * specified value. - * More formally, returns true if and only - * if this RenderingHints - * contains at least one mapping to a value v such that + * More formally, returns {@code true} if and only + * if this {@code RenderingHints} + * contains at least one mapping to a value {@code v} such that *

            * (value==null ? v==null : value.equals(v))
            * 
      . * This operation will probably require time linear in the - * RenderingHints size for most implementations - * of RenderingHints. + * {@code RenderingHints} size for most implementations + * of {@code RenderingHints}. * * @param value value whose presence in this - * RenderingHints is to be tested. - * @return true if this RenderingHints + * {@code RenderingHints} is to be tested. + * @return {@code true} if this {@code RenderingHints} * maps one or more keys to the specified value. */ public boolean containsValue(Object value) { @@ -1139,19 +1139,19 @@ public class RenderingHints /** * Adds all of the keys and corresponding values from the specified - * RenderingHints object to this - * RenderingHints object. Keys that are present in - * this RenderingHints object, but not in the specified - * RenderingHints object are not affected. + * {@code RenderingHints} object to this + * {@code RenderingHints} object. Keys that are present in + * this {@code RenderingHints} object, but not in the specified + * {@code RenderingHints} object are not affected. * @param hints the set of key/value pairs to be added to this - * RenderingHints object + * {@code RenderingHints} object */ public void add(RenderingHints hints) { hintmap.putAll(hints.hintmap); } /** - * Clears this RenderingHints object of all key/value + * Clears this {@code RenderingHints} object of all key/value * pairs. */ public void clear() { @@ -1202,93 +1202,93 @@ public class RenderingHints } /** - * Returns a Set view of the Keys contained in this - * RenderingHints. The Set is backed by the - * RenderingHints, so changes to the - * RenderingHints are reflected in the Set, - * and vice-versa. If the RenderingHints is modified - * while an iteration over the Set is in progress, - * the results of the iteration are undefined. The Set + * Returns a {@code Set} view of the Keys contained in this + * {@code RenderingHints}. The Set is backed by the + * {@code RenderingHints}, so changes to the + * {@code RenderingHints} are reflected in the {@code Set}, + * and vice-versa. If the {@code RenderingHints} is modified + * while an iteration over the {@code Set} is in progress, + * the results of the iteration are undefined. The {@code Set} * supports element removal, which removes the corresponding - * mapping from the RenderingHints, via the - * Iterator.remove, Set.remove, - * removeAll retainAll, and - * clear operations. It does not support - * the add or addAll operations. + * mapping from the {@code RenderingHints}, via the + * {@code Iterator.remove}, {@code Set.remove}, + * {@code removeAll retainAll}, and + * {@code clear} operations. It does not support + * the {@code add} or {@code addAll} operations. * - * @return a Set view of the keys contained - * in this RenderingHints. + * @return a {@code Set} view of the keys contained + * in this {@code RenderingHints}. */ public Set keySet() { return hintmap.keySet(); } /** - * Returns a Collection view of the values - * contained in this RenderingHints. - * The Collection is backed by the - * RenderingHints, so changes to - * the RenderingHints are reflected in - * the Collection, and vice-versa. - * If the RenderingHints is modified while - * an iteration over the Collection is + * Returns a {@code Collection} view of the values + * contained in this {@code RenderingHints}. + * The {@code Collection} is backed by the + * {@code RenderingHints}, so changes to + * the {@code RenderingHints} are reflected in + * the {@code Collection}, and vice-versa. + * If the {@code RenderingHints} is modified while + * an iteration over the {@code Collection} is * in progress, the results of the iteration are undefined. - * The Collection supports element removal, + * The {@code Collection} supports element removal, * which removes the corresponding mapping from the - * RenderingHints, via the - * Iterator.remove, - * Collection.remove, removeAll, - * retainAll and clear operations. - * It does not support the add or - * addAll operations. + * {@code RenderingHints}, via the + * {@code Iterator.remove}, + * {@code Collection.remove}, {@code removeAll}, + * {@code retainAll} and {@code clear} operations. + * It does not support the {@code add} or + * {@code addAll} operations. * - * @return a Collection view of the values - * contained in this RenderingHints. + * @return a {@code Collection} view of the values + * contained in this {@code RenderingHints}. */ public Collection values() { return hintmap.values(); } /** - * Returns a Set view of the mappings contained - * in this RenderingHints. Each element in the - * returned Set is a Map.Entry. - * The Set is backed by the RenderingHints, - * so changes to the RenderingHints are reflected - * in the Set, and vice-versa. If the - * RenderingHints is modified while - * while an iteration over the Set is in progress, + * Returns a {@code Set} view of the mappings contained + * in this {@code RenderingHints}. Each element in the + * returned {@code Set} is a {@code Map.Entry}. + * The {@code Set} is backed by the {@code RenderingHints}, + * so changes to the {@code RenderingHints} are reflected + * in the {@code Set}, and vice-versa. If the + * {@code RenderingHints} is modified while + * while an iteration over the {@code Set} is in progress, * the results of the iteration are undefined. *

      - * The entrySet returned from a RenderingHints object + * The entrySet returned from a {@code RenderingHints} object * is not modifiable. * - * @return a Set view of the mappings contained in - * this RenderingHints. + * @return a {@code Set} view of the mappings contained in + * this {@code RenderingHints}. */ public Set> entrySet() { return Collections.unmodifiableMap(hintmap).entrySet(); } /** - * Compares the specified Object with this - * RenderingHints for equality. - * Returns true if the specified object is also a - * Map and the two Map objects represent - * the same mappings. More formally, two Map objects - * t1 and t2 represent the same mappings - * if t1.keySet().equals(t2.keySet()) and for every - * key k in t1.keySet(), + * Compares the specified {@code Object} with this + * {@code RenderingHints} for equality. + * Returns {@code true} if the specified object is also a + * {@code Map} and the two {@code Map} objects represent + * the same mappings. More formally, two {@code Map} objects + * {@code t1} and {@code t2} represent the same mappings + * if {@code t1.keySet().equals(t2.keySet())} and for every + * key {@code k} in {@code t1.keySet()}, *

            * (t1.get(k)==null ? t2.get(k)==null : t1.get(k).equals(t2.get(k)))
            * 
      . - * This ensures that the equals method works properly across - * different implementations of the Map interface. + * This ensures that the {@code equals} method works properly across + * different implementations of the {@code Map} interface. * - * @param o Object to be compared for equality with - * this RenderingHints. - * @return true if the specified Object - * is equal to this RenderingHints. + * @param o {@code Object} to be compared for equality with + * this {@code RenderingHints}. + * @return {@code true} if the specified {@code Object} + * is equal to this {@code RenderingHints}. */ public boolean equals(Object o) { if (o instanceof RenderingHints) { @@ -1300,16 +1300,16 @@ public class RenderingHints } /** - * Returns the hash code value for this RenderingHints. - * The hash code of a RenderingHints is defined to be - * the sum of the hashCodes of each Entry in the - * RenderingHints object's entrySet view. This ensures that - * t1.equals(t2) implies that - * t1.hashCode()==t2.hashCode() for any two Map - * objects t1 and t2, as required by the general - * contract of Object.hashCode. + * Returns the hash code value for this {@code RenderingHints}. + * The hash code of a {@code RenderingHints} is defined to be + * the sum of the hashCodes of each {@code Entry} in the + * {@code RenderingHints} object's entrySet view. This ensures that + * {@code t1.equals(t2)} implies that + * {@code t1.hashCode()==t2.hashCode()} for any two {@code Map} + * objects {@code t1} and {@code t2}, as required by the general + * contract of {@code Object.hashCode}. * - * @return the hash code value for this RenderingHints. + * @return the hash code value for this {@code RenderingHints}. * @see java.util.Map.Entry#hashCode() * @see Object#hashCode() * @see Object#equals(Object) @@ -1320,8 +1320,8 @@ public class RenderingHints } /** - * Creates a clone of this RenderingHints object - * that has the same contents as this RenderingHints + * Creates a clone of this {@code RenderingHints} object + * that has the same contents as this {@code RenderingHints} * object. * @return a clone of this instance. */ @@ -1344,7 +1344,7 @@ public class RenderingHints /** * Returns a rather long string representation of the hashmap * which contains the mappings of keys to values for this - * RenderingHints object. + * {@code RenderingHints} object. * @return a string representation of this object. */ public String toString() { diff --git a/jdk/src/java.desktop/share/classes/java/awt/Robot.java b/jdk/src/java.desktop/share/classes/java/awt/Robot.java index a915b2232b9..8483ed35297 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Robot.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Robot.java @@ -49,12 +49,12 @@ import sun.awt.image.SunWritableRaster; * Using the class to generate input events differs from posting * events to the AWT event queue or AWT components in that the * events are generated in the platform's native input - * queue. For example, Robot.mouseMove will actually move + * queue. For example, {@code Robot.mouseMove} will actually move * the mouse cursor instead of just generating mouse move events. *

      * Note that some platforms require special privileges or extensions * to access low-level input control. If the current platform configuration - * does not allow input control, an AWTException will be thrown + * does not allow input control, an {@code AWTException} will be thrown * when trying to construct Robot objects. For example, X-Window systems * will throw the exception if the XTEST 2.2 standard extension is not supported * (or not enabled) by the X server. @@ -80,7 +80,7 @@ public class Robot { * @throws AWTException if the platform configuration does not allow * low-level input control. This exception is always thrown when * GraphicsEnvironment.isHeadless() returns true - * @throws SecurityException if createRobot permission is not granted + * @throws SecurityException if {@code createRobot} permission is not granted * @see java.awt.GraphicsEnvironment#isHeadless * @see SecurityManager#checkPermission * @see AWTPermission @@ -113,9 +113,9 @@ public class Robot { * @throws AWTException if the platform configuration does not allow * low-level input control. This exception is always thrown when * GraphicsEnvironment.isHeadless() returns true. - * @throws IllegalArgumentException if screen is not a screen + * @throws IllegalArgumentException if {@code screen} is not a screen * GraphicsDevice. - * @throws SecurityException if createRobot permission is not granted + * @throws SecurityException if {@code createRobot} permission is not granted * @see java.awt.GraphicsEnvironment#isHeadless * @see GraphicsDevice * @see SecurityManager#checkPermission @@ -336,14 +336,14 @@ public class Robot { /** * Presses a given key. The key should be released using the - * keyRelease method. + * {@code keyRelease} method. *

      * Key codes that have more than one physical key associated with them - * (e.g. KeyEvent.VK_SHIFT could mean either the + * (e.g. {@code KeyEvent.VK_SHIFT} could mean either the * left or right shift key) will map to the left key. * - * @param keycode Key to press (e.g. KeyEvent.VK_A) - * @throws IllegalArgumentException if keycode is not + * @param keycode Key to press (e.g. {@code KeyEvent.VK_A}) + * @throws IllegalArgumentException if {@code keycode} is not * a valid key * @see #keyRelease(int) * @see java.awt.event.KeyEvent @@ -358,11 +358,11 @@ public class Robot { * Releases a given key. *

      * Key codes that have more than one physical key associated with them - * (e.g. KeyEvent.VK_SHIFT could mean either the + * (e.g. {@code KeyEvent.VK_SHIFT} could mean either the * left or right shift key) will map to the left key. * - * @param keycode Key to release (e.g. KeyEvent.VK_A) - * @throws IllegalArgumentException if keycode is not a + * @param keycode Key to release (e.g. {@code KeyEvent.VK_A}) + * @throws IllegalArgumentException if {@code keycode} is not a * valid key * @see #keyPress(int) * @see java.awt.event.KeyEvent @@ -399,8 +399,8 @@ public class Robot { * not include the mouse cursor. * @param screenRect Rect to capture in screen coordinates * @return The captured image - * @throws IllegalArgumentException if screenRect width and height are not greater than zero - * @throws SecurityException if readDisplayPixels permission is not granted + * @throws IllegalArgumentException if {@code screenRect} width and height are not greater than zero + * @throws SecurityException if {@code readDisplayPixels} permission is not granted * @see SecurityManager#checkPermission * @see AWTPermission */ @@ -470,18 +470,18 @@ public class Robot { } /** - * Returns whether this Robot automatically invokes waitForIdle + * Returns whether this Robot automatically invokes {@code waitForIdle} * after generating an event. - * @return Whether waitForIdle is automatically called + * @return Whether {@code waitForIdle} is automatically called */ public synchronized boolean isAutoWaitForIdle() { return isAutoWaitForIdle; } /** - * Sets whether this Robot automatically invokes waitForIdle + * Sets whether this Robot automatically invokes {@code waitForIdle} * after generating an event. - * @param isOn Whether waitForIdle is automatically invoked + * @param isOn Whether {@code waitForIdle} is automatically invoked */ public synchronized void setAutoWaitForIdle(boolean isOn) { isAutoWaitForIdle = isOn; @@ -526,8 +526,8 @@ public class Robot { /** * Sleeps for the specified time. - * To catch any InterruptedExceptions that occur, - * Thread.sleep() may be used instead. + * To catch any {@code InterruptedException}s that occur, + * {@code Thread.sleep()} may be used instead. * * @param ms time to sleep in milliseconds * @throws IllegalArgumentException if {@code ms} diff --git a/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java b/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java index 65eaed68924..8ae391daa89 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java @@ -47,8 +47,8 @@ import java.io.IOException; * *

      * The state of the horizontal and vertical scrollbars is represented - * by two ScrollPaneAdjustable objects (one for each - * dimension) which implement the Adjustable interface. + * by two {@code ScrollPaneAdjustable} objects (one for each + * dimension) which implement the {@code Adjustable} interface. * The API provides methods to access those objects such that the * attributes on the Adjustable object (such as unitIncrement, value, * etc.) can be manipulated. @@ -71,7 +71,7 @@ import java.io.IOException; * be reset using setSize(). *

      * Scrolling with the wheel on a wheel-equipped mouse is enabled by default. - * This can be disabled using setWheelScrollingEnabled. + * This can be disabled using {@code setWheelScrollingEnabled}. * Wheel scrolling can be customized by setting the block and * unit increment of the horizontal and vertical Adjustables. * For information on how mouse wheel events are dispatched, see @@ -136,9 +136,9 @@ public class ScrollPane extends Container implements Accessible { /** * An adjustable vertical scrollbar. * It is important to note that you must NOT call 3 - * Adjustable methods, namely: - * setMinimum(), setMaximum(), - * setVisibleAmount(). + * {@code Adjustable} methods, namely: + * {@code setMinimum()}, {@code setMaximum()}, + * {@code setVisibleAmount()}. * * @serial * @see #getVAdjustable @@ -148,9 +148,9 @@ public class ScrollPane extends Container implements Accessible { /** * An adjustable horizontal scrollbar. * It is important to note that you must NOT call 3 - * Adjustable methods, namely: - * setMinimum(), setMaximum(), - * setVisibleAmount(). + * {@code Adjustable} methods, namely: + * {@code setMinimum()}, {@code setMaximum()}, + * {@code setVisibleAmount()}. * * @serial * @see #getHAdjustable @@ -318,10 +318,10 @@ public class ScrollPane extends Container implements Accessible { } /** - * Returns the ScrollPaneAdjustable object which + * Returns the {@code ScrollPaneAdjustable} object which * represents the state of the vertical scrollbar. * The declared return type of this method is - * Adjustable to maintain backward compatibility. + * {@code Adjustable} to maintain backward compatibility. * * @see java.awt.ScrollPaneAdjustable * @return the vertical scrollbar state @@ -331,10 +331,10 @@ public class ScrollPane extends Container implements Accessible { } /** - * Returns the ScrollPaneAdjustable object which + * Returns the {@code ScrollPaneAdjustable} object which * represents the state of the horizontal scrollbar. * The declared return type of this method is - * Adjustable to maintain backward compatibility. + * {@code Adjustable} to maintain backward compatibility. * * @see java.awt.ScrollPaneAdjustable * @return the horizontal scrollbar state @@ -488,7 +488,7 @@ public class ScrollPane extends Container implements Accessible { /** * @deprecated As of JDK version 1.1, - * replaced by doLayout(). + * replaced by {@code doLayout()}. */ @Deprecated public void layout() { @@ -573,11 +573,11 @@ public class ScrollPane extends Container implements Accessible { /** * Returns a string representing the state of this - * ScrollPane. This + * {@code ScrollPane}. This * method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this scroll pane */ @@ -610,8 +610,8 @@ public class ScrollPane extends Container implements Accessible { /** * Process mouse wheel events that are delivered to this - * ScrollPane by scrolling an appropriate amount. - *

      Note that if the event parameter is null + * {@code ScrollPane} by scrolling an appropriate amount. + *

      Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -643,9 +643,9 @@ public class ScrollPane extends Container implements Accessible { * Enables/disables scrolling in response to movement of the mouse wheel. * Wheel scrolling is enabled by default. * - * @param handleWheel true if scrolling should be done + * @param handleWheel {@code true} if scrolling should be done * automatically for a MouseWheelEvent, - * false otherwise. + * {@code false} otherwise. * @see #isWheelScrollingEnabled * @see java.awt.event.MouseWheelEvent * @see java.awt.event.MouseWheelListener @@ -683,8 +683,8 @@ public class ScrollPane extends Container implements Accessible { /** * Reads default serializable fields to stream. * @exception HeadlessException if - * GraphicsEnvironment.isHeadless() returns - * true + * {@code GraphicsEnvironment.isHeadless()} returns + * {@code true} * @see java.awt.GraphicsEnvironment#isHeadless */ private void readObject(ObjectInputStream s) @@ -779,7 +779,7 @@ public class ScrollPane extends Container implements Accessible { /** * This class implements accessibility support for the - * ScrollPane class. It provides an implementation of the + * {@code ScrollPane} class. It provides an implementation of the * Java Accessibility API appropriate to scroll pane user-interface * elements. * @since 1.3 diff --git a/jdk/src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java b/jdk/src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java index 6d3a6d01bf9..657c7d7e6d1 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ScrollPaneAdjustable.java @@ -34,15 +34,15 @@ import java.io.Serializable; /** * This class represents the state of a horizontal or vertical - * scrollbar of a ScrollPane. Objects of this class are - * returned by ScrollPane methods. + * scrollbar of a {@code ScrollPane}. Objects of this class are + * returned by {@code ScrollPane} methods. * * @since 1.4 */ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** - * The ScrollPane this object is a scrollbar of. + * The {@code ScrollPane} this object is a scrollbar of. * @serial */ private ScrollPane sp; @@ -59,8 +59,8 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * The value of this scrollbar. - * value should be greater than minimum - * and less than maximum + * {@code value} should be greater than {@code minimum} + * and less than {@code maximum} * * @serial * @see #getValue @@ -70,14 +70,14 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * The minimum value of this scrollbar. - * This value can only be set by the ScrollPane. + * This value can only be set by the {@code ScrollPane}. *

      * ATTN: In current implementation - * minimum is always 0. This field can - * only be altered via setSpan method and - * ScrollPane always calls that method with - * 0 for the minimum. getMinimum method - * always returns 0 without checking this field. + * {@code minimum} is always {@code 0}. This field can + * only be altered via {@code setSpan} method and + * {@code ScrollPane} always calls that method with + * {@code 0} for the minimum. {@code getMinimum} method + * always returns {@code 0} without checking this field. * * @serial * @see #getMinimum @@ -87,7 +87,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * The maximum value of this scrollbar. - * This value can only be set by the ScrollPane. + * This value can only be set by the {@code ScrollPane}. * * @serial * @see #getMaximum @@ -97,7 +97,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * The size of the visible portion of this scrollbar. - * This value can only be set by the ScrollPane. + * This value can only be set by the {@code ScrollPane}. * * @serial * @see #getVisibleAmount @@ -106,7 +106,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { private int visibleAmount; /** - * The adjusting status of the Scrollbar. + * The adjusting status of the {@code Scrollbar}. * True if the value is in the process of changing as a result of * actions being taken by the user. * @@ -141,7 +141,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { private AdjustmentListener adjustmentListener; /** - * Error message for AWTError reported when one of + * Error message for {@code AWTError} reported when one of * the public but unsupported methods is called. */ private static final String SCROLLPANE_ONLY = @@ -174,13 +174,13 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * Constructs a new object to represent specified scrollabar - * of the specified ScrollPane. + * of the specified {@code ScrollPane}. * Only ScrollPane creates instances of this class. - * @param sp ScrollPane - * @param l AdjustmentListener to add upon creation. + * @param sp {@code ScrollPane} + * @param l {@code AdjustmentListener} to add upon creation. * @param orientation specifies which scrollbar this object represents, - * can be either Adjustable.HORIZONTAL - * or Adjustable.VERTICAL. + * can be either {@code Adjustable.HORIZONTAL} + * or {@code Adjustable.VERTICAL}. */ ScrollPaneAdjustable(ScrollPane sp, AdjustmentListener l, int orientation) { this.sp = sp; @@ -190,8 +190,8 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * This is called by the scrollpane itself to update the - * minimum, maximum and - * visible values. The scrollpane is the only one + * {@code minimum}, {@code maximum} and + * {@code visible} values. The scrollpane is the only one * that should be changing these since it is the source of these * values. */ @@ -208,8 +208,8 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * Returns the orientation of this scrollbar. * @return the orientation of this scrollbar, either - * Adjustable.HORIZONTAL or - * Adjustable.VERTICAL + * {@code Adjustable.HORIZONTAL} or + * {@code Adjustable.VERTICAL} */ public int getOrientation() { return orientation; @@ -218,7 +218,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * This method should NOT be called by user code. * This method is public for this class to properly implement - * Adjustable interface. + * {@code Adjustable} interface. * * @throws AWTError Always throws an error when called. */ @@ -235,7 +235,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * This method should NOT be called by user code. * This method is public for this class to properly implement - * Adjustable interface. + * {@code Adjustable} interface. * * @throws AWTError Always throws an error when called. */ @@ -272,7 +272,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * This method should NOT be called by user code. * This method is public for this class to properly implement - * Adjustable interface. + * {@code Adjustable} interface. * * @throws AWTError Always throws an error when called. */ @@ -286,7 +286,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** - * Sets the valueIsAdjusting property. + * Sets the {@code valueIsAdjusting} property. * * @param b new adjustment-in-progress status * @see #getValueIsAdjusting @@ -307,7 +307,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { * Returns true if the value is in the process of changing as a * result of actions being taken by the user. * - * @return the value of the valueIsAdjusting property + * @return the value of the {@code valueIsAdjusting} property * @see #setValueIsAdjusting */ public boolean getValueIsAdjusting() { @@ -361,8 +361,8 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * Adds the specified adjustment listener to receive adjustment - * events from this ScrollPaneAdjustable. - * If l is null, no exception is thrown + * events from this {@code ScrollPaneAdjustable}. + * If {@code l} is {@code null}, no exception is thrown * and no action is performed. *

      Refer to AWT Threading Issues for details on AWT's threading model. @@ -382,8 +382,8 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * Removes the specified adjustment listener so that it no longer - * receives adjustment events from this ScrollPaneAdjustable. - * If l is null, no exception is thrown + * receives adjustment events from this {@code ScrollPaneAdjustable}. + * If {@code l} is {@code null}, no exception is thrown * and no action is performed. *

      Refer to AWT Threading Issues for details on AWT's threading model. @@ -404,10 +404,10 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { /** * Returns an array of all the adjustment listeners - * registered on this ScrollPaneAdjustable. + * registered on this {@code ScrollPaneAdjustable}. * - * @return all of this ScrollPaneAdjustable's - * AdjustmentListeners + * @return all of this {@code ScrollPaneAdjustable}'s + * {@code AdjustmentListener}s * or an empty array if no adjustment * listeners are currently registered * @@ -435,7 +435,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { * This method is intended to be used only for debugging purposes, * and the content and format of the returned string may vary * between implementations. The returned string may be empty but - * may not be null. + * may not be {@code null}. * * @return the parameter string of this scrollbar. */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Scrollbar.java b/jdk/src/java.desktop/share/classes/java/awt/Scrollbar.java index ae2cb0e7d41..7bec1ef7956 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Scrollbar.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Scrollbar.java @@ -34,7 +34,7 @@ import javax.accessibility.*; /** - * The Scrollbar class embodies a scroll bar, a + * The {@code Scrollbar} class embodies a scroll bar, a * familiar user-interface object. A scroll bar provides a * convenient means for allowing a user to select from a * range of values. The following three vertical @@ -72,9 +72,9 @@ import javax.accessibility.*; *


      *

      * Note that the actual maximum value of the scroll bar is the - * maximum minus the visible amount. - * In the previous example, because the maximum is - * 300 and the visible amount is 60, the actual maximum + * {@code maximum} minus the {@code visible amount}. + * In the previous example, because the {@code maximum} is + * 300 and the {@code visible amount} is 60, the actual maximum * value is 240. The range of the scrollbar track is 0 - 300. * The left side of the bubble indicates the value of the * scroll bar. @@ -89,39 +89,39 @@ import javax.accessibility.*; * increment and block decrement areas. *

      * When the user changes the value of the scroll bar, the scroll bar - * receives an instance of AdjustmentEvent. + * receives an instance of {@code AdjustmentEvent}. * The scroll bar processes this event, passing it along to * any registered listeners. *

      * Any object that wishes to be notified of changes to the * scroll bar's value should implement - * AdjustmentListener, an interface defined in - * the package java.awt.event. + * {@code AdjustmentListener}, an interface defined in + * the package {@code java.awt.event}. * Listeners can be added and removed dynamically by calling - * the methods addAdjustmentListener and - * removeAdjustmentListener. + * the methods {@code addAdjustmentListener} and + * {@code removeAdjustmentListener}. *

      - * The AdjustmentEvent class defines five types + * The {@code AdjustmentEvent} class defines five types * of adjustment event, listed here: * *

        - *
      • AdjustmentEvent.TRACK is sent out when the + *
      • {@code AdjustmentEvent.TRACK} is sent out when the * user drags the scroll bar's bubble. - *
      • AdjustmentEvent.UNIT_INCREMENT is sent out + *
      • {@code AdjustmentEvent.UNIT_INCREMENT} is sent out * when the user clicks in the left arrow of a horizontal scroll * bar, or the top arrow of a vertical scroll bar, or makes the * equivalent gesture from the keyboard. - *
      • AdjustmentEvent.UNIT_DECREMENT is sent out + *
      • {@code AdjustmentEvent.UNIT_DECREMENT} is sent out * when the user clicks in the right arrow of a horizontal scroll * bar, or the bottom arrow of a vertical scroll bar, or makes the * equivalent gesture from the keyboard. - *
      • AdjustmentEvent.BLOCK_INCREMENT is sent out + *
      • {@code AdjustmentEvent.BLOCK_INCREMENT} is sent out * when the user clicks in the track, to the left of the bubble * on a horizontal scroll bar, or above the bubble on a vertical * scroll bar. By convention, the Page Up * key is equivalent, if the user is using a keyboard that * defines a Page Up key. - *
      • AdjustmentEvent.BLOCK_DECREMENT is sent out + *
      • {@code AdjustmentEvent.BLOCK_DECREMENT} is sent out * when the user clicks in the track, to the right of the bubble * on a horizontal scroll bar, or below the bubble on a vertical * scroll bar. By convention, the Page Down @@ -138,23 +138,23 @@ import javax.accessibility.*; * and the corresponding JDK 1.0 event type it replaces. * *
          - *
        • AdjustmentEvent.TRACK replaces - * Event.SCROLL_ABSOLUTE - *
        • AdjustmentEvent.UNIT_INCREMENT replaces - * Event.SCROLL_LINE_UP - *
        • AdjustmentEvent.UNIT_DECREMENT replaces - * Event.SCROLL_LINE_DOWN - *
        • AdjustmentEvent.BLOCK_INCREMENT replaces - * Event.SCROLL_PAGE_UP - *
        • AdjustmentEvent.BLOCK_DECREMENT replaces - * Event.SCROLL_PAGE_DOWN + *
        • {@code AdjustmentEvent.TRACK} replaces + * {@code Event.SCROLL_ABSOLUTE} + *
        • {@code AdjustmentEvent.UNIT_INCREMENT} replaces + * {@code Event.SCROLL_LINE_UP} + *
        • {@code AdjustmentEvent.UNIT_DECREMENT} replaces + * {@code Event.SCROLL_LINE_DOWN} + *
        • {@code AdjustmentEvent.BLOCK_INCREMENT} replaces + * {@code Event.SCROLL_PAGE_UP} + *
        • {@code AdjustmentEvent.BLOCK_DECREMENT} replaces + * {@code Event.SCROLL_PAGE_DOWN} *
        *

        - * Note: We recommend using a Scrollbar + * Note: We recommend using a {@code Scrollbar} * for value selection only. If you want to implement * a scrollable component inside a container, we recommend you use * a {@link ScrollPane ScrollPane}. If you use a - * Scrollbar for this purpose, you are likely to + * {@code Scrollbar} for this purpose, you are likely to * encounter issues with painting, key handling, sizing and * positioning. * @@ -176,10 +176,10 @@ public class Scrollbar extends Component implements Adjustable, Accessible { public static final int VERTICAL = 1; /** - * The value of the Scrollbar. - * This property must be greater than or equal to minimum + * The value of the {@code Scrollbar}. + * This property must be greater than or equal to {@code minimum} * and less than or equal to - * maximum - visibleAmount + * {@code maximum - visibleAmount} * * @serial * @see #getValue @@ -188,8 +188,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { int value; /** - * The maximum value of the Scrollbar. - * This value must be greater than the minimum + * The maximum value of the {@code Scrollbar}. + * This value must be greater than the {@code minimum} * value.
        * * @serial @@ -199,8 +199,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { int maximum; /** - * The minimum value of the Scrollbar. - * This value must be less than the maximum + * The minimum value of the {@code Scrollbar}. + * This value must be less than the {@code maximum} * value.
        * * @serial @@ -210,7 +210,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { int minimum; /** - * The size of the Scrollbar's bubble. + * The size of the {@code Scrollbar}'s bubble. * When a scroll bar is used to select a range of values, * the visibleAmount represents the size of this range. * Depending on platform, this may be visually indicated @@ -223,11 +223,11 @@ public class Scrollbar extends Component implements Adjustable, Accessible { int visibleAmount; /** - * The Scrollbar's orientation--being either horizontal + * The {@code Scrollbar}'s orientation--being either horizontal * or vertical. * This value should be specified when the scrollbar is created.
        - * orientation can be either : VERTICAL or - * HORIZONTAL only. + * orientation can be either : {@code VERTICAL} or + * {@code HORIZONTAL} only. * * @serial * @see #getOrientation @@ -258,7 +258,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { int pageIncrement = 10; /** - * The adjusting status of the Scrollbar. + * The adjusting status of the {@code Scrollbar}. * True if the value is in the process of changing as a result of * actions being taken by the user. * @@ -306,7 +306,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * orientation * indicates whether the scroll bar is vertical *
        or horizontal - * Scrollbar.VERTICAL + * {@code Scrollbar.VERTICAL} * * * value @@ -360,14 +360,14 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Constructs a new scroll bar with the specified orientation. *

        - * The orientation argument must take one of the two - * values Scrollbar.HORIZONTAL, - * or Scrollbar.VERTICAL, + * The {@code orientation} argument must take one of the two + * values {@code Scrollbar.HORIZONTAL}, + * or {@code Scrollbar.VERTICAL}, * indicating a horizontal or vertical scroll bar, respectively. * * @param orientation indicates the orientation of the scroll bar * @exception IllegalArgumentException when an illegal value for - * the orientation argument is supplied + * the {@code orientation} argument is supplied * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless @@ -380,9 +380,9 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * Constructs a new scroll bar with the specified orientation, * initial value, visible amount, and minimum and maximum values. *

        - * The orientation argument must take one of the two - * values Scrollbar.HORIZONTAL, - * or Scrollbar.VERTICAL, + * The {@code orientation} argument must take one of the two + * values {@code Scrollbar.HORIZONTAL}, + * or {@code Scrollbar.VERTICAL}, * indicating a horizontal or vertical scroll bar, respectively. *

        * The parameters supplied to this constructor are subject to the @@ -395,7 +395,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * @param minimum the minimum value of the scroll bar * @param maximum the maximum value of the scroll bar * @exception IllegalArgumentException when an illegal value for - * the orientation argument is supplied + * the {@code orientation} argument is supplied * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see #setValues @@ -416,8 +416,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { } /** - * Constructs a name for this component. Called by getName - * when the name is null. + * Constructs a name for this component. Called by {@code getName} + * when the name is {@code null}. */ String constructComponentName() { synchronized (Scrollbar.class) { @@ -426,8 +426,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { } /** - * Creates the Scrollbar's peer. The peer allows you to modify - * the appearance of the Scrollbar without changing any of its + * Creates the {@code Scrollbar}'s peer. The peer allows you to modify + * the appearance of the {@code Scrollbar} without changing any of its * functionality. */ public void addNotify() { @@ -442,8 +442,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * Returns the orientation of this scroll bar. * * @return the orientation of this scroll bar, either - * Scrollbar.HORIZONTAL or - * Scrollbar.VERTICAL + * {@code Scrollbar.HORIZONTAL} or + * {@code Scrollbar.VERTICAL} * @see java.awt.Scrollbar#setOrientation */ public int getOrientation() { @@ -454,11 +454,11 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * Sets the orientation for this scroll bar. * * @param orientation the orientation of this scroll bar, either - * Scrollbar.HORIZONTAL or - * Scrollbar.VERTICAL + * {@code Scrollbar.HORIZONTAL} or + * {@code Scrollbar.VERTICAL} * @see java.awt.Scrollbar#getOrientation * @exception IllegalArgumentException if the value supplied - * for orientation is not a + * for {@code orientation} is not a * legal value * @since 1.1 */ @@ -506,20 +506,20 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Sets the value of this scroll bar to the specified value. *

        - * If the value supplied is less than the current minimum - * or greater than the current maximum - visibleAmount, - * then either minimum or maximum - visibleAmount + * If the value supplied is less than the current {@code minimum} + * or greater than the current {@code maximum - visibleAmount}, + * then either {@code minimum} or {@code maximum - visibleAmount} * is substituted, as appropriate. *

        * Normally, a program should change a scroll bar's - * value only by calling setValues. - * The setValues method simultaneously + * value only by calling {@code setValues}. + * The {@code setValues} method simultaneously * and synchronously sets the minimum, maximum, visible amount, * and value properties of a scroll bar, so that they are * mutually consistent. *

        * Calling this method does not fire an - * AdjustmentEvent. + * {@code AdjustmentEvent}. * * @param newValue the new value of the scroll bar * @see java.awt.Scrollbar#setValues @@ -547,21 +547,21 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Sets the minimum value of this scroll bar. *

        - * When setMinimum is called, the minimum value + * When {@code setMinimum} is called, the minimum value * is changed, and other values (including the maximum, the * visible amount, and the current scroll bar value) * are changed to be consistent with the new minimum. *

        * Normally, a program should change a scroll bar's minimum - * value only by calling setValues. - * The setValues method simultaneously + * value only by calling {@code setValues}. + * The {@code setValues} method simultaneously * and synchronously sets the minimum, maximum, visible amount, * and value properties of a scroll bar, so that they are * mutually consistent. *

        - * Note that setting the minimum value to Integer.MAX_VALUE + * Note that setting the minimum value to {@code Integer.MAX_VALUE} * will result in the new minimum value being set to - * Integer.MAX_VALUE - 1. + * {@code Integer.MAX_VALUE - 1}. * * @param newMinimum the new minimum value for this scroll bar * @see java.awt.Scrollbar#setValues @@ -591,21 +591,21 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Sets the maximum value of this scroll bar. *

        - * When setMaximum is called, the maximum value + * When {@code setMaximum} is called, the maximum value * is changed, and other values (including the minimum, the * visible amount, and the current scroll bar value) * are changed to be consistent with the new maximum. *

        * Normally, a program should change a scroll bar's maximum - * value only by calling setValues. - * The setValues method simultaneously + * value only by calling {@code setValues}. + * The {@code setValues} method simultaneously * and synchronously sets the minimum, maximum, visible amount, * and value properties of a scroll bar, so that they are * mutually consistent. *

        - * Note that setting the maximum value to Integer.MIN_VALUE + * Note that setting the maximum value to {@code Integer.MIN_VALUE} * will result in the new maximum value being set to - * Integer.MIN_VALUE + 1. + * {@code Integer.MIN_VALUE + 1}. * * @param newMaximum the new maximum value * for this scroll bar @@ -645,7 +645,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * moveable (e.g. when it takes up the entire length of the * scroll bar's track, or when the scroll bar is disabled). * Whether the bubble is displayed or not will not affect - * the value returned by getVisibleAmount. + * the value returned by {@code getVisibleAmount}. * * @return the visible amount of this scroll bar * @see java.awt.Scrollbar#setVisibleAmount @@ -660,7 +660,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * * @return the visible amount of this scroll bar * @deprecated As of JDK version 1.1, - * replaced by getVisibleAmount(). + * replaced by {@code getVisibleAmount()}. */ @Deprecated public int getVisible() { @@ -683,16 +683,16 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * moveable (e.g. when it takes up the entire length of the * scroll bar's track, or when the scroll bar is disabled). * Whether the bubble is displayed or not will not affect - * the value returned by getVisibleAmount. + * the value returned by {@code getVisibleAmount}. *

        - * If the visible amount supplied is less than one - * or greater than the current maximum - minimum, - * then either one or maximum - minimum + * If the visible amount supplied is less than {@code one} + * or greater than the current {@code maximum - minimum}, + * then either {@code one} or {@code maximum - minimum} * is substituted, as appropriate. *

        * Normally, a program should change a scroll bar's - * value only by calling setValues. - * The setValues method simultaneously + * value only by calling {@code setValues}. + * The {@code setValues} method simultaneously * and synchronously sets the minimum, maximum, visible amount, * and value properties of a scroll bar, so that they are * mutually consistent. @@ -737,7 +737,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * @param v the increment value * * @deprecated As of JDK version 1.1, - * replaced by setUnitIncrement(int). + * replaced by {@code setUnitIncrement(int)}. */ @Deprecated public synchronized void setLineIncrement(int v) { @@ -779,7 +779,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * * @return the unit increment for this scrollbar * @deprecated As of JDK version 1.1, - * replaced by getUnitIncrement(). + * replaced by {@code getUnitIncrement()}. */ @Deprecated public int getLineIncrement() { @@ -811,7 +811,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * * @param v the block increment * @deprecated As of JDK version 1.1, - * replaced by setBlockIncrement(). + * replaced by {@code setBlockIncrement()}. */ @Deprecated public synchronized void setPageIncrement(int v) { @@ -851,7 +851,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * @return the block increment of this scroll bar * * @deprecated As of JDK version 1.1, - * replaced by getBlockIncrement(). + * replaced by {@code getBlockIncrement()}. */ @Deprecated public int getPageIncrement() { @@ -860,8 +860,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Sets the values of four properties for this scroll bar: - * value, visibleAmount, - * minimum, and maximum. + * {@code value}, {@code visibleAmount}, + * {@code minimum}, and {@code maximum}. * If the values supplied for these properties are inconsistent * or incorrect, they will be changed to ensure consistency. *

        @@ -869,18 +869,18 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * of four scroll bar properties, assuring that the values of * these properties are mutually consistent. It enforces the * following constraints: - * maximum must be greater than minimum, - * maximum - minimum must not be greater - * than Integer.MAX_VALUE, - * visibleAmount must be greater than zero. - * visibleAmount must not be greater than - * maximum - minimum, - * value must not be less than minimum, - * and value must not be greater than - * maximum - visibleAmount + * {@code maximum} must be greater than {@code minimum}, + * {@code maximum - minimum} must not be greater + * than {@code Integer.MAX_VALUE}, + * {@code visibleAmount} must be greater than zero. + * {@code visibleAmount} must not be greater than + * {@code maximum - minimum}, + * {@code value} must not be less than {@code minimum}, + * and {@code value} must not be greater than + * {@code maximum - visibleAmount} *

        * Calling this method does not fire an - * AdjustmentEvent. + * {@code AdjustmentEvent}. * * @param value is the position in the current window * @param visible is the visible amount of the scroll bar @@ -943,7 +943,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * Returns true if the value is in the process of changing as a * result of actions being taken by the user. * - * @return the value of the valueIsAdjusting property + * @return the value of the {@code valueIsAdjusting} property * @see #setValueIsAdjusting * @since 1.4 */ @@ -952,7 +952,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { } /** - * Sets the valueIsAdjusting property. + * Sets the {@code valueIsAdjusting} property. * * @param b new adjustment-in-progress status * @see #getValueIsAdjusting @@ -978,8 +978,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Adds the specified adjustment listener to receive instances of - * AdjustmentEvent from this scroll bar. - * If l is null, no exception is thrown and no + * {@code AdjustmentEvent} from this scroll bar. + * If l is {@code null}, no exception is thrown and no * action is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -1001,8 +1001,8 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Removes the specified adjustment listener so that it no longer - * receives instances of AdjustmentEvent from this scroll bar. - * If l is null, no exception is thrown and no action + * receives instances of {@code AdjustmentEvent} from this scroll bar. + * If l is {@code null}, no exception is thrown and no action * is performed. *

        Refer to AWT Threading Issues for details on AWT's threading model. @@ -1025,7 +1025,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * Returns an array of all the adjustment listeners * registered on this scrollbar. * - * @return all of this scrollbar's AdjustmentListeners + * @return all of this scrollbar's {@code AdjustmentListener}s * or an empty array if no adjustment * listeners are currently registered * @see #addAdjustmentListener @@ -1041,15 +1041,15 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Returns an array of all the objects currently registered * as FooListeners - * upon this Scrollbar. + * upon this {@code Scrollbar}. * FooListeners are registered using the * addFooListener method. *

        - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * Scrollbar c + * {@code Scrollbar c} * for its mouse listeners with the following code: * *

        MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));
        @@ -1058,13 +1058,13 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this component, * or an empty array if no such listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @since 1.3 */ @@ -1092,11 +1092,11 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Processes events on this scroll bar. If the event is an - * instance of AdjustmentEvent, it invokes the - * processAdjustmentEvent method. + * instance of {@code AdjustmentEvent}, it invokes the + * {@code processAdjustmentEvent} method. * Otherwise, it invokes its superclass's - * processEvent method. - *

        Note that if the event parameter is null + * {@code processEvent} method. + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -1116,17 +1116,17 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Processes adjustment events occurring on this * scrollbar by dispatching them to any registered - * AdjustmentListener objects. + * {@code AdjustmentListener} objects. *

        * This method is not called unless adjustment events are * enabled for this component. Adjustment events are enabled * when one of the following occurs: *

          - *
        • An AdjustmentListener object is registered - * via addAdjustmentListener. - *
        • Adjustment events are enabled via enableEvents. + *
        • An {@code AdjustmentListener} object is registered + * via {@code addAdjustmentListener}. + *
        • Adjustment events are enabled via {@code enableEvents}. *
        - *

        Note that if the event parameter is null + *

        Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -1145,11 +1145,11 @@ public class Scrollbar extends Component implements Adjustable, Accessible { } /** - * Returns a string representing the state of this Scrollbar. + * Returns a string representing the state of this {@code Scrollbar}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this scroll bar */ @@ -1176,17 +1176,17 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Writes default serializable fields to stream. Writes - * a list of serializable AdjustmentListeners + * a list of serializable {@code AdjustmentListeners} * as optional data. The non-serializable listeners are * detected and no attempt is made to serialize them. * - * @param s the ObjectOutputStream to write - * @serialData null terminated sequence of 0 - * or more pairs; the pair consists of a String - * and an Object; the String indicates + * @param s the {@code ObjectOutputStream} to write + * @serialData {@code null} terminated sequence of 0 + * or more pairs; the pair consists of a {@code String} + * and an {@code Object}; the {@code String} indicates * the type of object and is one of the following: - * adjustmentListenerK indicating an - * AdjustmentListener object + * {@code adjustmentListenerK} indicating an + * {@code AdjustmentListener} object * * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) * @see java.awt.Component#adjustmentListenerK @@ -1202,16 +1202,16 @@ public class Scrollbar extends Component implements Adjustable, Accessible { } /** - * Reads the ObjectInputStream and if - * it isn't null adds a listener to + * Reads the {@code ObjectInputStream} and if + * it isn't {@code null} adds a listener to * receive adjustment events fired by the - * Scrollbar. + * {@code Scrollbar}. * Unrecognized keys or values will be ignored. * - * @param s the ObjectInputStream to read + * @param s the {@code ObjectInputStream} to read * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns - * true + * {@code GraphicsEnvironment.isHeadless} returns + * {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @see #writeObject(ObjectOutputStream) */ @@ -1239,14 +1239,14 @@ public class Scrollbar extends Component implements Adjustable, Accessible { //////////////// /** - * Gets the AccessibleContext associated with this - * Scrollbar. For scrollbars, the - * AccessibleContext takes the form of an - * AccessibleAWTScrollBar. A new - * AccessibleAWTScrollBar instance is created if necessary. + * Gets the {@code AccessibleContext} associated with this + * {@code Scrollbar}. For scrollbars, the + * {@code AccessibleContext} takes the form of an + * {@code AccessibleAWTScrollBar}. A new + * {@code AccessibleAWTScrollBar} instance is created if necessary. * - * @return an AccessibleAWTScrollBar that serves as the - * AccessibleContext of this ScrollBar + * @return an {@code AccessibleAWTScrollBar} that serves as the + * {@code AccessibleContext} of this {@code ScrollBar} * @since 1.3 */ public AccessibleContext getAccessibleContext() { @@ -1258,7 +1258,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * This class implements accessibility support for the - * Scrollbar class. It provides an implementation of + * {@code Scrollbar} class. It provides an implementation of * the Java Accessibility API appropriate to scrollbar * user-interface elements. * @since 1.3 @@ -1274,7 +1274,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Get the state set of this object. * - * @return an instance of AccessibleState + * @return an instance of {@code AccessibleState} * containing the current state of the object * @see AccessibleState */ @@ -1294,7 +1294,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { /** * Get the role of this object. * - * @return an instance of AccessibleRole + * @return an instance of {@code AccessibleRole} * describing the role of the object */ public AccessibleRole getAccessibleRole() { @@ -1302,11 +1302,11 @@ public class Scrollbar extends Component implements Adjustable, Accessible { } /** - * Get the AccessibleValue associated with this + * Get the {@code AccessibleValue} associated with this * object. In the implementation of the Java Accessibility * API for this class, return this object, which is * responsible for implementing the - * AccessibleValue interface on behalf of itself. + * {@code AccessibleValue} interface on behalf of itself. * * @return this object */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Shape.java b/jdk/src/java.desktop/share/classes/java/awt/Shape.java index 0ff0fbbc09e..209063c46a2 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Shape.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Shape.java @@ -31,36 +31,36 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; /** - * The Shape interface provides definitions for objects - * that represent some form of geometric shape. The Shape + * The {@code Shape} interface provides definitions for objects + * that represent some form of geometric shape. The {@code Shape} * is described by a {@link PathIterator} object, which can express the - * outline of the Shape as well as a rule for determining + * outline of the {@code Shape} as well as a rule for determining * how the outline divides the 2D plane into interior and exterior - * points. Each Shape object provides callbacks to get the + * points. Each {@code Shape} object provides callbacks to get the * bounding box of the geometry, determine whether points or * rectangles lie partly or entirely within the interior - * of the Shape, and retrieve a PathIterator - * object that describes the trajectory path of the Shape + * of the {@code Shape}, and retrieve a {@code PathIterator} + * object that describes the trajectory path of the {@code Shape} * outline. *

        * Definition of insideness: * A point is considered to lie inside a - * Shape if and only if: + * {@code Shape} if and only if: *

          *
        • it lies completely - * inside theShape boundary or + * inside the {@code Shape} boundary or *
        • - * it lies exactly on the Shape boundary and the + * it lies exactly on the {@code Shape} boundary and the * space immediately adjacent to the - * point in the increasing X direction is + * point in the increasing {@code X} direction is * entirely inside the boundary or *
        • * it lies exactly on a horizontal boundary segment and the * space immediately adjacent to the point in the - * increasing Y direction is inside the boundary. + * increasing {@code Y} direction is inside the boundary. *
        - *

        The contains and intersects methods - * consider the interior of a Shape to be the area it + *

        The {@code contains} and {@code intersects} methods + * consider the interior of a {@code Shape} to be the area it * encloses as if it were filled. This means that these methods * consider * unclosed shapes to be implicitly closed for the purpose of @@ -78,14 +78,14 @@ import java.awt.geom.Rectangle2D; public interface Shape { /** * Returns an integer {@link Rectangle} that completely encloses the - * Shape. Note that there is no guarantee that the - * returned Rectangle is the smallest bounding box that - * encloses the Shape, only that the Shape - * lies entirely within the indicated Rectangle. The - * returned Rectangle might also fail to completely - * enclose the Shape if the Shape overflows + * {@code Shape}. Note that there is no guarantee that the + * returned {@code Rectangle} is the smallest bounding box that + * encloses the {@code Shape}, only that the {@code Shape} + * lies entirely within the indicated {@code Rectangle}. The + * returned {@code Rectangle} might also fail to completely + * enclose the {@code Shape} if the {@code Shape} overflows * the limited range of the integer data type. The - * getBounds2D method generally returns a + * {@code getBounds2D} method generally returns a * tighter bounding box due to its greater flexibility in * representation. * @@ -114,8 +114,8 @@ public interface Shape { *

        * {@code bounds.contains(x,y)} does not imply {@code shape.contains(x,y)} *

        - * @return an integer Rectangle that completely encloses - * the Shape. + * @return an integer {@code Rectangle} that completely encloses + * the {@code Shape}. * @see #getBounds2D * @since 1.2 */ @@ -123,15 +123,15 @@ public interface Shape { /** * Returns a high precision and more accurate bounding box of - * the Shape than the getBounds method. + * the {@code Shape} than the {@code getBounds} method. * Note that there is no guarantee that the returned * {@link Rectangle2D} is the smallest bounding box that encloses - * the Shape, only that the Shape lies - * entirely within the indicated Rectangle2D. The + * the {@code Shape}, only that the {@code Shape} lies + * entirely within the indicated {@code Rectangle2D}. The * bounding box returned by this method is usually tighter than that - * returned by the getBounds method and never fails due + * returned by the {@code getBounds} method and never fails due * to overflow problems since the return value can be an instance of - * the Rectangle2D that uses double precision values to + * the {@code Rectangle2D} that uses double precision values to * store the dimensions. * *

        @@ -159,8 +159,8 @@ public interface Shape { *

        * {@code bounds.contains(p)} does not imply {@code shape.contains(p)} *

        - * @return an instance of Rectangle2D that is a - * high-precision bounding box of the Shape. + * @return an instance of {@code Rectangle2D} that is a + * high-precision bounding box of the {@code Shape}. * @see #getBounds * @since 1.2 */ @@ -168,13 +168,13 @@ public interface Shape { /** * Tests if the specified coordinates are inside the boundary of the - * Shape, as described by the + * {@code Shape}, as described by the * * definition of insideness. * @param x the specified X coordinate to be tested * @param y the specified Y coordinate to be tested - * @return true if the specified coordinates are inside - * the Shape boundary; false + * @return {@code true} if the specified coordinates are inside + * the {@code Shape} boundary; {@code false} * otherwise. * @since 1.2 */ @@ -182,30 +182,30 @@ public interface Shape { /** * Tests if a specified {@link Point2D} is inside the boundary - * of the Shape, as described by the + * of the {@code Shape}, as described by the * * definition of insideness. - * @param p the specified Point2D to be tested - * @return true if the specified Point2D is - * inside the boundary of the Shape; - * false otherwise. + * @param p the specified {@code Point2D} to be tested + * @return {@code true} if the specified {@code Point2D} is + * inside the boundary of the {@code Shape}; + * {@code false} otherwise. * @since 1.2 */ public boolean contains(Point2D p); /** - * Tests if the interior of the Shape intersects the + * Tests if the interior of the {@code Shape} intersects the * interior of a specified rectangular area. - * The rectangular area is considered to intersect the Shape + * The rectangular area is considered to intersect the {@code Shape} * if any point is contained in both the interior of the - * Shape and the specified rectangular area. + * {@code Shape} and the specified rectangular area. *

        * The {@code Shape.intersects()} method allows a {@code Shape} * implementation to conservatively return {@code true} when: *

          *
        • * there is a high probability that the rectangular area and the - * Shape intersect, but + * {@code Shape} intersect, but *
        • * the calculations to accurately determine this intersection * are prohibitively expensive. @@ -224,24 +224,24 @@ public interface Shape { * of the specified rectangular area * @param w the width of the specified rectangular area * @param h the height of the specified rectangular area - * @return true if the interior of the Shape and + * @return {@code true} if the interior of the {@code Shape} and * the interior of the rectangular area intersect, or are * both highly likely to intersect and intersection calculations - * would be too expensive to perform; false otherwise. + * would be too expensive to perform; {@code false} otherwise. * @see java.awt.geom.Area * @since 1.2 */ public boolean intersects(double x, double y, double w, double h); /** - * Tests if the interior of the Shape intersects the - * interior of a specified Rectangle2D. + * Tests if the interior of the {@code Shape} intersects the + * interior of a specified {@code Rectangle2D}. * The {@code Shape.intersects()} method allows a {@code Shape} * implementation to conservatively return {@code true} when: *
            *
          • - * there is a high probability that the Rectangle2D and the - * Shape intersect, but + * there is a high probability that the {@code Rectangle2D} and the + * {@code Shape} intersect, but *
          • * the calculations to accurately determine this intersection * are prohibitively expensive. @@ -254,11 +254,11 @@ public interface Shape { * {@code Shape} objects and therefore can be used if a more precise * answer is required. * - * @param r the specified Rectangle2D - * @return true if the interior of the Shape and - * the interior of the specified Rectangle2D + * @param r the specified {@code Rectangle2D} + * @return {@code true} if the interior of the {@code Shape} and + * the interior of the specified {@code Rectangle2D} * intersect, or are both highly likely to intersect and intersection - * calculations would be too expensive to perform; false + * calculations would be too expensive to perform; {@code false} * otherwise. * @see #intersects(double, double, double, double) * @since 1.2 @@ -266,20 +266,20 @@ public interface Shape { public boolean intersects(Rectangle2D r); /** - * Tests if the interior of the Shape entirely contains + * Tests if the interior of the {@code Shape} entirely contains * the specified rectangular area. All coordinates that lie inside - * the rectangular area must lie within the Shape for the + * the rectangular area must lie within the {@code Shape} for the * entire rectangular area to be considered contained within the - * Shape. + * {@code Shape}. *

            * The {@code Shape.contains()} method allows a {@code Shape} * implementation to conservatively return {@code false} when: *

              *
            • - * the intersect method returns true and + * the {@code intersect} method returns {@code true} and *
            • * the calculations to determine whether or not the - * Shape entirely contains the rectangular area are + * {@code Shape} entirely contains the rectangular area are * prohibitively expensive. *
            * This means that for some {@code Shapes} this method might @@ -296,11 +296,11 @@ public interface Shape { * of the specified rectangular area * @param w the width of the specified rectangular area * @param h the height of the specified rectangular area - * @return true if the interior of the Shape + * @return {@code true} if the interior of the {@code Shape} * entirely contains the specified rectangular area; - * false otherwise or, if the Shape + * {@code false} otherwise or, if the {@code Shape} * contains the rectangular area and the - * intersects method returns true + * {@code intersects} method returns {@code true} * and the containment calculations would be too expensive to * perform. * @see java.awt.geom.Area @@ -310,16 +310,16 @@ public interface Shape { public boolean contains(double x, double y, double w, double h); /** - * Tests if the interior of the Shape entirely contains the - * specified Rectangle2D. + * Tests if the interior of the {@code Shape} entirely contains the + * specified {@code Rectangle2D}. * The {@code Shape.contains()} method allows a {@code Shape} * implementation to conservatively return {@code false} when: *
              *
            • - * the intersect method returns true and + * the {@code intersect} method returns {@code true} and *
            • * the calculations to determine whether or not the - * Shape entirely contains the Rectangle2D + * {@code Shape} entirely contains the {@code Rectangle2D} * are prohibitively expensive. *
            * This means that for some {@code Shapes} this method might @@ -330,12 +330,12 @@ public interface Shape { * {@code Shape} objects and therefore can be used if a more precise * answer is required. * - * @param r The specified Rectangle2D - * @return true if the interior of the Shape - * entirely contains the Rectangle2D; - * false otherwise or, if the Shape - * contains the Rectangle2D and the - * intersects method returns true + * @param r The specified {@code Rectangle2D} + * @return {@code true} if the interior of the {@code Shape} + * entirely contains the {@code Rectangle2D}; + * {@code false} otherwise or, if the {@code Shape} + * contains the {@code Rectangle2D} and the + * {@code intersects} method returns {@code true} * and the containment calculations would be too expensive to * perform. * @see #contains(double, double, double, double) @@ -345,44 +345,44 @@ public interface Shape { /** * Returns an iterator object that iterates along the - * Shape boundary and provides access to the geometry of the - * Shape outline. If an optional {@link AffineTransform} + * {@code Shape} boundary and provides access to the geometry of the + * {@code Shape} outline. If an optional {@link AffineTransform} * is specified, the coordinates returned in the iteration are * transformed accordingly. *

            - * Each call to this method returns a fresh PathIterator - * object that traverses the geometry of the Shape object - * independently from any other PathIterator objects in use + * Each call to this method returns a fresh {@code PathIterator} + * object that traverses the geometry of the {@code Shape} object + * independently from any other {@code PathIterator} objects in use * at the same time. *

            * It is recommended, but not guaranteed, that objects - * implementing the Shape interface isolate iterations + * implementing the {@code Shape} interface isolate iterations * that are in process from any changes that might occur to the original * object's geometry during such iterations. * - * @param at an optional AffineTransform to be applied to the + * @param at an optional {@code AffineTransform} to be applied to the * coordinates as they are returned in the iteration, or - * null if untransformed coordinates are desired - * @return a new PathIterator object, which independently - * traverses the geometry of the Shape. + * {@code null} if untransformed coordinates are desired + * @return a new {@code PathIterator} object, which independently + * traverses the geometry of the {@code Shape}. * @since 1.2 */ public PathIterator getPathIterator(AffineTransform at); /** - * Returns an iterator object that iterates along the Shape + * Returns an iterator object that iterates along the {@code Shape} * boundary and provides access to a flattened view of the - * Shape outline geometry. + * {@code Shape} outline geometry. *

            * Only SEG_MOVETO, SEG_LINETO, and SEG_CLOSE point types are * returned by the iterator. *

            - * If an optional AffineTransform is specified, + * If an optional {@code AffineTransform} is specified, * the coordinates returned in the iteration are transformed * accordingly. *

            * The amount of subdivision of the curved segments is controlled - * by the flatness parameter, which specifies the + * by the {@code flatness} parameter, which specifies the * maximum distance that any point on the unflattened transformed * curve can deviate from the returned flattened path segments. * Note that a limit on the accuracy of the flattened path might be @@ -390,24 +390,24 @@ public interface Shape { * treated as larger values. This limit, if there is one, is * defined by the particular implementation that is used. *

            - * Each call to this method returns a fresh PathIterator - * object that traverses the Shape object geometry - * independently from any other PathIterator objects in use at + * Each call to this method returns a fresh {@code PathIterator} + * object that traverses the {@code Shape} object geometry + * independently from any other {@code PathIterator} objects in use at * the same time. *

            * It is recommended, but not guaranteed, that objects - * implementing the Shape interface isolate iterations + * implementing the {@code Shape} interface isolate iterations * that are in process from any changes that might occur to the original * object's geometry during such iterations. * - * @param at an optional AffineTransform to be applied to the + * @param at an optional {@code AffineTransform} to be applied to the * coordinates as they are returned in the iteration, or - * null if untransformed coordinates are desired + * {@code null} if untransformed coordinates are desired * @param flatness the maximum distance that the line segments used to * approximate the curved segments are allowed to deviate * from any point on the original curve - * @return a new PathIterator that independently traverses - * a flattened view of the geometry of the Shape. + * @return a new {@code PathIterator} that independently traverses + * a flattened view of the geometry of the {@code Shape}. * @since 1.2 */ public PathIterator getPathIterator(AffineTransform at, double flatness); diff --git a/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java b/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java index 3cf8ac0a6cd..4b6fab00428 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java +++ b/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java @@ -48,7 +48,7 @@ import sun.awt.image.SunWritableRaster; * Place the image in the jar archive and specify the path in the option. * The path should not have a leading slash. *
            - * For example, in the manifest.mf file: + * For example, in the {@code manifest.mf} file: *

              * Manifest-Version: 1.0
              * Main-Class: Test
            @@ -89,7 +89,7 @@ import sun.awt.image.SunWritableRaster;
              * can exist, and it may be obtained by using the {@link #getSplashScreen()}
              * static method. In case the splash screen has not been created at
              * application startup via the command line or manifest file option,
            - * the getSplashScreen method returns null.
            + * the {@code getSplashScreen} method returns {@code null}.
              *
              * @author Oleg Semenov
              * @since 1.6
            @@ -108,7 +108,7 @@ public final class SplashScreen {
                  *         supported by the current toolkit
                  * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
                  *         returns true
            -     * @return the {@link SplashScreen} instance, or null if there is
            +     * @return the {@link SplashScreen} instance, or {@code null} if there is
                  *         none or it has already been closed
                  */
                 public static  SplashScreen getSplashScreen() {
            @@ -142,9 +142,9 @@ public final class SplashScreen {
                  * The splash screen window is resized according to the size of
                  * the image and is centered on the screen.
                  *
            -     * @param imageURL the non-null URL for the new
            +     * @param imageURL the non-{@code null} URL for the new
                  *        splash screen image
            -     * @throws NullPointerException if {@code imageURL} is null
            +     * @throws NullPointerException if {@code imageURL} is {@code null}
                  * @throws IOException if there was an error while loading the image
                  * @throws IllegalStateException if the splash screen has already been
                  *         closed
            @@ -282,7 +282,7 @@ public final class SplashScreen {
                  * displayed over the main image using alpha blending. Also note that drawing
                  * on the overlay image does not necessarily update the contents of splash
                  * screen window. You should call {@code update()} on the
            -     * SplashScreen when you want the splash screen to be
            +     * {@code SplashScreen} when you want the splash screen to be
                  * updated immediately.
                  * 

            * The pixel (0, 0) in the coordinate space of the graphics context @@ -402,7 +402,7 @@ public final class SplashScreen { /** * The instance reference for the singleton. - * (null if no instance exists yet.) + * ({@code null} if no instance exists yet.) * * @see #getSplashScreen * @see #close diff --git a/jdk/src/java.desktop/share/classes/java/awt/Stroke.java b/jdk/src/java.desktop/share/classes/java/awt/Stroke.java index 93ff2e8b32d..291c3857362 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Stroke.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Stroke.java @@ -26,43 +26,43 @@ package java.awt; /** - * The Stroke interface allows a + * The {@code Stroke} interface allows a * {@link Graphics2D} object to obtain a {@link Shape} that is the * decorated outline, or stylistic representation of the outline, - * of the specified Shape. - * Stroking a Shape is like tracing its outline with a + * of the specified {@code Shape}. + * Stroking a {@code Shape} is like tracing its outline with a * marking pen of the appropriate size and shape. * The area where the pen would place ink is the area enclosed by the - * outline Shape. + * outline {@code Shape}. *

            - * The methods of the Graphics2D interface that use the - * outline Shape returned by a Stroke object - * include draw and any other methods that are + * The methods of the {@code Graphics2D} interface that use the + * outline {@code Shape} returned by a {@code Stroke} object + * include {@code draw} and any other methods that are * implemented in terms of that method, such as - * drawLine, drawRect, - * drawRoundRect, drawOval, - * drawArc, drawPolyline, - * and drawPolygon. + * {@code drawLine}, {@code drawRect}, + * {@code drawRoundRect}, {@code drawOval}, + * {@code drawArc}, {@code drawPolyline}, + * and {@code drawPolygon}. *

            - * The objects of the classes implementing Stroke - * must be read-only because Graphics2D does not + * The objects of the classes implementing {@code Stroke} + * must be read-only because {@code Graphics2D} does not * clone these objects either when they are set as an attribute - * with the setStroke method or when the - * Graphics2D object is itself cloned. - * If a Stroke object is modified after it is set in - * the Graphics2D context then the behavior + * with the {@code setStroke} method or when the + * {@code Graphics2D} object is itself cloned. + * If a {@code Stroke} object is modified after it is set in + * the {@code Graphics2D} context then the behavior * of subsequent rendering would be undefined. * @see BasicStroke * @see Graphics2D#setStroke */ public interface Stroke { /** - * Returns an outline Shape which encloses the area that - * should be painted when the Shape is stroked according + * Returns an outline {@code Shape} which encloses the area that + * should be painted when the {@code Shape} is stroked according * to the rules defined by the - * object implementing the Stroke interface. - * @param p a Shape to be stroked - * @return the stroked outline Shape. + * object implementing the {@code Stroke} interface. + * @param p a {@code Shape} to be stroked + * @return the stroked outline {@code Shape}. */ Shape createStrokedShape (Shape p); } diff --git a/jdk/src/java.desktop/share/classes/java/awt/SystemColor.java b/jdk/src/java.desktop/share/classes/java/awt/SystemColor.java index 38a173f339a..75b3e58d6af 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/SystemColor.java +++ b/jdk/src/java.desktop/share/classes/java/awt/SystemColor.java @@ -36,15 +36,15 @@ import java.lang.annotation.Native; * update of the system colors (when the user changes the colors) * the actual RGB values of these symbolic colors will also change * dynamically. In order to compare the "current" RGB value of a - * SystemColor object with a non-symbolic Color object, - * getRGB should be used rather than equals. + * {@code SystemColor} object with a non-symbolic Color object, + * {@code getRGB} should be used rather than {@code equals}. *

            * Note that the way in which these system colors are applied to GUI objects * may vary slightly from platform to platform since GUI objects may be * rendered differently on each platform. *

            - * System color values may also be available through the getDesktopProperty - * method on java.awt.Toolkit. + * System color values may also be available through the {@code getDesktopProperty} + * method on {@code java.awt.Toolkit}. * * @see Toolkit#getDesktopProperty * @@ -380,28 +380,28 @@ public final class SystemColor extends Color implements java.io.Serializable { /** * The color rendered for light areas of 3D control objects, such as pushbuttons. - * This color is typically derived from the control background color + * This color is typically derived from the {@code control} background color * to provide a 3D effect. */ public static final SystemColor controlHighlight = new SystemColor((byte)CONTROL_HIGHLIGHT); /** * The color rendered for highlight areas of 3D control objects, such as pushbuttons. - * This color is typically derived from the control background color + * This color is typically derived from the {@code control} background color * to provide a 3D effect. */ public static final SystemColor controlLtHighlight = new SystemColor((byte)CONTROL_LT_HIGHLIGHT); /** * The color rendered for shadow areas of 3D control objects, such as pushbuttons. - * This color is typically derived from the control background color + * This color is typically derived from the {@code control} background color * to provide a 3D effect. */ public static final SystemColor controlShadow = new SystemColor((byte)CONTROL_SHADOW); /** * The color rendered for dark shadow areas on 3D control objects, such as pushbuttons. - * This color is typically derived from the control background color + * This color is typically derived from the {@code control} background color * to provide a 3D effect. */ public static final SystemColor controlDkShadow = new SystemColor((byte)CONTROL_DK_SHADOW); @@ -487,13 +487,13 @@ public final class SystemColor extends Color implements java.io.Serializable { } /** - * Returns a string representation of this Color's values. + * Returns a string representation of this {@code Color}'s values. * This method is intended to be used only for debugging purposes, * and the content and format of the returned string may vary between * implementations. - * The returned string may be empty but may not be null. + * The returned string may be empty but may not be {@code null}. * - * @return a string representation of this Color + * @return a string representation of this {@code Color} */ public String toString() { return getClass().getName() + "[i=" + (index) + "]"; diff --git a/jdk/src/java.desktop/share/classes/java/awt/SystemTray.java b/jdk/src/java.desktop/share/classes/java/awt/SystemTray.java index e61716ee537..46ed1ff807c 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/SystemTray.java +++ b/jdk/src/java.desktop/share/classes/java/awt/SystemTray.java @@ -36,7 +36,7 @@ import sun.awt.AWTAccessor; import sun.awt.AWTPermissions; /** - * The SystemTray class represents the system tray for a + * The {@code SystemTray} class represents the system tray for a * desktop. On Microsoft Windows it is referred to as the "Taskbar * Status Area", on Gnome it is referred to as the "Notification * Area", on KDE it is referred to as the "System Tray". The system @@ -47,19 +47,19 @@ import sun.awt.AWTPermissions; * throws {@link UnsupportedOperationException}. To detect whether the * system tray is supported, use {@link SystemTray#isSupported}. * - *

            The SystemTray may contain one or more {@link + *

            The {@code SystemTray} may contain one or more {@link * TrayIcon TrayIcons}, which are added to the tray using the {@link * #add} method, and removed when no longer needed, using the - * {@link #remove}. TrayIcon consists of an + * {@link #remove}. {@code TrayIcon} consists of an * image, a popup menu and a set of associated listeners. Please see * the {@link TrayIcon} class for details. * - *

            Every Java application has a single SystemTray + *

            Every Java application has a single {@code SystemTray} * instance that allows the app to interface with the system tray of - * the desktop while the app is running. The SystemTray + * the desktop while the app is running. The {@code SystemTray} * instance can be obtained from the {@link #getSystemTray} method. * An application may not create its own instance of - * SystemTray. + * {@code SystemTray}. * *

            The following code snippet demonstrates how to access * and customize the system tray: @@ -141,7 +141,7 @@ public class SystemTray { } /** - * Private SystemTray constructor. + * Private {@code SystemTray} constructor. * */ private SystemTray() { @@ -149,7 +149,7 @@ public class SystemTray { } /** - * Gets the SystemTray instance that represents the + * Gets the {@code SystemTray} instance that represents the * desktop's tray area. This always returns the same instance per * application. On some platforms the system tray may not be * supported. You may use the {@link #isSupported} method to @@ -160,12 +160,12 @@ public class SystemTray { * {@code SystemTray} instance. Otherwise this method will throw a * SecurityException. * - * @return the SystemTray instance that represents + * @return the {@code SystemTray} instance that represents * the desktop's tray area * @throws UnsupportedOperationException if the system tray isn't * supported by the current platform * @throws HeadlessException if - * GraphicsEnvironment.isHeadless() returns true + * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @throws SecurityException if {@code accessSystemTray} permission * is not granted * @see #add(TrayIcon) @@ -203,15 +203,15 @@ public class SystemTray { * both the action listener and the popup menu. See the {@link * SystemTray example} for an example of how to do this. * - *

            Note: When implementing SystemTray and - * TrayIcon it is strongly recommended that + *

            Note: When implementing {@code SystemTray} and + * {@code TrayIcon} it is strongly recommended that * you assign different gestures to the popup menu and an action * event. Overloading a gesture for both purposes is confusing * and may prevent the user from accessing one or the other. * * @see #getSystemTray - * @return false if no system tray access is supported; this - * method returns true if the minimal system tray access is + * @return {@code false} if no system tray access is supported; this + * method returns {@code true} if the minimal system tray access is * supported but does not guarantee that all system tray * functionality is supported for the current platform */ @@ -231,20 +231,20 @@ public class SystemTray { } /** - * Adds a TrayIcon to the SystemTray. + * Adds a {@code TrayIcon} to the {@code SystemTray}. * The tray icon becomes visible in the system tray once it is * added. The order in which icons are displayed in a tray is not * specified - it is platform and implementation-dependent. * *

            All icons added by the application are automatically - * removed from the SystemTray upon application exit + * removed from the {@code SystemTray} upon application exit * and also when the desktop system tray becomes unavailable. * - * @param trayIcon the TrayIcon to be added - * @throws NullPointerException if trayIcon is - * null + * @param trayIcon the {@code TrayIcon} to be added + * @throws NullPointerException if {@code trayIcon} is + * {@code null} * @throws IllegalArgumentException if the same instance of - * a TrayIcon is added more than once + * a {@code TrayIcon} is added more than once * @throws AWTException if the desktop system tray is missing * @see #remove(TrayIcon) * @see #getSystemTray @@ -284,18 +284,18 @@ public class SystemTray { } /** - * Removes the specified TrayIcon from the - * SystemTray. + * Removes the specified {@code TrayIcon} from the + * {@code SystemTray}. * *

            All icons added by the application are automatically - * removed from the SystemTray upon application exit + * removed from the {@code SystemTray} upon application exit * and also when the desktop system tray becomes unavailable. * - *

            If trayIcon is null or was not + *

            If {@code trayIcon} is {@code null} or was not * added to the system tray, no exception is thrown and no action * is performed. * - * @param trayIcon the TrayIcon to be removed + * @param trayIcon the {@code TrayIcon} to be removed * @see #add(TrayIcon) * @see TrayIcon */ @@ -328,8 +328,8 @@ public class SystemTray { * *

            The returned array is a copy of the actual array and may be * modified in any way without affecting the system tray. To - * remove a TrayIcon from the - * SystemTray, use the {@link + * remove a {@code TrayIcon} from the + * {@code SystemTray}, use the {@link * #remove(TrayIcon)} method. * * @return an array of all tray icons added to this tray, or an @@ -351,7 +351,7 @@ public class SystemTray { * occupy in the system tray. Developers may use this methods to * acquire the preferred size for the image property of a tray icon * before it is created. For convenience, there is a similar - * method {@link TrayIcon#getSize} in the TrayIcon class. + * method {@link TrayIcon#getSize} in the {@code TrayIcon} class. * * @return the default size of a tray icon, in pixels * @see TrayIcon#setImageAutoSize(boolean) @@ -383,7 +383,7 @@ public class SystemTray { * * {@code systemTray} * This property contains {@code SystemTray} instance when the system tray - * is available or null otherwise.
            This property is changed + * is available or {@code null} otherwise.
            This property is changed * when the system tray becomes available or unavailable on the desktop.
            * The property is accessed by the {@link #getSystemTray} method. * diff --git a/jdk/src/java.desktop/share/classes/java/awt/TextArea.java b/jdk/src/java.desktop/share/classes/java/awt/TextArea.java index eab879730de..a2f4246a33c 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/TextArea.java +++ b/jdk/src/java.desktop/share/classes/java/awt/TextArea.java @@ -35,7 +35,7 @@ import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; /** - * A TextArea object is a multi-line region + * A {@code TextArea} object is a multi-line region * that displays text. It can be set to allow editing or * to be read-only. *

            @@ -56,7 +56,7 @@ import javax.accessibility.AccessibleStateSet; public class TextArea extends TextComponent { /** - * The number of rows in the TextArea. + * The number of rows in the {@code TextArea}. * This parameter will determine the text area's height. * Guaranteed to be non-negative. * @@ -67,7 +67,7 @@ public class TextArea extends TextComponent { int rows; /** - * The number of columns in the TextArea. + * The number of columns in the {@code TextArea}. * A column is an approximate average character * width that is platform-dependent. * This parameter will determine the text area's width. @@ -109,10 +109,10 @@ public class TextArea extends TextComponent { /** * Determines which scrollbars are created for the * text area. It can be one of four values : - * SCROLLBARS_BOTH = both scrollbars.
            - * SCROLLBARS_HORIZONTAL_ONLY = Horizontal bar only.
            - * SCROLLBARS_VERTICAL_ONLY = Vertical bar only.
            - * SCROLLBARS_NONE = No scrollbars.
            + * {@code SCROLLBARS_BOTH} = both scrollbars.
            + * {@code SCROLLBARS_HORIZONTAL_ONLY} = Horizontal bar only.
            + * {@code SCROLLBARS_VERTICAL_ONLY} = Vertical bar only.
            + * {@code SCROLLBARS_NONE} = No scrollbars.
            * * @serial * @see #getScrollbarVisibility() @@ -155,7 +155,7 @@ public class TextArea extends TextComponent { * {@link #SCROLLBARS_BOTH}, so both vertical and horizontal * scrollbars will be visible for this text area. * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns true + * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ public TextArea() throws HeadlessException { @@ -168,10 +168,10 @@ public class TextArea extends TextComponent { * {@link #SCROLLBARS_BOTH}, so both vertical and horizontal * scrollbars will be visible for this text area. * @param text the text to be displayed; if - * text is null, the empty - * string "" will be displayed + * {@code text} is {@code null}, the empty + * string {@code ""} will be displayed * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns true + * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ public TextArea(String text) throws HeadlessException { @@ -189,7 +189,7 @@ public class TextArea extends TextComponent { * @param rows the number of rows * @param columns the number of columns * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns true + * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ public TextArea(int rows, int columns) throws HeadlessException { @@ -205,12 +205,12 @@ public class TextArea extends TextComponent { * vertical and horizontal scrollbars will be visible for this * text area. * @param text the text to be displayed; if - * text is null, the empty - * string "" will be displayed + * {@code text} is {@code null}, the empty + * string {@code ""} will be displayed * @param rows the number of rows * @param columns the number of columns * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns true + * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ public TextArea(String text, int rows, int columns) @@ -221,36 +221,36 @@ public class TextArea extends TextComponent { /** * Constructs a new text area with the specified text, * and with the rows, columns, and scroll bar visibility - * as specified. All TextArea constructors defer to + * as specified. All {@code TextArea} constructors defer to * this one. *

            - * The TextArea class defines several constants + * The {@code TextArea} class defines several constants * that can be supplied as values for the - * scrollbars argument: + * {@code scrollbars} argument: *

              - *
            • SCROLLBARS_BOTH, - *
            • SCROLLBARS_VERTICAL_ONLY, - *
            • SCROLLBARS_HORIZONTAL_ONLY, - *
            • SCROLLBARS_NONE. + *
            • {@code SCROLLBARS_BOTH}, + *
            • {@code SCROLLBARS_VERTICAL_ONLY}, + *
            • {@code SCROLLBARS_HORIZONTAL_ONLY}, + *
            • {@code SCROLLBARS_NONE}. *
            * Any other value for the - * scrollbars argument is invalid and will result in + * {@code scrollbars} argument is invalid and will result in * this text area being created with scrollbar visibility equal to * the default value of {@link #SCROLLBARS_BOTH}. * @param text the text to be displayed; if - * text is null, the empty - * string "" will be displayed + * {@code text} is {@code null}, the empty + * string {@code ""} will be displayed * @param rows the number of rows; if - * rows is less than 0, - * rows is set to 0 + * {@code rows} is less than {@code 0}, + * {@code rows} is set to {@code 0} * @param columns the number of columns; if - * columns is less than 0, - * columns is set to 0 + * {@code columns} is less than {@code 0}, + * {@code columns} is set to {@code 0} * @param scrollbars a constant that determines what * scrollbars are created to view the text area * @since 1.1 * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns true + * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ public TextArea(String text, int rows, int columns, int scrollbars) @@ -273,8 +273,8 @@ public class TextArea extends TextComponent { } /** - * Construct a name for this component. Called by getName - * when the name is null. + * Construct a name for this component. Called by {@code getName} + * when the name is {@code null}. */ String constructComponentName() { synchronized (TextArea.class) { @@ -283,8 +283,8 @@ public class TextArea extends TextComponent { } /** - * Creates the TextArea's peer. The peer allows us to modify - * the appearance of the TextArea without changing any of its + * Creates the {@code TextArea}'s peer. The peer allows us to modify + * the appearance of the {@code TextArea} without changing any of its * functionality. */ public void addNotify() { @@ -298,11 +298,11 @@ public class TextArea extends TextComponent { /** * Inserts the specified text at the specified position * in this text area. - *

            Note that passing null or inconsistent + *

            Note that passing {@code null} or inconsistent * parameters is invalid and will result in unspecified * behavior. * - * @param str the non-null text to insert + * @param str the non-{@code null} text to insert * @param pos the position at which to insert * @see java.awt.TextComponent#setText * @see java.awt.TextArea#replaceRange @@ -320,7 +320,7 @@ public class TextArea extends TextComponent { * @param str the non-{@code null} text to insert * @param pos the position at which to insert * @deprecated As of JDK version 1.1, - * replaced by insert(String, int). + * replaced by {@code insert(String, int)}. */ @Deprecated public synchronized void insertText(String str, int pos) { @@ -333,11 +333,11 @@ public class TextArea extends TextComponent { /** * Appends the given text to the text area's current text. - *

            Note that passing null or inconsistent + *

            Note that passing {@code null} or inconsistent * parameters is invalid and will result in unspecified * behavior. * - * @param str the non-null text to append + * @param str the non-{@code null} text to append * @see java.awt.TextArea#insert * @since 1.1 */ @@ -350,7 +350,7 @@ public class TextArea extends TextComponent { * * @param str the text to append * @deprecated As of JDK version 1.1, - * replaced by append(String). + * replaced by {@code append(String)}. */ @Deprecated public synchronized void appendText(String str) { @@ -365,11 +365,11 @@ public class TextArea extends TextComponent { * same as the end position). * The text position is zero-based. The inserted substring may be * of a different length than the text it replaces. - *

            Note that passing null or inconsistent + *

            Note that passing {@code null} or inconsistent * parameters is invalid and will result in unspecified * behavior. * - * @param str the non-null text to use as + * @param str the non-{@code null} text to use as * the replacement * @param start the start position * @param end the end position @@ -391,7 +391,7 @@ public class TextArea extends TextComponent { * @param start the start position * @param end the end position * @deprecated As of JDK version 1.1, - * replaced by replaceRange(String, int, int). + * replaced by {@code replaceRange(String, int, int)}. */ @Deprecated public synchronized void replaceText(String str, int start, int end) { @@ -419,8 +419,8 @@ public class TextArea extends TextComponent { * @see #getRows() * @see #setColumns(int) * @exception IllegalArgumentException if the value - * supplied for rows - * is less than 0 + * supplied for {@code rows} + * is less than {@code 0} * @since 1.1 */ public void setRows(int rows) { @@ -450,8 +450,8 @@ public class TextArea extends TextComponent { * @see #getColumns() * @see #setRows(int) * @exception IllegalArgumentException if the value - * supplied for columns - * is less than 0 + * supplied for {@code columns} + * is less than {@code 0} * @since 1.1 */ public void setColumns(int columns) { @@ -469,9 +469,9 @@ public class TextArea extends TextComponent { * Returns an enumerated value that indicates which scroll bars * the text area uses. *

            - * The TextArea class defines four integer constants + * The {@code TextArea} class defines four integer constants * that are used to specify which scroll bars are available. - * TextArea has one constructor that gives the + * {@code TextArea} has one constructor that gives the * application discretion over scroll bars. * * @return an integer that indicates which scroll bars are used @@ -510,7 +510,7 @@ public class TextArea extends TextComponent { * @param columns the number of columns * @return the preferred dimensions needed for the text area * @deprecated As of JDK version 1.1, - * replaced by getPreferredSize(int, int). + * replaced by {@code getPreferredSize(int, int)}. */ @Deprecated public Dimension preferredSize(int rows, int columns) { @@ -534,7 +534,7 @@ public class TextArea extends TextComponent { /** * @deprecated As of JDK version 1.1, - * replaced by getPreferredSize(). + * replaced by {@code getPreferredSize()}. */ @Deprecated public Dimension preferredSize() { @@ -568,7 +568,7 @@ public class TextArea extends TextComponent { * @param columns the number of columns * @return the minimum size for the text area * @deprecated As of JDK version 1.1, - * replaced by getMinimumSize(int, int). + * replaced by {@code getMinimumSize(int, int)}. */ @Deprecated public Dimension minimumSize(int rows, int columns) { @@ -592,7 +592,7 @@ public class TextArea extends TextComponent { /** * @deprecated As of JDK version 1.1, - * replaced by getMinimumSize(). + * replaced by {@code getMinimumSize()}. */ @Deprecated public Dimension minimumSize() { @@ -604,11 +604,11 @@ public class TextArea extends TextComponent { } /** - * Returns a string representing the state of this TextArea. + * Returns a string representing the state of this {@code TextArea}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this text area */ @@ -650,8 +650,8 @@ public class TextArea extends TextComponent { /** * Read the ObjectInputStream. * @exception HeadlessException if - * GraphicsEnvironment.isHeadless() returns - * true + * {@code GraphicsEnvironment.isHeadless()} returns + * {@code true} * @see java.awt.GraphicsEnvironment#isHeadless */ private void readObject(ObjectInputStream s) @@ -689,14 +689,14 @@ public class TextArea extends TextComponent { /** - * Returns the AccessibleContext associated with - * this TextArea. For text areas, the - * AccessibleContext takes the form of an - * AccessibleAWTTextArea. - * A new AccessibleAWTTextArea instance is created if necessary. + * Returns the {@code AccessibleContext} associated with + * this {@code TextArea}. For text areas, the + * {@code AccessibleContext} takes the form of an + * {@code AccessibleAWTTextArea}. + * A new {@code AccessibleAWTTextArea} instance is created if necessary. * - * @return an AccessibleAWTTextArea that serves as the - * AccessibleContext of this TextArea + * @return an {@code AccessibleAWTTextArea} that serves as the + * {@code AccessibleContext} of this {@code TextArea} * @since 1.3 */ public AccessibleContext getAccessibleContext() { @@ -708,7 +708,7 @@ public class TextArea extends TextComponent { /** * This class implements accessibility support for the - * TextArea class. It provides an implementation of the + * {@code TextArea} class. It provides an implementation of the * Java Accessibility API appropriate to text area user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/TextComponent.java b/jdk/src/java.desktop/share/classes/java/awt/TextComponent.java index 191412a30b7..29e0bb1ecba 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/TextComponent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/TextComponent.java @@ -38,11 +38,11 @@ import sun.awt.AWTPermissions; import sun.awt.InputMethodSupport; /** - * The TextComponent class is the superclass of + * The {@code TextComponent} class is the superclass of * any component that allows the editing of some text. *

            * A text component embodies a string of text. The - * TextComponent class defines a set of methods + * {@code TextComponent} class defines a set of methods * that determine whether or not this text is editable. If the * component is editable, it defines another set of methods * that supports a text insertion caret. @@ -61,7 +61,7 @@ public class TextComponent extends Component implements Accessible { /** * The value of the text. - * A null value is the same as "". + * A {@code null} value is the same as "". * * @serial * @see #setText(String) @@ -71,9 +71,9 @@ public class TextComponent extends Component implements Accessible { /** * A boolean indicating whether or not this - * TextComponent is editable. - * It will be true if the text component - * is editable and false if not. + * {@code TextComponent} is editable. + * It will be {@code true} if the text component + * is editable and {@code false} if not. * * @serial * @see #isEditable() @@ -82,7 +82,7 @@ public class TextComponent extends Component implements Accessible { /** * The selection refers to the selected text, and the - * selectionStart is the start position + * {@code selectionStart} is the start position * of the selected text. * * @serial @@ -93,7 +93,7 @@ public class TextComponent extends Component implements Accessible { /** * The selection refers to the selected text, and the - * selectionEnd + * {@code selectionEnd} * is the end position of the selected text. * * @serial @@ -120,12 +120,12 @@ public class TextComponent extends Component implements Accessible { /** * Constructs a new text component initialized with the * specified text. Sets the value of the cursor to - * Cursor.TEXT_CURSOR. + * {@code Cursor.TEXT_CURSOR}. * @param text the text to be displayed; if - * text is null, the empty - * string "" will be displayed + * {@code text} is {@code null}, the empty + * string {@code ""} will be displayed * @exception HeadlessException if - * GraphicsEnvironment.isHeadless + * {@code GraphicsEnvironment.isHeadless} * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see java.awt.Cursor @@ -203,9 +203,9 @@ public class TextComponent extends Component implements Accessible { } /** - * Removes the TextComponent's peer. + * Removes the {@code TextComponent}'s peer. * The peer allows us to modify the appearance of the - * TextComponent without changing its + * {@code TextComponent} without changing its * functionality. */ public void removeNotify() { @@ -224,7 +224,7 @@ public class TextComponent extends Component implements Accessible { * Sets the text that is presented by this * text component to be the specified text. * @param t the new text; - * if this parameter is null then + * if this parameter is {@code null} then * the text is set to the empty string "" * @see java.awt.TextComponent#getText */ @@ -251,7 +251,7 @@ public class TextComponent extends Component implements Accessible { * Returns the text that is presented by this text component. * By default, this is an empty string. * - * @return the value of this TextComponent + * @return the value of this {@code TextComponent} * @see java.awt.TextComponent#setText */ public synchronized String getText() { @@ -274,8 +274,8 @@ public class TextComponent extends Component implements Accessible { /** * Indicates whether or not this text component is editable. - * @return true if this text component is - * editable; false otherwise. + * @return {@code true} if this text component is + * editable; {@code false} otherwise. * @see java.awt.TextComponent#setEditable * @since 1.0 */ @@ -287,8 +287,8 @@ public class TextComponent extends Component implements Accessible { * Sets the flag that determines whether or not this * text component is editable. *

            - * If the flag is set to true, this text component - * becomes user editable. If the flag is set to false, + * If the flag is set to {@code true}, this text component + * becomes user editable. If the flag is set to {@code false}, * the user cannot change the text of this text component. * By default, non-editable text components have a background color * of SystemColor.control. This default can be overridden by @@ -367,7 +367,7 @@ public class TextComponent extends Component implements Accessible { * to be at or before the current selection end. It also * cannot be set to less than zero, the beginning of the * component's text. - * If the caller supplies a value for selectionStart + * If the caller supplies a value for {@code selectionStart} * that is out of bounds, the method enforces these constraints * silently, and without failure. * @param selectionStart the start position of the @@ -403,7 +403,7 @@ public class TextComponent extends Component implements Accessible { * the specified position. The new end point is constrained * to be at or after the current selection start. It also * cannot be set beyond the end of the component's text. - * If the caller supplies a value for selectionEnd + * If the caller supplies a value for {@code selectionEnd} * that is out of bounds, the method enforces these constraints * silently, and without failure. * @param selectionEnd the end position of the @@ -429,8 +429,8 @@ public class TextComponent extends Component implements Accessible { * equal to the length of the text component's text. The * character positions are indexed starting with zero. * The length of the selection is - * endPosition - startPosition, so the - * character at endPosition is not selected. + * {@code endPosition} - {@code startPosition}, so the + * character at {@code endPosition} is not selected. * If the start and end positions of the selected text are equal, * all text is deselected. *

            @@ -443,10 +443,10 @@ public class TextComponent extends Component implements Accessible { * start position, it is reset to the start position. * * @param selectionStart the zero-based index of the first - character (char value) to be selected + * character ({@code char} value) to be selected * @param selectionEnd the zero-based end position of the - text to be selected; the character (char value) at - selectionEnd is not selected + * text to be selected; the character ({@code char} value) at + * {@code selectionEnd} is not selected * @see java.awt.TextComponent#setSelectionStart * @see java.awt.TextComponent#setSelectionEnd * @see java.awt.TextComponent#selectAll @@ -495,13 +495,13 @@ public class TextComponent extends Component implements Accessible { * and the last character of the text, inclusive. * If the passed-in value is greater than this range, * the value is set to the last character (or 0 if - * the TextComponent contains no text) + * the {@code TextComponent} contains no text) * and no error is returned. If the passed-in value is - * less than 0, an IllegalArgumentException + * less than 0, an {@code IllegalArgumentException} * is thrown. * * @param position the position of the text insertion caret - * @exception IllegalArgumentException if position + * @exception IllegalArgumentException if {@code position} * is less than zero * @since 1.1 */ @@ -553,7 +553,7 @@ public class TextComponent extends Component implements Accessible { /** * Adds the specified text event listener to receive text events * from this text component. - * If l is null, no exception is + * If {@code l} is {@code null}, no exception is * thrown and no action is performed. *

            Refer to AWT Threading Issues for details on AWT's threading model. @@ -574,7 +574,7 @@ public class TextComponent extends Component implements Accessible { /** * Removes the specified text event listener so that it no longer * receives text events from this text component - * If l is null, no exception is + * If {@code l} is {@code null}, no exception is * thrown and no action is performed. *

            Refer to AWT Threading Issues for details on AWT's threading model. @@ -596,7 +596,7 @@ public class TextComponent extends Component implements Accessible { * Returns an array of all the text listeners * registered on this text component. * - * @return all of this text component's TextListeners + * @return all of this text component's {@code TextListener}s * or an empty array if no text * listeners are currently registered * @@ -612,16 +612,16 @@ public class TextComponent extends Component implements Accessible { /** * Returns an array of all the objects currently registered * as FooListeners - * upon this TextComponent. + * upon this {@code TextComponent}. * FooListeners are registered using the * addFooListener method. * *

            - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * TextComponent t + * {@code TextComponent t} * for its text listeners with the following code: * *

            TextListener[] tls = (TextListener[])(t.getListeners(TextListener.class));
            @@ -630,14 +630,14 @@ public class TextComponent extends Component implements Accessible { * * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this text component, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @see #getTextListeners * @since 1.3 @@ -666,9 +666,9 @@ public class TextComponent extends Component implements Accessible { /** * Processes events on this text component. If the event is a - * TextEvent, it invokes the processTextEvent - * method else it invokes its superclass's processEvent. - *

            Note that if the event parameter is null + * {@code TextEvent}, it invokes the {@code processTextEvent} + * method else it invokes its superclass's {@code processEvent}. + *

            Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -684,17 +684,17 @@ public class TextComponent extends Component implements Accessible { /** * Processes text events occurring on this text component by - * dispatching them to any registered TextListener objects. + * dispatching them to any registered {@code TextListener} objects. *

            * NOTE: This method will not be called unless text events * are enabled for this component. This happens when one of the * following occurs: *

              - *
            • A TextListener object is registered - * via addTextListener - *
            • Text events are enabled via enableEvents + *
            • A {@code TextListener} object is registered + * via {@code addTextListener} + *
            • Text events are enabled via {@code enableEvents} *
            - *

            Note that if the event parameter is null + *

            Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -715,11 +715,11 @@ public class TextComponent extends Component implements Accessible { /** * Returns a string representing the state of this - * TextComponent. This + * {@code TextComponent}. This * method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this text component */ @@ -795,8 +795,8 @@ public class TextComponent extends Component implements Accessible { * ignored. * * @exception HeadlessException if - * GraphicsEnvironment.isHeadless() returns - * true + * {@code GraphicsEnvironment.isHeadless()} returns + * {@code true} * @see #removeTextListener * @see #addTextListener * @see java.awt.GraphicsEnvironment#isHeadless @@ -850,7 +850,7 @@ public class TextComponent extends Component implements Accessible { /** * This class implements accessibility support for the - * TextComponent class. It provides an implementation of the + * {@code TextComponent} class. It provides an implementation of the * Java Accessibility API appropriate to text component user-interface * elements. * @since 1.3 diff --git a/jdk/src/java.desktop/share/classes/java/awt/TextField.java b/jdk/src/java.desktop/share/classes/java/awt/TextField.java index 7c5563088c3..effdfd43d24 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/TextField.java +++ b/jdk/src/java.desktop/share/classes/java/awt/TextField.java @@ -34,12 +34,12 @@ import javax.accessibility.*; /** - * A TextField object is a text component + * A {@code TextField} object is a text component * that allows for the editing of a single line of text. *

            * For example, the following image depicts a frame with four * text fields of varying widths. Two of these text fields - * display the predefined text "Hello". + * display the predefined text {@code "Hello"}. *

            * The preceding text describes this image. @@ -59,27 +59,27 @@ import javax.accessibility.*; *


            *

            * Every time the user types a key in the text field, one or - * more key events are sent to the text field. A KeyEvent + * more key events are sent to the text field. A {@code KeyEvent} * may be one of three types: keyPressed, keyReleased, or keyTyped. * The properties of a key event indicate which of these types * it is, as well as additional information about the event, * such as what modifiers are applied to the key event and the * time at which the event occurred. *

            - * The key event is passed to every KeyListener - * or KeyAdapter object which registered to receive such - * events using the component's addKeyListener method. - * (KeyAdapter objects implement the - * KeyListener interface.) + * The key event is passed to every {@code KeyListener} + * or {@code KeyAdapter} object which registered to receive such + * events using the component's {@code addKeyListener} method. + * ({@code KeyAdapter} objects implement the + * {@code KeyListener} interface.) *

            - * It is also possible to fire an ActionEvent. + * It is also possible to fire an {@code ActionEvent}. * If action events are enabled for the text field, they may - * be fired by pressing the Return key. + * be fired by pressing the {@code Return} key. *

            - * The TextField class's processEvent + * The {@code TextField} class's {@code processEvent} * method examines the action event and passes it along to - * processActionEvent. The latter method redirects the - * event to any ActionListener objects that have + * {@code processActionEvent}. The latter method redirects the + * event to any {@code ActionListener} objects that have * registered to receive action events generated by this * text field. * @@ -112,7 +112,7 @@ public class TextField extends TextComponent { * The echo character, which is used when * the user wishes to disguise the characters * typed into the text field. - * The disguises are removed if echoChar = 0. + * The disguises are removed if echoChar = {@code 0}. * * @serial * @see #getEchoChar() @@ -157,8 +157,8 @@ public class TextField extends TextComponent { /** * Constructs a new text field initialized with the specified text. * @param text the text to be displayed. If - * text is null, the empty - * string "" will be displayed. + * {@code text} is {@code null}, the empty + * string {@code ""} will be displayed. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless @@ -172,8 +172,8 @@ public class TextField extends TextComponent { * of columns. A column is an approximate average character * width that is platform-dependent. * @param columns the number of columns. If - * columns is less than 0, - * columns is set to 0. + * {@code columns} is less than {@code 0}, + * {@code columns} is set to {@code 0}. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless @@ -188,11 +188,11 @@ public class TextField extends TextComponent { * number of columns. A column is an approximate average character * width that is platform-dependent. * @param text the text to be displayed. If - * text is null, the empty - * string "" will be displayed. + * {@code text} is {@code null}, the empty + * string {@code ""} will be displayed. * @param columns the number of columns. If - * columns is less than 0, - * columns is set to 0. + * {@code columns} is less than {@code 0}, + * {@code columns} is set to {@code 0}. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless @@ -230,7 +230,7 @@ public class TextField extends TextComponent { * An echo character is useful for text fields where * user input should not be echoed to the screen, as in * the case of a text field for entering a password. - * If echoChar = 0, user + * If {@code echoChar} = {@code 0}, user * input is echoed to the screen unchanged. *

            * A Java platform implementation may support only a limited, @@ -252,7 +252,7 @@ public class TextField extends TextComponent { * An echo character is useful for text fields where * user input should not be echoed to the screen, as in * the case of a text field for entering a password. - * Setting echoChar = 0 allows + * Setting {@code echoChar} = {@code 0} allows * user input to be echoed to the screen again. *

            * A Java platform implementation may support only a limited, @@ -277,7 +277,7 @@ public class TextField extends TextComponent { * @param c the echo character for this text field * * @deprecated As of JDK version 1.1, - * replaced by setEchoChar(char). + * replaced by {@code setEchoChar(char)}. */ @Deprecated public synchronized void setEchoCharacter(char c) { @@ -329,9 +329,9 @@ public class TextField extends TextComponent { * An echo character is useful for text fields where * user input should not be echoed to the screen, as in * the case of a text field for entering a password. - * @return true if this text field has + * @return {@code true} if this text field has * a character set for echoing; - * false otherwise. + * {@code false} otherwise. * @see java.awt.TextField#setEchoChar * @see java.awt.TextField#getEchoChar */ @@ -356,8 +356,8 @@ public class TextField extends TextComponent { * @param columns the number of columns. * @see java.awt.TextField#getColumns * @exception IllegalArgumentException if the value - * supplied for columns - * is less than 0. + * supplied for {@code columns} + * is less than {@code 0}. * @since 1.1 */ public void setColumns(int columns) { @@ -398,7 +398,7 @@ public class TextField extends TextComponent { * @return the preferred size for the text field * * @deprecated As of JDK version 1.1, - * replaced by getPreferredSize(int). + * replaced by {@code getPreferredSize(int)}. */ @Deprecated public Dimension preferredSize(int columns) { @@ -422,7 +422,7 @@ public class TextField extends TextComponent { /** * @deprecated As of JDK version 1.1, - * replaced by getPreferredSize(). + * replaced by {@code getPreferredSize()}. */ @Deprecated public Dimension preferredSize() { @@ -452,7 +452,7 @@ public class TextField extends TextComponent { * @param columns the number of columns * @return the minimum size for this text field * @deprecated As of JDK version 1.1, - * replaced by getMinimumSize(int). + * replaced by {@code getMinimumSize(int)}. */ @Deprecated public Dimension minimumSize(int columns) { @@ -476,7 +476,7 @@ public class TextField extends TextComponent { /** * @deprecated As of JDK version 1.1, - * replaced by getMinimumSize(). + * replaced by {@code getMinimumSize()}. */ @Deprecated public Dimension minimumSize() { @@ -532,7 +532,7 @@ public class TextField extends TextComponent { * Returns an array of all the action listeners * registered on this textfield. * - * @return all of this textfield's ActionListeners + * @return all of this textfield's {@code ActionListener}s * or an empty array if no action * listeners are currently registered * @@ -548,16 +548,16 @@ public class TextField extends TextComponent { /** * Returns an array of all the objects currently registered * as FooListeners - * upon this TextField. + * upon this {@code TextField}. * FooListeners are registered using the * addFooListener method. * *

            - * You can specify the listenerType argument + * You can specify the {@code listenerType} argument * with a class literal, such as * FooListener.class. * For example, you can query a - * TextField t + * {@code TextField t} * for its action listeners with the following code: * *

            ActionListener[] als = (ActionListener[])(t.getListeners(ActionListener.class));
            @@ -566,14 +566,14 @@ public class TextField extends TextComponent { * * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this textfield, * or an empty array if no such * listeners have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @see #getActionListeners * @since 1.3 @@ -602,11 +602,11 @@ public class TextField extends TextComponent { /** * Processes events on this text field. If the event - * is an instance of ActionEvent, - * it invokes the processActionEvent - * method. Otherwise, it invokes processEvent + * is an instance of {@code ActionEvent}, + * it invokes the {@code processActionEvent} + * method. Otherwise, it invokes {@code processEvent} * on the superclass. - *

            Note that if the event parameter is null + *

            Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -626,17 +626,17 @@ public class TextField extends TextComponent { /** * Processes action events occurring on this text field by * dispatching them to any registered - * ActionListener objects. + * {@code ActionListener} objects. *

            * This method is not called unless action events are * enabled for this component. Action events are enabled * when one of the following occurs: *

              - *
            • An ActionListener object is registered - * via addActionListener. - *
            • Action events are enabled via enableEvents. + *
            • An {@code ActionListener} object is registered + * via {@code addActionListener}. + *
            • Action events are enabled via {@code enableEvents}. *
            - *

            Note that if the event parameter is null + *

            Note that if the event parameter is {@code null} * the behavior is unspecified and may result in an * exception. * @@ -654,11 +654,11 @@ public class TextField extends TextComponent { } /** - * Returns a string representing the state of this TextField. + * Returns a string representing the state of this {@code TextField}. * This method is intended to be used only for debugging purposes, and the * content and format of the returned string may vary between * implementations. The returned string may be empty but may not be - * null. + * {@code null}. * * @return the parameter string of this text field */ @@ -712,8 +712,8 @@ public class TextField extends TextComponent { * ignored. * * @exception HeadlessException if - * GraphicsEnvironment.isHeadless() returns - * true + * {@code GraphicsEnvironment.isHeadless()} returns + * {@code true} * @see #removeActionListener(ActionListener) * @see #addActionListener(ActionListener) * @see java.awt.GraphicsEnvironment#isHeadless @@ -769,7 +769,7 @@ public class TextField extends TextComponent { /** * This class implements accessibility support for the - * TextField class. It provides an implementation of the + * {@code TextField} class. It provides an implementation of the * Java Accessibility API appropriate to text field user-interface elements. * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/TexturePaint.java b/jdk/src/java.desktop/share/classes/java/awt/TexturePaint.java index 8333965b114..387e5612984 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/TexturePaint.java +++ b/jdk/src/java.desktop/share/classes/java/awt/TexturePaint.java @@ -31,18 +31,18 @@ import java.awt.image.BufferedImage; import java.awt.image.ColorModel; /** - * The TexturePaint class provides a way to fill a + * The {@code TexturePaint} class provides a way to fill a * {@link Shape} with a texture that is specified as - * a {@link BufferedImage}. The size of the BufferedImage - * object should be small because the BufferedImage data - * is copied by the TexturePaint object. + * a {@link BufferedImage}. The size of the {@code BufferedImage} + * object should be small because the {@code BufferedImage} data + * is copied by the {@code TexturePaint} object. * At construction time, the texture is anchored to the upper * left corner of a {@link Rectangle2D} that is * specified in user space. Texture is computed for * locations in the device space by conceptually replicating the - * specified Rectangle2D infinitely in all directions - * in user space and mapping the BufferedImage to each - * replicated Rectangle2D. + * specified {@code Rectangle2D} infinitely in all directions + * in user space and mapping the {@code BufferedImage} to each + * replicated {@code Rectangle2D}. * @see Paint * @see Graphics2D#setPaint * @version 1.48, 06/05/07 @@ -57,10 +57,10 @@ public class TexturePaint implements Paint { double sy; /** - * Constructs a TexturePaint object. - * @param txtr the BufferedImage object with the texture + * Constructs a {@code TexturePaint} object. + * @param txtr the {@code BufferedImage} object with the texture * used for painting - * @param anchor the Rectangle2D in user space used to + * @param anchor the {@code Rectangle2D} in user space used to * anchor and replicate the texture */ public TexturePaint(BufferedImage txtr, @@ -73,9 +73,9 @@ public class TexturePaint implements Paint { } /** - * Returns the BufferedImage texture used to + * Returns the {@code BufferedImage} texture used to * fill the shapes. - * @return a BufferedImage. + * @return a {@code BufferedImage}. */ public BufferedImage getImage() { return bufImg; @@ -84,8 +84,8 @@ public class TexturePaint implements Paint { /** * Returns a copy of the anchor rectangle which positions and * sizes the textured image. - * @return the Rectangle2D used to anchor and - * size this TexturePaint. + * @return the {@code Rectangle2D} used to anchor and + * size this {@code TexturePaint}. */ public Rectangle2D getAnchorRect() { return new Rectangle2D.Double(tx, ty, @@ -139,8 +139,8 @@ public class TexturePaint implements Paint { } /** - * Returns the transparency mode for this TexturePaint. - * @return the transparency mode for this TexturePaint + * Returns the transparency mode for this {@code TexturePaint}. + * @return the transparency mode for this {@code TexturePaint} * as an integer value. * @see Transparency */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java b/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java index ee020270f19..663a6c72a1b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java @@ -69,7 +69,7 @@ import javax.accessibility.AccessibilityProvider; /** * This class is the abstract superclass of all actual * implementations of the Abstract Window Toolkit. Subclasses of - * the Toolkit class are used to bind the various components + * the {@code Toolkit} class are used to bind the various components * to particular native toolkit implementations. *

            * Many GUI events may be delivered to user @@ -82,8 +82,8 @@ import javax.accessibility.AccessibilityProvider; * limited to: *

              *
            • Scrolling to a specified position. - *
              For example, calling ScrollPane.setScrollPosition - * and then getScrollPosition may return an incorrect + *
              For example, calling {@code ScrollPane.setScrollPosition} + * and then {@code getScrollPosition} may return an incorrect * value if the original request has not yet been processed. * *
            • Moving the focus from one component to another. @@ -94,25 +94,25 @@ import javax.accessibility.AccessibilityProvider; * Tutorial. * *
            • Making a top-level container visible. - *
              Calling setVisible(true) on a Window, - * Frame or Dialog may occur + *
              Calling {@code setVisible(true)} on a {@code Window}, + * {@code Frame} or {@code Dialog} may occur * asynchronously. * *
            • Setting the size or location of a top-level container. - *
              Calls to setSize, setBounds or - * setLocation on a Window, - * Frame or Dialog are forwarded + *
              Calls to {@code setSize}, {@code setBounds} or + * {@code setLocation} on a {@code Window}, + * {@code Frame} or {@code Dialog} are forwarded * to the underlying window management system and may be * ignored or modified. See {@link java.awt.Window} for * more information. *
            *

            * Most applications should not call any of the methods in this - * class directly. The methods defined by Toolkit are + * class directly. The methods defined by {@code Toolkit} are * the "glue" that joins the platform-independent classes in the - * java.awt package with their counterparts in - * java.awt.peer. Some methods defined by - * Toolkit query the native operating system directly. + * {@code java.awt} package with their counterparts in + * {@code java.awt.peer}. Some methods defined by + * {@code Toolkit} query the native operating system directly. * * @author Sami Shaio * @author Arthur van Hoff @@ -247,8 +247,8 @@ public abstract class Toolkit { /** * Gets the size of the screen. On systems with multiple displays, the * primary display is used. Multi-screen aware display dimensions are - * available from GraphicsConfiguration and - * GraphicsDevice. + * available from {@code GraphicsConfiguration} and + * {@code GraphicsDevice}. * @return the size of this toolkit's screen, in pixels. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true @@ -271,7 +271,7 @@ public abstract class Toolkit { /** * Gets the insets of the screen. - * @param gc a GraphicsConfiguration + * @param gc a {@code GraphicsConfiguration} * @return the insets of this toolkit's screen, in pixels. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true @@ -291,14 +291,14 @@ public abstract class Toolkit { /** * Determines the color model of this toolkit's screen. *

            - * ColorModel is an abstract class that + * {@code ColorModel} is an abstract class that * encapsulates the ability to translate between the * pixel values of an image and its red, green, blue, * and alpha components. *

            * This toolkit method is called by the - * getColorModel method - * of the Component class. + * {@code getColorModel} method + * of the {@code Component} class. * @return the color model of this toolkit's screen. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true @@ -332,8 +332,8 @@ public abstract class Toolkit { * Gets the screen device metrics for rendering of the font. * @param font a font * @return the screen metrics of the specified font in this toolkit - * @deprecated As of JDK version 1.2, replaced by the Font - * method getLineMetrics. + * @deprecated As of JDK version 1.2, replaced by the {@code Font} + * method {@code getLineMetrics}. * @see java.awt.font.LineMetrics * @see java.awt.Font#getLineMetrics * @see java.awt.GraphicsEnvironment#getScreenDevices @@ -606,22 +606,22 @@ public abstract class Toolkit { * with the same filename to the same returned Image. *

            * Since the mechanism required to facilitate this sharing of - * Image objects may continue to hold onto images + * {@code Image} objects may continue to hold onto images * that are no longer in use for an indefinite period of time, * developers are encouraged to implement their own caching of * images by using the {@link #createImage(java.lang.String) createImage} * variant wherever available. * If the image data contained in the specified file changes, - * the Image object returned from this method may + * the {@code Image} object returned from this method may * still contain stale information which was loaded from the * file after a prior call. * Previously loaded image data can be manually discarded by * calling the {@link Image#flush flush} method on the - * returned Image. + * returned {@code Image}. *

            * This method first checks if there is a security manager installed. * If so, the method calls the security manager's - * checkRead method with the file specified to ensure + * {@code checkRead} method with the file specified to ensure * that the access to the image is allowed. * @param filename the name of a file containing pixel data * in a recognized file format. @@ -641,27 +641,27 @@ public abstract class Toolkit { * with the same URL to the same returned Image. *

            * Since the mechanism required to facilitate this sharing of - * Image objects may continue to hold onto images + * {@code Image} objects may continue to hold onto images * that are no longer in use for an indefinite period of time, * developers are encouraged to implement their own caching of * images by using the {@link #createImage(java.net.URL) createImage} * variant wherever available. * If the image data stored at the specified URL changes, - * the Image object returned from this method may + * the {@code Image} object returned from this method may * still contain stale information which was fetched from the * URL after a prior call. * Previously loaded image data can be manually discarded by * calling the {@link Image#flush flush} method on the - * returned Image. + * returned {@code Image}. *

            * This method first checks if there is a security manager installed. * If so, the method calls the security manager's - * checkPermission method with the + * {@code checkPermission} method with the * url.openConnection().getPermission() permission to ensure * that the access to the image is allowed. For compatibility * with pre-1.2 security managers, if the access is denied with - * FilePermission or SocketPermission, - * the method throws the SecurityException + * {@code FilePermission} or {@code SocketPermission}, + * the method throws the {@code SecurityException} * if the corresponding 1.1-style SecurityManager.checkXXX method * also denies permission. * @param url the URL to use in fetching the pixel data. @@ -681,7 +681,7 @@ public abstract class Toolkit { *

            * This method first checks if there is a security manager installed. * If so, the method calls the security manager's - * checkRead method with the specified file to ensure + * {@code checkRead} method with the specified file to ensure * that the image creation is allowed. * @param filename the name of a file containing pixel data * in a recognized file format. @@ -700,12 +700,12 @@ public abstract class Toolkit { *

            * This method first checks if there is a security manager installed. * If so, the method calls the security manager's - * checkPermission method with the + * {@code checkPermission} method with the * url.openConnection().getPermission() permission to ensure * that the image creation is allowed. For compatibility * with pre-1.2 security managers, if the access is denied with - * FilePermission or SocketPermission, - * the method throws SecurityException + * {@code FilePermission} or {@code SocketPermission}, + * the method throws {@code SecurityException} * if the corresponding 1.1-style SecurityManager.checkXXX method * also denies permission. * @param url the URL to use in fetching the pixel data. @@ -722,7 +722,7 @@ public abstract class Toolkit { * Prepares an image for rendering. *

            * If the values of the width and height arguments are both - * -1, this method prepares the image for rendering + * {@code -1}, this method prepares the image for rendering * on the default screen; otherwise, this method prepares an image * for rendering on the default screen at the specified width and height. *

            @@ -730,23 +730,23 @@ public abstract class Toolkit { * and an appropriately scaled screen representation of the image is * generated. *

            - * This method is called by components prepareImage + * This method is called by components {@code prepareImage} * methods. *

            * Information on the flags returned by this method can be found - * with the definition of the ImageObserver interface. + * with the definition of the {@code ImageObserver} interface. * @param image the image for which to prepare a * screen representation. * @param width the width of the desired screen - * representation, or -1. + * representation, or {@code -1}. * @param height the height of the desired screen - * representation, or -1. - * @param observer the ImageObserver + * representation, or {@code -1}. + * @param observer the {@code ImageObserver} * object to be notified as the * image is being prepared. - * @return true if the image has already been - * fully prepared; false otherwise. + * @return {@code true} if the image has already been + * fully prepared; {@code false} otherwise. * @see java.awt.Component#prepareImage(java.awt.Image, * java.awt.image.ImageObserver) * @see java.awt.Component#prepareImage(java.awt.Image, @@ -761,30 +761,30 @@ public abstract class Toolkit { * being prepared for display. *

            * If the values of the width and height arguments are both - * -1, this method returns the construction status of + * {@code -1}, this method returns the construction status of * a screen representation of the specified image in this toolkit. * Otherwise, this method returns the construction status of a * scaled representation of the image at the specified width * and height. *

            * This method does not cause the image to begin loading. - * An application must call prepareImage to force + * An application must call {@code prepareImage} to force * the loading of an image. *

            - * This method is called by the component's checkImage + * This method is called by the component's {@code checkImage} * methods. *

            * Information on the flags returned by this method can be found - * with the definition of the ImageObserver interface. + * with the definition of the {@code ImageObserver} interface. * @param image the image whose status is being checked. * @param width the width of the scaled version whose status is - * being checked, or -1. + * being checked, or {@code -1}. * @param height the height of the scaled version whose status - * is being checked, or -1. - * @param observer the ImageObserver object to be + * is being checked, or {@code -1}. + * @param observer the {@code ImageObserver} object to be * notified as the image is being prepared. * @return the bitwise inclusive OR of the - * ImageObserver flags for the + * {@code ImageObserver} flags for the * image data that is currently available. * @see java.awt.Toolkit#prepareImage(java.awt.Image, * int, int, java.awt.image.ImageObserver) @@ -840,17 +840,17 @@ public abstract class Toolkit { int imagelength); /** - * Gets a PrintJob object which is the result of initiating + * Gets a {@code PrintJob} object which is the result of initiating * a print operation on the toolkit's platform. *

            * Each actual implementation of this method should first check if there * is a security manager installed. If there is, the method should call - * the security manager's checkPrintJobAccess method to + * the security manager's {@code checkPrintJobAccess} method to * ensure initiation of a print operation is allowed. If the default - * implementation of checkPrintJobAccess is used (that is, + * implementation of {@code checkPrintJobAccess} is used (that is, * that method is not overriden), then this results in a call to the - * security manager's checkPermission method with a - * RuntimePermission("queuePrintJob") permission. + * security manager's {@code checkPermission} method with a + * {@code RuntimePermission("queuePrintJob")} permission. * * @param frame the parent of the print dialog. May not be null. * @param jobtitle the title of the PrintJob. A null title is equivalent @@ -862,7 +862,7 @@ public abstract class Toolkit { * takes JobAttributes and PageAttributes objects. This object * may be updated to reflect the user's job choices on exit. May * be null. - * @return a PrintJob object, or null if the + * @return a {@code PrintJob} object, or {@code null} if the * user cancelled the print job. * @throws NullPointerException if frame is null * @throws SecurityException if this thread is not allowed to initiate a @@ -876,17 +876,17 @@ public abstract class Toolkit { Properties props); /** - * Gets a PrintJob object which is the result of initiating + * Gets a {@code PrintJob} object which is the result of initiating * a print operation on the toolkit's platform. *

            * Each actual implementation of this method should first check if there * is a security manager installed. If there is, the method should call - * the security manager's checkPrintJobAccess method to + * the security manager's {@code checkPrintJobAccess} method to * ensure initiation of a print operation is allowed. If the default - * implementation of checkPrintJobAccess is used (that is, + * implementation of {@code checkPrintJobAccess} is used (that is, * that method is not overriden), then this results in a call to the - * security manager's checkPermission method with a - * RuntimePermission("queuePrintJob") permission. + * security manager's {@code checkPermission} method with a + * {@code RuntimePermission("queuePrintJob")} permission. * * @param frame the parent of the print dialog. May not be null. * @param jobtitle the title of the PrintJob. A null title is equivalent @@ -900,7 +900,7 @@ public abstract class Toolkit { * job. The attributes will be updated to reflect the user's * choices as outlined in the PageAttributes documentation. May be * null. - * @return a PrintJob object, or null if the + * @return a {@code PrintJob} object, or {@code null} if the * user cancelled the print job. * @throws NullPointerException if frame is null * @throws IllegalArgumentException if pageAttributes specifies differing @@ -952,20 +952,20 @@ public abstract class Toolkit { * applications which use native clipboard facilities. *

            * In addition to any and all default formats text returned by the system - * Clipboard's getTransferData() method is available in the + * Clipboard's {@code getTransferData()} method is available in the * following flavors: *

              *
            • DataFlavor.stringFlavor
            • *
            • DataFlavor.plainTextFlavor (deprecated)
            • *
            - * As with java.awt.datatransfer.StringSelection, if the - * requested flavor is DataFlavor.plainTextFlavor, or an + * As with {@code java.awt.datatransfer.StringSelection}, if the + * requested flavor is {@code DataFlavor.plainTextFlavor}, or an * equivalent flavor, a Reader is returned. Note: The behavior of - * the system Clipboard's getTransferData() method for - * DataFlavor.plainTextFlavor, and equivalent DataFlavors, is - * inconsistent with the definition of DataFlavor.plainTextFlavor - * . Because of this, support for - * DataFlavor.plainTextFlavor, and equivalent flavors, is + * the system Clipboard's {@code getTransferData()} method for + * {@code DataFlavor.plainTextFlavor}, and equivalent DataFlavors, is + * inconsistent with the definition of {@code DataFlavor.plainTextFlavor}. + * Because of this, support for + * {@code DataFlavor.plainTextFlavor}, and equivalent flavors, is * deprecated. *

            * Each actual implementation of this method should first check if there @@ -990,37 +990,37 @@ public abstract class Toolkit { /** * Gets the singleton instance of the system selection as a - * Clipboard object. This allows an application to read and + * {@code Clipboard} object. This allows an application to read and * modify the current, system-wide selection. *

            * An application is responsible for updating the system selection whenever * the user selects text, using either the mouse or the keyboard. * Typically, this is implemented by installing a - * FocusListener on all Components which support - * text selection, and, between FOCUS_GAINED and - * FOCUS_LOST events delivered to that Component, - * updating the system selection Clipboard when the selection - * changes inside the Component. Properly updating the system + * {@code FocusListener} on all {@code Component}s which support + * text selection, and, between {@code FOCUS_GAINED} and + * {@code FOCUS_LOST} events delivered to that {@code Component}, + * updating the system selection {@code Clipboard} when the selection + * changes inside the {@code Component}. Properly updating the system * selection ensures that a Java application will interact correctly with * native applications and other Java applications running simultaneously - * on the system. Note that java.awt.TextComponent and - * javax.swing.text.JTextComponent already adhere to this + * on the system. Note that {@code java.awt.TextComponent} and + * {@code javax.swing.text.JTextComponent} already adhere to this * policy. When using these classes, and their subclasses, developers need * not write any additional code. *

            - * Some platforms do not support a system selection Clipboard. - * On those platforms, this method will return null. In such a + * Some platforms do not support a system selection {@code Clipboard}. + * On those platforms, this method will return {@code null}. In such a * case, an application is absolved from its responsibility to update the - * system selection Clipboard as described above. + * system selection {@code Clipboard} as described above. *

            * Each actual implementation of this method should first check if there * is a security manager installed. If there is, the method should call * the security manager's {@link SecurityManager#checkPermission * checkPermission} method to check {@code AWTPermission("accessClipboard")}. * - * @return the system selection as a Clipboard, or - * null if the native platform does not support a - * system selection Clipboard + * @return the system selection as a {@code Clipboard}, or + * {@code null} if the native platform does not support a + * system selection {@code Clipboard} * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @@ -1050,13 +1050,13 @@ public abstract class Toolkit { * key for menu shortcuts. *

            * Menu shortcuts, which are embodied in the - * MenuShortcut class, are handled by the - * MenuBar class. + * {@code MenuShortcut} class, are handled by the + * {@code MenuBar} class. *

            - * By default, this method returns Event.CTRL_MASK. + * By default, this method returns {@code Event.CTRL_MASK}. * Toolkit implementations should override this method if the * Control key isn't the correct key for accelerators. - * @return the modifier mask on the Event class + * @return the modifier mask on the {@code Event} class * that is used for menu shortcuts on this toolkit. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true @@ -1083,7 +1083,7 @@ public abstract class Toolkit { * @param keyCode the key code * @return {@code true} if the given key is currently in its "on" state; * otherwise {@code false} - * @exception java.lang.IllegalArgumentException if keyCode + * @exception java.lang.IllegalArgumentException if {@code keyCode} * is not one of the valid key codes * @exception java.lang.UnsupportedOperationException if the host system doesn't * allow getting the state of this key programmatically, or if the keyboard @@ -1119,7 +1119,7 @@ public abstract class Toolkit { * * @param keyCode the key code * @param on the state of the key - * @exception java.lang.IllegalArgumentException if keyCode + * @exception java.lang.IllegalArgumentException if {@code keyCode} * is not one of the valid key codes * @exception java.lang.UnsupportedOperationException if the host system doesn't * allow setting the state of this key programmatically, or if the keyboard @@ -1163,7 +1163,7 @@ public abstract class Toolkit { * @param cursor the image to display when the cursor is activated * @param hotSpot the X and Y of the large cursor's hot spot; the * hotSpot values must be less than the Dimension returned by - * getBestCursorSize + * {@code getBestCursorSize} * @param name a localized description of the cursor, for Java Accessibility use * @exception IndexOutOfBoundsException if the hotSpot values are outside * the bounds of the cursor @@ -1252,10 +1252,10 @@ public abstract class Toolkit { /** * Returns whether Toolkit supports this state for - * Frames. This method tells whether the UI + * {@code Frame}s. This method tells whether the UI * concept of, say, maximization or iconification is * supported. It will always return false for "compound" states - * like Frame.ICONIFIED|Frame.MAXIMIZED_VERT. + * like {@code Frame.ICONIFIED|Frame.MAXIMIZED_VERT}. * In other words, the rule of thumb is that only queries with a * single frame state constant as an argument are meaningful. *

            Note that supporting a given concept is a platform- @@ -1280,11 +1280,11 @@ public abstract class Toolkit { *

          * * @param state one of named frame state constants. - * @return true is this frame state is supported by - * this Toolkit implementation, false otherwise. + * @return {@code true} is this frame state is supported by + * this Toolkit implementation, {@code false} otherwise. * @exception HeadlessException - * if GraphicsEnvironment.isHeadless() - * returns true. + * if {@code GraphicsEnvironment.isHeadless()} + * returns {@code true}. * @see java.awt.Window#addWindowStateListener * @since 1.4 */ @@ -1431,7 +1431,7 @@ public abstract class Toolkit { * {@link SecurityManager#checkPermission checkPermission} method * is called to check {@code AWTPermission("accessEventQueue")}. * - * @return the EventQueue object + * @return the {@code EventQueue} object * @throws SecurityException * if a security manager is set and it denies access to * the {@code EventQueue} @@ -1446,10 +1446,10 @@ public abstract class Toolkit { } /** - * Gets the application's or applet's EventQueue + * Gets the application's or applet's {@code EventQueue} * instance, without checking access. For security reasons, - * this can only be called from a Toolkit subclass. - * @return the EventQueue object + * this can only be called from a {@code Toolkit} subclass. + * @return the {@code EventQueue} object */ protected abstract EventQueue getSystemEventQueueImpl(); @@ -1664,8 +1664,8 @@ public abstract class Toolkit { * Returns whether the always-on-top mode is supported by this toolkit. * To detect whether the always-on-top mode is supported for a * particular Window, use {@link Window#isAlwaysOnTopSupported}. - * @return true, if current toolkit supports the always-on-top mode, - * otherwise returns false + * @return {@code true}, if current toolkit supports the always-on-top mode, + * otherwise returns {@code false} * @see Window#isAlwaysOnTopSupported * @see Window#setAlwaysOnTop(boolean) * @since 1.6 @@ -1677,12 +1677,12 @@ public abstract class Toolkit { /** * Returns whether the given modality type is supported by this toolkit. If * a dialog with unsupported modality type is created, then - * Dialog.ModalityType.MODELESS is used instead. + * {@code Dialog.ModalityType.MODELESS} is used instead. * * @param modalityType modality type to be checked for support by this toolkit * - * @return true, if current toolkit supports given modality - * type, false otherwise + * @return {@code true}, if current toolkit supports given modality + * type, {@code false} otherwise * * @see java.awt.Dialog.ModalityType * @see java.awt.Dialog#getModalityType @@ -1695,12 +1695,12 @@ public abstract class Toolkit { /** * Returns whether the given modal exclusion type is supported by this * toolkit. If an unsupported modal exclusion type property is set on a window, - * then Dialog.ModalExclusionType.NO_EXCLUDE is used instead. + * then {@code Dialog.ModalExclusionType.NO_EXCLUDE} is used instead. * * @param modalExclusionType modal exclusion type to be checked for support by this toolkit * - * @return true, if current toolkit supports given modal exclusion - * type, false otherwise + * @return {@code true}, if current toolkit supports given modal exclusion + * type, {@code false} otherwise * * @see java.awt.Dialog.ModalExclusionType * @see java.awt.Window#getModalExclusionType @@ -1739,16 +1739,16 @@ public abstract class Toolkit { /** * Adds an AWTEventListener to receive all AWTEvents dispatched - * system-wide that conform to the given eventMask. + * system-wide that conform to the given {@code eventMask}. *

          - * First, if there is a security manager, its checkPermission + * First, if there is a security manager, its {@code checkPermission} * method is called with an - * AWTPermission("listenToAllAWTEvents") permission. + * {@code AWTPermission("listenToAllAWTEvents")} permission. * This may result in a SecurityException. *

          - * eventMask is a bitmask of event types to receive. + * {@code eventMask} is a bitmask of event types to receive. * It is constructed by bitwise OR-ing together the event masks - * defined in AWTEvent. + * defined in {@code AWTEvent}. *

          * Note: event listener use is not recommended for normal * application use, but are intended solely to support special @@ -1761,7 +1761,7 @@ public abstract class Toolkit { * @param eventMask the bitmask of event types to receive * @throws SecurityException * if a security manager exists and its - * checkPermission method doesn't allow the operation. + * {@code checkPermission} method doesn't allow the operation. * @see #removeAWTEventListener * @see #getAWTEventListeners * @see SecurityManager#checkPermission @@ -1815,9 +1815,9 @@ public abstract class Toolkit { /** * Removes an AWTEventListener from receiving dispatched AWTEvents. *

          - * First, if there is a security manager, its checkPermission + * First, if there is a security manager, its {@code checkPermission} * method is called with an - * AWTPermission("listenToAllAWTEvents") permission. + * {@code AWTPermission("listenToAllAWTEvents")} permission. * This may result in a SecurityException. *

          * Note: event listener use is not recommended for normal @@ -1830,7 +1830,7 @@ public abstract class Toolkit { * @param listener the event listener. * @throws SecurityException * if a security manager exists and its - * checkPermission method doesn't allow the operation. + * {@code checkPermission} method doesn't allow the operation. * @see #addAWTEventListener * @see #getAWTEventListeners * @see SecurityManager#checkPermission @@ -1884,23 +1884,23 @@ public abstract class Toolkit { return calls[ci]; } /** - * Returns an array of all the AWTEventListeners + * Returns an array of all the {@code AWTEventListener}s * registered on this toolkit. * If there is a security manager, its {@code checkPermission} * method is called with an * {@code AWTPermission("listenToAllAWTEvents")} permission. * This may result in a SecurityException. * Listeners can be returned - * within AWTEventListenerProxy objects, which also contain + * within {@code AWTEventListenerProxy} objects, which also contain * the event mask for the given listener. * Note that listener objects * added multiple times appear only once in the returned array. * - * @return all of the AWTEventListeners or an empty + * @return all of the {@code AWTEventListener}s or an empty * array if no listeners are currently registered * @throws SecurityException * if a security manager exists and its - * checkPermission method doesn't allow the operation. + * {@code checkPermission} method doesn't allow the operation. * @see #addAWTEventListener * @see #removeAWTEventListener * @see SecurityManager#checkPermission @@ -1932,7 +1932,7 @@ public abstract class Toolkit { } /** - * Returns an array of all the AWTEventListeners + * Returns an array of all the {@code AWTEventListener}s * registered on this toolkit which listen to all of the event * types specified in the {@code eventMask} argument. * If there is a security manager, its {@code checkPermission} @@ -1940,19 +1940,19 @@ public abstract class Toolkit { * {@code AWTPermission("listenToAllAWTEvents")} permission. * This may result in a SecurityException. * Listeners can be returned - * within AWTEventListenerProxy objects, which also contain + * within {@code AWTEventListenerProxy} objects, which also contain * the event mask for the given listener. * Note that listener objects * added multiple times appear only once in the returned array. * * @param eventMask the bitmask of event types to listen for - * @return all of the AWTEventListeners registered + * @return all of the {@code AWTEventListener}s registered * on this toolkit for the specified * event types, or an empty array if no such listeners * are currently registered * @throws SecurityException * if a security manager exists and its - * checkPermission method doesn't allow the operation. + * {@code checkPermission} method doesn't allow the operation. * @see #addAWTEventListener * @see #removeAWTEventListener * @see SecurityManager#checkPermission @@ -2167,9 +2167,9 @@ public abstract class Toolkit { * The style field of the input method highlight is ignored. The map * returned is unmodifiable. * @param highlight input method highlight - * @return style attribute map, or null + * @return style attribute map, or {@code null} * @exception HeadlessException if - * GraphicsEnvironment.isHeadless returns true + * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.3 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/Transparency.java b/jdk/src/java.desktop/share/classes/java/awt/Transparency.java index 42b87caa4c5..6cdeb111ecc 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Transparency.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Transparency.java @@ -28,7 +28,7 @@ package java.awt; import java.lang.annotation.Native; /** - * The Transparency interface defines the common transparency + * The {@code Transparency} interface defines the common transparency * modes for implementing classes. */ public interface Transparency { @@ -53,8 +53,8 @@ public interface Transparency { @Native public static final int TRANSLUCENT = 3; /** - * Returns the type of this Transparency. - * @return the field type of this Transparency, which is + * Returns the type of this {@code Transparency}. + * @return the field type of this {@code Transparency}, which is * either OPAQUE, BITMASK or TRANSLUCENT. */ public int getTransparency(); diff --git a/jdk/src/java.desktop/share/classes/java/awt/TrayIcon.java b/jdk/src/java.desktop/share/classes/java/awt/TrayIcon.java index 3c7182afcfa..08ad08d8820 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/TrayIcon.java +++ b/jdk/src/java.desktop/share/classes/java/awt/TrayIcon.java @@ -36,32 +36,32 @@ import java.security.AccessControlContext; import java.security.AccessController; /** - * A TrayIcon object represents a tray icon that can be + * A {@code TrayIcon} object represents a tray icon that can be * added to the {@link SystemTray system tray}. A - * TrayIcon can have a tooltip (text), an image, a popup + * {@code TrayIcon} can have a tooltip (text), an image, a popup * menu, and a set of listeners associated with it. * - *

          A TrayIcon can generate various {@link MouseEvent + *

          A {@code TrayIcon} can generate various {@link MouseEvent * MouseEvents} and supports adding corresponding listeners to receive - * notification of these events. TrayIcon processes some + * notification of these events. {@code TrayIcon} processes some * of the events by itself. For example, by default, when the - * right-mouse click is performed on the TrayIcon it + * right-mouse click is performed on the {@code TrayIcon} it * displays the specified popup menu. When the mouse hovers - * over the TrayIcon the tooltip is displayed. + * over the {@code TrayIcon} the tooltip is displayed. * - *

          Note: When the MouseEvent is - * dispatched to its registered listeners its component - * property will be set to null. (See {@link + *

          Note: When the {@code MouseEvent} is + * dispatched to its registered listeners its {@code component} + * property will be set to {@code null}. (See {@link * java.awt.event.ComponentEvent#getComponent}) The - * source property will be set to this - * TrayIcon. (See {@link + * {@code source} property will be set to this + * {@code TrayIcon}. (See {@link * java.util.EventObject#getSource}) * *

          Note: A well-behaved {@link TrayIcon} implementation * will assign different gestures to showing a popup menu and * selecting a tray icon. * - *

          A TrayIcon can generate an {@link ActionEvent + *

          A {@code TrayIcon} can generate an {@link ActionEvent * ActionEvent}. On some platforms, this occurs when the user selects * the tray icon using either the mouse or keyboard. * @@ -71,7 +71,7 @@ import java.security.AccessController; * SecurityException. * *

          See the {@link SystemTray} class overview for an example on how - * to use the TrayIcon API. + * to use the {@code TrayIcon} API. * * @since 1.6 * @see SystemTray#add @@ -147,11 +147,11 @@ public class TrayIcon { } /** - * Creates a TrayIcon with the specified image. + * Creates a {@code TrayIcon} with the specified image. * - * @param image the Image to be used - * @throws IllegalArgumentException if image is - * null + * @param image the {@code Image} to be used + * @throws IllegalArgumentException if {@code image} is + * {@code null} * @throws UnsupportedOperationException if the system tray isn't * supported by the current platform * @throws HeadlessException if @@ -173,14 +173,14 @@ public class TrayIcon { } /** - * Creates a TrayIcon with the specified image and + * Creates a {@code TrayIcon} with the specified image and * tooltip text. * - * @param image the Image to be used + * @param image the {@code Image} to be used * @param tooltip the string to be used as tooltip text; if the - * value is null no tooltip is shown - * @throws IllegalArgumentException if image is - * null + * value is {@code null} no tooltip is shown + * @throws IllegalArgumentException if {@code image} is + * {@code null} * @throws UnsupportedOperationException if the system tray isn't * supported by the current platform * @throws HeadlessException if @@ -199,15 +199,15 @@ public class TrayIcon { } /** - * Creates a TrayIcon with the specified image, + * Creates a {@code TrayIcon} with the specified image, * tooltip and popup menu. * - * @param image the Image to be used + * @param image the {@code Image} to be used * @param tooltip the string to be used as tooltip text; if the - * value is null no tooltip is shown + * value is {@code null} no tooltip is shown * @param popup the menu to be used for the tray icon's popup - * menu; if the value is null no popup menu is shown - * @throws IllegalArgumentException if image is null + * menu; if the value is {@code null} no popup menu is shown + * @throws IllegalArgumentException if {@code image} is {@code null} * @throws UnsupportedOperationException if the system tray isn't * supported by the current platform * @throws HeadlessException if @@ -229,7 +229,7 @@ public class TrayIcon { } /** - * Sets the image for this TrayIcon. The previous + * Sets the image for this {@code TrayIcon}. The previous * tray icon image is discarded without calling the {@link * java.awt.Image#flush} method — you will need to call it * manually. @@ -243,8 +243,8 @@ public class TrayIcon { *

          Calling this method with the same image that is currently * being used has no effect. * - * @throws NullPointerException if image is null - * @param image the non-null Image to be used + * @throws NullPointerException if {@code image} is {@code null} + * @param image the non-null {@code Image} to be used * @see #getImage * @see Image * @see SystemTray#add(TrayIcon) @@ -263,7 +263,7 @@ public class TrayIcon { } /** - * Returns the current image used for this TrayIcon. + * Returns the current image used for this {@code TrayIcon}. * * @return the image * @see #setImage(Image) @@ -274,13 +274,13 @@ public class TrayIcon { } /** - * Sets the popup menu for this TrayIcon. If - * popup is null, no popup menu will be - * associated with this TrayIcon. + * Sets the popup menu for this {@code TrayIcon}. If + * {@code popup} is {@code null}, no popup menu will be + * associated with this {@code TrayIcon}. * - *

          Note that this popup must not be added to any + *

          Note that this {@code popup} must not be added to any * parent before or after it is set on the tray icon. If you add - * it to some parent, the popup may be removed from + * it to some parent, the {@code popup} may be removed from * that parent. * *

          The {@code popup} can be set on one {@code TrayIcon} only. @@ -295,7 +295,7 @@ public class TrayIcon { * * @throws IllegalArgumentException if the {@code popup} is already * set for another {@code TrayIcon} - * @param popup a PopupMenu or null to + * @param popup a {@code PopupMenu} or {@code null} to * remove any popup menu * @see #getPopupMenu */ @@ -318,9 +318,9 @@ public class TrayIcon { } /** - * Returns the popup menu associated with this TrayIcon. + * Returns the popup menu associated with this {@code TrayIcon}. * - * @return the popup menu or null if none exists + * @return the popup menu or {@code null} if none exists * @see #setPopupMenu(PopupMenu) */ public PopupMenu getPopupMenu() { @@ -328,16 +328,16 @@ public class TrayIcon { } /** - * Sets the tooltip string for this TrayIcon. The + * Sets the tooltip string for this {@code TrayIcon}. The * tooltip is displayed automatically when the mouse hovers over - * the icon. Setting the tooltip to null removes any + * the icon. Setting the tooltip to {@code null} removes any * tooltip text. * * When displayed, the tooltip string may be truncated on some platforms; * the number of characters that may be displayed is platform-dependent. * * @param tooltip the string for the tooltip; if the value is - * null no tooltip is shown + * {@code null} no tooltip is shown * @see #getToolTip */ public void setToolTip(String tooltip) { @@ -351,9 +351,9 @@ public class TrayIcon { /** * Returns the tooltip string associated with this - * TrayIcon. + * {@code TrayIcon}. * - * @return the tooltip string or null if none exists + * @return the tooltip string or {@code null} if none exists * @see #setToolTip(String) */ public String getToolTip() { @@ -364,18 +364,18 @@ public class TrayIcon { * Sets the auto-size property. Auto-size determines whether the * tray image is automatically sized to fit the space allocated * for the image on the tray. By default, the auto-size property - * is set to false. + * is set to {@code false}. * - *

          If auto-size is false, and the image size + *

          If auto-size is {@code false}, and the image size * doesn't match the tray icon space, the image is painted as-is * inside that space — if larger than the allocated space, it will * be cropped. * - *

          If auto-size is true, the image is stretched or shrunk to + *

          If auto-size is {@code true}, the image is stretched or shrunk to * fit the tray icon space. * - * @param autosize true to auto-size the image, - * false otherwise + * @param autosize {@code true} to auto-size the image, + * {@code false} otherwise * @see #isImageAutoSize */ public void setImageAutoSize(boolean autosize) { @@ -390,8 +390,8 @@ public class TrayIcon { /** * Returns the value of the auto-size property. * - * @return true if the image will be auto-sized, - * false otherwise + * @return {@code true} if the image will be auto-sized, + * {@code false} otherwise * @see #setImageAutoSize(boolean) */ public boolean isImageAutoSize() { @@ -400,15 +400,15 @@ public class TrayIcon { /** * Adds the specified mouse listener to receive mouse events from - * this TrayIcon. Calling this method with a - * null value has no effect. + * this {@code TrayIcon}. Calling this method with a + * {@code null} value has no effect. * *

          Note: The {@code MouseEvent}'s coordinates (received * from the {@code TrayIcon}) are relative to the screen, not the * {@code TrayIcon}. * - *

          Note: The MOUSE_ENTERED and - * MOUSE_EXITED mouse events are not supported. + *

          Note: The {@code MOUSE_ENTERED} and + * {@code MOUSE_EXITED} mouse events are not supported. *

          Refer to AWT Threading Issues for details on AWT's threading model. * @@ -427,7 +427,7 @@ public class TrayIcon { /** * Removes the specified mouse listener. Calling this method with - * null or an invalid value has no effect. + * {@code null} or an invalid value has no effect. *

          Refer to AWT Threading Issues for details on AWT's threading model. * @@ -446,10 +446,10 @@ public class TrayIcon { /** * Returns an array of all the mouse listeners - * registered on this TrayIcon. + * registered on this {@code TrayIcon}. * - * @return all of the MouseListeners registered on - * this TrayIcon or an empty array if no mouse + * @return all of the {@code MouseListeners} registered on + * this {@code TrayIcon} or an empty array if no mouse * listeners are currently registered * * @see #addMouseListener(MouseListener) @@ -462,14 +462,14 @@ public class TrayIcon { /** * Adds the specified mouse listener to receive mouse-motion - * events from this TrayIcon. Calling this method - * with a null value has no effect. + * events from this {@code TrayIcon}. Calling this method + * with a {@code null} value has no effect. * *

          Note: The {@code MouseEvent}'s coordinates (received * from the {@code TrayIcon}) are relative to the screen, not the * {@code TrayIcon}. * - *

          Note: The MOUSE_DRAGGED mouse event is not supported. + *

          Note: The {@code MOUSE_DRAGGED} mouse event is not supported. *

          Refer to AWT Threading Issues for details on AWT's threading model. * @@ -488,7 +488,7 @@ public class TrayIcon { /** * Removes the specified mouse-motion listener. Calling this method with - * null or an invalid value has no effect. + * {@code null} or an invalid value has no effect. *

          Refer to AWT Threading Issues for details on AWT's threading model. * @@ -507,10 +507,10 @@ public class TrayIcon { /** * Returns an array of all the mouse-motion listeners - * registered on this TrayIcon. + * registered on this {@code TrayIcon}. * - * @return all of the MouseInputListeners registered on - * this TrayIcon or an empty array if no mouse + * @return all of the {@code MouseInputListeners} registered on + * this {@code TrayIcon} or an empty array if no mouse * listeners are currently registered * * @see #addMouseMotionListener(MouseMotionListener) @@ -524,7 +524,7 @@ public class TrayIcon { /** * Returns the command name of the action event fired by this tray icon. * - * @return the action command name, or null if none exists + * @return the action command name, or {@code null} if none exists * @see #addActionListener(ActionListener) * @see #setActionCommand(String) */ @@ -535,7 +535,7 @@ public class TrayIcon { /** * Sets the command name for the action event fired by this tray * icon. By default, this action command is set to - * null. + * {@code null}. * * @param command a string used to set the tray icon's * action command. @@ -549,12 +549,12 @@ public class TrayIcon { /** * Adds the specified action listener to receive - * ActionEvents from this TrayIcon. + * {@code ActionEvent}s from this {@code TrayIcon}. * Action events usually occur when a user selects the tray icon, * using either the mouse or keyboard. The conditions in which * action events are generated are platform-dependent. * - *

          Calling this method with a null value has no + *

          Calling this method with a {@code null} value has no * effect. *

          Refer to AWT Threading Issues for details on AWT's threading model. @@ -574,7 +574,7 @@ public class TrayIcon { /** * Removes the specified action listener. Calling this method with - * null or an invalid value has no effect. + * {@code null} or an invalid value has no effect. *

          Refer to AWT Threading Issues for details on AWT's threading model. * @@ -594,10 +594,10 @@ public class TrayIcon { /** * Returns an array of all the action listeners - * registered on this TrayIcon. + * registered on this {@code TrayIcon}. * - * @return all of the ActionListeners registered on - * this TrayIcon or an empty array if no action + * @return all of the {@code ActionListeners} registered on + * this {@code TrayIcon} or an empty array if no action * listeners are currently registered * * @see #addActionListener(ActionListener) @@ -633,9 +633,9 @@ public class TrayIcon { * disappear after a time or if the user clicks on it. Clicking * on the message may trigger an {@code ActionEvent}. * - *

          Either the caption or the text may be null, but an - * NullPointerException is thrown if both are - * null. + *

          Either the caption or the text may be {@code null}, but an + * {@code NullPointerException} is thrown if both are + * {@code null}. * * When displayed, the caption or text strings may be truncated on * some platforms; the number of characters that may be displayed is @@ -645,12 +645,12 @@ public class TrayIcon { * showing a message. * * @param caption the caption displayed above the text, usually in - * bold; may be null + * bold; may be {@code null} * @param text the text displayed for the particular message; may be - * null + * {@code null} * @param messageType an enum indicating the message type - * @throws NullPointerException if both caption - * and text are null + * @throws NullPointerException if both {@code caption} + * and {@code text} are {@code null} */ public void displayMessage(String caption, String text, MessageType messageType) { if (caption == null && text == null) { diff --git a/jdk/src/java.desktop/share/classes/java/awt/Window.java b/jdk/src/java.desktop/share/classes/java/awt/Window.java index 72fee8d1c9c..7ac8023acdd 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Window.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Window.java @@ -1926,7 +1926,7 @@ public class Window extends Container implements Accessible { * with a class literal, such as * FooListener.class. * For example, you can query a - * {@code Window} {@code w} + * {@code Window w} * for its window listeners with the following code: * *

          WindowListener[] wls = (WindowListener[])(w.getListeners(WindowListener.class));
          diff --git a/jdk/src/java.desktop/share/classes/java/awt/color/ColorSpace.java b/jdk/src/java.desktop/share/classes/java/awt/color/ColorSpace.java index 08feedd844e..ca28f64be1a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/color/ColorSpace.java +++ b/jdk/src/java.desktop/share/classes/java/awt/color/ColorSpace.java @@ -268,7 +268,7 @@ public abstract class ColorSpace implements java.io.Serializable { /** * Constructs a ColorSpace object given a color space type * and the number of components. - * @param type one of the ColorSpace type constants + * @param type one of the {@code ColorSpace} type constants * @param numcomponents the number of components in the color space */ protected ColorSpace (int type, int numcomponents) { @@ -283,7 +283,7 @@ public abstract class ColorSpace implements java.io.Serializable { * @param colorspace a specific color space identified by one of * the predefined class constants (e.g. CS_sRGB, CS_LINEAR_RGB, * CS_CIEXYZ, CS_GRAY, or CS_PYCC) - * @return the requested ColorSpace object + * @return the requested {@code ColorSpace} object */ // NOTE: This method may be called by privileged threads. // DO NOT INVOKE CLIENT CODE ON THIS THREAD! @@ -366,8 +366,8 @@ public abstract class ColorSpace implements java.io.Serializable { /** * Returns true if the ColorSpace is CS_sRGB. - * @return true if this is a CS_sRGB color - * space, false if it is not + * @return {@code true} if this is a {@code CS_sRGB} color + * space, {@code false} if it is not */ public boolean isCS_sRGB () { /* REMIND - make sure we know sRGBspace exists already */ @@ -381,10 +381,10 @@ public abstract class ColorSpace implements java.io.Serializable { * This method transforms color values using algorithms designed * to produce the best perceptual match between input and output * colors. In order to do colorimetric conversion of color values, - * you should use the toCIEXYZ + * you should use the {@code toCIEXYZ} * method of this color space to first convert from the input * color space to the CS_CIEXYZ color space, and then use the - * fromCIEXYZ method of the CS_sRGB color space to + * {@code fromCIEXYZ} method of the CS_sRGB color space to * convert from CS_CIEXYZ to the output color space. * See {@link #toCIEXYZ(float[]) toCIEXYZ} and * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. @@ -405,10 +405,10 @@ public abstract class ColorSpace implements java.io.Serializable { * This method transforms color values using algorithms designed * to produce the best perceptual match between input and output * colors. In order to do colorimetric conversion of color values, - * you should use the toCIEXYZ + * you should use the {@code toCIEXYZ} * method of the CS_sRGB color space to first convert from the input * color space to the CS_CIEXYZ color space, and then use the - * fromCIEXYZ method of this color space to + * {@code fromCIEXYZ} method of this color space to * convert from CS_CIEXYZ to the output color space. * See {@link #toCIEXYZ(float[]) toCIEXYZ} and * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. @@ -438,7 +438,7 @@ public abstract class ColorSpace implements java.io.Serializable { * A further transformation is necessary to compute the XYZ values * that would be measured using current CIE recommended practices. * See the {@link ICC_ColorSpace#toCIEXYZ(float[]) toCIEXYZ} method of - * ICC_ColorSpace for further information. + * {@code ICC_ColorSpace} for further information. * * @param colorvalue a float array with length of at least the number * of components in this ColorSpace @@ -466,7 +466,7 @@ public abstract class ColorSpace implements java.io.Serializable { * current CIE recommended practices, they must be converted to D50 * relative values before being passed to this method. * See the {@link ICC_ColorSpace#fromCIEXYZ(float[]) fromCIEXYZ} method of - * ICC_ColorSpace for further information. + * {@code ICC_ColorSpace} for further information. * * @param colorvalue a float array with length of at least 3 * @return a float array with length equal to the number of @@ -486,7 +486,7 @@ public abstract class ColorSpace implements java.io.Serializable { * primaries. * * @return the type constant that represents the type of this - * ColorSpace + * {@code ColorSpace} */ public int getType() { return type; @@ -494,7 +494,7 @@ public abstract class ColorSpace implements java.io.Serializable { /** * Returns the number of components of this ColorSpace. - * @return The number of components in this ColorSpace. + * @return The number of components in this {@code ColorSpace}. */ public int getNumComponents() { return numComponents; @@ -505,7 +505,7 @@ public abstract class ColorSpace implements java.io.Serializable { * * @param idx the component index * @return the name of the component at the specified index - * @throws IllegalArgumentException if idx is + * @throws IllegalArgumentException if {@code idx} is * less than 0 or greater than numComponents - 1 */ public String getName (int idx) { diff --git a/jdk/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java b/jdk/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java index e80054c767f..cf6f640f1eb 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java +++ b/jdk/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java @@ -142,10 +142,10 @@ public class ICC_ColorSpace extends ColorSpace { * This method transforms color values using algorithms designed * to produce the best perceptual match between input and output * colors. In order to do colorimetric conversion of color values, - * you should use the toCIEXYZ + * you should use the {@code toCIEXYZ} * method of this color space to first convert from the input * color space to the CS_CIEXYZ color space, and then use the - * fromCIEXYZ method of the CS_sRGB color space to + * {@code fromCIEXYZ} method of the CS_sRGB color space to * convert from CS_CIEXYZ to the output color space. * See {@link #toCIEXYZ(float[]) toCIEXYZ} and * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. @@ -194,10 +194,10 @@ public class ICC_ColorSpace extends ColorSpace { * This method transforms color values using algorithms designed * to produce the best perceptual match between input and output * colors. In order to do colorimetric conversion of color values, - * you should use the toCIEXYZ + * you should use the {@code toCIEXYZ} * method of the CS_sRGB color space to first convert from the input * color space to the CS_CIEXYZ color space, and then use the - * fromCIEXYZ method of this color space to + * {@code fromCIEXYZ} method of this color space to * convert from CS_CIEXYZ to the output color space. * See {@link #toCIEXYZ(float[]) toCIEXYZ} and * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. 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 90f87280a7f..3adc80fa59f 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 @@ -766,8 +766,8 @@ public class ICC_Profile implements Serializable { * a byte array. Throws an IllegalArgumentException if the data * does not correspond to a valid ICC Profile. * @param data the specified ICC Profile data - * @return an ICC_Profile object corresponding to - * the data in the specified data array. + * @return an {@code ICC_Profile} object corresponding to + * the data in the specified {@code data} array. */ public static ICC_Profile getInstance(byte[] data) { ICC_Profile thisProfile; @@ -821,11 +821,11 @@ public class ICC_Profile implements Serializable { * * @param cspace the type of color space to create a profile for. * The specified type is one of the color - * space constants defined in the ColorSpace class. + * space constants defined in the {@code ColorSpace} class. * - * @return an ICC_Profile object corresponding to - * the specified ColorSpace type. - * @exception IllegalArgumentException If cspace is not + * @return an {@code ICC_Profile} object corresponding to + * the specified {@code ColorSpace} type. + * @exception IllegalArgumentException If {@code cspace} is not * one of the predefined color space types. */ public static ICC_Profile getInstance (int cspace) { @@ -956,7 +956,7 @@ public class ICC_Profile implements Serializable { * Profile data. * @param fileName The file that contains the data for the profile. * - * @return an ICC_Profile object corresponding to + * @return an {@code ICC_Profile} object corresponding to * the data in the specified file. * @exception IOException If the specified file cannot be opened or * an I/O error occurs while reading the file. @@ -997,8 +997,8 @@ public class ICC_Profile implements Serializable { * error occurs while reading the stream. * @param s The input stream from which to read the profile data. * - * @return an ICC_Profile object corresponding to the - * data in the specified InputStream. + * @return an {@code ICC_Profile} object corresponding to the + * data in the specified {@code InputStream}. * * @exception IOException If an I/O error occurs while reading the stream. * @@ -1213,7 +1213,7 @@ public class ICC_Profile implements Serializable { * characteristics of the space, e.g. the chromaticities of the * primaries. * @return One of the color space type constants defined in the - * ColorSpace class. + * {@code ColorSpace} class. */ public int getColorSpaceType() { if (deferralInfo != null) { @@ -1245,7 +1245,7 @@ public class ICC_Profile implements Serializable { * color space defined in the ICC specification. For a device * link profile, this could be any of the color space type constants. * @return One of the color space type constants defined in the - * ColorSpace class. + * {@code ColorSpace} class. */ public int getPCSType() { if (ProfileDeferralMgr.deferring) { @@ -1342,7 +1342,7 @@ public class ICC_Profile implements Serializable { * want to get. * * @return A byte array that contains the tagged data element. Returns - * null if the specified tag doesn't exist. + * {@code null} if the specified tag doesn't exist. * @see #setData(int, byte[]) */ public byte[] getData(int tagSignature) { @@ -1929,7 +1929,7 @@ public class ICC_Profile implements Serializable { /** * Version of the format of additional serialized data in the - * stream. Version 1 corresponds to Java 2 + * stream. Version {@code 1} corresponds to Java 2 * Platform, v1.3. * @since 1.3 * @serial @@ -1943,17 +1943,17 @@ public class ICC_Profile implements Serializable { * * @param s stream used for serialization. * @throws IOException - * thrown by ObjectInputStream. + * thrown by {@code ObjectInputStream}. * @serialData - * The String is the name of one of + * The {@code String} is the name of one of * CS_* constants defined in the * {@link ColorSpace} class if the profile object is a profile * for a predefined color space (for example - * "CS_sRGB"). The string is null + * {@code "CS_sRGB"}). The string is {@code null} * otherwise. *

          - * The byte[] array is the profile data for the - * profile. For predefined color spaces null is + * The {@code byte[]} array is the profile data for the + * profile. For predefined color spaces {@code null} is * written instead of the profile data. If in the future * versions of Java API new predefined color spaces will be * added, future versions of this class may choose to write @@ -2003,19 +2003,19 @@ public class ICC_Profile implements Serializable { * * @param s stream used for deserialization. * @throws IOException - * thrown by ObjectInputStream. + * thrown by {@code ObjectInputStream}. * @throws ClassNotFoundException - * thrown by ObjectInputStream. + * thrown by {@code ObjectInputStream}. * @serialData - * The String is the name of one of + * The {@code String} is the name of one of * CS_* constants defined in the * {@link ColorSpace} class if the profile object is a profile * for a predefined color space (for example - * "CS_sRGB"). The string is null + * {@code "CS_sRGB"}). The string is {@code null} * otherwise. *

          - * The byte[] array is the profile data for the - * profile. It will usually be null for the + * The {@code byte[]} array is the profile data for the + * profile. It will usually be {@code null} for the * predefined profiles. *

          * If the string is recognized as a constant name for diff --git a/jdk/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java b/jdk/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java index 4929e8a7190..39a243adb43 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java +++ b/jdk/src/java.desktop/share/classes/java/awt/color/ICC_ProfileRGB.java @@ -45,13 +45,13 @@ import sun.java2d.cmm.ProfileDeferralInfo; * that represents profiles which meet the following criteria: *

            *
          • The profile's color space type is RGB.
          • - *
          • The profile includes the redColorantTag, - * greenColorantTag, blueColorantTag, - * redTRCTag, greenTRCTag, - * blueTRCTag, and mediaWhitePointTag tags.
          • + *
          • The profile includes the {@code redColorantTag}, + * {@code greenColorantTag}, {@code blueColorantTag}, + * {@code redTRCTag}, {@code greenTRCTag}, + * {@code blueTRCTag}, and {@code mediaWhitePointTag} tags.
          • *
          - * The ICC_Profile getInstance method will - * return an ICC_ProfileRGB object when these conditions are met. + * The {@code ICC_Profile getInstance} method will + * return an {@code ICC_ProfileRGB} object when these conditions are met. * Three-component, matrix-based input profiles and RGB display profiles are * examples of this type of profile. *

          @@ -109,7 +109,7 @@ extends ICC_Profile { /** - * Constructs an new ICC_ProfileRGB from a CMM ID. + * Constructs an new {@code ICC_ProfileRGB} from a CMM ID. * * @param p The CMM ID for the profile. * @@ -119,7 +119,7 @@ extends ICC_Profile { } /** - * Constructs a new ICC_ProfileRGB from a + * Constructs a new {@code ICC_ProfileRGB} from a * ProfileDeferralInfo object. * * @param pdi @@ -131,10 +131,10 @@ extends ICC_Profile { /** * Returns an array that contains the components of the profile's - * mediaWhitePointTag. + * {@code mediaWhitePointTag}. * - * @return A 3-element float array containing the x, y, - * and z components of the profile's mediaWhitePointTag. + * @return A 3-element {@code float} array containing the x, y, + * and z components of the profile's {@code mediaWhitePointTag}. */ public float[] getMediaWhitePoint() { return super.getMediaWhitePoint(); @@ -142,17 +142,17 @@ extends ICC_Profile { /** - * Returns a 3x3 float matrix constructed from the - * X, Y, and Z components of the profile's redColorantTag, - * greenColorantTag, and blueColorantTag. + * Returns a 3x3 {@code float} matrix constructed from the + * X, Y, and Z components of the profile's {@code redColorantTag}, + * {@code greenColorantTag}, and {@code blueColorantTag}. *

          * This matrix can be used for color transforms in the forward * direction of the profile--from the profile color space * to the CIEXYZ PCS. * - * @return A 3x3 float array that contains the x, y, and z - * components of the profile's redColorantTag, - * greenColorantTag, and blueColorantTag. + * @return A 3x3 {@code float} array that contains the x, y, and z + * components of the profile's {@code redColorantTag}, + * {@code greenColorantTag}, and {@code blueColorantTag}. */ public float[][] getMatrix() { float[][] theMatrix = new float[3][3]; @@ -191,7 +191,7 @@ extends ICC_Profile { *   linearComponent = deviceComponent * * - * @param component The ICC_ProfileRGB constant that + * @param component The {@code ICC_ProfileRGB} constant that * represents the component whose TRC you want to retrieve * @return the gamma value as a float. * @exception ProfileDataException if the profile does not specify @@ -225,8 +225,8 @@ extends ICC_Profile { /** * Returns the TRC for a particular component as an array. - * Component must be REDCOMPONENT, - * GREENCOMPONENT, or BLUECOMPONENT. + * Component must be {@code REDCOMPONENT}, + * {@code GREENCOMPONENT}, or {@code BLUECOMPONENT}. * Otherwise the returned array * represents a lookup table where the input component value * is conceptually in the range [0.0, 1.0]. Value 0.0 maps @@ -236,18 +236,18 @@ extends ICC_Profile { * array. Output values also map linearly to the range [0.0, 1.0]. * Value 0.0 is represented by an array value of 0x0000 and * value 1.0 by 0xFFFF. In other words, the values are really unsigned - * short values even though they are returned in a - * short array. + * {@code short} values even though they are returned in a + * {@code short} array. * * If the profile has specified the corresponding TRC * as linear (gamma = 1.0) or as a simple gamma value, this method * throws an exception. In this case, the {@link #getGamma(int)} * method should be used to get the gamma value. * - * @param component The ICC_ProfileRGB constant that + * @param component The {@code ICC_ProfileRGB} constant that * represents the component whose TRC you want to retrieve: - * REDCOMPONENT, GREENCOMPONENT, or - * BLUECOMPONENT. + * {@code REDCOMPONENT}, {@code GREENCOMPONENT}, or + * {@code BLUECOMPONENT}. * * @return a short array representing the TRC. * @exception ProfileDataException if the profile does not specify diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/Autoscroll.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/Autoscroll.java index 0e3f0fb459a..b144a6b8d47 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/Autoscroll.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/Autoscroll.java @@ -37,17 +37,17 @@ import java.awt.Point; * and institute a scroll operation in order to make obscured region(s) * visible to the user. This feature is known as autoscrolling. *

          - * If a GUI control is both an active DropTarget + * If a GUI control is both an active {@code DropTarget} * and is also scrollable, it * can receive notifications of autoscrolling gestures by the user from * the DnD system by implementing this interface. *

          * An autoscrolling gesture is initiated by the user by keeping the drag - * cursor motionless with a border region of the Component, + * cursor motionless with a border region of the {@code Component}, * referred to as * the "autoscrolling region", for a predefined period of time, this will - * result in repeated scroll requests to the Component - * until the drag Cursor resumes its motion. + * result in repeated scroll requests to the {@code Component} + * until the drag {@code Cursor} resumes its motion. * * @since 1.2 */ @@ -55,13 +55,13 @@ import java.awt.Point; public interface Autoscroll { /** - * This method returns the Insets describing + * This method returns the {@code Insets} describing * the autoscrolling region or border relative * to the geometry of the implementing Component. *

          - * This value is read once by the DropTarget - * upon entry of the drag Cursor - * into the associated Component. + * This value is read once by the {@code DropTarget} + * upon entry of the drag {@code Cursor} + * into the associated {@code Component}. * * @return the Insets */ @@ -69,9 +69,9 @@ public interface Autoscroll { public Insets getAutoscrollInsets(); /** - * notify the Component to autoscroll + * notify the {@code Component} to autoscroll * - * @param cursorLocn A Point indicating the + * @param cursorLocn A {@code Point} indicating the * location of the cursor that triggered this operation. */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DnDConstants.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DnDConstants.java index e4c5fb42206..88b70fc9900 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DnDConstants.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DnDConstants.java @@ -37,28 +37,28 @@ public final class DnDConstants { private DnDConstants() {} // define null private constructor. /** - * An int representing no action. + * An {@code int} representing no action. */ @Native public static final int ACTION_NONE = 0x0; /** - * An int representing a "copy" action. + * An {@code int} representing a "copy" action. */ @Native public static final int ACTION_COPY = 0x1; /** - * An int representing a "move" action. + * An {@code int} representing a "move" action. */ @Native public static final int ACTION_MOVE = 0x2; /** - * An int representing a "copy" or - * "move" action. + * An {@code int} representing a "copy" or + * "move" action. */ @Native public static final int ACTION_COPY_OR_MOVE = ACTION_COPY | ACTION_MOVE; /** - * An int representing a "link" action. + * An {@code int} representing a "link" action. * * The link verb is found in many, if not all native DnD platforms, and the * actual interpretation of LINK semantics is both platform @@ -76,7 +76,7 @@ public final class DnDConstants { @Native public static final int ACTION_LINK = 0x40000000; /** - * An int representing a "reference" + * An {@code int} representing a "reference" * action (synonym for ACTION_LINK). */ @Native public static final int ACTION_REFERENCE = ACTION_LINK; diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DnDEventMulticaster.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DnDEventMulticaster.java index f4e059f9e00..dc7fc7f2138 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DnDEventMulticaster.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DnDEventMulticaster.java @@ -31,7 +31,7 @@ import java.util.EventListener; /** - * A class extends AWTEventMulticaster to implement efficient and + * A class extends {@code AWTEventMulticaster} to implement efficient and * thread-safe multi-cast event dispatching for the drag-and-drop events defined * in the java.awt.dnd package. * @@ -44,9 +44,9 @@ class DnDEventMulticaster extends AWTEventMulticaster /** * Creates an event multicaster instance which chains listener-a - * with listener-b. Input parameters a and b - * should not be null, though implementations may vary in - * choosing whether or not to throw NullPointerException + * with listener-b. Input parameters {@code a} and {@code b} + * should not be {@code null}, though implementations may vary in + * choosing whether or not to throw {@code NullPointerException} * in that case. * * @param a listener-a @@ -57,10 +57,10 @@ class DnDEventMulticaster extends AWTEventMulticaster } /** - * Handles the DragSourceDragEvent by invoking - * dragEnter on listener-a and listener-b. + * Handles the {@code DragSourceDragEvent} by invoking + * {@code dragEnter} on listener-a and listener-b. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dragEnter(DragSourceDragEvent dsde) { ((DragSourceListener)a).dragEnter(dsde); @@ -68,10 +68,10 @@ class DnDEventMulticaster extends AWTEventMulticaster } /** - * Handles the DragSourceDragEvent by invoking - * dragOver on listener-a and listener-b. + * Handles the {@code DragSourceDragEvent} by invoking + * {@code dragOver} on listener-a and listener-b. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dragOver(DragSourceDragEvent dsde) { ((DragSourceListener)a).dragOver(dsde); @@ -79,10 +79,10 @@ class DnDEventMulticaster extends AWTEventMulticaster } /** - * Handles the DragSourceDragEvent by invoking - * dropActionChanged on listener-a and listener-b. + * Handles the {@code DragSourceDragEvent} by invoking + * {@code dropActionChanged} on listener-a and listener-b. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dropActionChanged(DragSourceDragEvent dsde) { ((DragSourceListener)a).dropActionChanged(dsde); @@ -90,10 +90,10 @@ class DnDEventMulticaster extends AWTEventMulticaster } /** - * Handles the DragSourceEvent by invoking - * dragExit on listener-a and listener-b. + * Handles the {@code DragSourceEvent} by invoking + * {@code dragExit} on listener-a and listener-b. * - * @param dse the DragSourceEvent + * @param dse the {@code DragSourceEvent} */ public void dragExit(DragSourceEvent dse) { ((DragSourceListener)a).dragExit(dse); @@ -101,10 +101,10 @@ class DnDEventMulticaster extends AWTEventMulticaster } /** - * Handles the DragSourceDropEvent by invoking - * dragDropEnd on listener-a and listener-b. + * Handles the {@code DragSourceDropEvent} by invoking + * {@code dragDropEnd} on listener-a and listener-b. * - * @param dsde the DragSourceDropEvent + * @param dsde the {@code DragSourceDropEvent} */ public void dragDropEnd(DragSourceDropEvent dsde) { ((DragSourceListener)a).dragDropEnd(dsde); @@ -112,10 +112,10 @@ class DnDEventMulticaster extends AWTEventMulticaster } /** - * Handles the DragSourceDragEvent by invoking - * dragMouseMoved on listener-a and listener-b. + * Handles the {@code DragSourceDragEvent} by invoking + * {@code dragMouseMoved} on listener-a and listener-b. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dragMouseMoved(DragSourceDragEvent dsde) { ((DragSourceMotionListener)a).dragMouseMoved(dsde); diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureEvent.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureEvent.java index 3dff336a794..b87b709feb2 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureEvent.java @@ -49,12 +49,12 @@ import java.io.ObjectOutputStream; /** - * A DragGestureEvent is passed - * to DragGestureListener's + * A {@code DragGestureEvent} is passed + * to {@code DragGestureListener}'s * dragGestureRecognized() method - * when a particular DragGestureRecognizer detects that a + * when a particular {@code DragGestureRecognizer} detects that a * platform dependent drag initiating gesture has occurred - * on the Component that it is tracking. + * on the {@code Component} that it is tracking. * * The {@code action} field of any {@code DragGestureEvent} instance should take one of the following * values: @@ -76,19 +76,19 @@ public class DragGestureEvent extends EventObject { private static final long serialVersionUID = 9080172649166731306L; /** - * Constructs a DragGestureEvent object given by the - * DragGestureRecognizer instance firing this event, + * Constructs a {@code DragGestureEvent} object given by the + * {@code DragGestureRecognizer} instance firing this event, * an {@code act} parameter representing * the user's preferred action, an {@code ori} parameter * indicating the origin of the drag, and a {@code List} of * events that comprise the gesture({@code evs} parameter). * - * @param dgr The DragGestureRecognizer firing this event + * @param dgr The {@code DragGestureRecognizer} firing this event * @param act The user's preferred action. * For information on allowable values, see * the class description for {@link DragGestureEvent} * @param ori The origin of the drag - * @param evs The List of events that comprise the gesture + * @param evs The {@code List} of events that comprise the gesture * * @throws IllegalArgumentException if any parameter equals {@code null} * @throws IllegalArgumentException if the act parameter does not comply with @@ -123,9 +123,9 @@ public class DragGestureEvent extends EventObject { } /** - * Returns the source as a DragGestureRecognizer. + * Returns the source as a {@code DragGestureRecognizer}. * - * @return the source as a DragGestureRecognizer + * @return the source as a {@code DragGestureRecognizer} */ public DragGestureRecognizer getSourceAsDragGestureRecognizer() { @@ -133,8 +133,8 @@ public class DragGestureEvent extends EventObject { } /** - * Returns the Component associated - * with this DragGestureEvent. + * Returns the {@code Component} associated + * with this {@code DragGestureEvent}. * * @return the Component */ @@ -142,16 +142,16 @@ public class DragGestureEvent extends EventObject { public Component getComponent() { return component; } /** - * Returns the DragSource. + * Returns the {@code DragSource}. * - * @return the DragSource + * @return the {@code DragSource} */ public DragSource getDragSource() { return dragSource; } /** - * Returns a Point in the coordinates - * of the Component over which the drag originated. + * Returns a {@code Point} in the coordinates + * of the {@code Component} over which the drag originated. * * @return the Point where the drag originated in Component coords. */ @@ -161,7 +161,7 @@ public class DragGestureEvent extends EventObject { } /** - * Returns an Iterator for the events + * Returns an {@code Iterator} for the events * comprising the gesture. * * @return an Iterator for the events comprising the gesture @@ -170,7 +170,7 @@ public class DragGestureEvent extends EventObject { public Iterator iterator() { return events.iterator(); } /** - * Returns an Object array of the + * Returns an {@code Object} array of the * events comprising the drag gesture. * * @return an array of the events comprising the gesture @@ -181,7 +181,7 @@ public class DragGestureEvent extends EventObject { /** * Returns an array of the events comprising the drag gesture. * - * @param array the array of EventObject sub(types) + * @param array the array of {@code EventObject} sub(types) * * @return an array of the events comprising the gesture */ @@ -189,7 +189,7 @@ public class DragGestureEvent extends EventObject { public Object[] toArray(Object[] array) { return events.toArray(array); } /** - * Returns an int representing the + * Returns an {@code int} representing the * action selected by the user. * * @return the action selected by the user @@ -208,22 +208,22 @@ public class DragGestureEvent extends EventObject { } /** - * Starts the drag operation given the Cursor for this drag - * operation and the Transferable representing the source data + * Starts the drag operation given the {@code Cursor} for this drag + * operation and the {@code Transferable} representing the source data * for this drag operation. *
          - * If a null Cursor is specified no exception will + * If a {@code null Cursor} is specified no exception will * be thrown and default drag cursors will be used instead. *
          - * If a null Transferable is specified - * NullPointerException will be thrown. + * If a {@code null Transferable} is specified + * {@code NullPointerException} will be thrown. * @param dragCursor The initial {@code Cursor} for this drag operation * or {@code null} for the default cursor handling; * see * DragSourceContext * for more details on the cursor handling mechanism * during drag and drop - * @param transferable The Transferable representing the source + * @param transferable The {@code Transferable} representing the source * data for this drag operation. * * @throws InvalidDnDOperationException if the Drag and Drop @@ -239,9 +239,9 @@ public class DragGestureEvent extends EventObject { } /** - * Starts the drag given the initial Cursor to display, - * the Transferable object, - * and the DragSourceListener to use. + * Starts the drag given the initial {@code Cursor} to display, + * the {@code Transferable} object, + * and the {@code DragSourceListener} to use. * * @param dragCursor The initial {@code Cursor} for this drag operation * or {@code null} for the default cursor handling; @@ -264,11 +264,11 @@ public class DragGestureEvent extends EventObject { } /** - * Start the drag given the initial Cursor to display, - * a drag Image, the offset of - * the Image, - * the Transferable object, and - * the DragSourceListener to use. + * Start the drag given the initial {@code Cursor} to display, + * a drag {@code Image}, the offset of + * the {@code Image}, + * the {@code Transferable} object, and + * the {@code DragSourceListener} to use. * * @param dragCursor The initial {@code Cursor} for this drag operation * or {@code null} for the default cursor handling; @@ -293,16 +293,16 @@ public class DragGestureEvent extends EventObject { } /** - * Serializes this DragGestureEvent. Performs default - * serialization and then writes out this object's List of - * gesture events if and only if the List can be serialized. - * If not, null is written instead. In this case, a - * DragGestureEvent created from the resulting deserialized - * stream will contain an empty List of gesture events. + * Serializes this {@code DragGestureEvent}. Performs default + * serialization and then writes out this object's {@code List} of + * gesture events if and only if the {@code List} can be serialized. + * If not, {@code null} is written instead. In this case, a + * {@code DragGestureEvent} created from the resulting deserialized + * stream will contain an empty {@code List} of gesture events. * * @serialData The default serializable fields, in alphabetical order, - * followed by either a List instance, or - * null. + * followed by either a {@code List} instance, or + * {@code null}. * @since 1.4 */ private void writeObject(ObjectOutputStream s) throws IOException { @@ -312,16 +312,16 @@ public class DragGestureEvent extends EventObject { } /** - * Deserializes this DragGestureEvent. This method first - * performs default deserialization for all non-transient + * Deserializes this {@code DragGestureEvent}. This method first + * performs default deserialization for all non-{@code transient} * fields. An attempt is then made to deserialize this object's - * List of gesture events as well. This is first attempted - * by deserializing the field events, because, in releases - * prior to 1.4, a non-transient field of this name stored the - * List of gesture events. If this fails, the next object in - * the stream is used instead. If the resulting List is - * null, this object's List of gesture events - * is set to an empty List. + * {@code List} of gesture events as well. This is first attempted + * by deserializing the field {@code events}, because, in releases + * prior to 1.4, a non-{@code transient} field of this name stored the + * {@code List} of gesture events. If this fails, the next object in + * the stream is used instead. If the resulting {@code List} is + * {@code null}, this object's {@code List} of gesture events + * is set to an empty {@code List}. * * @since 1.4 */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureListener.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureListener.java index f3e600e6cd4..e04fbfa4bb5 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureListener.java @@ -56,7 +56,7 @@ import java.util.EventListener; * * @see java.awt.dnd.DragGestureRecognizer * @see java.awt.dnd.DragGestureEvent - * @param dge the DragGestureEvent describing + * @param dge the {@code DragGestureEvent} describing * the gesture that has just occurred */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureRecognizer.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureRecognizer.java index b3dbeb5f477..0a64aa5c62f 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureRecognizer.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragGestureRecognizer.java @@ -40,41 +40,41 @@ import java.io.ObjectOutputStream; import java.io.Serializable; /** - * The DragGestureRecognizer is an + * The {@code DragGestureRecognizer} is an * abstract base class for the specification * of a platform-dependent listener that can be associated with a particular - * Component in order to + * {@code Component} in order to * identify platform-dependent drag initiating gestures. *

          - * The appropriate DragGestureRecognizer + * The appropriate {@code DragGestureRecognizer} * subclass instance is obtained from the * {@link DragSource} associated with - * a particular Component, or from the Toolkit object via its + * a particular {@code Component}, or from the {@code Toolkit} object via its * {@link java.awt.Toolkit#createDragGestureRecognizer createDragGestureRecognizer()} * method. *

          - * Once the DragGestureRecognizer - * is associated with a particular Component + * Once the {@code DragGestureRecognizer} + * is associated with a particular {@code Component} * it will register the appropriate listener interfaces on that - * Component - * in order to track the input events delivered to the Component. + * {@code Component} + * in order to track the input events delivered to the {@code Component}. *

          - * Once the DragGestureRecognizer identifies a sequence of events - * on the Component as a drag initiating gesture, it will notify - * its unicast DragGestureListener by + * Once the {@code DragGestureRecognizer} identifies a sequence of events + * on the {@code Component} as a drag initiating gesture, it will notify + * its unicast {@code DragGestureListener} by * invoking its * {@link java.awt.dnd.DragGestureListener#dragGestureRecognized gestureRecognized()} * method. *

          - * When a concrete DragGestureRecognizer + * When a concrete {@code DragGestureRecognizer} * instance detects a drag initiating - * gesture on the Component it is associated with, + * gesture on the {@code Component} it is associated with, * it fires a {@link DragGestureEvent} to - * the DragGestureListener registered on - * its unicast event source for DragGestureListener - * events. This DragGestureListener is responsible + * the {@code DragGestureListener} registered on + * its unicast event source for {@code DragGestureListener} + * events. This {@code DragGestureListener} is responsible * for causing the associated - * DragSource to start the Drag and Drop operation (if + * {@code DragSource} to start the Drag and Drop operation (if * appropriate). * * @author Laurence P. G. Cable @@ -88,36 +88,36 @@ public abstract class DragGestureRecognizer implements Serializable { private static final long serialVersionUID = 8996673345831063337L; /** - * Construct a new DragGestureRecognizer - * given the DragSource to be used - * in this Drag and Drop operation, the Component - * this DragGestureRecognizer should "observe" + * Construct a new {@code DragGestureRecognizer} + * given the {@code DragSource} to be used + * in this Drag and Drop operation, the {@code Component} + * this {@code DragGestureRecognizer} should "observe" * for drag initiating gestures, the action(s) supported * for this Drag and Drop operation, and the - * DragGestureListener to notify + * {@code DragGestureListener} to notify * once a drag initiating gesture has been detected. * - * @param ds the DragSource this - * DragGestureRecognizer + * @param ds the {@code DragSource} this + * {@code DragGestureRecognizer} * will use to process the Drag and Drop operation * - * @param c the Component - * this DragGestureRecognizer + * @param c the {@code Component} + * this {@code DragGestureRecognizer} * should "observe" the event stream to, * in order to detect a drag initiating gesture. - * If this value is null, the - * DragGestureRecognizer - * is not associated with any Component. + * If this value is {@code null}, the + * {@code DragGestureRecognizer} + * is not associated with any {@code Component}. * * @param sa the set (logical OR) of the - * DnDConstants + * {@code DnDConstants} * that this Drag and Drop operation will support * - * @param dgl the DragGestureRecognizer + * @param dgl the {@code DragGestureRecognizer} * to notify when a drag gesture is detected * * @throws IllegalArgumentException - * if ds is null. + * if ds is {@code null}. */ protected DragGestureRecognizer(DragSource ds, Component c, int sa, DragGestureListener dgl) { @@ -137,30 +137,30 @@ public abstract class DragGestureRecognizer implements Serializable { } /** - * Construct a new DragGestureRecognizer - * given the DragSource to be used in this + * Construct a new {@code DragGestureRecognizer} + * given the {@code DragSource} to be used in this * Drag and Drop - * operation, the Component this - * DragGestureRecognizer should "observe" + * operation, the {@code Component} this + * {@code DragGestureRecognizer} should "observe" * for drag initiating gestures, and the action(s) * supported for this Drag and Drop operation. * - * @param ds the DragSource this - * DragGestureRecognizer will use to + * @param ds the {@code DragSource} this + * {@code DragGestureRecognizer} will use to * process the Drag and Drop operation * - * @param c the Component this - * DragGestureRecognizer should "observe" the event + * @param c the {@code Component} this + * {@code DragGestureRecognizer} should "observe" the event * stream to, in order to detect a drag initiating gesture. - * If this value is null, the - * DragGestureRecognizer - * is not associated with any Component. + * If this value is {@code null}, the + * {@code DragGestureRecognizer} + * is not associated with any {@code Component}. * - * @param sa the set (logical OR) of the DnDConstants + * @param sa the set (logical OR) of the {@code DnDConstants} * that this Drag and Drop operation will support * * @throws IllegalArgumentException - * if ds is null. + * if ds is {@code null}. */ protected DragGestureRecognizer(DragSource ds, Component c, int sa) { @@ -168,27 +168,27 @@ public abstract class DragGestureRecognizer implements Serializable { } /** - * Construct a new DragGestureRecognizer - * given the DragSource to be used + * Construct a new {@code DragGestureRecognizer} + * given the {@code DragSource} to be used * in this Drag and Drop operation, and - * the Component this - * DragGestureRecognizer + * the {@code Component} this + * {@code DragGestureRecognizer} * should "observe" for drag initiating gestures. * - * @param ds the DragSource this - * DragGestureRecognizer + * @param ds the {@code DragSource} this + * {@code DragGestureRecognizer} * will use to process the Drag and Drop operation * - * @param c the Component - * this DragGestureRecognizer + * @param c the {@code Component} + * this {@code DragGestureRecognizer} * should "observe" the event stream to, * in order to detect a drag initiating gesture. - * If this value is null, - * the DragGestureRecognizer - * is not associated with any Component. + * If this value is {@code null}, + * the {@code DragGestureRecognizer} + * is not associated with any {@code Component}. * * @throws IllegalArgumentException - * if ds is null. + * if ds is {@code null}. */ protected DragGestureRecognizer(DragSource ds, Component c) { @@ -196,16 +196,16 @@ public abstract class DragGestureRecognizer implements Serializable { } /** - * Construct a new DragGestureRecognizer - * given the DragSource to be used in this + * Construct a new {@code DragGestureRecognizer} + * given the {@code DragSource} to be used in this * Drag and Drop operation. * - * @param ds the DragSource this - * DragGestureRecognizer will + * @param ds the {@code DragSource} this + * {@code DragGestureRecognizer} will * use to process the Drag and Drop operation * * @throws IllegalArgumentException - * if ds is null. + * if ds is {@code null}. */ protected DragGestureRecognizer(DragSource ds) { @@ -229,8 +229,8 @@ public abstract class DragGestureRecognizer implements Serializable { protected abstract void unregisterListeners(); /** - * This method returns the DragSource - * this DragGestureRecognizer + * This method returns the {@code DragSource} + * this {@code DragGestureRecognizer} * will use in order to process the Drag and Drop * operation. * @@ -240,9 +240,9 @@ public abstract class DragGestureRecognizer implements Serializable { public DragSource getDragSource() { return dragSource; } /** - * This method returns the Component + * This method returns the {@code Component} * that is to be "observed" by the - * DragGestureRecognizer + * {@code DragGestureRecognizer} * for drag initiating gestures. * * @return The Component this DragGestureRecognizer @@ -257,7 +257,7 @@ public abstract class DragGestureRecognizer implements Serializable { * registerListeners() and unregisterListeners() are called as a side * effect as appropriate. * - * @param c The Component or null + * @param c The {@code Component} or {@code null} */ public synchronized void setComponent(Component c) { @@ -309,13 +309,13 @@ public abstract class DragGestureRecognizer implements Serializable { public void resetRecognizer() { events.clear(); } /** - * Register a new DragGestureListener. + * Register a new {@code DragGestureListener}. * - * @param dgl the DragGestureListener to register - * with this DragGestureRecognizer. + * @param dgl the {@code DragGestureListener} to register + * with this {@code DragGestureRecognizer}. * * @throws java.util.TooManyListenersException if a - * DragGestureListener has already been added. + * {@code DragGestureListener} has already been added. */ public synchronized void addDragGestureListener(DragGestureListener dgl) throws TooManyListenersException { @@ -331,11 +331,11 @@ public abstract class DragGestureRecognizer implements Serializable { /** * unregister the current DragGestureListener * - * @param dgl the DragGestureListener to unregister - * from this DragGestureRecognizer + * @param dgl the {@code DragGestureListener} to unregister + * from this {@code DragGestureRecognizer} * * @throws IllegalArgumentException if - * dgl is not (equal to) the currently registered DragGestureListener. + * dgl is not (equal to) the currently registered {@code DragGestureListener}. */ public synchronized void removeDragGestureListener(DragGestureListener dgl) { @@ -370,16 +370,16 @@ public abstract class DragGestureRecognizer implements Serializable { * all Events that are recognized as part of the series of Events that go * to comprise a Drag and Drop initiating gesture via this API. *

          - * This method is used by a DragGestureRecognizer - * implementation to add an InputEvent + * This method is used by a {@code DragGestureRecognizer} + * implementation to add an {@code InputEvent} * subclass (that it believes is one in a series * of events that comprise a Drag and Drop operation) * to the array of events that this - * DragGestureRecognizer maintains internally. + * {@code DragGestureRecognizer} maintains internally. * - * @param awtie the InputEvent - * to add to this DragGestureRecognizer's - * internal array of events. Note that null + * @param awtie the {@code InputEvent} + * to add to this {@code DragGestureRecognizer}'s + * internal array of events. Note that {@code null} * is not a valid value, and will be ignored. */ @@ -388,14 +388,14 @@ public abstract class DragGestureRecognizer implements Serializable { } /** - * Serializes this DragGestureRecognizer. This method first + * Serializes this {@code DragGestureRecognizer}. This method first * performs default serialization. Then, this object's - * DragGestureListener is written out if and only if it can be - * serialized. If not, null is written instead. + * {@code DragGestureListener} is written out if and only if it can be + * serialized. If not, {@code null} is written instead. * * @serialData The default serializable fields, in alphabetical order, - * followed by either a DragGestureListener, or - * null. + * followed by either a {@code DragGestureListener}, or + * {@code null}. * @since 1.4 */ private void writeObject(ObjectOutputStream s) throws IOException { @@ -406,9 +406,9 @@ public abstract class DragGestureRecognizer implements Serializable { } /** - * Deserializes this DragGestureRecognizer. This method first - * performs default deserialization for all non-transient - * fields. This object's DragGestureListener is then + * Deserializes this {@code DragGestureRecognizer}. This method first + * performs default deserialization for all non-{@code transient} + * fields. This object's {@code DragGestureListener} is then * deserialized as well by using the next object in the stream. * * @since 1.4 @@ -437,30 +437,30 @@ public abstract class DragGestureRecognizer implements Serializable { */ /** - * The DragSource + * The {@code DragSource} * associated with this - * DragGestureRecognizer. + * {@code DragGestureRecognizer}. * * @serial */ protected DragSource dragSource; /** - * The Component - * associated with this DragGestureRecognizer. + * The {@code Component} + * associated with this {@code DragGestureRecognizer}. * * @serial */ protected Component component; /** - * The DragGestureListener - * associated with this DragGestureRecognizer. + * The {@code DragGestureListener} + * associated with this {@code DragGestureRecognizer}. */ protected transient DragGestureListener dragGestureListener; /** - * An int representing + * An {@code int} representing * the type(s) of action(s) used * in this Drag and Drop operation. * @@ -470,7 +470,7 @@ public abstract class DragGestureRecognizer implements Serializable { /** * The list of events (in order) that - * the DragGestureRecognizer + * the {@code DragGestureRecognizer} * "recognized" as a "gesture" that triggers a drag. * * @serial diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSource.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSource.java index 073686e857e..cb028a399a8 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSource.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSource.java @@ -49,7 +49,7 @@ import sun.security.action.GetIntegerAction; /** - * The DragSource is the entity responsible + * The {@code DragSource} is the entity responsible * for the initiation of the Drag * and Drop operation, and may be used in a number of scenarios: *

            @@ -57,49 +57,49 @@ import sun.security.action.GetIntegerAction; *
          • 1 instance per class of potential Drag Initiator object (e.g * TextField). [implementation dependent] *
          • 1 per instance of a particular - * Component, or application specific - * object associated with a Component + * {@code Component}, or application specific + * object associated with a {@code Component} * instance in the GUI. [implementation dependent] *
          • Some other arbitrary association. [implementation dependent] *
          * - * Once the DragSource is - * obtained, a DragGestureRecognizer should - * also be obtained to associate the DragSource + * Once the {@code DragSource} is + * obtained, a {@code DragGestureRecognizer} should + * also be obtained to associate the {@code DragSource} * with a particular - * Component. + * {@code Component}. *

          * The initial interpretation of the user's gesture, * and the subsequent starting of the drag operation * are the responsibility of the implementing - * Component, which is usually - * implemented by a DragGestureRecognizer. + * {@code Component}, which is usually + * implemented by a {@code DragGestureRecognizer}. *

          * When a drag gesture occurs, the - * DragSource's + * {@code DragSource}'s * startDrag() method shall be * invoked in order to cause processing * of the user's navigational * gestures and delivery of Drag and Drop * protocol notifications. A - * DragSource shall only + * {@code DragSource} shall only * permit a single Drag and Drop operation to be * current at any one time, and shall * reject any further startDrag() requests - * by throwing an IllegalDnDOperationException + * by throwing an {@code IllegalDnDOperationException} * until such time as the extant operation is complete. *

          * The startDrag() method invokes the * createDragSourceContext() method to * instantiate an appropriate - * DragSourceContext - * and associate the DragSourceContextPeer + * {@code DragSourceContext} + * and associate the {@code DragSourceContextPeer} * with that. *

          * If the Drag and Drop System is * unable to initiate a drag operation for * some reason, the startDrag() method throws - * a java.awt.dnd.InvalidDnDOperationException + * a {@code java.awt.dnd.InvalidDnDOperationException} * to signal such a condition. Typically this * exception is thrown when the underlying platform * system is either not in a state to @@ -111,7 +111,7 @@ import sun.security.action.GetIntegerAction; * until the operation is complete. * The operation(s) are constant for the * duration of the operation with respect to the - * DragSource. + * {@code DragSource}. * * @since 1.2 */ @@ -140,9 +140,9 @@ public class DragSource implements Serializable { /** - * The default Cursor to use with a copy operation indicating - * that a drop is currently allowed. null if - * GraphicsEnvironment.isHeadless() returns true. + * The default {@code Cursor} to use with a copy operation indicating + * that a drop is currently allowed. {@code null} if + * {@code GraphicsEnvironment.isHeadless()} returns {@code true}. * * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -150,9 +150,9 @@ public class DragSource implements Serializable { load("DnD.Cursor.CopyDrop"); /** - * The default Cursor to use with a move operation indicating - * that a drop is currently allowed. null if - * GraphicsEnvironment.isHeadless() returns true. + * The default {@code Cursor} to use with a move operation indicating + * that a drop is currently allowed. {@code null} if + * {@code GraphicsEnvironment.isHeadless()} returns {@code true}. * * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -160,9 +160,9 @@ public class DragSource implements Serializable { load("DnD.Cursor.MoveDrop"); /** - * The default Cursor to use with a link operation indicating - * that a drop is currently allowed. null if - * GraphicsEnvironment.isHeadless() returns true. + * The default {@code Cursor} to use with a link operation indicating + * that a drop is currently allowed. {@code null} if + * {@code GraphicsEnvironment.isHeadless()} returns {@code true}. * * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -170,9 +170,9 @@ public class DragSource implements Serializable { load("DnD.Cursor.LinkDrop"); /** - * The default Cursor to use with a copy operation indicating - * that a drop is currently not allowed. null if - * GraphicsEnvironment.isHeadless() returns true. + * The default {@code Cursor} to use with a copy operation indicating + * that a drop is currently not allowed. {@code null} if + * {@code GraphicsEnvironment.isHeadless()} returns {@code true}. * * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -180,9 +180,9 @@ public class DragSource implements Serializable { load("DnD.Cursor.CopyNoDrop"); /** - * The default Cursor to use with a move operation indicating - * that a drop is currently not allowed. null if - * GraphicsEnvironment.isHeadless() returns true. + * The default {@code Cursor} to use with a move operation indicating + * that a drop is currently not allowed. {@code null} if + * {@code GraphicsEnvironment.isHeadless()} returns {@code true}. * * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -190,9 +190,9 @@ public class DragSource implements Serializable { load("DnD.Cursor.MoveNoDrop"); /** - * The default Cursor to use with a link operation indicating - * that a drop is currently not allowed. null if - * GraphicsEnvironment.isHeadless() returns true. + * The default {@code Cursor} to use with a link operation indicating + * that a drop is currently not allowed. {@code null} if + * {@code GraphicsEnvironment.isHeadless()} returns {@code true}. * * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -209,7 +209,7 @@ public class DragSource implements Serializable { static final String dragSourceMotionListenerK = "dragSourceMotionL"; /** - * Gets the DragSource object associated with + * Gets the {@code DragSource} object associated with * the underlying platform. * * @return the platform DragSource @@ -228,7 +228,7 @@ public class DragSource implements Serializable { /** * Reports * whether or not drag - * Image support + * {@code Image} support * is available on the underlying platform. * * @return if the Drag Image support is available on this platform @@ -249,7 +249,7 @@ public class DragSource implements Serializable { } /** - * Creates a new DragSource. + * Creates a new {@code DragSource}. * * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true @@ -262,28 +262,28 @@ public class DragSource implements Serializable { } /** - * Start a drag, given the DragGestureEvent + * Start a drag, given the {@code DragGestureEvent} * that initiated the drag, the initial - * Cursor to use, - * the Image to drag, - * the offset of the Image origin - * from the hotspot of the Cursor at + * {@code Cursor} to use, + * the {@code Image} to drag, + * the offset of the {@code Image} origin + * from the hotspot of the {@code Cursor} at * the instant of the trigger, - * the Transferable subject data - * of the drag, the DragSourceListener, - * and the FlavorMap. + * the {@code Transferable} subject data + * of the drag, the {@code DragSourceListener}, + * and the {@code FlavorMap}. * - * @param trigger the DragGestureEvent that initiated the drag + * @param trigger the {@code DragGestureEvent} that initiated the drag * @param dragCursor the initial {@code Cursor} for this drag operation * or {@code null} for the default cursor handling; * see DragSourceContext * for more details on the cursor handling mechanism during drag and drop * @param dragImage the image to drag or {@code null} - * @param imageOffset the offset of the Image origin from the hotspot - * of the Cursor at the instant of the trigger + * @param imageOffset the offset of the {@code Image} origin from the hotspot + * of the {@code Cursor} at the instant of the trigger * @param transferable the subject data of the drag - * @param dsl the DragSourceListener - * @param flavorMap the FlavorMap to use, or null + * @param dsl the {@code DragSourceListener} + * @param flavorMap the {@code FlavorMap} to use, or {@code null} * * @throws java.awt.dnd.InvalidDnDOperationException * if the Drag and Drop @@ -322,22 +322,22 @@ public class DragSource implements Serializable { } /** - * Start a drag, given the DragGestureEvent + * Start a drag, given the {@code DragGestureEvent} * that initiated the drag, the initial - * Cursor to use, - * the Transferable subject data - * of the drag, the DragSourceListener, - * and the FlavorMap. + * {@code Cursor} to use, + * the {@code Transferable} subject data + * of the drag, the {@code DragSourceListener}, + * and the {@code FlavorMap}. * - * @param trigger the DragGestureEvent that + * @param trigger the {@code DragGestureEvent} that * initiated the drag * @param dragCursor the initial {@code Cursor} for this drag operation * or {@code null} for the default cursor handling; * see DragSourceContext * for more details on the cursor handling mechanism during drag and drop * @param transferable the subject data of the drag - * @param dsl the DragSourceListener - * @param flavorMap the FlavorMap to use or null + * @param dsl the {@code DragSourceListener} + * @param flavorMap the {@code FlavorMap} to use or {@code null} * * @throws java.awt.dnd.InvalidDnDOperationException * if the Drag and Drop @@ -355,26 +355,26 @@ public class DragSource implements Serializable { } /** - * Start a drag, given the DragGestureEvent - * that initiated the drag, the initial Cursor + * Start a drag, given the {@code DragGestureEvent} + * that initiated the drag, the initial {@code Cursor} * to use, - * the Image to drag, - * the offset of the Image origin - * from the hotspot of the Cursor + * the {@code Image} to drag, + * the offset of the {@code Image} origin + * from the hotspot of the {@code Cursor} * at the instant of the trigger, * the subject data of the drag, and - * the DragSourceListener. + * the {@code DragSourceListener}. * - * @param trigger the DragGestureEvent that initiated the drag + * @param trigger the {@code DragGestureEvent} that initiated the drag * @param dragCursor the initial {@code Cursor} for this drag operation * or {@code null} for the default cursor handling; * see DragSourceContext * for more details on the cursor handling mechanism during drag and drop - * @param dragImage the Image to drag or null - * @param dragOffset the offset of the Image origin from the hotspot - * of the Cursor at the instant of the trigger + * @param dragImage the {@code Image} to drag or {@code null} + * @param dragOffset the offset of the {@code Image} origin from the hotspot + * of the {@code Cursor} at the instant of the trigger * @param transferable the subject data of the drag - * @param dsl the DragSourceListener + * @param dsl the {@code DragSourceListener} * * @throws java.awt.dnd.InvalidDnDOperationException * if the Drag and Drop @@ -393,20 +393,20 @@ public class DragSource implements Serializable { } /** - * Start a drag, given the DragGestureEvent + * Start a drag, given the {@code DragGestureEvent} * that initiated the drag, the initial - * Cursor to + * {@code Cursor} to * use, - * the Transferable subject data - * of the drag, and the DragSourceListener. + * the {@code Transferable} subject data + * of the drag, and the {@code DragSourceListener}. * - * @param trigger the DragGestureEvent that initiated the drag + * @param trigger the {@code DragGestureEvent} that initiated the drag * @param dragCursor the initial {@code Cursor} for this drag operation * or {@code null} for the default cursor handling; * see DragSourceContext class * for more details on the cursor handling mechanism during drag and drop * @param transferable the subject data of the drag - * @param dsl the DragSourceListener + * @param dsl the {@code DragSourceListener} * * @throws java.awt.dnd.InvalidDnDOperationException * if the Drag and Drop @@ -426,46 +426,46 @@ public class DragSource implements Serializable { * Creates the {@code DragSourceContext} to handle the current drag * operation. *

          - * To incorporate a new DragSourceContext - * subclass, subclass DragSource and + * To incorporate a new {@code DragSourceContext} + * subclass, subclass {@code DragSource} and * override this method. *

          - * If dragImage is null, no image is used + * If {@code dragImage} is {@code null}, no image is used * to represent the drag over feedback for this drag operation, but - * NullPointerException is not thrown. + * {@code NullPointerException} is not thrown. *

          - * If dsl is null, no drag source listener - * is registered with the created DragSourceContext, - * but NullPointerException is not thrown. + * If {@code dsl} is {@code null}, no drag source listener + * is registered with the created {@code DragSourceContext}, + * but {@code NullPointerException} is not thrown. * - * @param dgl The DragGestureEvent that triggered the + * @param dgl The {@code DragGestureEvent} that triggered the * drag * @param dragCursor The initial {@code Cursor} for this drag operation * or {@code null} for the default cursor handling; * see DragSourceContext class * for more details on the cursor handling mechanism during drag and drop - * @param dragImage The Image to drag or null - * @param imageOffset The offset of the Image origin from the + * @param dragImage The {@code Image} to drag or {@code null} + * @param imageOffset The offset of the {@code Image} origin from the * hotspot of the cursor at the instant of the trigger * @param t The subject data of the drag - * @param dsl The DragSourceListener + * @param dsl The {@code DragSourceListener} * - * @return the DragSourceContext + * @return the {@code DragSourceContext} * - * @throws NullPointerException if dscp is null - * @throws NullPointerException if dgl is null - * @throws NullPointerException if dragImage is not - * null and imageOffset is null - * @throws NullPointerException if t is null - * @throws IllegalArgumentException if the Component - * associated with the trigger event is null. - * @throws IllegalArgumentException if the DragSource for the - * trigger event is null. + * @throws NullPointerException if {@code dscp} is {@code null} + * @throws NullPointerException if {@code dgl} is {@code null} + * @throws NullPointerException if {@code dragImage} is not + * {@code null} and {@code imageOffset} is {@code null} + * @throws NullPointerException if {@code t} is {@code null} + * @throws IllegalArgumentException if the {@code Component} + * associated with the trigger event is {@code null}. + * @throws IllegalArgumentException if the {@code DragSource} for the + * trigger event is {@code null}. * @throws IllegalArgumentException if the drag action for the - * trigger event is DnDConstants.ACTION_NONE. + * trigger event is {@code DnDConstants.ACTION_NONE}. * @throws IllegalArgumentException if the source actions for the - * DragGestureRecognizer associated with the trigger - * event are equal to DnDConstants.ACTION_NONE. + * {@code DragGestureRecognizer} associated with the trigger + * event are equal to {@code DnDConstants.ACTION_NONE}. */ protected DragSourceContext createDragSourceContext(DragGestureEvent dgl, @@ -479,33 +479,33 @@ public class DragSource implements Serializable { /** * This method returns the - * FlavorMap for this DragSource. + * {@code FlavorMap} for this {@code DragSource}. * - * @return the FlavorMap for this DragSource + * @return the {@code FlavorMap} for this {@code DragSource} */ public FlavorMap getFlavorMap() { return flavorMap; } /** - * Creates a new DragGestureRecognizer + * Creates a new {@code DragGestureRecognizer} * that implements the specified * abstract subclass of - * DragGestureRecognizer, and - * sets the specified Component - * and DragGestureListener on + * {@code DragGestureRecognizer}, and + * sets the specified {@code Component} + * and {@code DragGestureListener} on * the newly created object. * * @param the type of {@code DragGestureRecognizer} to create * @param recognizerAbstractClass the requested abstract type * @param actions the permitted source drag actions - * @param c the Component target - * @param dgl the DragGestureListener to notify + * @param c the {@code Component} target + * @param dgl the {@code DragGestureListener} to notify * - * @return the new DragGestureRecognizer or null - * if the Toolkit.createDragGestureRecognizer method + * @return the new {@code DragGestureRecognizer} or {@code null} + * if the {@code Toolkit.createDragGestureRecognizer} method * has no implementation available for - * the requested DragGestureRecognizer - * subclass and returns null + * the requested {@code DragGestureRecognizer} + * subclass and returns {@code null} */ public T @@ -518,26 +518,26 @@ public class DragSource implements Serializable { /** - * Creates a new DragGestureRecognizer + * Creates a new {@code DragGestureRecognizer} * that implements the default - * abstract subclass of DragGestureRecognizer - * for this DragSource, - * and sets the specified Component - * and DragGestureListener on the + * abstract subclass of {@code DragGestureRecognizer} + * for this {@code DragSource}, + * and sets the specified {@code Component} + * and {@code DragGestureListener} on the * newly created object. * - * For this DragSource - * the default is MouseDragGestureRecognizer. + * For this {@code DragSource} + * the default is {@code MouseDragGestureRecognizer}. * - * @param c the Component target for the recognizer + * @param c the {@code Component} target for the recognizer * @param actions the permitted source actions - * @param dgl the DragGestureListener to notify + * @param dgl the {@code DragGestureListener} to notify * - * @return the new DragGestureRecognizer or null - * if the Toolkit.createDragGestureRecognizer method + * @return the new {@code DragGestureRecognizer} or {@code null} + * if the {@code Toolkit.createDragGestureRecognizer} method * has no implementation available for - * the requested DragGestureRecognizer - * subclass and returns null + * the requested {@code DragGestureRecognizer} + * subclass and returns {@code null} */ public DragGestureRecognizer createDefaultDragGestureRecognizer(Component c, int actions, DragGestureListener dgl) { @@ -545,13 +545,13 @@ public class DragSource implements Serializable { } /** - * Adds the specified DragSourceListener to this - * DragSource to receive drag source events during drag - * operations initiated with this DragSource. - * If a null listener is specified, no action is taken and no + * Adds the specified {@code DragSourceListener} to this + * {@code DragSource} to receive drag source events during drag + * operations initiated with this {@code DragSource}. + * If a {@code null} listener is specified, no action is taken and no * exception is thrown. * - * @param dsl the DragSourceListener to add + * @param dsl the {@code DragSourceListener} to add * * @see #removeDragSourceListener * @see #getDragSourceListeners @@ -566,15 +566,15 @@ public class DragSource implements Serializable { } /** - * Removes the specified DragSourceListener from this - * DragSource. - * If a null listener is specified, no action is taken and no + * Removes the specified {@code DragSourceListener} from this + * {@code DragSource}. + * If a {@code null} listener is specified, no action is taken and no * exception is thrown. * If the listener specified by the argument was not previously added to - * this DragSource, no action is taken and no exception + * this {@code DragSource}, no action is taken and no exception * is thrown. * - * @param dsl the DragSourceListener to remove + * @param dsl the {@code DragSourceListener} to remove * * @see #addDragSourceListener * @see #getDragSourceListeners @@ -589,11 +589,11 @@ public class DragSource implements Serializable { } /** - * Gets all the DragSourceListeners - * registered with this DragSource. + * Gets all the {@code DragSourceListener}s + * registered with this {@code DragSource}. * - * @return all of this DragSource's - * DragSourceListeners or an empty array if no + * @return all of this {@code DragSource}'s + * {@code DragSourceListener}s or an empty array if no * such listeners are currently registered * * @see #addDragSourceListener @@ -605,13 +605,13 @@ public class DragSource implements Serializable { } /** - * Adds the specified DragSourceMotionListener to this - * DragSource to receive drag motion events during drag - * operations initiated with this DragSource. - * If a null listener is specified, no action is taken and no + * Adds the specified {@code DragSourceMotionListener} to this + * {@code DragSource} to receive drag motion events during drag + * operations initiated with this {@code DragSource}. + * If a {@code null} listener is specified, no action is taken and no * exception is thrown. * - * @param dsml the DragSourceMotionListener to add + * @param dsml the {@code DragSourceMotionListener} to add * * @see #removeDragSourceMotionListener * @see #getDragSourceMotionListeners @@ -626,15 +626,15 @@ public class DragSource implements Serializable { } /** - * Removes the specified DragSourceMotionListener from this - * DragSource. - * If a null listener is specified, no action is taken and no + * Removes the specified {@code DragSourceMotionListener} from this + * {@code DragSource}. + * If a {@code null} listener is specified, no action is taken and no * exception is thrown. * If the listener specified by the argument was not previously added to - * this DragSource, no action is taken and no exception + * this {@code DragSource}, no action is taken and no exception * is thrown. * - * @param dsml the DragSourceMotionListener to remove + * @param dsml the {@code DragSourceMotionListener} to remove * * @see #addDragSourceMotionListener * @see #getDragSourceMotionListeners @@ -649,11 +649,11 @@ public class DragSource implements Serializable { } /** - * Gets all of the DragSourceMotionListeners - * registered with this DragSource. + * Gets all of the {@code DragSourceMotionListener}s + * registered with this {@code DragSource}. * - * @return all of this DragSource's - * DragSourceMotionListeners or an empty array if no + * @return all of this {@code DragSource}'s + * {@code DragSourceMotionListener}s or an empty array if no * such listeners are currently registered * * @see #addDragSourceMotionListener @@ -666,21 +666,21 @@ public class DragSource implements Serializable { /** * Gets all the objects currently registered as - * FooListeners upon this DragSource. + * FooListeners upon this {@code DragSource}. * FooListeners are registered using the * addFooListener method. * * @param the type of listener objects * @param listenerType the type of listeners requested; this parameter * should specify an interface that descends from - * java.util.EventListener + * {@code java.util.EventListener} * @return an array of all objects registered as * FooListeners on this - * DragSource, or an empty array if no such listeners + * {@code DragSource}, or an empty array if no such listeners * have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements - * java.util.EventListener + * {@code java.util.EventListener} * * @see #getDragSourceListeners * @see #getDragSourceMotionListeners @@ -697,12 +697,12 @@ public class DragSource implements Serializable { } /** - * This method calls dragEnter on the - * DragSourceListeners registered with this - * DragSource, and passes them the specified - * DragSourceDragEvent. + * This method calls {@code dragEnter} on the + * {@code DragSourceListener}s registered with this + * {@code DragSource}, and passes them the specified + * {@code DragSourceDragEvent}. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ void processDragEnter(DragSourceDragEvent dsde) { DragSourceListener dsl = listener; @@ -712,12 +712,12 @@ public class DragSource implements Serializable { } /** - * This method calls dragOver on the - * DragSourceListeners registered with this - * DragSource, and passes them the specified - * DragSourceDragEvent. + * This method calls {@code dragOver} on the + * {@code DragSourceListener}s registered with this + * {@code DragSource}, and passes them the specified + * {@code DragSourceDragEvent}. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ void processDragOver(DragSourceDragEvent dsde) { DragSourceListener dsl = listener; @@ -727,12 +727,12 @@ public class DragSource implements Serializable { } /** - * This method calls dropActionChanged on the - * DragSourceListeners registered with this - * DragSource, and passes them the specified - * DragSourceDragEvent. + * This method calls {@code dropActionChanged} on the + * {@code DragSourceListener}s registered with this + * {@code DragSource}, and passes them the specified + * {@code DragSourceDragEvent}. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ void processDropActionChanged(DragSourceDragEvent dsde) { DragSourceListener dsl = listener; @@ -742,12 +742,12 @@ public class DragSource implements Serializable { } /** - * This method calls dragExit on the - * DragSourceListeners registered with this - * DragSource, and passes them the specified - * DragSourceEvent. + * This method calls {@code dragExit} on the + * {@code DragSourceListener}s registered with this + * {@code DragSource}, and passes them the specified + * {@code DragSourceEvent}. * - * @param dse the DragSourceEvent + * @param dse the {@code DragSourceEvent} */ void processDragExit(DragSourceEvent dse) { DragSourceListener dsl = listener; @@ -757,12 +757,12 @@ public class DragSource implements Serializable { } /** - * This method calls dragDropEnd on the - * DragSourceListeners registered with this - * DragSource, and passes them the specified - * DragSourceDropEvent. + * This method calls {@code dragDropEnd} on the + * {@code DragSourceListener}s registered with this + * {@code DragSource}, and passes them the specified + * {@code DragSourceDropEvent}. * - * @param dsde the DragSourceEvent + * @param dsde the {@code DragSourceEvent} */ void processDragDropEnd(DragSourceDropEvent dsde) { DragSourceListener dsl = listener; @@ -772,12 +772,12 @@ public class DragSource implements Serializable { } /** - * This method calls dragMouseMoved on the - * DragSourceMotionListeners registered with this - * DragSource, and passes them the specified - * DragSourceDragEvent. + * This method calls {@code dragMouseMoved} on the + * {@code DragSourceMotionListener}s registered with this + * {@code DragSource}, and passes them the specified + * {@code DragSourceDragEvent}. * - * @param dsde the DragSourceEvent + * @param dsde the {@code DragSourceEvent} */ void processDragMouseMoved(DragSourceDragEvent dsde) { DragSourceMotionListener dsml = motionListener; @@ -787,33 +787,33 @@ public class DragSource implements Serializable { } /** - * Serializes this DragSource. This method first performs + * Serializes this {@code DragSource}. This method first performs * default serialization. Next, it writes out this object's - * FlavorMap if and only if it can be serialized. If not, - * null is written instead. Next, it writes out - * Serializable listeners registered with this - * object. Listeners are written in a null-terminated sequence - * of 0 or more pairs. The pair consists of a String and an - * Object; the String indicates the type of the - * Object and is one of the following: + * {@code FlavorMap} if and only if it can be serialized. If not, + * {@code null} is written instead. Next, it writes out + * {@code Serializable} listeners registered with this + * object. Listeners are written in a {@code null}-terminated sequence + * of 0 or more pairs. The pair consists of a {@code String} and an + * {@code Object}; the {@code String} indicates the type of the + * {@code Object} and is one of the following: *

            - *
          • dragSourceListenerK indicating a - * DragSourceListener object; - *
          • dragSourceMotionListenerK indicating a - * DragSourceMotionListener object. + *
          • {@code dragSourceListenerK} indicating a + * {@code DragSourceListener} object; + *
          • {@code dragSourceMotionListenerK} indicating a + * {@code DragSourceMotionListener} object. *
          * - * @serialData Either a FlavorMap instance, or - * null, followed by a null-terminated + * @serialData Either a {@code FlavorMap} instance, or + * {@code null}, followed by a {@code null}-terminated * sequence of 0 or more pairs; the pair consists of a - * String and an Object; the - * String indicates the type of the Object + * {@code String} and an {@code Object}; the + * {@code String} indicates the type of the {@code Object} * and is one of the following: *
            - *
          • dragSourceListenerK indicating a - * DragSourceListener object; - *
          • dragSourceMotionListenerK indicating a - * DragSourceMotionListener object. + *
          • {@code dragSourceListenerK} indicating a + * {@code DragSourceListener} object; + *
          • {@code dragSourceMotionListenerK} indicating a + * {@code DragSourceMotionListener} object. *
          . * @since 1.4 */ @@ -828,24 +828,24 @@ public class DragSource implements Serializable { } /** - * Deserializes this DragSource. This method first performs - * default deserialization. Next, this object's FlavorMap is + * Deserializes this {@code DragSource}. This method first performs + * default deserialization. Next, this object's {@code FlavorMap} is * deserialized by using the next object in the stream. - * If the resulting FlavorMap is null, this - * object's FlavorMap is set to the default FlavorMap for - * this thread's ClassLoader. + * If the resulting {@code FlavorMap} is {@code null}, this + * object's {@code FlavorMap} is set to the default FlavorMap for + * this thread's {@code ClassLoader}. * Next, this object's listeners are deserialized by reading a - * null-terminated sequence of 0 or more key/value pairs + * {@code null}-terminated sequence of 0 or more key/value pairs * from the stream: *
            - *
          • If a key object is a String equal to - * dragSourceListenerK, a DragSourceListener is + *
          • If a key object is a {@code String} equal to + * {@code dragSourceListenerK}, a {@code DragSourceListener} is * deserialized using the corresponding value object and added to this - * DragSource. - *
          • If a key object is a String equal to - * dragSourceMotionListenerK, a - * DragSourceMotionListener is deserialized using the - * corresponding value object and added to this DragSource. + * {@code DragSource}. + *
          • If a key object is a {@code String} equal to + * {@code dragSourceMotionListenerK}, a + * {@code DragSourceMotionListener} is deserialized using the + * corresponding value object and added to this {@code DragSource}. *
          • Otherwise, the key/value pair is skipped. *
          * @@ -884,13 +884,13 @@ public class DragSource implements Serializable { * Returns the drag gesture motion threshold. The drag gesture motion threshold * defines the recommended behavior for {@link MouseDragGestureRecognizer}s. *

          - * If the system property awt.dnd.drag.threshold is set to + * If the system property {@code awt.dnd.drag.threshold} is set to * a positive integer, this method returns the value of the system property; * otherwise if a pertinent desktop property is available and supported by * the implementation of the Java platform, this method returns the value of * that property; otherwise this method returns some default value. * The pertinent desktop property can be queried using - * java.awt.Toolkit.getDesktopProperty("DnD.gestureMotionThreshold"). + * {@code java.awt.Toolkit.getDesktopProperty("DnD.gestureMotionThreshold")}. * * @return the drag gesture motion threshold * @see MouseDragGestureRecognizer diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceAdapter.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceAdapter.java index 1d406819074..9470c5990bc 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceAdapter.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceAdapter.java @@ -30,22 +30,22 @@ package java.awt.dnd; * this class are empty. This class exists only as a convenience for creating * listener objects. *

          - * Extend this class to create a DragSourceEvent listener + * Extend this class to create a {@code DragSourceEvent} listener * and override the methods for the events of interest. (If you implement the - * DragSourceListener interface, you have to define all of + * {@code DragSourceListener} interface, you have to define all of * the methods in it. This abstract class defines null methods for them * all, so you only have to define methods for events you care about.) *

          * Create a listener object using the extended class and then register it with - * a DragSource. When the drag enters, moves over, or exits + * a {@code DragSource}. When the drag enters, moves over, or exits * a drop site, when the drop action changes, and when the drag ends, the * relevant method in the listener object is invoked, and the - * DragSourceEvent is passed to it. + * {@code DragSourceEvent} is passed to it. *

          - * The drop site is associated with the previous dragEnter() - * invocation if the latest invocation of dragEnter() on this + * The drop site is associated with the previous {@code dragEnter()} + * invocation if the latest invocation of {@code dragEnter()} on this * adapter corresponds to that drop site and is not followed by a - * dragExit() invocation on this adapter. + * {@code dragExit()} invocation on this adapter. * * @see DragSourceEvent * @see DragSourceListener @@ -67,7 +67,7 @@ public abstract class DragSourceAdapter *

        • The drop site accepts the drag. *
        * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dragEnter(DragSourceDragEvent dsde) {} @@ -82,14 +82,14 @@ public abstract class DragSourceAdapter *
      • The drop site accepts the drag. *
      * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dragOver(DragSourceDragEvent dsde) {} /** * Called whenever the mouse is moved during a drag operation. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dragMouseMoved(DragSourceDragEvent dsde) {} @@ -100,7 +100,7 @@ public abstract class DragSourceAdapter * Such devices are typically the mouse buttons or keyboard * modifiers that the user is interacting with. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dropActionChanged(DragSourceDragEvent dsde) {} @@ -122,21 +122,21 @@ public abstract class DragSourceAdapter * has rejected the drag. * * - * @param dse the DragSourceEvent + * @param dse the {@code DragSourceEvent} */ public void dragExit(DragSourceEvent dse) {} /** * This method is invoked to signify that the Drag and Drop * operation is complete. The getDropSuccess() method of - * the DragSourceDropEvent can be used to + * the {@code DragSourceDropEvent} can be used to * determine the termination state. The getDropAction() method * returns the operation that the drop site selected * to apply to the Drop operation. Once this method is complete, the - * current DragSourceContext and + * current {@code DragSourceContext} and * associated resources become invalid. * - * @param dsde the DragSourceDropEvent + * @param dsde the {@code DragSourceDropEvent} */ public void dragDropEnd(DragSourceDropEvent dsde) {} } diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceContext.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceContext.java index 7e0d0030175..7d858548ddb 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceContext.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceContext.java @@ -46,22 +46,22 @@ import sun.awt.AWTAccessor; import sun.awt.ComponentFactory; /** - * The DragSourceContext class is responsible for managing the + * The {@code DragSourceContext} class is responsible for managing the * initiator side of the Drag and Drop protocol. In particular, it is responsible * for managing drag event notifications to the * {@linkplain DragSourceListener DragSourceListeners} * and {@linkplain DragSourceMotionListener DragSourceMotionListeners}, and providing the * {@link Transferable} representing the source data for the drag operation. *

      - * Note that the DragSourceContext itself - * implements the DragSourceListener and - * DragSourceMotionListener interfaces. + * Note that the {@code DragSourceContext} itself + * implements the {@code DragSourceListener} and + * {@code DragSourceMotionListener} interfaces. * This is to allow the platform peer * (the {@link DragSourceContextPeer} instance) * created by the {@link DragSource} to notify - * the DragSourceContext of + * the {@code DragSourceContext} of * state changes in the ongoing operation. This allows the - * DragSourceContext object to interpose + * {@code DragSourceContext} object to interpose * itself between the platform and the * listeners provided by the initiator of the drag operation. *

      @@ -97,28 +97,28 @@ public class DragSourceContext // used by updateCurrentCursor /** - * An int used by updateCurrentCursor() - * indicating that the Cursor should change - * to the default (no drop) Cursor. + * An {@code int} used by updateCurrentCursor() + * indicating that the {@code Cursor} should change + * to the default (no drop) {@code Cursor}. */ protected static final int DEFAULT = 0; /** - * An int used by updateCurrentCursor() - * indicating that the Cursor - * has entered a DropTarget. + * An {@code int} used by updateCurrentCursor() + * indicating that the {@code Cursor} + * has entered a {@code DropTarget}. */ protected static final int ENTER = 1; /** - * An int used by updateCurrentCursor() - * indicating that the Cursor is - * over a DropTarget. + * An {@code int} used by updateCurrentCursor() + * indicating that the {@code Cursor} is + * over a {@code DropTarget}. */ protected static final int OVER = 2; /** - * An int used by updateCurrentCursor() + * An {@code int} used by updateCurrentCursor() * indicating that the user operation has changed. */ @@ -129,35 +129,35 @@ public class DragSourceContext } /** - * Called from DragSource, this constructor creates a new - * DragSourceContext given the - * DragSourceContextPeer for this Drag, the - * DragGestureEvent that triggered the Drag, the initial - * Cursor to use for the Drag, an (optional) - * Image to display while the Drag is taking place, the offset - * of the Image origin from the hotspot at the instant of the - * triggering event, the Transferable subject data, and the - * DragSourceListener to use during the Drag and Drop + * Called from {@code DragSource}, this constructor creates a new + * {@code DragSourceContext} given the + * {@code DragSourceContextPeer} for this Drag, the + * {@code DragGestureEvent} that triggered the Drag, the initial + * {@code Cursor} to use for the Drag, an (optional) + * {@code Image} to display while the Drag is taking place, the offset + * of the {@code Image} origin from the hotspot at the instant of the + * triggering event, the {@code Transferable} subject data, and the + * {@code DragSourceListener} to use during the Drag and Drop * operation. *
      - * If DragSourceContextPeer is null - * NullPointerException is thrown. + * If {@code DragSourceContextPeer} is {@code null} + * {@code NullPointerException} is thrown. *
      - * If DragGestureEvent is null - * NullPointerException is thrown. + * If {@code DragGestureEvent} is {@code null} + * {@code NullPointerException} is thrown. *
      - * If Cursor is null no exception is thrown and + * If {@code Cursor} is {@code null} no exception is thrown and * the default drag cursor behavior is activated for this drag operation. *
      - * If Image is null no exception is thrown. + * If {@code Image} is {@code null} no exception is thrown. *
      - * If Image is not null and the offset is - * null NullPointerException is thrown. + * If {@code Image} is not {@code null} and the offset is + * {@code null NullPointerException} is thrown. *
      - * If Transferable is null - * NullPointerException is thrown. + * If {@code Transferable} is {@code null} + * {@code NullPointerException} is thrown. *
      - * If DragSourceListener is null no exception + * If {@code DragSourceListener} is {@code null} no exception * is thrown. * * @param trigger the triggering event @@ -165,21 +165,21 @@ public class DragSourceContext * or {@code null} for the default cursor handling; * see class level documentation * for more details on the cursor handling mechanism during drag and drop - * @param dragImage the Image to drag (or null) + * @param dragImage the {@code Image} to drag (or {@code null}) * @param offset the offset of the image origin from the hotspot at the * instant of the triggering event - * @param t the Transferable - * @param dsl the DragSourceListener + * @param t the {@code Transferable} + * @param dsl the {@code DragSourceListener} * - * @throws IllegalArgumentException if the Component associated - * with the trigger event is null. - * @throws IllegalArgumentException if the DragSource for the - * trigger event is null. + * @throws IllegalArgumentException if the {@code Component} associated + * with the trigger event is {@code null}. + * @throws IllegalArgumentException if the {@code DragSource} for the + * trigger event is {@code null}. * @throws IllegalArgumentException if the drag action for the - * trigger event is DnDConstants.ACTION_NONE. + * trigger event is {@code DnDConstants.ACTION_NONE}. * @throws IllegalArgumentException if the source actions for the - * DragGestureRecognizer associated with the trigger - * event are equal to DnDConstants.ACTION_NONE. + * {@code DragGestureRecognizer} associated with the trigger + * event are equal to {@code DnDConstants.ACTION_NONE}. * @throws NullPointerException if dscp, trigger, or t are null, or * if dragImage is non-null and offset is null */ @@ -240,26 +240,26 @@ public class DragSourceContext } /** - * Returns the DragSource - * that instantiated this DragSourceContext. + * Returns the {@code DragSource} + * that instantiated this {@code DragSourceContext}. * - * @return the DragSource that - * instantiated this DragSourceContext + * @return the {@code DragSource} that + * instantiated this {@code DragSourceContext} */ public DragSource getDragSource() { return trigger.getDragSource(); } /** - * Returns the Component associated with this - * DragSourceContext. + * Returns the {@code Component} associated with this + * {@code DragSourceContext}. * - * @return the Component that started the drag + * @return the {@code Component} that started the drag */ public Component getComponent() { return trigger.getComponent(); } /** - * Returns the DragGestureEvent + * Returns the {@code DragGestureEvent} * that initially triggered the drag. * * @return the Event that triggered the drag @@ -268,9 +268,9 @@ public class DragSourceContext public DragGestureEvent getTrigger() { return trigger; } /** - * Returns a bitwise mask of DnDConstants that + * Returns a bitwise mask of {@code DnDConstants} that * represent the set of drop actions supported by the drag source for the - * drag operation associated with this DragSourceContext. + * drag operation associated with this {@code DragSourceContext}. * * @return the drop actions supported by the drag source */ @@ -280,8 +280,8 @@ public class DragSourceContext /** * Sets the cursor for this drag operation to the specified - * Cursor. If the specified Cursor - * is null, the default drag cursor behavior is + * {@code Cursor}. If the specified {@code Cursor} + * is {@code null}, the default drag cursor behavior is * activated for this drag operation, otherwise it is deactivated. * * @param c the initial {@code Cursor} for this drag operation, @@ -298,25 +298,25 @@ public class DragSourceContext } /** - * Returns the current drag Cursor. + * Returns the current drag {@code Cursor}. * - * @return the current drag Cursor + * @return the current drag {@code Cursor} */ public Cursor getCursor() { return cursor; } /** - * Add a DragSourceListener to this - * DragSourceContext if one has not already been added. - * If a DragSourceListener already exists, - * this method throws a TooManyListenersException. + * Add a {@code DragSourceListener} to this + * {@code DragSourceContext} if one has not already been added. + * If a {@code DragSourceListener} already exists, + * this method throws a {@code TooManyListenersException}. * - * @param dsl the DragSourceListener to add. - * Note that while null is not prohibited, + * @param dsl the {@code DragSourceListener} to add. + * Note that while {@code null} is not prohibited, * it is not acceptable as a parameter. * * @throws TooManyListenersException if - * a DragSourceListener has already been added + * a {@code DragSourceListener} has already been added */ public synchronized void addDragSourceListener(DragSourceListener dsl) throws TooManyListenersException { @@ -331,11 +331,11 @@ public class DragSourceContext } /** - * Removes the specified DragSourceListener - * from this DragSourceContext. + * Removes the specified {@code DragSourceListener} + * from this {@code DragSourceContext}. * - * @param dsl the DragSourceListener to remove; - * note that while null is not prohibited, + * @param dsl the {@code DragSourceListener} to remove; + * note that while {@code null} is not prohibited, * it is not acceptable as a parameter */ @@ -347,8 +347,8 @@ public class DragSourceContext } /** - * Notifies the peer that the Transferable's - * DataFlavors have changed. + * Notifies the peer that the {@code Transferable}'s + * {@code DataFlavor}s have changed. */ public void transferablesFlavorsChanged() { @@ -356,13 +356,13 @@ public class DragSourceContext } /** - * Calls dragEnter on the - * DragSourceListeners registered with this - * DragSourceContext and with the associated - * DragSource, and passes them the specified - * DragSourceDragEvent. + * Calls {@code dragEnter} on the + * {@code DragSourceListener}s registered with this + * {@code DragSourceContext} and with the associated + * {@code DragSource}, and passes them the specified + * {@code DragSourceDragEvent}. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dragEnter(DragSourceDragEvent dsde) { DragSourceListener dsl = listener; @@ -375,13 +375,13 @@ public class DragSourceContext } /** - * Calls dragOver on the - * DragSourceListeners registered with this - * DragSourceContext and with the associated - * DragSource, and passes them the specified - * DragSourceDragEvent. + * Calls {@code dragOver} on the + * {@code DragSourceListener}s registered with this + * {@code DragSourceContext} and with the associated + * {@code DragSource}, and passes them the specified + * {@code DragSourceDragEvent}. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dragOver(DragSourceDragEvent dsde) { DragSourceListener dsl = listener; @@ -394,13 +394,13 @@ public class DragSourceContext } /** - * Calls dragExit on the - * DragSourceListeners registered with this - * DragSourceContext and with the associated - * DragSource, and passes them the specified - * DragSourceEvent. + * Calls {@code dragExit} on the + * {@code DragSourceListener}s registered with this + * {@code DragSourceContext} and with the associated + * {@code DragSource}, and passes them the specified + * {@code DragSourceEvent}. * - * @param dse the DragSourceEvent + * @param dse the {@code DragSourceEvent} */ public void dragExit(DragSourceEvent dse) { DragSourceListener dsl = listener; @@ -413,13 +413,13 @@ public class DragSourceContext } /** - * Calls dropActionChanged on the - * DragSourceListeners registered with this - * DragSourceContext and with the associated - * DragSource, and passes them the specified - * DragSourceDragEvent. + * Calls {@code dropActionChanged} on the + * {@code DragSourceListener}s registered with this + * {@code DragSourceContext} and with the associated + * {@code DragSource}, and passes them the specified + * {@code DragSourceDragEvent}. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ public void dropActionChanged(DragSourceDragEvent dsde) { DragSourceListener dsl = listener; @@ -432,13 +432,13 @@ public class DragSourceContext } /** - * Calls dragDropEnd on the - * DragSourceListeners registered with this - * DragSourceContext and with the associated - * DragSource, and passes them the specified - * DragSourceDropEvent. + * Calls {@code dragDropEnd} on the + * {@code DragSourceListener}s registered with this + * {@code DragSourceContext} and with the associated + * {@code DragSource}, and passes them the specified + * {@code DragSourceDropEvent}. * - * @param dsde the DragSourceDropEvent + * @param dsde the {@code DragSourceDropEvent} */ public void dragDropEnd(DragSourceDropEvent dsde) { DragSourceListener dsl = listener; @@ -449,13 +449,13 @@ public class DragSourceContext } /** - * Calls dragMouseMoved on the - * DragSourceMotionListeners registered with the - * DragSource associated with this - * DragSourceContext, and them passes the specified - * DragSourceDragEvent. + * Calls {@code dragMouseMoved} on the + * {@code DragSourceMotionListener}s registered with the + * {@code DragSource} associated with this + * {@code DragSourceContext}, and them passes the specified + * {@code DragSourceDragEvent}. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} * @since 1.4 */ public void dragMouseMoved(DragSourceDragEvent dsde) { @@ -463,10 +463,10 @@ public class DragSourceContext } /** - * Returns the Transferable associated with - * this DragSourceContext. + * Returns the {@code Transferable} associated with + * this {@code DragSourceContext}. * - * @return the Transferable + * @return the {@code Transferable} */ public Transferable getTransferable() { return transferable; } @@ -478,9 +478,9 @@ public class DragSourceContext * * @param sourceAct the actions supported by the drag source * @param targetAct the drop target action - * @param status one of the fields DEFAULT, - * ENTER, OVER, - * CHANGED + * @param status one of the fields {@code DEFAULT}, + * {@code ENTER}, {@code OVER}, + * {@code CHANGED} */ @SuppressWarnings("fallthrough") protected synchronized void updateCurrentCursor(int sourceAct, int targetAct, int status) { @@ -532,21 +532,21 @@ public class DragSourceContext } /** - * Serializes this DragSourceContext. This method first + * Serializes this {@code DragSourceContext}. This method first * performs default serialization. Next, this object's - * Transferable is written out if and only if it can be - * serialized. If not, null is written instead. In this case, - * a DragSourceContext created from the resulting deserialized - * stream will contain a dummy Transferable which supports no - * DataFlavors. Finally, this object's - * DragSourceListener is written out if and only if it can be - * serialized. If not, null is written instead. + * {@code Transferable} is written out if and only if it can be + * serialized. If not, {@code null} is written instead. In this case, + * a {@code DragSourceContext} created from the resulting deserialized + * stream will contain a dummy {@code Transferable} which supports no + * {@code DataFlavor}s. Finally, this object's + * {@code DragSourceListener} is written out if and only if it can be + * serialized. If not, {@code null} is written instead. * * @serialData The default serializable fields, in alphabetical order, - * followed by either a Transferable instance, or - * null, followed by either a - * DragSourceListener instance, or - * null. + * followed by either a {@code Transferable} instance, or + * {@code null}, followed by either a + * {@code DragSourceListener} instance, or + * {@code null}. * @since 1.4 */ private void writeObject(ObjectOutputStream s) throws IOException { @@ -559,14 +559,14 @@ public class DragSourceContext } /** - * Deserializes this DragSourceContext. This method first - * performs default deserialization for all non-transient - * fields. This object's Transferable and - * DragSourceListener are then deserialized as well by using + * Deserializes this {@code DragSourceContext}. This method first + * performs default deserialization for all non-{@code transient} + * fields. This object's {@code Transferable} and + * {@code DragSourceListener} are then deserialized as well by using * the next two objects in the stream. If the resulting - * Transferable is null, this object's - * Transferable is set to a dummy Transferable - * which supports no DataFlavors. + * {@code Transferable} is {@code null}, this object's + * {@code Transferable} is set to a dummy {@code Transferable} + * which supports no {@code DataFlavor}s. * * @since 1.4 */ @@ -654,7 +654,7 @@ public class DragSourceContext private transient DragSourceListener listener; /** - * true if the custom drag cursor is used instead of the + * {@code true} if the custom drag cursor is used instead of the * default one. * * @serial @@ -662,9 +662,9 @@ public class DragSourceContext private boolean useCustomCursor; /** - * A bitwise mask of DnDConstants that represents the set of + * A bitwise mask of {@code DnDConstants} that represents the set of * drop actions supported by the drag source for the drag operation associated - * with this DragSourceContext. + * with this {@code DragSourceContext.} * * @serial */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceDragEvent.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceDragEvent.java index 63e60d92a20..b8d89d2b575 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceDragEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceDragEvent.java @@ -28,19 +28,19 @@ package java.awt.dnd; import java.awt.event.InputEvent; /** - * The DragSourceDragEvent is - * delivered from the DragSourceContextPeer, - * via the DragSourceContext, to the DragSourceListener - * registered with that DragSourceContext and with its associated - * DragSource. + * The {@code DragSourceDragEvent} is + * delivered from the {@code DragSourceContextPeer}, + * via the {@code DragSourceContext}, to the {@code DragSourceListener} + * registered with that {@code DragSourceContext} and with its associated + * {@code DragSource}. *

      - * The DragSourceDragEvent reports the target drop action + * The {@code DragSourceDragEvent} reports the target drop action * and the user drop action that reflect the current state of * the drag operation. *

      - * Target drop action is one of DnDConstants that represents + * Target drop action is one of {@code DnDConstants} that represents * the drop action selected by the current drop target if this drop action is - * supported by the drag source or DnDConstants.ACTION_NONE if this + * supported by the drag source or {@code DnDConstants.ACTION_NONE} if this * drop action is not supported by the drag source. *

      * User drop action depends on the drop actions supported by the drag @@ -52,18 +52,18 @@ import java.awt.event.InputEvent; * Shift -> ACTION_MOVE * * If the user selects a drop action, the user drop action is one of - * DnDConstants that represents the selected drop action if this + * {@code DnDConstants} that represents the selected drop action if this * drop action is supported by the drag source or - * DnDConstants.ACTION_NONE if this drop action is not supported + * {@code DnDConstants.ACTION_NONE} if this drop action is not supported * by the drag source. *

      * If the user doesn't select a drop action, the set of - * DnDConstants that represents the set of drop actions supported - * by the drag source is searched for DnDConstants.ACTION_MOVE, - * then for DnDConstants.ACTION_COPY, then for - * DnDConstants.ACTION_LINK and the user drop action is the + * {@code DnDConstants} that represents the set of drop actions supported + * by the drag source is searched for {@code DnDConstants.ACTION_MOVE}, + * then for {@code DnDConstants.ACTION_COPY}, then for + * {@code DnDConstants.ACTION_LINK} and the user drop action is the * first constant found. If no constant is found the user drop action - * is DnDConstants.ACTION_NONE. + * is {@code DnDConstants.ACTION_NONE}. * * @since 1.2 * @@ -74,25 +74,25 @@ public class DragSourceDragEvent extends DragSourceEvent { private static final long serialVersionUID = 481346297933902471L; /** - * Constructs a DragSourceDragEvent. + * Constructs a {@code DragSourceDragEvent}. * This class is typically - * instantiated by the DragSourceContextPeer + * instantiated by the {@code DragSourceContextPeer} * rather than directly * by client code. - * The coordinates for this DragSourceDragEvent - * are not specified, so getLocation will return - * null for this event. + * The coordinates for this {@code DragSourceDragEvent} + * are not specified, so {@code getLocation} will return + * {@code null} for this event. *

      - * The arguments dropAction and action should - * be one of DnDConstants that represents a single action. - * The argument modifiers should be either a bitwise mask - * of old java.awt.event.InputEvent.*_MASK constants or a - * bitwise mask of extended java.awt.event.InputEvent.*_DOWN_MASK + * The arguments {@code dropAction} and {@code action} should + * be one of {@code DnDConstants} that represents a single action. + * The argument {@code modifiers} should be either a bitwise mask + * of old {@code java.awt.event.InputEvent.*_MASK} constants or a + * bitwise mask of extended {@code java.awt.event.InputEvent.*_DOWN_MASK} * constants. - * This constructor does not throw any exception for invalid dropAction, - * action and modifiers. + * This constructor does not throw any exception for invalid {@code dropAction}, + * {@code action} and {@code modifiers}. * - * @param dsc the DragSourceContext that is to manage + * @param dsc the {@code DragSourceContext} that is to manage * notifications for this event. * @param dropAction the user drop action. * @param action the target drop action. @@ -103,7 +103,7 @@ public class DragSourceDragEvent extends DragSourceEvent { * in one event. Use of the extended modifiers is * preferred. * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if {@code dsc} is {@code null}. * * @see java.awt.event.InputEvent * @see DragSourceEvent#getLocation @@ -128,20 +128,20 @@ public class DragSourceDragEvent extends DragSourceEvent { } /** - * Constructs a DragSourceDragEvent given the specified - * DragSourceContext, user drop action, target drop action, + * Constructs a {@code DragSourceDragEvent} given the specified + * {@code DragSourceContext}, user drop action, target drop action, * modifiers and coordinates. *

      - * The arguments dropAction and action should - * be one of DnDConstants that represents a single action. - * The argument modifiers should be either a bitwise mask - * of old java.awt.event.InputEvent.*_MASK constants or a - * bitwise mask of extended java.awt.event.InputEvent.*_DOWN_MASK + * The arguments {@code dropAction} and {@code action} should + * be one of {@code DnDConstants} that represents a single action. + * The argument {@code modifiers} should be either a bitwise mask + * of old {@code java.awt.event.InputEvent.*_MASK} constants or a + * bitwise mask of extended {@code java.awt.event.InputEvent.*_DOWN_MASK} * constants. - * This constructor does not throw any exception for invalid dropAction, - * action and modifiers. + * This constructor does not throw any exception for invalid {@code dropAction}, + * {@code action} and {@code modifiers}. * - * @param dsc the DragSourceContext associated with this + * @param dsc the {@code DragSourceContext} associated with this * event. * @param dropAction the user drop action. * @param action the target drop action. @@ -154,7 +154,7 @@ public class DragSourceDragEvent extends DragSourceEvent { * @param x the horizontal coordinate for the cursor location * @param y the vertical coordinate for the cursor location * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if {@code dsc} is {@code null}. * * @see java.awt.event.InputEvent * @since 1.4 @@ -192,12 +192,12 @@ public class DragSourceDragEvent extends DragSourceEvent { ((InputEvent.ALT_GRAPH_DOWN_MASK << 1) - 1) & ~JDK_1_3_MODIFIERS; /** - * This method returns an int representing + * This method returns an {@code int} representing * the current state of the input device modifiers * associated with the user's gesture. Typically these * would be mouse buttons or keyboard modifiers. *

      - * If the modifiers passed to the constructor + * If the {@code modifiers} passed to the constructor * are invalid, this method returns them unchanged. * * @return the current state of the input device modifiers @@ -208,12 +208,12 @@ public class DragSourceDragEvent extends DragSourceEvent { } /** - * This method returns an int representing + * This method returns an {@code int} representing * the current state of the input device extended modifiers * associated with the user's gesture. * See {@link InputEvent#getModifiersEx} *

      - * If the modifiers passed to the constructor + * If the {@code modifiers} passed to the constructor * are invalid, this method returns them unchanged. * * @return the current state of the input device extended modifiers @@ -270,7 +270,7 @@ public class DragSourceDragEvent extends DragSourceEvent { private int gestureModifiers = 0; /** - * Indicates whether the gestureModifiers are invalid. + * Indicates whether the {@code gestureModifiers} are invalid. * * @serial */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceDropEvent.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceDropEvent.java index f31e3d233dc..84317613ddc 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceDropEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceDropEvent.java @@ -26,12 +26,12 @@ package java.awt.dnd; /** - * The DragSourceDropEvent is delivered - * from the DragSourceContextPeer, - * via the DragSourceContext, to the dragDropEnd - * method of DragSourceListeners registered with that - * DragSourceContext and with its associated - * DragSource. + * The {@code DragSourceDropEvent} is delivered + * from the {@code DragSourceContextPeer}, + * via the {@code DragSourceContext}, to the {@code dragDropEnd} + * method of {@code DragSourceListener}s registered with that + * {@code DragSourceContext} and with its associated + * {@code DragSource}. * It contains sufficient information for the * originator of the operation * to provide appropriate feedback to the end user @@ -45,24 +45,24 @@ public class DragSourceDropEvent extends DragSourceEvent { private static final long serialVersionUID = -5571321229470821891L; /** - * Construct a DragSourceDropEvent for a drop, + * Construct a {@code DragSourceDropEvent} for a drop, * given the - * DragSourceContext, the drop action, - * and a boolean indicating if the drop was successful. - * The coordinates for this DragSourceDropEvent - * are not specified, so getLocation will return - * null for this event. + * {@code DragSourceContext}, the drop action, + * and a {@code boolean} indicating if the drop was successful. + * The coordinates for this {@code DragSourceDropEvent} + * are not specified, so {@code getLocation} will return + * {@code null} for this event. *

      - * The argument action should be one of DnDConstants + * The argument {@code action} should be one of {@code DnDConstants} * that represents a single action. - * This constructor does not throw any exception for invalid action. + * This constructor does not throw any exception for invalid {@code action}. * - * @param dsc the DragSourceContext - * associated with this DragSourceDropEvent + * @param dsc the {@code DragSourceContext} + * associated with this {@code DragSourceDropEvent} * @param action the drop action * @param success a boolean indicating if the drop was successful * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if {@code dsc} is {@code null}. * * @see DragSourceEvent#getLocation */ @@ -75,22 +75,22 @@ public class DragSourceDropEvent extends DragSourceEvent { } /** - * Construct a DragSourceDropEvent for a drop, given the - * DragSourceContext, the drop action, a boolean + * Construct a {@code DragSourceDropEvent} for a drop, given the + * {@code DragSourceContext}, the drop action, a {@code boolean} * indicating if the drop was successful, and coordinates. *

      - * The argument action should be one of DnDConstants + * The argument {@code action} should be one of {@code DnDConstants} * that represents a single action. - * This constructor does not throw any exception for invalid action. + * This constructor does not throw any exception for invalid {@code action}. * - * @param dsc the DragSourceContext - * associated with this DragSourceDropEvent + * @param dsc the {@code DragSourceContext} + * associated with this {@code DragSourceDropEvent} * @param action the drop action * @param success a boolean indicating if the drop was successful * @param x the horizontal coordinate for the cursor location * @param y the vertical coordinate for the cursor location * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if {@code dsc} is {@code null}. * * @since 1.4 */ @@ -103,15 +103,15 @@ public class DragSourceDropEvent extends DragSourceEvent { } /** - * Construct a DragSourceDropEvent + * Construct a {@code DragSourceDropEvent} * for a drag that does not result in a drop. - * The coordinates for this DragSourceDropEvent - * are not specified, so getLocation will return - * null for this event. + * The coordinates for this {@code DragSourceDropEvent} + * are not specified, so {@code getLocation} will return + * {@code null} for this event. * - * @param dsc the DragSourceContext + * @param dsc the {@code DragSourceContext} * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if {@code dsc} is {@code null}. * * @see DragSourceEvent#getLocation */ @@ -123,12 +123,12 @@ public class DragSourceDropEvent extends DragSourceEvent { } /** - * This method returns a boolean indicating + * This method returns a {@code boolean} indicating * if the drop was successful. * - * @return true if the drop target accepted the drop and + * @return {@code true} if the drop target accepted the drop and * successfully performed a drop action; - * false if the drop target rejected the drop or + * {@code false} if the drop target rejected the drop or * if the drop target accepted the drop, but failed to perform * a drop action. */ @@ -136,13 +136,13 @@ public class DragSourceDropEvent extends DragSourceEvent { public boolean getDropSuccess() { return dropSuccess; } /** - * This method returns an int representing + * This method returns an {@code int} representing * the action performed by the target on the subject of the drop. * * @return the action performed by the target on the subject of the drop * if the drop target accepted the drop and the target drop action * is supported by the drag source; otherwise, - * DnDConstants.ACTION_NONE. + * {@code DnDConstants.ACTION_NONE}. */ public int getDropAction() { return dropAction; } @@ -152,7 +152,7 @@ public class DragSourceDropEvent extends DragSourceEvent { */ /** - * true if the drop was successful. + * {@code true} if the drop was successful. * * @serial */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceEvent.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceEvent.java index b9f55e15170..5a389b0dd08 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceEvent.java @@ -31,23 +31,23 @@ import java.util.EventObject; /** * This class is the base class for - * DragSourceDragEvent and - * DragSourceDropEvent. + * {@code DragSourceDragEvent} and + * {@code DragSourceDropEvent}. *

      - * DragSourceEvents are generated whenever the drag enters, moves + * {@code DragSourceEvent}s are generated whenever the drag enters, moves * over, or exits a drop site, when the drop action changes, and when the drag - * ends. The location for the generated DragSourceEvent specifies + * ends. The location for the generated {@code DragSourceEvent} specifies * the mouse cursor location in screen coordinates at the moment this event * occurred. *

      * In a multi-screen environment without a virtual device, the cursor location is * specified in the coordinate system of the initiator - * GraphicsConfiguration. The initiator - * GraphicsConfiguration is the GraphicsConfiguration - * of the Component on which the drag gesture for the current drag + * {@code GraphicsConfiguration}. The initiator + * {@code GraphicsConfiguration} is the {@code GraphicsConfiguration} + * of the {@code Component} on which the drag gesture for the current drag * operation was recognized. If the cursor location is outside the bounds of - * the initiator GraphicsConfiguration, the reported coordinates are - * clipped to fit within the bounds of that GraphicsConfiguration. + * the initiator {@code GraphicsConfiguration}, the reported coordinates are + * clipped to fit within the bounds of that {@code GraphicsConfiguration}. *

      * In a multi-screen environment with a virtual device, the location is specified * in the corresponding virtual coordinate system. If the cursor location is @@ -62,7 +62,7 @@ public class DragSourceEvent extends EventObject { private static final long serialVersionUID = -763287114604032641L; /** - * The boolean indicating whether the cursor location + * The {@code boolean} indicating whether the cursor location * is specified for this event. * * @serial @@ -88,15 +88,15 @@ public class DragSourceEvent extends EventObject { private final int y; /** - * Construct a DragSourceEvent - * given a specified DragSourceContext. - * The coordinates for this DragSourceEvent - * are not specified, so getLocation will return - * null for this event. + * Construct a {@code DragSourceEvent} + * given a specified {@code DragSourceContext}. + * The coordinates for this {@code DragSourceEvent} + * are not specified, so {@code getLocation} will return + * {@code null} for this event. * - * @param dsc the DragSourceContext + * @param dsc the {@code DragSourceContext} * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if {@code dsc} is {@code null}. * * @see #getLocation */ @@ -109,15 +109,15 @@ public class DragSourceEvent extends EventObject { } /** - * Construct a DragSourceEvent given a specified - * DragSourceContext, and coordinates of the cursor + * Construct a {@code DragSourceEvent} given a specified + * {@code DragSourceContext}, and coordinates of the cursor * location. * - * @param dsc the DragSourceContext + * @param dsc the {@code DragSourceContext} * @param x the horizontal coordinate for the cursor location * @param y the vertical coordinate for the cursor location * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if {@code dsc} is {@code null}. * * @since 1.4 */ @@ -129,10 +129,10 @@ public class DragSourceEvent extends EventObject { } /** - * This method returns the DragSourceContext that + * This method returns the {@code DragSourceContext} that * originated the event. * - * @return the DragSourceContext that originated the event + * @return the {@code DragSourceContext} that originated the event */ public DragSourceContext getDragSourceContext() { @@ -140,13 +140,13 @@ public class DragSourceEvent extends EventObject { } /** - * This method returns a Point indicating the cursor + * This method returns a {@code Point} indicating the cursor * location in screen coordinates at the moment this event occurred, or - * null if the cursor location is not specified for this + * {@code null} if the cursor location is not specified for this * event. * - * @return the Point indicating the cursor location - * or null if the cursor location is not specified + * @return the {@code Point} indicating the cursor location + * or {@code null} if the cursor location is not specified * @since 1.4 */ public Point getLocation() { diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceListener.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceListener.java index e568b6a5ad7..dc3122f1607 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceListener.java @@ -28,19 +28,19 @@ package java.awt.dnd; import java.util.EventListener; /** - * The DragSourceListener defines the + * The {@code DragSourceListener} defines the * event interface for originators of * Drag and Drop operations to track the state of the user's gesture, and to * provide appropriate "drag over" * feedback to the user throughout the * Drag and Drop operation. *

      - * The drop site is associated with the previous dragEnter() - * invocation if the latest invocation of dragEnter() on this + * The drop site is associated with the previous {@code dragEnter()} + * invocation if the latest invocation of {@code dragEnter()} on this * listener: *

        *
      • corresponds to that drop site and - *
      • is not followed by a dragExit() invocation on this listener. + *
      • is not followed by a {@code dragExit()} invocation on this listener. *
      * * @since 1.2 @@ -58,7 +58,7 @@ public interface DragSourceListener extends EventListener { *
    3. The drop site accepts the drag. * * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ void dragEnter(DragSourceDragEvent dsde); @@ -73,7 +73,7 @@ public interface DragSourceListener extends EventListener { *
    4. The drop site accepts the drag. * * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ void dragOver(DragSourceDragEvent dsde); @@ -84,7 +84,7 @@ public interface DragSourceListener extends EventListener { * Such devices are typically the mouse buttons or keyboard * modifiers that the user is interacting with. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ void dropActionChanged(DragSourceDragEvent dsde); @@ -106,21 +106,21 @@ public interface DragSourceListener extends EventListener { * has rejected the drag. * * - * @param dse the DragSourceEvent + * @param dse the {@code DragSourceEvent} */ void dragExit(DragSourceEvent dse); /** * This method is invoked to signify that the Drag and Drop * operation is complete. The getDropSuccess() method of - * the DragSourceDropEvent can be used to + * the {@code DragSourceDropEvent} can be used to * determine the termination state. The getDropAction() method * returns the operation that the drop site selected * to apply to the Drop operation. Once this method is complete, the - * current DragSourceContext and + * current {@code DragSourceContext} and * associated resources become invalid. * - * @param dsde the DragSourceDropEvent + * @param dsde the {@code DragSourceDropEvent} */ void dragDropEnd(DragSourceDropEvent dsde); } diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceMotionListener.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceMotionListener.java index 92bf6e12807..95bde275d2a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceMotionListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DragSourceMotionListener.java @@ -33,14 +33,14 @@ import java.util.EventListener; *

      * The class that is interested in processing mouse motion events during * a drag operation either implements this interface or extends the abstract - * DragSourceAdapter class (overriding only the methods of + * {@code DragSourceAdapter} class (overriding only the methods of * interest). *

      * Create a listener object using that class and then register it with - * a DragSource. Whenever the mouse moves during a drag - * operation initiated with this DragSource, that object's - * dragMouseMoved method is invoked, and the - * DragSourceDragEvent is passed to it. + * a {@code DragSource}. Whenever the mouse moves during a drag + * operation initiated with this {@code DragSource}, that object's + * {@code dragMouseMoved} method is invoked, and the + * {@code DragSourceDragEvent} is passed to it. * * @see DragSourceDragEvent * @see DragSource @@ -55,7 +55,7 @@ public interface DragSourceMotionListener extends EventListener { /** * Called whenever the mouse is moved during a drag operation. * - * @param dsde the DragSourceDragEvent + * @param dsde the {@code DragSourceDragEvent} */ void dragMouseMoved(DragSourceDragEvent dsde); } diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java index 6fbb8cad8b4..bd8e54e1f34 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java @@ -54,15 +54,15 @@ import sun.awt.AWTAccessor.ComponentAccessor; /** - * The DropTarget is associated - * with a Component when that Component + * The {@code DropTarget} is associated + * with a {@code Component} when that {@code Component} * wishes * to accept drops during Drag and Drop operations. *

      * Each - * DropTarget is associated with a FlavorMap. - * The default FlavorMap hereafter designates the - * FlavorMap returned by SystemFlavorMap.getDefaultFlavorMap(). + * {@code DropTarget} is associated with a {@code FlavorMap}. + * The default {@code FlavorMap} hereafter designates the + * {@code FlavorMap} returned by {@code SystemFlavorMap.getDefaultFlavorMap()}. * * @since 1.2 */ @@ -72,20 +72,20 @@ public class DropTarget implements DropTargetListener, Serializable { private static final long serialVersionUID = -6283860791671019047L; /** - * Creates a new DropTarget given the Component - * to associate itself with, an int representing + * Creates a new DropTarget given the {@code Component} + * to associate itself with, an {@code int} representing * the default acceptable action(s) to - * support, a DropTargetListener - * to handle event processing, a boolean indicating - * if the DropTarget is currently accepting drops, and - * a FlavorMap to use (or null for the default FlavorMap). + * support, a {@code DropTargetListener} + * to handle event processing, a {@code boolean} indicating + * if the {@code DropTarget} is currently accepting drops, and + * a {@code FlavorMap} to use (or null for the default {@code FlavorMap}). *

      * The Component will receive drops only if it is enabled. - * @param c The Component with which this DropTarget is associated - * @param ops The default acceptable actions for this DropTarget - * @param dtl The DropTargetListener for this DropTarget - * @param act Is the DropTarget accepting drops. - * @param fm The FlavorMap to use, or null for the default FlavorMap + * @param c The {@code Component} with which this {@code DropTarget} is associated + * @param ops The default acceptable actions for this {@code DropTarget} + * @param dtl The {@code DropTargetListener} for this {@code DropTarget} + * @param act Is the {@code DropTarget} accepting drops. + * @param fm The {@code FlavorMap} to use, or null for the default {@code FlavorMap} * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -121,18 +121,18 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Creates a DropTarget given the Component - * to associate itself with, an int representing + * Creates a {@code DropTarget} given the {@code Component} + * to associate itself with, an {@code int} representing * the default acceptable action(s) - * to support, a DropTargetListener - * to handle event processing, and a boolean indicating - * if the DropTarget is currently accepting drops. + * to support, a {@code DropTargetListener} + * to handle event processing, and a {@code boolean} indicating + * if the {@code DropTarget} is currently accepting drops. *

      * The Component will receive drops only if it is enabled. - * @param c The Component with which this DropTarget is associated - * @param ops The default acceptable actions for this DropTarget - * @param dtl The DropTargetListener for this DropTarget - * @param act Is the DropTarget accepting drops. + * @param c The {@code Component} with which this {@code DropTarget} is associated + * @param ops The default acceptable actions for this {@code DropTarget} + * @param dtl The {@code DropTargetListener} for this {@code DropTarget} + * @param act Is the {@code DropTarget} accepting drops. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -145,7 +145,7 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Creates a DropTarget. + * Creates a {@code DropTarget}. * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -155,13 +155,13 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Creates a DropTarget given the Component - * to associate itself with, and the DropTargetListener + * Creates a {@code DropTarget} given the {@code Component} + * to associate itself with, and the {@code DropTargetListener} * to handle event processing. *

      * The Component will receive drops only if it is enabled. - * @param c The Component with which this DropTarget is associated - * @param dtl The DropTargetListener for this DropTarget + * @param c The {@code Component} with which this {@code DropTarget} is associated + * @param dtl The {@code DropTargetListener} for this {@code DropTarget} * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -173,15 +173,15 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Creates a DropTarget given the Component - * to associate itself with, an int representing + * Creates a {@code DropTarget} given the {@code Component} + * to associate itself with, an {@code int} representing * the default acceptable action(s) to support, and a - * DropTargetListener to handle event processing. + * {@code DropTargetListener} to handle event processing. *

      * The Component will receive drops only if it is enabled. - * @param c The Component with which this DropTarget is associated - * @param ops The default acceptable actions for this DropTarget - * @param dtl The DropTargetListener for this DropTarget + * @param c The {@code Component} with which this {@code DropTarget} is associated + * @param ops The default acceptable actions for this {@code DropTarget} + * @param dtl The {@code DropTargetListener} for this {@code DropTarget} * @exception HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -195,11 +195,11 @@ public class DropTarget implements DropTargetListener, Serializable { /** * Note: this interface is required to permit the safe association * of a DropTarget with a Component in one of two ways, either: - * component.setDropTarget(droptarget); - * or droptarget.setComponent(component); + * {@code component.setDropTarget(droptarget);} + * or {@code droptarget.setComponent(component);} *

      * The Component will receive drops only if it is enabled. - * @param c The new Component this DropTarget + * @param c The new {@code Component} this {@code DropTarget} * is to be associated with. */ @@ -229,10 +229,10 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Gets the Component associated - * with this DropTarget. + * Gets the {@code Component} associated + * with this {@code DropTarget}. * - * @return the current Component + * @return the current {@code Component} */ public synchronized Component getComponent() { @@ -240,7 +240,7 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Sets the default acceptable actions for this DropTarget + * Sets the default acceptable actions for this {@code DropTarget} * * @param ops the default actions * @see java.awt.dnd.DnDConstants @@ -259,8 +259,8 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Gets an int representing the - * current action(s) supported by this DropTarget. + * Gets an {@code int} representing the + * current action(s) supported by this {@code DropTarget}. * * @return the current default actions */ @@ -270,10 +270,10 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Sets the DropTarget active if true, - * inactive if false. + * Sets the DropTarget active if {@code true}, + * inactive if {@code false}. * - * @param isActive sets the DropTarget (in)active. + * @param isActive sets the {@code DropTarget} (in)active. */ public synchronized void setActive(boolean isActive) { @@ -286,10 +286,10 @@ public class DropTarget implements DropTargetListener, Serializable { /** * Reports whether or not - * this DropTarget + * this {@code DropTarget} * is currently active (ready to accept drops). * - * @return true if active, false if not + * @return {@code true} if active, {@code false} if not */ public boolean isActive() { @@ -297,13 +297,13 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Adds a new DropTargetListener (UNICAST SOURCE). + * Adds a new {@code DropTargetListener} (UNICAST SOURCE). * - * @param dtl The new DropTargetListener + * @param dtl The new {@code DropTargetListener} * * @throws TooManyListenersException if a - * DropTargetListener is already added to this - * DropTarget. + * {@code DropTargetListener} is already added to this + * {@code DropTarget}. */ public synchronized void addDropTargetListener(DropTargetListener dtl) throws TooManyListenersException { @@ -318,7 +318,7 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Removes the current DropTargetListener (UNICAST SOURCE). + * Removes the current {@code DropTargetListener} (UNICAST SOURCE). * * @param dtl the DropTargetListener to deregister. */ @@ -333,16 +333,16 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Calls dragEnter on the registered - * DropTargetListener and passes it - * the specified DropTargetDragEvent. - * Has no effect if this DropTarget + * Calls {@code dragEnter} on the registered + * {@code DropTargetListener} and passes it + * the specified {@code DropTargetDragEvent}. + * Has no effect if this {@code DropTarget} * is not active. * - * @param dtde the DropTargetDragEvent + * @param dtde the {@code DropTargetDragEvent} * - * @throws NullPointerException if this DropTarget - * is active and dtde is null + * @throws NullPointerException if this {@code DropTarget} + * is active and {@code dtde} is {@code null} * * @see #isActive */ @@ -360,16 +360,16 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Calls dragOver on the registered - * DropTargetListener and passes it - * the specified DropTargetDragEvent. - * Has no effect if this DropTarget + * Calls {@code dragOver} on the registered + * {@code DropTargetListener} and passes it + * the specified {@code DropTargetDragEvent}. + * Has no effect if this {@code DropTarget} * is not active. * - * @param dtde the DropTargetDragEvent + * @param dtde the {@code DropTargetDragEvent} * - * @throws NullPointerException if this DropTarget - * is active and dtde is null + * @throws NullPointerException if this {@code DropTarget} + * is active and {@code dtde} is {@code null} * * @see #isActive */ @@ -382,16 +382,16 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Calls dropActionChanged on the registered - * DropTargetListener and passes it - * the specified DropTargetDragEvent. - * Has no effect if this DropTarget + * Calls {@code dropActionChanged} on the registered + * {@code DropTargetListener} and passes it + * the specified {@code DropTargetDragEvent}. + * Has no effect if this {@code DropTarget} * is not active. * - * @param dtde the DropTargetDragEvent + * @param dtde the {@code DropTargetDragEvent} * - * @throws NullPointerException if this DropTarget - * is active and dtde is null + * @throws NullPointerException if this {@code DropTarget} + * is active and {@code dtde} is {@code null} * * @see #isActive */ @@ -404,17 +404,17 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Calls dragExit on the registered - * DropTargetListener and passes it - * the specified DropTargetEvent. - * Has no effect if this DropTarget + * Calls {@code dragExit} on the registered + * {@code DropTargetListener} and passes it + * the specified {@code DropTargetEvent}. + * Has no effect if this {@code DropTarget} * is not active. *

      * This method itself does not throw any exception * for null parameter but for exceptions thrown by * the respective method of the listener. * - * @param dte the DropTargetEvent + * @param dte the {@code DropTargetEvent} * * @see #isActive */ @@ -429,17 +429,17 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Calls drop on the registered - * DropTargetListener and passes it - * the specified DropTargetDropEvent - * if this DropTarget is active. + * Calls {@code drop} on the registered + * {@code DropTargetListener} and passes it + * the specified {@code DropTargetDropEvent} + * if this {@code DropTarget} is active. * - * @param dtde the DropTargetDropEvent + * @param dtde the {@code DropTargetDropEvent} * - * @throws NullPointerException if dtde is null + * @throws NullPointerException if {@code dtde} is null * and at least one of the following is true: this - * DropTarget is not active, or there is - * no a DropTargetListener registered. + * {@code DropTarget} is not active, or there is + * no a {@code DropTargetListener} registered. * * @see #isActive */ @@ -456,11 +456,11 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Gets the FlavorMap - * associated with this DropTarget. - * If no FlavorMap has been set for this - * DropTarget, it is associated with the default - * FlavorMap. + * Gets the {@code FlavorMap} + * associated with this {@code DropTarget}. + * If no {@code FlavorMap} has been set for this + * {@code DropTarget}, it is associated with the default + * {@code FlavorMap}. * * @return the FlavorMap for this DropTarget */ @@ -468,10 +468,10 @@ public class DropTarget implements DropTargetListener, Serializable { public FlavorMap getFlavorMap() { return flavorMap; } /** - * Sets the FlavorMap associated - * with this DropTarget. + * Sets the {@code FlavorMap} associated + * with this {@code DropTarget}. * - * @param fm the new FlavorMap, or null to + * @param fm the new {@code FlavorMap}, or null to * associate the default FlavorMap with this DropTarget. */ @@ -544,10 +544,10 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Gets the DropTargetContext associated - * with this DropTarget. + * Gets the {@code DropTargetContext} associated + * with this {@code DropTarget}. * - * @return the DropTargetContext associated with this DropTarget. + * @return the {@code DropTargetContext} associated with this {@code DropTarget}. */ public DropTargetContext getDropTargetContext() { @@ -571,14 +571,14 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Serializes this DropTarget. Performs default serialization, - * and then writes out this object's DropTargetListener if and - * only if it can be serialized. If not, null is written + * Serializes this {@code DropTarget}. Performs default serialization, + * and then writes out this object's {@code DropTargetListener} if and + * only if it can be serialized. If not, {@code null} is written * instead. * * @serialData The default serializable fields, in alphabetical order, - * followed by either a DropTargetListener - * instance, or null. + * followed by either a {@code DropTargetListener} + * instance, or {@code null}. * @since 1.4 */ private void writeObject(ObjectOutputStream s) throws IOException { @@ -589,13 +589,13 @@ public class DropTarget implements DropTargetListener, Serializable { } /** - * Deserializes this DropTarget. This method first performs - * default deserialization for all non-transient fields. An + * Deserializes this {@code DropTarget}. This method first performs + * default deserialization for all non-{@code transient} fields. An * attempt is then made to deserialize this object's - * DropTargetListener as well. This is first attempted by - * deserializing the field dtListener, because, in releases - * prior to 1.4, a non-transient field of this name stored the - * DropTargetListener. If this fails, the next object in the + * {@code DropTargetListener} as well. This is first attempted by + * deserializing the field {@code dtListener}, because, in releases + * prior to 1.4, a non-{@code transient} field of this name stored the + * {@code DropTargetListener}. If this fails, the next object in the * stream is used instead. * * @since 1.4 @@ -639,8 +639,8 @@ public class DropTarget implements DropTargetListener, Serializable { /** * construct a DropTargetAutoScroller * - * @param c the Component - * @param p the Point + * @param c the {@code Component} + * @param p the {@code Point} */ protected DropTargetAutoScroller(Component c, Point p) { @@ -709,7 +709,7 @@ public class DropTarget implements DropTargetListener, Serializable { /** * cause autoscroll to occur * - * @param newLocn the Point + * @param newLocn the {@code Point} */ protected synchronized void updateLocation(Point newLocn) { @@ -733,7 +733,7 @@ public class DropTarget implements DropTargetListener, Serializable { /** * cause autoscroll to occur * - * @param e the ActionEvent + * @param e the {@code ActionEvent} */ public synchronized void actionPerformed(ActionEvent e) { @@ -766,8 +766,8 @@ public class DropTarget implements DropTargetListener, Serializable { /** * create an embedded autoscroller * - * @param c the Component - * @param p the Point + * @param c the {@code Component} + * @param p the {@code Point} * @return an embedded autoscroller */ @@ -778,7 +778,7 @@ public class DropTarget implements DropTargetListener, Serializable { /** * initialize autoscrolling * - * @param p the Point + * @param p the {@code Point} */ protected void initializeAutoscrolling(Point p) { @@ -790,7 +790,7 @@ public class DropTarget implements DropTargetListener, Serializable { /** * update autoscrolling with current cursor location * - * @param dragCursorLocn the Point + * @param dragCursorLocn the {@code Point} */ protected void updateAutoscroll(Point dragCursorLocn) { @@ -843,7 +843,7 @@ public class DropTarget implements DropTargetListener, Serializable { int actions = DnDConstants.ACTION_COPY_OR_MOVE; /** - * true if the DropTarget is accepting Drag & Drop operations. + * {@code true} if the DropTarget is accepting Drag & Drop operations. * * @serial */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetAdapter.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetAdapter.java index 2da3bf7eae2..f019ae108a5 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetAdapter.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetAdapter.java @@ -30,39 +30,39 @@ package java.awt.dnd; * this class are empty. This class exists only as a convenience for creating * listener objects. *

      - * Extend this class to create a DropTargetEvent listener + * Extend this class to create a {@code DropTargetEvent} listener * and override the methods for the events of interest. (If you implement the - * DropTargetListener interface, you have to define all of + * {@code DropTargetListener} interface, you have to define all of * the methods in it. This abstract class defines a null implementation for - * every method except drop(DropTargetDropEvent), so you only have + * every method except {@code drop(DropTargetDropEvent)}, so you only have * to define methods for events you care about.) You must provide an - * implementation for at least drop(DropTargetDropEvent). This + * implementation for at least {@code drop(DropTargetDropEvent)}. This * method cannot have a null implementation because its specification requires * that you either accept or reject the drop, and, if accepted, indicate * whether the drop was successful. *

      * Create a listener object using the extended class and then register it with - * a DropTarget. When the drag enters, moves over, or exits - * the operable part of the drop site for that DropTarget, when + * a {@code DropTarget}. When the drag enters, moves over, or exits + * the operable part of the drop site for that {@code DropTarget}, when * the drop action changes, and when the drop occurs, the relevant method in - * the listener object is invoked, and the DropTargetEvent is + * the listener object is invoked, and the {@code DropTargetEvent} is * passed to it. *

      - * The operable part of the drop site for the DropTarget is - * the part of the associated Component's geometry that is not + * The operable part of the drop site for the {@code DropTarget} is + * the part of the associated {@code Component}'s geometry that is not * obscured by an overlapping top-level window or by another - * Component higher in the Z-order that has an associated active - * DropTarget. + * {@code Component} higher in the Z-order that has an associated active + * {@code DropTarget}. *

      * During the drag, the data associated with the current drag operation can be - * retrieved by calling getTransferable() on - * DropTargetDragEvent instances passed to the listener's + * retrieved by calling {@code getTransferable()} on + * {@code DropTargetDragEvent} instances passed to the listener's * methods. *

      - * Note that getTransferable() on the - * DropTargetDragEvent instance should only be called within the + * Note that {@code getTransferable()} on the + * {@code DropTargetDragEvent} instance should only be called within the * respective listener's method and all the necessary data should be retrieved - * from the returned Transferable before that method returns. + * from the returned {@code Transferable} before that method returns. * * @see DropTargetEvent * @see DropTargetListener @@ -74,19 +74,19 @@ public abstract class DropTargetAdapter implements DropTargetListener { /** * Called while a drag operation is ongoing, when the mouse pointer enters - * the operable part of the drop site for the DropTarget + * the operable part of the drop site for the {@code DropTarget} * registered with this listener. * - * @param dtde the DropTargetDragEvent + * @param dtde the {@code DropTargetDragEvent} */ public void dragEnter(DropTargetDragEvent dtde) {} /** * Called when a drag operation is ongoing, while the mouse pointer is still - * over the operable part of the drop site for the DropTarget + * over the operable part of the drop site for the {@code DropTarget} * registered with this listener. * - * @param dtde the DropTargetDragEvent + * @param dtde the {@code DropTargetDragEvent} */ public void dragOver(DropTargetDragEvent dtde) {} @@ -94,16 +94,16 @@ public abstract class DropTargetAdapter implements DropTargetListener { * Called if the user has modified * the current drop gesture. * - * @param dtde the DropTargetDragEvent + * @param dtde the {@code DropTargetDragEvent} */ public void dropActionChanged(DropTargetDragEvent dtde) {} /** * Called while a drag operation is ongoing, when the mouse pointer has * exited the operable part of the drop site for the - * DropTarget registered with this listener. + * {@code DropTarget} registered with this listener. * - * @param dte the DropTargetEvent + * @param dte the {@code DropTargetEvent} */ public void dragExit(DropTargetEvent dte) {} } diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetDragEvent.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetDragEvent.java index 00639cf9043..9a6b57d450b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetDragEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetDragEvent.java @@ -33,15 +33,15 @@ import java.awt.datatransfer.Transferable; import java.util.List; /** - * The DropTargetDragEvent is delivered to a - * DropTargetListener via its + * The {@code DropTargetDragEvent} is delivered to a + * {@code DropTargetListener} via its * dragEnter() and dragOver() methods. *

      - * The DropTargetDragEvent reports the source drop actions + * The {@code DropTargetDragEvent} reports the source drop actions * and the user drop action that reflect the current state of * the drag operation. *

      - * Source drop actions is a bitwise mask of DnDConstants + * Source drop actions is a bitwise mask of {@code DnDConstants} * that represents the set of drop actions supported by the drag source for * this drag operation. *

      @@ -54,18 +54,18 @@ import java.util.List; * Shift -> ACTION_MOVE * * If the user selects a drop action, the user drop action is one of - * DnDConstants that represents the selected drop action if this + * {@code DnDConstants} that represents the selected drop action if this * drop action is supported by the drag source or - * DnDConstants.ACTION_NONE if this drop action is not supported + * {@code DnDConstants.ACTION_NONE} if this drop action is not supported * by the drag source. *

      * If the user doesn't select a drop action, the set of - * DnDConstants that represents the set of drop actions supported - * by the drag source is searched for DnDConstants.ACTION_MOVE, - * then for DnDConstants.ACTION_COPY, then for - * DnDConstants.ACTION_LINK and the user drop action is the + * {@code DnDConstants} that represents the set of drop actions supported + * by the drag source is searched for {@code DnDConstants.ACTION_MOVE}, + * then for {@code DnDConstants.ACTION_COPY}, then for + * {@code DnDConstants.ACTION_LINK} and the user drop action is the * first constant found. If no constant is found the user drop action - * is DnDConstants.ACTION_NONE. + * is {@code DnDConstants.ACTION_NONE}. * * @since 1.2 */ @@ -75,10 +75,10 @@ public class DropTargetDragEvent extends DropTargetEvent { private static final long serialVersionUID = -8422265619058953682L; /** - * Construct a DropTargetDragEvent given the - * DropTargetContext for this operation, - * the location of the "Drag" Cursor's hotspot - * in the Component's coordinates, the + * Construct a {@code DropTargetDragEvent} given the + * {@code DropTargetContext} for this operation, + * the location of the "Drag" {@code Cursor}'s hotspot + * in the {@code Component}'s coordinates, the * user drop action, and the source drop actions. * * @param dtc The DropTargetContext for this operation @@ -89,10 +89,10 @@ public class DropTargetDragEvent extends DropTargetEvent { * * @throws NullPointerException if cursorLocn is null * @throws IllegalArgumentException if dropAction is not one of - * DnDConstants. + * {@code DnDConstants}. * @throws IllegalArgumentException if srcActions is not - * a bitwise mask of DnDConstants. - * @throws IllegalArgumentException if dtc is null. + * a bitwise mask of {@code DnDConstants}. + * @throws IllegalArgumentException if dtc is {@code null}. */ public DropTargetDragEvent(DropTargetContext dtc, Point cursorLocn, int dropAction, int srcActions) { @@ -114,13 +114,13 @@ public class DropTargetDragEvent extends DropTargetEvent { } /** - * This method returns a Point - * indicating the Cursor's current - * location within the Component's + * This method returns a {@code Point} + * indicating the {@code Cursor}'s current + * location within the {@code Component'}s * coordinates. * * @return the current cursor location in - * Component's coords. + * {@code Component}'s coords. */ public Point getLocation() { @@ -129,8 +129,8 @@ public class DropTargetDragEvent extends DropTargetEvent { /** - * This method returns the current DataFlavors from the - * DropTargetContext. + * This method returns the current {@code DataFlavor}s from the + * {@code DropTargetContext}. * * @return current DataFlavors from the DropTargetContext */ @@ -140,10 +140,10 @@ public class DropTargetDragEvent extends DropTargetEvent { } /** - * This method returns the current DataFlavors - * as a java.util.List + * This method returns the current {@code DataFlavor}s + * as a {@code java.util.List} * - * @return a java.util.List of the Current DataFlavors + * @return a {@code java.util.List} of the Current {@code DataFlavor}s */ public List getCurrentDataFlavorsAsList() { @@ -151,10 +151,10 @@ public class DropTargetDragEvent extends DropTargetEvent { } /** - * This method returns a boolean indicating - * if the specified DataFlavor is supported. + * This method returns a {@code boolean} indicating + * if the specified {@code DataFlavor} is supported. * - * @param df the DataFlavor to test + * @param df the {@code DataFlavor} to test * * @return if a particular DataFlavor is supported */ @@ -195,11 +195,11 @@ public class DropTargetDragEvent extends DropTargetEvent { * Accepts the drag. * * This method should be called from a - * DropTargetListeners dragEnter, - * dragOver, and dropActionChanged + * {@code DropTargetListeners dragEnter}, + * {@code dragOver}, and {@code dropActionChanged} * methods if the implementation wishes to accept an operation * from the srcActions other than the one selected by - * the user as represented by the dropAction. + * the user as represented by the {@code dropAction}. * * @param dragOperation the operation accepted by the target */ @@ -209,7 +209,7 @@ public class DropTargetDragEvent extends DropTargetEvent { /** * Rejects the drag as a result of examining either the - * dropAction or the available DataFlavor + * {@code dropAction} or the available {@code DataFlavor} * types. */ public void rejectDrag() { diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetDropEvent.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetDropEvent.java index 6b197ae6b1f..7fdee103b3d 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetDropEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetDropEvent.java @@ -33,14 +33,14 @@ import java.awt.datatransfer.Transferable; import java.util.List; /** - * The DropTargetDropEvent is delivered - * via the DropTargetListener drop() method. + * The {@code DropTargetDropEvent} is delivered + * via the {@code DropTargetListener} drop() method. *

      - * The DropTargetDropEvent reports the source drop actions + * The {@code DropTargetDropEvent} reports the source drop actions * and the user drop action that reflect the current state of the * drag-and-drop operation. *

      - * Source drop actions is a bitwise mask of DnDConstants + * Source drop actions is a bitwise mask of {@code DnDConstants} * that represents the set of drop actions supported by the drag source for * this drag-and-drop operation. *

      @@ -53,18 +53,18 @@ import java.util.List; * Shift -> ACTION_MOVE * * If the user selects a drop action, the user drop action is one of - * DnDConstants that represents the selected drop action if this + * {@code DnDConstants} that represents the selected drop action if this * drop action is supported by the drag source or - * DnDConstants.ACTION_NONE if this drop action is not supported + * {@code DnDConstants.ACTION_NONE} if this drop action is not supported * by the drag source. *

      * If the user doesn't select a drop action, the set of - * DnDConstants that represents the set of drop actions supported - * by the drag source is searched for DnDConstants.ACTION_MOVE, - * then for DnDConstants.ACTION_COPY, then for - * DnDConstants.ACTION_LINK and the user drop action is the + * {@code DnDConstants} that represents the set of drop actions supported + * by the drag source is searched for {@code DnDConstants.ACTION_MOVE}, + * then for {@code DnDConstants.ACTION_COPY}, then for + * {@code DnDConstants.ACTION_LINK} and the user drop action is the * first constant found. If no constant is found the user drop action - * is DnDConstants.ACTION_NONE. + * is {@code DnDConstants.ACTION_NONE}. * * @since 1.2 */ @@ -74,31 +74,31 @@ public class DropTargetDropEvent extends DropTargetEvent { private static final long serialVersionUID = -1721911170440459322L; /** - * Construct a DropTargetDropEvent given - * the DropTargetContext for this operation, - * the location of the drag Cursor's - * hotspot in the Component's coordinates, + * Construct a {@code DropTargetDropEvent} given + * the {@code DropTargetContext} for this operation, + * the location of the drag {@code Cursor}'s + * hotspot in the {@code Component}'s coordinates, * the currently * selected user drop action, and the current set of * actions supported by the source. * By default, this constructor * assumes that the target is not in the same virtual machine as * the source; that is, {@link #isLocalTransfer()} will - * return false. + * return {@code false}. * - * @param dtc The DropTargetContext for this operation + * @param dtc The {@code DropTargetContext} for this operation * @param cursorLocn The location of the "Drag" Cursor's - * hotspot in Component coordinates + * hotspot in {@code Component} coordinates * @param dropAction the user drop action. * @param srcActions the source drop actions. * * @throws NullPointerException - * if cursorLocn is null + * if cursorLocn is {@code null} * @throws IllegalArgumentException - * if dropAction is not one of DnDConstants. + * if dropAction is not one of {@code DnDConstants}. * @throws IllegalArgumentException - * if srcActions is not a bitwise mask of DnDConstants. - * @throws IllegalArgumentException if dtc is null. + * if srcActions is not a bitwise mask of {@code DnDConstants}. + * @throws IllegalArgumentException if dtc is {@code null}. */ public DropTargetDropEvent(DropTargetContext dtc, Point cursorLocn, int dropAction, int srcActions) { @@ -120,13 +120,13 @@ public class DropTargetDropEvent extends DropTargetEvent { } /** - * Construct a DropTargetEvent given the - * DropTargetContext for this operation, - * the location of the drag Cursor's hotspot - * in the Component's + * Construct a {@code DropTargetEvent} given the + * {@code DropTargetContext} for this operation, + * the location of the drag {@code Cursor}'s hotspot + * in the {@code Component}'s * coordinates, the currently selected user drop action, * the current set of actions supported by the source, - * and a boolean indicating if the source is in the same JVM + * and a {@code boolean} indicating if the source is in the same JVM * as the target. * * @param dtc The DropTargetContext for this operation @@ -137,11 +137,11 @@ public class DropTargetDropEvent extends DropTargetEvent { * @param isLocal True if the source is in the same JVM as the target * * @throws NullPointerException - * if cursorLocn is null + * if cursorLocn is {@code null} * @throws IllegalArgumentException - * if dropAction is not one of DnDConstants. - * @throws IllegalArgumentException if srcActions is not a bitwise mask of DnDConstants. - * @throws IllegalArgumentException if dtc is null. + * if dropAction is not one of {@code DnDConstants}. + * @throws IllegalArgumentException if srcActions is not a bitwise mask of {@code DnDConstants}. + * @throws IllegalArgumentException if dtc is {@code null}. */ public DropTargetDropEvent(DropTargetContext dtc, Point cursorLocn, int dropAction, int srcActions, boolean isLocal) { @@ -151,11 +151,11 @@ public class DropTargetDropEvent extends DropTargetEvent { } /** - * This method returns a Point - * indicating the Cursor's current - * location in the Component's coordinates. + * This method returns a {@code Point} + * indicating the {@code Cursor}'s current + * location in the {@code Component}'s coordinates. * - * @return the current Cursor location in Component's coords. + * @return the current {@code Cursor} location in Component's coords. */ public Point getLocation() { @@ -175,7 +175,7 @@ public class DropTargetDropEvent extends DropTargetEvent { /** * This method returns the currently available - * DataFlavors as a java.util.List. + * {@code DataFlavor}s as a {@code java.util.List}. * * @return the currently available DataFlavors as a java.util.List */ @@ -185,11 +185,11 @@ public class DropTargetDropEvent extends DropTargetEvent { } /** - * This method returns a boolean indicating if the - * specified DataFlavor is available + * This method returns a {@code boolean} indicating if the + * specified {@code DataFlavor} is available * from the source. * - * @param df the DataFlavor to test + * @param df the {@code DataFlavor} to test * * @return if the DataFlavor specified is available from the source */ @@ -213,10 +213,10 @@ public class DropTargetDropEvent extends DropTargetEvent { public int getDropAction() { return dropAction; } /** - * This method returns the Transferable object + * This method returns the {@code Transferable} object * associated with the drop. * - * @return the Transferable associated with the drop + * @return the {@code Transferable} associated with the drop */ public Transferable getTransferable() { @@ -242,10 +242,10 @@ public class DropTargetDropEvent extends DropTargetEvent { } /** - * This method notifies the DragSource + * This method notifies the {@code DragSource} * that the drop transfer(s) are completed. * - * @param success a boolean indicating that the drop transfer(s) are completed. + * @param success a {@code boolean} indicating that the drop transfer(s) are completed. */ public void dropComplete(boolean success) { @@ -253,7 +253,7 @@ public class DropTargetDropEvent extends DropTargetEvent { } /** - * This method returns an int indicating if + * This method returns an {@code int} indicating if * the source is in the same JVM as the target. * * @return if the Source is in the same JVM @@ -291,7 +291,7 @@ public class DropTargetDropEvent extends DropTargetEvent { private int dropAction = DnDConstants.ACTION_NONE; /** - * true if the source is in the same JVM as the target. + * {@code true} if the source is in the same JVM as the target. * * @serial */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetEvent.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetEvent.java index e7911ab8cbb..3dfe215b0a2 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetEvent.java @@ -29,12 +29,12 @@ import java.util.EventObject; import java.awt.dnd.DropTargetContext; /** - * The DropTargetEvent is the base - * class for both the DropTargetDragEvent - * and the DropTargetDropEvent. + * The {@code DropTargetEvent} is the base + * class for both the {@code DropTargetDragEvent} + * and the {@code DropTargetDropEvent}. * It encapsulates the current state of the Drag and * Drop operations, in particular the current - * DropTargetContext. + * {@code DropTargetContext}. * * @since 1.2 * @@ -45,10 +45,10 @@ public class DropTargetEvent extends java.util.EventObject { private static final long serialVersionUID = 2821229066521922993L; /** - * Construct a DropTargetEvent object with - * the specified DropTargetContext. + * Construct a {@code DropTargetEvent} object with + * the specified {@code DropTargetContext}. * - * @param dtc The DropTargetContext + * @param dtc The {@code DropTargetContext} * @throws NullPointerException if {@code dtc} equals {@code null}. * @see #getSource() * @see #getDropTargetContext() @@ -61,10 +61,10 @@ public class DropTargetEvent extends java.util.EventObject { } /** - * This method returns the DropTargetContext - * associated with this DropTargetEvent. + * This method returns the {@code DropTargetContext} + * associated with this {@code DropTargetEvent}. * - * @return the DropTargetContext + * @return the {@code DropTargetContext} */ public DropTargetContext getDropTargetContext() { @@ -72,8 +72,8 @@ public class DropTargetEvent extends java.util.EventObject { } /** - * The DropTargetContext associated with this - * DropTargetEvent. + * The {@code DropTargetContext} associated with this + * {@code DropTargetEvent}. * * @serial */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetListener.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetListener.java index ec04be74e32..be540d424a4 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/DropTargetListener.java @@ -31,37 +31,37 @@ import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; /** - * The DropTargetListener interface + * The {@code DropTargetListener} interface * is the callback interface used by the - * DropTarget class to provide + * {@code DropTarget} class to provide * notification of DnD operations that involve - * the subject DropTarget. Methods of + * the subject {@code DropTarget}. Methods of * this interface may be implemented to provide * "drag under" visual feedback to the user throughout * the Drag and Drop operation. *

      * Create a listener object by implementing the interface and then register it - * with a DropTarget. When the drag enters, moves over, or exits - * the operable part of the drop site for that DropTarget, when + * with a {@code DropTarget}. When the drag enters, moves over, or exits + * the operable part of the drop site for that {@code DropTarget}, when * the drop action changes, and when the drop occurs, the relevant method in - * the listener object is invoked, and the DropTargetEvent is + * the listener object is invoked, and the {@code DropTargetEvent} is * passed to it. *

      - * The operable part of the drop site for the DropTarget is - * the part of the associated Component's geometry that is not + * The operable part of the drop site for the {@code DropTarget} is + * the part of the associated {@code Component}'s geometry that is not * obscured by an overlapping top-level window or by another - * Component higher in the Z-order that has an associated active - * DropTarget. + * {@code Component} higher in the Z-order that has an associated active + * {@code DropTarget}. *

      * During the drag, the data associated with the current drag operation can be - * retrieved by calling getTransferable() on - * DropTargetDragEvent instances passed to the listener's + * retrieved by calling {@code getTransferable()} on + * {@code DropTargetDragEvent} instances passed to the listener's * methods. *

      - * Note that getTransferable() on the - * DropTargetDragEvent instance should only be called within the + * Note that {@code getTransferable()} on the + * {@code DropTargetDragEvent} instance should only be called within the * respective listener's method and all the necessary data should be retrieved - * from the returned Transferable before that method returns. + * from the returned {@code Transferable} before that method returns. * * @since 1.2 */ @@ -70,20 +70,20 @@ public interface DropTargetListener extends EventListener { /** * Called while a drag operation is ongoing, when the mouse pointer enters - * the operable part of the drop site for the DropTarget + * the operable part of the drop site for the {@code DropTarget} * registered with this listener. * - * @param dtde the DropTargetDragEvent + * @param dtde the {@code DropTargetDragEvent} */ void dragEnter(DropTargetDragEvent dtde); /** * Called when a drag operation is ongoing, while the mouse pointer is still - * over the operable part of the drop site for the DropTarget + * over the operable part of the drop site for the {@code DropTarget} * registered with this listener. * - * @param dtde the DropTargetDragEvent + * @param dtde the {@code DropTargetDragEvent} */ void dragOver(DropTargetDragEvent dtde); @@ -92,7 +92,7 @@ public interface DropTargetListener extends EventListener { * Called if the user has modified * the current drop gesture. * - * @param dtde the DropTargetDragEvent + * @param dtde the {@code DropTargetDragEvent} */ void dropActionChanged(DropTargetDragEvent dtde); @@ -100,52 +100,52 @@ public interface DropTargetListener extends EventListener { /** * Called while a drag operation is ongoing, when the mouse pointer has * exited the operable part of the drop site for the - * DropTarget registered with this listener. + * {@code DropTarget} registered with this listener. * - * @param dte the DropTargetEvent + * @param dte the {@code DropTargetEvent} */ void dragExit(DropTargetEvent dte); /** * Called when the drag operation has terminated with a drop on - * the operable part of the drop site for the DropTarget + * the operable part of the drop site for the {@code DropTarget} * registered with this listener. *

      * This method is responsible for undertaking * the transfer of the data associated with the - * gesture. The DropTargetDropEvent - * provides a means to obtain a Transferable + * gesture. The {@code DropTargetDropEvent} + * provides a means to obtain a {@code Transferable} * object that represents the data object(s) to * be transferred.

      - * From this method, the DropTargetListener + * From this method, the {@code DropTargetListener} * shall accept or reject the drop via the * acceptDrop(int dropAction) or rejectDrop() methods of the - * DropTargetDropEvent parameter. + * {@code DropTargetDropEvent} parameter. *

      * Subsequent to acceptDrop(), but not before, - * DropTargetDropEvent's getTransferable() + * {@code DropTargetDropEvent}'s getTransferable() * method may be invoked, and data transfer may be - * performed via the returned Transferable's + * performed via the returned {@code Transferable}'s * getTransferData() method. *

      * At the completion of a drop, an implementation * of this method is required to signal the success/failure * of the drop by passing an appropriate - * boolean to the DropTargetDropEvent's + * {@code boolean} to the {@code DropTargetDropEvent}'s * dropComplete(boolean success) method. *

      * Note: The data transfer should be completed before the call to the - * DropTargetDropEvent's dropComplete(boolean success) method. + * {@code DropTargetDropEvent}'s dropComplete(boolean success) method. * After that, a call to the getTransferData() method of the - * Transferable returned by - * DropTargetDropEvent.getTransferable() is guaranteed to + * {@code Transferable} returned by + * {@code DropTargetDropEvent.getTransferable()} is guaranteed to * succeed only if the data transfer is local; that is, only if - * DropTargetDropEvent.isLocalTransfer() returns - * true. Otherwise, the behavior of the call is + * {@code DropTargetDropEvent.isLocalTransfer()} returns + * {@code true}. Otherwise, the behavior of the call is * implementation-dependent. * - * @param dtde the DropTargetDropEvent + * @param dtde the {@code DropTargetDropEvent} */ void drop(DropTargetDropEvent dtde); diff --git a/jdk/src/java.desktop/share/classes/java/awt/dnd/MouseDragGestureRecognizer.java b/jdk/src/java.desktop/share/classes/java/awt/dnd/MouseDragGestureRecognizer.java index cf975835f22..0c5a623f754 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/dnd/MouseDragGestureRecognizer.java +++ b/jdk/src/java.desktop/share/classes/java/awt/dnd/MouseDragGestureRecognizer.java @@ -32,8 +32,8 @@ import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; /** - * This abstract subclass of DragGestureRecognizer - * defines a DragGestureRecognizer + * This abstract subclass of {@code DragGestureRecognizer} + * defines a {@code DragGestureRecognizer} * for mouse-based gestures. * * Each platform implements its own concrete subclass of this class, @@ -67,12 +67,12 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i private static final long serialVersionUID = 6220099344182281120L; /** - * Construct a new MouseDragGestureRecognizer - * given the DragSource for the - * Component c, the Component + * Construct a new {@code MouseDragGestureRecognizer} + * given the {@code DragSource} for the + * {@code Component} c, the {@code Component} * to observe, the action(s) * permitted for this drag operation, and - * the DragGestureListener to + * the {@code DragGestureListener} to * notify when a drag gesture is detected. * * @param ds The DragSource for the Component c @@ -87,10 +87,10 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i } /** - * Construct a new MouseDragGestureRecognizer - * given the DragSource for - * the Component c, - * the Component to observe, and the action(s) + * Construct a new {@code MouseDragGestureRecognizer} + * given the {@code DragSource} for + * the {@code Component} c, + * the {@code Component} to observe, and the action(s) * permitted for this drag operation. * * @param ds The DragSource for the Component c @@ -103,10 +103,10 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i } /** - * Construct a new MouseDragGestureRecognizer - * given the DragSource for the - * Component c, and the - * Component to observe. + * Construct a new {@code MouseDragGestureRecognizer} + * given the {@code DragSource} for the + * {@code Component} c, and the + * {@code Component} to observe. * * @param ds The DragSource for the Component c * @param c The Component to observe @@ -117,8 +117,8 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i } /** - * Construct a new MouseDragGestureRecognizer - * given the DragSource for the Component. + * Construct a new {@code MouseDragGestureRecognizer} + * given the {@code DragSource} for the {@code Component}. * * @param ds The DragSource for the Component */ @@ -151,16 +151,16 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i /** * Invoked when the mouse has been clicked on a component. * - * @param e the MouseEvent + * @param e the {@code MouseEvent} */ public void mouseClicked(MouseEvent e) { } /** * Invoked when a mouse button has been - * pressed on a Component. + * pressed on a {@code Component}. * - * @param e the MouseEvent + * @param e the {@code MouseEvent} */ public void mousePressed(MouseEvent e) { } @@ -168,7 +168,7 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i /** * Invoked when a mouse button has been released on a component. * - * @param e the MouseEvent + * @param e the {@code MouseEvent} */ public void mouseReleased(MouseEvent e) { } @@ -176,7 +176,7 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i /** * Invoked when the mouse enters a component. * - * @param e the MouseEvent + * @param e the {@code MouseEvent} */ public void mouseEntered(MouseEvent e) { } @@ -184,7 +184,7 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i /** * Invoked when the mouse exits a component. * - * @param e the MouseEvent + * @param e the {@code MouseEvent} */ public void mouseExited(MouseEvent e) { } @@ -192,7 +192,7 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i /** * Invoked when a mouse button is pressed on a component. * - * @param e the MouseEvent + * @param e the {@code MouseEvent} */ public void mouseDragged(MouseEvent e) { } @@ -201,7 +201,7 @@ public abstract class MouseDragGestureRecognizer extends DragGestureRecognizer i * Invoked when the mouse button has been moved on a component * (with no buttons no down). * - * @param e the MouseEvent + * @param e the {@code MouseEvent} */ public void mouseMoved(MouseEvent e) { } diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/AWTEventListener.java b/jdk/src/java.desktop/share/classes/java/awt/event/AWTEventListener.java index e56191fd988..f0050c740c4 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/AWTEventListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/AWTEventListener.java @@ -41,9 +41,9 @@ import java.awt.AWTEvent; * The class that is interested in monitoring AWT events * implements this interface, and the object created with that * class is registered with the Toolkit, using the Toolkit's - * addAWTEventListener method. When an event is + * {@code addAWTEventListener} method. When an event is * dispatched anywhere in the AWT, that object's - * eventDispatched method is invoked. + * {@code eventDispatched} method is invoked. * * @see java.awt.AWTEvent * @see java.awt.Toolkit#addAWTEventListener diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ActionEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/ActionEvent.java index 24a91ac0cd2..6ce79554eeb 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ActionEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ActionEvent.java @@ -32,17 +32,17 @@ import java.lang.annotation.Native; /** * A semantic event which indicates that a component-defined action occurred. * This high-level event is generated by a component (such as a - * Button) when + * {@code Button}) when * the component-specific action occurs (such as being pressed). - * The event is passed to every ActionListener object + * The event is passed to every {@code ActionListener} object * that registered to receive such events using the component's - * addActionListener method. + * {@code addActionListener} method. *

      - * Note: To invoke an ActionEvent on a - * Button using the keyboard, use the Space bar. + * Note: To invoke an {@code ActionEvent} on a + * {@code Button} using the keyboard, use the Space bar. *

      - * The object that implements the ActionListener interface - * gets this ActionEvent when the event occurs. The listener + * The object that implements the {@code ActionListener} interface + * gets this {@code ActionEvent} when the event occurs. The listener * is therefore spared the details of processing individual mouse movements * and mouse clicks, and can instead process a "meaningful" (semantic) * event like "button pressed". @@ -137,12 +137,12 @@ public class ActionEvent extends AWTEvent { private static final long serialVersionUID = -7671078796273832149L; /** - * Constructs an ActionEvent object. + * Constructs an {@code ActionEvent} object. *

      * This method throws an - * IllegalArgumentException if source - * is null. - * A null command string is legal, + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. + * A {@code null command} string is legal, * but not recommended. * * @param source The object that originated the event @@ -151,7 +151,7 @@ public class ActionEvent extends AWTEvent { * the class description for {@link ActionEvent} * @param command A string that may specify a command (possibly one * of several) associated with the event - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getSource() * @see #getID() * @see #getActionCommand() @@ -161,12 +161,12 @@ public class ActionEvent extends AWTEvent { } /** - * Constructs an ActionEvent object with modifier keys. + * Constructs an {@code ActionEvent} object with modifier keys. *

      * This method throws an - * IllegalArgumentException if source - * is null. - * A null command string is legal, + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. + * A {@code null command} string is legal, * but not recommended. * * @param source The object that originated the event @@ -179,7 +179,7 @@ public class ActionEvent extends AWTEvent { * (shift, ctrl, alt, meta). * Passing negative parameter is not recommended. * Zero value means that no modifiers were passed - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getSource() * @see #getID() * @see #getActionCommand() @@ -190,13 +190,13 @@ public class ActionEvent extends AWTEvent { } /** - * Constructs an ActionEvent object with the specified + * Constructs an {@code ActionEvent} object with the specified * modifier keys and timestamp. *

      * This method throws an - * IllegalArgumentException if source - * is null. - * A null command string is legal, + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. + * A {@code null command} string is legal, * but not recommended. * * @param source The object that originated the event @@ -212,7 +212,7 @@ public class ActionEvent extends AWTEvent { * @param when A long that gives the time the event occurred. * Passing negative or zero value * is not recommended - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getSource() * @see #getID() * @see #getActionCommand() @@ -237,9 +237,9 @@ public class ActionEvent extends AWTEvent { * and the event would be the same in each case, but the command string * would identify the intended action. *

      - * Note that if a null command string was passed - * to the constructor for this ActionEvent, this - * this method returns null. + * Note that if a {@code null} command string was passed + * to the constructor for this {@code ActionEvent}, this + * this method returns {@code null}. * * @return the string identifying the command for this event */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ActionListener.java b/jdk/src/java.desktop/share/classes/java/awt/event/ActionListener.java index bbb87dbddfb..50b94c46a18 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ActionListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ActionListener.java @@ -32,8 +32,8 @@ import java.util.EventListener; * The class that is interested in processing an action event * implements this interface, and the object created with that * class is registered with a component, using the component's - * addActionListener method. When the action event - * occurs, that object's actionPerformed method is + * {@code addActionListener} method. When the action event + * occurs, that object's {@code actionPerformed} method is * invoked. * * @see ActionEvent diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/AdjustmentEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/AdjustmentEvent.java index 66d54c3c247..f113319c57b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/AdjustmentEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/AdjustmentEvent.java @@ -107,7 +107,7 @@ public class AdjustmentEvent extends AWTEvent { Adjustable adjustable; /** - * value will contain the new value of the + * {@code value} will contain the new value of the * adjustable object. This value will always be in a * range associated adjustable object. * @@ -117,7 +117,7 @@ public class AdjustmentEvent extends AWTEvent { int value; /** - * The adjustmentType describes how the adjustable + * The {@code adjustmentType} describes how the adjustable * object value has changed. * This value can be increased/decreased by a block or unit amount * where the block is associated with page increments/decrements, @@ -130,7 +130,7 @@ public class AdjustmentEvent extends AWTEvent { /** - * The isAdjusting is true if the event is one + * The {@code isAdjusting} is true if the event is one * of the series of multiple adjustment events. * * @since 1.4 @@ -147,14 +147,14 @@ public class AdjustmentEvent extends AWTEvent { /** - * Constructs an AdjustmentEvent object with the - * specified Adjustable source, event type, + * Constructs an {@code AdjustmentEvent} object with the + * specified {@code Adjustable} source, event type, * adjustment type, and value. *

      This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Adjustable object where the + * @param source The {@code Adjustable} object where the * event originated * @param id An integer indicating the type of event. * For information on allowable values, see @@ -163,7 +163,7 @@ public class AdjustmentEvent extends AWTEvent { * For information on allowable values, see * the class description for {@link AdjustmentEvent} * @param value The current value of the adjustment - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getSource() * @see #getID() * @see #getAdjustmentType() @@ -174,13 +174,13 @@ public class AdjustmentEvent extends AWTEvent { } /** - * Constructs an AdjustmentEvent object with the + * Constructs an {@code AdjustmentEvent} object with the * specified Adjustable source, event type, adjustment type, and value. *

      This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Adjustable object where the + * @param source The {@code Adjustable} object where the * event originated * @param id An integer indicating the type of event. * For information on allowable values, see @@ -189,10 +189,10 @@ public class AdjustmentEvent extends AWTEvent { * For information on allowable values, see * the class description for {@link AdjustmentEvent} * @param value The current value of the adjustment - * @param isAdjusting A boolean that equals true if the event is one + * @param isAdjusting A boolean that equals {@code true} if the event is one * of a series of multiple adjusting events, - * otherwise false - * @throws IllegalArgumentException if source is null + * otherwise {@code false} + * @throws IllegalArgumentException if {@code source} is null * @since 1.4 * @see #getSource() * @see #getID() @@ -209,9 +209,9 @@ public class AdjustmentEvent extends AWTEvent { } /** - * Returns the Adjustable object where this event originated. + * Returns the {@code Adjustable} object where this event originated. * - * @return the Adjustable object where this event originated + * @return the {@code Adjustable} object where this event originated */ public Adjustable getAdjustable() { return adjustable; @@ -243,11 +243,11 @@ public class AdjustmentEvent extends AWTEvent { } /** - * Returns true if this is one of multiple + * Returns {@code true} if this is one of multiple * adjustment events. * - * @return true if this is one of multiple - * adjustment events, otherwise returns false + * @return {@code true} if this is one of multiple + * adjustment events, otherwise returns {@code false} * @since 1.4 */ public boolean getValueIsAdjusting() { diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ComponentAdapter.java b/jdk/src/java.desktop/share/classes/java/awt/event/ComponentAdapter.java index 2e3ab4c2ca2..47cd188d2c3 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ComponentAdapter.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ComponentAdapter.java @@ -30,17 +30,17 @@ package java.awt.event; * The methods in this class are empty. This class exists as * convenience for creating listener objects. *

      - * Extend this class to create a ComponentEvent listener + * Extend this class to create a {@code ComponentEvent} listener * and override the methods for the events of interest. (If you implement the - * ComponentListener interface, you have to define all of + * {@code ComponentListener} interface, you have to define all of * the methods in it. This abstract class defines null methods for them * all, so you can only have to define methods for events you care about.) *

      * Create a listener object using your class and then register it with a - * component using the component's addComponentListener + * component using the component's {@code addComponentListener} * method. When the component's size, location, or visibility * changes, the relevant method in the listener object is invoked, - * and the ComponentEvent is passed to it. + * and the {@code ComponentEvent} is passed to it. * * @see ComponentEvent * @see ComponentListener diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ComponentEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/ComponentEvent.java index d168f6c1763..705a9fb5848 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ComponentEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ComponentEvent.java @@ -47,12 +47,12 @@ import java.lang.annotation.Native; *

      * This low-level event is generated by a component object (such as a * List) when the component is moved, resized, rendered invisible, or made - * visible again. The event is passed to every ComponentListener - * or ComponentAdapter object which registered to receive such - * events using the component's addComponentListener method. - * (ComponentAdapter objects implement the - * ComponentListener interface.) Each such listener object - * gets this ComponentEvent when the event occurs. + * visible again. The event is passed to every {@code ComponentListener} + * or {@code ComponentAdapter} object which registered to receive such + * events using the component's {@code addComponentListener} method. + * ({@code ComponentAdapter} objects implement the + * {@code ComponentListener} interface.) Each such listener object + * gets this {@code ComponentEvent} when the event occurs. *

      * An unspecified behavior will be caused if the {@code id} parameter * of any particular {@code ComponentEvent} instance is not @@ -103,16 +103,16 @@ public class ComponentEvent extends AWTEvent { private static final long serialVersionUID = 8101406823902992965L; /** - * Constructs a ComponentEvent object. + * Constructs a {@code ComponentEvent} object. *

      This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Component that originated the event + * @param source The {@code Component} that originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link ComponentEvent} - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getComponent() * @see #getID() */ @@ -123,9 +123,9 @@ public class ComponentEvent extends AWTEvent { /** * Returns the originator of the event. * - * @return the Component object that originated - * the event, or null if the object is not a - * Component. + * @return the {@code Component} object that originated + * the event, or {@code null} if the object is not a + * {@code Component}. */ public Component getComponent() { return (source instanceof Component) ? (Component)source : null; diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ComponentListener.java b/jdk/src/java.desktop/share/classes/java/awt/event/ComponentListener.java index e3e83e638d1..e316597590a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ComponentListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ComponentListener.java @@ -31,18 +31,18 @@ import java.util.EventListener; * The listener interface for receiving component events. * The class that is interested in processing a component event * either implements this interface (and all the methods it - * contains) or extends the abstract ComponentAdapter class + * contains) or extends the abstract {@code ComponentAdapter} class * (overriding only the methods of interest). * The listener object created from that class is then registered with a - * component using the component's addComponentListener + * component using the component's {@code addComponentListener} * method. When the component's size, location, or visibility * changes, the relevant method in the listener object is invoked, - * and the ComponentEvent is passed to it. + * and the {@code ComponentEvent} is passed to it. *

      * Component events are provided for notification purposes ONLY; * The AWT will automatically handle component moves and resizes * internally so that GUI layout works properly regardless of - * whether a program registers a ComponentListener or not. + * whether a program registers a {@code ComponentListener} or not. * * @see ComponentAdapter * @see ComponentEvent diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ContainerAdapter.java b/jdk/src/java.desktop/share/classes/java/awt/event/ContainerAdapter.java index e4af172bc39..9a333b3d666 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ContainerAdapter.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ContainerAdapter.java @@ -30,17 +30,17 @@ package java.awt.event; * The methods in this class are empty. This class exists as * convenience for creating listener objects. *

      - * Extend this class to create a ContainerEvent listener + * Extend this class to create a {@code ContainerEvent} listener * and override the methods for the events of interest. (If you implement the - * ContainerListener interface, you have to define all of + * {@code ContainerListener} interface, you have to define all of * the methods in it. This abstract class defines null methods for them * all, so you can only have to define methods for events you care about.) *

      * Create a listener object using the extended class and then register it with - * a component using the component's addContainerListener + * a component using the component's {@code addContainerListener} * method. When the container's contents change because a component has * been added or removed, the relevant method in the listener object is invoked, - * and the ContainerEvent is passed to it. + * and the {@code ContainerEvent} is passed to it. * * @see ContainerEvent * @see ContainerListener diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ContainerEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/ContainerEvent.java index 964b27cd22c..7aecc21b963 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ContainerEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ContainerEvent.java @@ -39,12 +39,12 @@ import java.awt.Component; *

      * This low-level event is generated by a container object (such as a * Panel) when a component is added to it or removed from it. - * The event is passed to every ContainerListener - * or ContainerAdapter object which registered to receive such - * events using the component's addContainerListener method. - * (ContainerAdapter objects implement the - * ContainerListener interface.) Each such listener object - * gets this ContainerEvent when the event occurs. + * The event is passed to every {@code ContainerListener} + * or {@code ContainerAdapter} object which registered to receive such + * events using the component's {@code addContainerListener} method. + * ({@code ContainerAdapter} objects implement the + * {@code ContainerListener} interface.) Each such listener object + * gets this {@code ContainerEvent} when the event occurs. *

      * An unspecified behavior will be caused if the {@code id} parameter * of any particular {@code ContainerEvent} instance is not @@ -95,18 +95,18 @@ public class ContainerEvent extends ComponentEvent { private static final long serialVersionUID = -4114942250539772041L; /** - * Constructs a ContainerEvent object. + * Constructs a {@code ContainerEvent} object. *

      This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Component object (container) + * @param source The {@code Component} object (container) * that originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link ContainerEvent} * @param child the component that was added or removed - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getContainer() * @see #getID() * @see #getChild() @@ -119,9 +119,9 @@ public class ContainerEvent extends ComponentEvent { /** * Returns the originator of the event. * - * @return the Container object that originated - * the event, or null if the object is not a - * Container. + * @return the {@code Container} object that originated + * the event, or {@code null} if the object is not a + * {@code Container}. */ public Container getContainer() { return (source instanceof Container) ? (Container)source : null; diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ContainerListener.java b/jdk/src/java.desktop/share/classes/java/awt/event/ContainerListener.java index c99c5b9c94b..a0557327c82 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ContainerListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ContainerListener.java @@ -31,13 +31,13 @@ import java.util.EventListener; * The listener interface for receiving container events. * The class that is interested in processing a container event * either implements this interface (and all the methods it - * contains) or extends the abstract ContainerAdapter class + * contains) or extends the abstract {@code ContainerAdapter} class * (overriding only the methods of interest). * The listener object created from that class is then registered with a - * component using the component's addContainerListener + * component using the component's {@code addContainerListener} * method. When the container's contents change because a component * has been added or removed, the relevant method in the listener object - * is invoked, and the ContainerEvent is passed to it. + * is invoked, and the {@code ContainerEvent} is passed to it. *

      * Container events are provided for notification purposes ONLY; * The AWT will automatically handle add and remove operations diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/FocusAdapter.java b/jdk/src/java.desktop/share/classes/java/awt/event/FocusAdapter.java index 5676d082e82..1525990d5aa 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/FocusAdapter.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/FocusAdapter.java @@ -30,17 +30,17 @@ package java.awt.event; * The methods in this class are empty. This class exists as * convenience for creating listener objects. *

      - * Extend this class to create a FocusEvent listener + * Extend this class to create a {@code FocusEvent} listener * and override the methods for the events of interest. (If you implement the - * FocusListener interface, you have to define all of + * {@code FocusListener} interface, you have to define all of * the methods in it. This abstract class defines null methods for them * all, so you can only have to define methods for events you care about.) *

      * Create a listener object using the extended class and then register it with - * a component using the component's addFocusListener + * a component using the component's {@code addFocusListener} * method. When the component gains or loses the keyboard focus, * the relevant method in the listener object is invoked, - * and the FocusEvent is passed to it. + * and the {@code FocusEvent} is passed to it. * * @see FocusEvent * @see FocusListener diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java index 2f9e1911c99..afef05edef0 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java @@ -32,11 +32,11 @@ import sun.awt.SunToolkit; /** * A low-level event which indicates that a Component has gained or lost the * input focus. This low-level event is generated by a Component (such as a - * TextField). The event is passed to every FocusListener or - * FocusAdapter object which registered to receive such events - * using the Component's addFocusListener method. ( - * FocusAdapter objects implement the FocusListener - * interface.) Each such listener object gets this FocusEvent when + * TextField). The event is passed to every {@code FocusListener} or + * {@code FocusAdapter} object which registered to receive such events + * using the Component's {@code addFocusListener} method. + * ({@code FocusAdapter} objects implement the {@code FocusListener} + * interface.) Each such listener object gets this {@code FocusEvent} when * the event occurs. *

      * There are two levels of focus events: permanent and temporary. Permanent @@ -114,30 +114,30 @@ public class FocusEvent extends ComponentEvent { private static final long serialVersionUID = 523753786457416396L; /** - * Constructs a FocusEvent object with the - * specified temporary state and opposite Component. - * The opposite Component is the other - * Component involved in this focus change. - * For a FOCUS_GAINED event, this is the - * Component that lost focus. For a - * FOCUS_LOST event, this is the Component + * Constructs a {@code FocusEvent} object with the + * specified temporary state and opposite {@code Component}. + * The opposite {@code Component} is the other + * {@code Component} involved in this focus change. + * For a {@code FOCUS_GAINED} event, this is the + * {@code Component} that lost focus. For a + * {@code FOCUS_LOST} event, this is the {@code Component} * that gained focus. If this focus change occurs with a native * application, with a Java application in a different VM, - * or with no other Component, then the opposite - * Component is null. + * or with no other {@code Component}, then the opposite + * {@code Component} is {@code null}. *

      This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Component that originated the event + * @param source The {@code Component} that originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link FocusEvent} - * @param temporary Equals true if the focus change is temporary; - * false otherwise + * @param temporary Equals {@code true} if the focus change is temporary; + * {@code false} otherwise * @param opposite The other Component involved in the focus change, - * or null - * @throws IllegalArgumentException if source equals {@code null} + * or {@code null} + * @throws IllegalArgumentException if {@code source} equals {@code null} * @see #getSource() * @see #getID() * @see #isTemporary() @@ -152,19 +152,19 @@ public class FocusEvent extends ComponentEvent { } /** - * Constructs a FocusEvent object and identifies + * Constructs a {@code FocusEvent} object and identifies * whether or not the change is temporary. *

      This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Component that originated the event + * @param source The {@code Component} that originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link FocusEvent} - * @param temporary Equals true if the focus change is temporary; - * false otherwise - * @throws IllegalArgumentException if source equals {@code null} + * @param temporary Equals {@code true} if the focus change is temporary; + * {@code false} otherwise + * @throws IllegalArgumentException if {@code source} equals {@code null} * @see #getSource() * @see #getID() * @see #isTemporary() @@ -174,17 +174,17 @@ public class FocusEvent extends ComponentEvent { } /** - * Constructs a FocusEvent object and identifies it + * Constructs a {@code FocusEvent} object and identifies it * as a permanent change in focus. *

      This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Component that originated the event + * @param source The {@code Component} that originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link FocusEvent} - * @throws IllegalArgumentException if source equals {@code null} + * @throws IllegalArgumentException if {@code source} equals {@code null} * @see #getSource() * @see #getID() */ @@ -195,8 +195,8 @@ public class FocusEvent extends ComponentEvent { /** * Identifies the focus change event as temporary or permanent. * - * @return true if the focus change is temporary; - * false otherwise + * @return {@code true} if the focus change is temporary; + * {@code false} otherwise */ public boolean isTemporary() { return temporary; diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/FocusListener.java b/jdk/src/java.desktop/share/classes/java/awt/event/FocusListener.java index 31edd5a0726..2acd1035305 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/FocusListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/FocusListener.java @@ -32,13 +32,13 @@ import java.util.EventListener; * a component. * The class that is interested in processing a focus event * either implements this interface (and all the methods it - * contains) or extends the abstract FocusAdapter class + * contains) or extends the abstract {@code FocusAdapter} class * (overriding only the methods of interest). * The listener object created from that class is then registered with a - * component using the component's addFocusListener + * component using the component's {@code addFocusListener} * method. When the component gains or loses the keyboard focus, * the relevant method in the listener object - * is invoked, and the FocusEvent is passed to it. + * is invoked, and the {@code FocusEvent} is passed to it. * * @see FocusAdapter * @see FocusEvent diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyBoundsAdapter.java b/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyBoundsAdapter.java index c17801468ad..5fa165a6839 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyBoundsAdapter.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyBoundsAdapter.java @@ -31,16 +31,16 @@ package java.awt.event; * convenience for creating listener objects. *

      * Extend this class and override the method for the event of interest. (If - * you implement the HierarchyBoundsListener interface, you have + * you implement the {@code HierarchyBoundsListener} interface, you have * to define both methods in it. This abstract class defines null methods for * them both, so you only have to define the method for the event you care * about.) *

      * Create a listener object using your class and then register it with a - * Component using the Component's addHierarchyBoundsListener + * Component using the Component's {@code addHierarchyBoundsListener} * method. When the hierarchy to which the Component belongs changes by * resize or movement of an ancestor, the relevant method in the listener - * object is invoked, and the HierarchyEvent is passed to it. + * object is invoked, and the {@code HierarchyEvent} is passed to it. * * @author David Mendenhall * @see HierarchyBoundsListener diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyBoundsListener.java b/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyBoundsListener.java index a8f21342e9e..bc997939b43 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyBoundsListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyBoundsListener.java @@ -31,18 +31,18 @@ import java.util.EventListener; * The listener interface for receiving ancestor moved and resized events. * The class that is interested in processing these events either implements * this interface (and all the methods it contains) or extends the abstract - * HierarchyBoundsAdapter class (overriding only the method of + * {@code HierarchyBoundsAdapter} class (overriding only the method of * interest). * The listener object created from that class is then registered with a - * Component using the Component's addHierarchyBoundsListener + * Component using the Component's {@code addHierarchyBoundsListener} * method. When the hierarchy to which the Component belongs changes by * the resizing or movement of an ancestor, the relevant method in the listener - * object is invoked, and the HierarchyEvent is passed to it. + * object is invoked, and the {@code HierarchyEvent} is passed to it. *

      * Hierarchy events are provided for notification purposes ONLY; * The AWT will automatically handle changes to the hierarchy internally so * that GUI layout works properly regardless of whether a - * program registers an HierarchyBoundsListener or not. + * program registers an {@code HierarchyBoundsListener} or not. * * @author David Mendenhall * @see HierarchyBoundsAdapter diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyEvent.java index 47107b35981..c6cde2b5f0c 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyEvent.java @@ -30,8 +30,8 @@ import java.awt.Component; import java.awt.Container; /** - * An event which indicates a change to the Component - * hierarchy to which Component belongs. + * An event which indicates a change to the {@code Component} + * hierarchy to which {@code Component} belongs. *

        *
      • Hierarchy Change Events (HierarchyListener) *
          @@ -57,18 +57,18 @@ import java.awt.Container; * This event is generated by a Container object (such as a Panel) when the * Container is added, removed, moved, or resized, and passed down the * hierarchy. It is also generated by a Component object when that object's - * addNotify, removeNotify, show, or - * hide method is called. The {@code ANCESTOR_MOVED} and + * {@code addNotify}, {@code removeNotify}, {@code show}, or + * {@code hide} method is called. The {@code ANCESTOR_MOVED} and * {@code ANCESTOR_RESIZED} - * events are dispatched to every HierarchyBoundsListener or - * HierarchyBoundsAdapter object which registered to receive - * such events using the Component's addHierarchyBoundsListener - * method. (HierarchyBoundsAdapter objects implement the - * HierarchyBoundsListener interface.) The {@code HIERARCHY_CHANGED} events are - * dispatched to every HierarchyListener object which registered - * to receive such events using the Component's addHierarchyListener - * method. Each such listener object gets this HierarchyEvent - * when the event occurs. + * events are dispatched to every {@code HierarchyBoundsListener} or + * {@code HierarchyBoundsAdapter} object which registered to receive + * such events using the Component's {@code addHierarchyBoundsListener} + * method. ({@code HierarchyBoundsAdapter} objects implement the + * {@code HierarchyBoundsListener} interface.) The {@code HIERARCHY_CHANGED} events are + * dispatched to every {@code HierarchyListener} object which registered + * to receive such events using the Component's {@code addHierarchyListener} + * method. Each such listener object gets this {@code HierarchyEvent} + * when the event occurs. *

          * An unspecified behavior will be caused if the {@code id} parameter * of any particular {@code HierarchyEvent} instance is not @@ -122,20 +122,20 @@ public class HierarchyEvent extends AWTEvent { public static final int HIERARCHY_LAST = ANCESTOR_RESIZED; /** - * A change flag indicates that the HIERARCHY_CHANGED event + * A change flag indicates that the {@code HIERARCHY_CHANGED} event * was generated by a reparenting operation. */ public static final int PARENT_CHANGED = 0x1; /** - * A change flag indicates that the HIERARCHY_CHANGED event + * A change flag indicates that the {@code HIERARCHY_CHANGED} event * was generated due to the changing of the hierarchy displayability. * To discern the * current displayability of the hierarchy, call the - * Component.isDisplayable method. Displayability changes occur + * {@code Component.isDisplayable} method. Displayability changes occur * in response to explicit or implicit calls of the - * Component.addNotify and - * Component.removeNotify methods. + * {@code Component.addNotify} and + * {@code Component.removeNotify} methods. * * @see java.awt.Component#isDisplayable() * @see java.awt.Component#addNotify() @@ -144,15 +144,15 @@ public class HierarchyEvent extends AWTEvent { public static final int DISPLAYABILITY_CHANGED = 0x2; /** - * A change flag indicates that the HIERARCHY_CHANGED event + * A change flag indicates that the {@code HIERARCHY_CHANGED} event * was generated due to the changing of the hierarchy showing state. * To discern the * current showing state of the hierarchy, call the - * Component.isShowing method. Showing state changes occur + * {@code Component.isShowing} method. Showing state changes occur * when either the displayability or visibility of the * hierarchy occurs. Visibility changes occur in response to explicit - * or implicit calls of the Component.show and - * Component.hide methods. + * or implicit calls of the {@code Component.show} and + * {@code Component.hide} methods. * * @see java.awt.Component#isShowing() * @see java.awt.Component#addNotify() @@ -167,24 +167,24 @@ public class HierarchyEvent extends AWTEvent { long changeFlags; /** - * Constructs an HierarchyEvent object to identify a - * change in the Component hierarchy. + * Constructs an {@code HierarchyEvent} object to identify a + * change in the {@code Component} hierarchy. *

          This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Component object that + * @param source The {@code Component} object that * originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link HierarchyEvent} - * @param changed The Component at the top of + * @param changed The {@code Component} at the top of * the hierarchy which was changed - * @param changedParent The parent of the changed component. + * @param changedParent The parent of the {@code changed} component. * This * may be the parent before or after the * change, depending on the type of change - * @throws IllegalArgumentException if source is {@code null} + * @throws IllegalArgumentException if {@code source} is {@code null} * @see #getSource() * @see #getID() * @see #getChanged() @@ -198,29 +198,29 @@ public class HierarchyEvent extends AWTEvent { } /** - * Constructs an HierarchyEvent object to identify - * a change in the Component hierarchy. + * Constructs an {@code HierarchyEvent} object to identify + * a change in the {@code Component} hierarchy. *

          This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Component object that + * @param source The {@code Component} object that * originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link HierarchyEvent} - * @param changed The Component at the top + * @param changed The {@code Component} at the top * of the hierarchy which was changed - * @param changedParent The parent of the changed component. + * @param changedParent The parent of the {@code changed} component. * This * may be the parent before or after the * change, depending on the type of change * @param changeFlags A bitmask which indicates the type(s) of - * the HIERARCHY_CHANGED events + * the {@code HIERARCHY_CHANGED} events * represented in this event object. * For information on allowable values, see * the class description for {@link HierarchyEvent} - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getSource() * @see #getID() * @see #getChanged() @@ -238,9 +238,9 @@ public class HierarchyEvent extends AWTEvent { /** * Returns the originator of the event. * - * @return the Component object that originated - * the event, or null if the object is not a - * Component. + * @return the {@code Component} object that originated + * the event, or {@code null} if the object is not a + * {@code Component}. */ public Component getComponent() { return (source instanceof Component) ? (Component)source : null; @@ -257,13 +257,13 @@ public class HierarchyEvent extends AWTEvent { } /** - * Returns the parent of the Component returned by - * getChanged(). For a HIERARCHY_CHANGED event where the - * change was of type PARENT_CHANGED via a call to - * Container.add, the parent returned is the parent + * Returns the parent of the Component returned by + * {@code getChanged()}. For a HIERARCHY_CHANGED event where the + * change was of type PARENT_CHANGED via a call to + * {@code Container.add}, the parent returned is the parent * after the add operation. For a HIERARCHY_CHANGED event where - * the change was of type PARENT_CHANGED via a call to - * Container.remove, the parent returned is the parent + * the change was of type PARENT_CHANGED via a call to + * {@code Container.remove}, the parent returned is the parent * before the remove operation. For all other events and types, * the parent returned is the parent during the operation. * diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyListener.java b/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyListener.java index b681b54212e..b3fb3640343 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/HierarchyListener.java @@ -32,15 +32,15 @@ import java.util.EventListener; * The class that is interested in processing a hierarchy changed event * should implement this interface. * The listener object created from that class is then registered with a - * Component using the Component's addHierarchyListener + * Component using the Component's {@code addHierarchyListener} * method. When the hierarchy to which the Component belongs changes, the - * hierarchyChanged method in the listener object is invoked, - * and the HierarchyEvent is passed to it. + * {@code hierarchyChanged} method in the listener object is invoked, + * and the {@code HierarchyEvent} is passed to it. *

          * Hierarchy events are provided for notification purposes ONLY; * The AWT will automatically handle changes to the hierarchy internally so * that GUI layout, displayability, and visibility work properly regardless - * of whether a program registers a HierarchyListener or not. + * of whether a program registers a {@code HierarchyListener} or not. * * @author David Mendenhall * @see HierarchyEvent @@ -49,7 +49,7 @@ import java.util.EventListener; public interface HierarchyListener extends EventListener { /** * Called when the hierarchy has been changed. To discern the actual - * type of change, call HierarchyEvent.getChangeFlags(). + * type of change, call {@code HierarchyEvent.getChangeFlags()}. * * @param e the event to be processed * @see HierarchyEvent#getChangeFlags() diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/InputEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/InputEvent.java index ecf993530d3..d332d2d2735 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/InputEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/InputEvent.java @@ -315,8 +315,8 @@ public abstract class InputEvent extends ComponentEvent { * Constructs an InputEvent object with the specified source component, * modifiers, and type. *

          This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * * @param source the object where the event originated * @param id the integer that identifies the event type. @@ -336,7 +336,7 @@ public abstract class InputEvent extends ComponentEvent { * Passing negative parameter * is not recommended. * Zero value means that no modifiers were passed - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getSource() * @see #getID() * @see #getWhen() @@ -442,16 +442,16 @@ public abstract class InputEvent extends ComponentEvent { * button 2, and then releases them in the same order, * the following sequence of events is generated: *

          -     *    MOUSE_PRESSED:  BUTTON1_DOWN_MASK
          -     *    MOUSE_PRESSED:  BUTTON1_DOWN_MASK | BUTTON2_DOWN_MASK
          -     *    MOUSE_RELEASED: BUTTON2_DOWN_MASK
          -     *    MOUSE_CLICKED:  BUTTON2_DOWN_MASK
          -     *    MOUSE_RELEASED:
          -     *    MOUSE_CLICKED:
          +     *    {@code MOUSE_PRESSED}:  {@code BUTTON1_DOWN_MASK}
          +     *    {@code MOUSE_PRESSED}:  {@code BUTTON1_DOWN_MASK | BUTTON2_DOWN_MASK}
          +     *    {@code MOUSE_RELEASED}: {@code BUTTON2_DOWN_MASK}
          +     *    {@code MOUSE_CLICKED}:  {@code BUTTON2_DOWN_MASK}
          +     *    {@code MOUSE_RELEASED}:
          +     *    {@code MOUSE_CLICKED}:
                * 
          *

          * It is not recommended to compare the return value of this method - * using == because new modifiers can be added in the future. + * using {@code ==} because new modifiers can be added in the future. * For example, the appropriate way to check that SHIFT and BUTTON1 are * down, but CTRL is up is demonstrated by the following code: *

          @@ -494,7 +494,7 @@ public abstract class InputEvent extends ComponentEvent {
                * Returns a String describing the extended modifier keys and
                * mouse buttons, such as "Shift", "Button1", or "Ctrl+Shift".
                * These strings can be localized by changing the
          -     * awt.properties file.
          +     * {@code awt.properties} file.
                * 

          * Note that passing negative parameter is incorrect, * and will cause the returning an unspecified string. diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java index e1ec9abbcf5..00e6413fea1 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java @@ -106,45 +106,45 @@ public class InputMethodEvent extends AWTEvent { private transient TextHitInfo visiblePosition; /** - * Constructs an InputMethodEvent with the specified + * Constructs an {@code InputMethodEvent} with the specified * source component, type, time, text, caret, and visiblePosition. *

          * The offsets of caret and visiblePosition are relative to the current - * composed text; that is, the composed text within text - * if this is an INPUT_METHOD_TEXT_CHANGED event, - * the composed text within the text of the - * preceding INPUT_METHOD_TEXT_CHANGED event otherwise. - *

          Note that passing in an invalid id results in + * composed text; that is, the composed text within {@code text} + * if this is an {@code INPUT_METHOD_TEXT_CHANGED} event, + * the composed text within the {@code text} of the + * preceding {@code INPUT_METHOD_TEXT_CHANGED} event otherwise. + *

          Note that passing in an invalid {@code id} results in * unspecified behavior. This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * * @param source the object where the event originated * @param id the event type * @param when a long integer that specifies the time the event occurred * @param text the combined committed and composed text, - * committed text first; must be null - * when the event type is CARET_POSITION_CHANGED; - * may be null for - * INPUT_METHOD_TEXT_CHANGED if there's no + * committed text first; must be {@code null} + * when the event type is {@code CARET_POSITION_CHANGED}; + * may be {@code null} for + * {@code INPUT_METHOD_TEXT_CHANGED} if there's no * committed or composed text * @param committedCharacterCount the number of committed * characters in the text * @param caret the caret (a.k.a. insertion point); - * null if there's no caret within current + * {@code null} if there's no caret within current * composed text * @param visiblePosition the position that's most important - * to be visible; null if there's no + * to be visible; {@code null} if there's no * recommendation for a visible position within current * composed text - * @throws IllegalArgumentException if id is not + * @throws IllegalArgumentException if {@code id} is not * in the range - * INPUT_METHOD_FIRST..INPUT_METHOD_LAST; - * or if id is CARET_POSITION_CHANGED and - * text is not null; - * or if committedCharacterCount is not in the range - * 0..(text.getEndIndex() - text.getBeginIndex()) - * @throws IllegalArgumentException if source is null + * {@code INPUT_METHOD_FIRST}..{@code INPUT_METHOD_LAST}; + * or if id is {@code CARET_POSITION_CHANGED} and + * {@code text} is not {@code null}; + * or if {@code committedCharacterCount} is not in the range + * {@code 0}..{@code (text.getEndIndex() - text.getBeginIndex())} + * @throws IllegalArgumentException if {@code source} is null * * @since 1.4 */ @@ -177,46 +177,46 @@ public class InputMethodEvent extends AWTEvent { } /** - * Constructs an InputMethodEvent with the specified + * Constructs an {@code InputMethodEvent} with the specified * source component, type, text, caret, and visiblePosition. *

          * The offsets of caret and visiblePosition are relative to the current - * composed text; that is, the composed text within text - * if this is an INPUT_METHOD_TEXT_CHANGED event, - * the composed text within the text of the - * preceding INPUT_METHOD_TEXT_CHANGED event otherwise. + * composed text; that is, the composed text within {@code text} + * if this is an {@code INPUT_METHOD_TEXT_CHANGED} event, + * the composed text within the {@code text} of the + * preceding {@code INPUT_METHOD_TEXT_CHANGED} event otherwise. * The time stamp for this event is initialized by invoking * {@link java.awt.EventQueue#getMostRecentEventTime()}. - *

          Note that passing in an invalid id results in + *

          Note that passing in an invalid {@code id} results in * unspecified behavior. This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * * @param source the object where the event originated * @param id the event type * @param text the combined committed and composed text, - * committed text first; must be null - * when the event type is CARET_POSITION_CHANGED; - * may be null for - * INPUT_METHOD_TEXT_CHANGED if there's no + * committed text first; must be {@code null} + * when the event type is {@code CARET_POSITION_CHANGED}; + * may be {@code null} for + * {@code INPUT_METHOD_TEXT_CHANGED} if there's no * committed or composed text * @param committedCharacterCount the number of committed * characters in the text * @param caret the caret (a.k.a. insertion point); - * null if there's no caret within current + * {@code null} if there's no caret within current * composed text * @param visiblePosition the position that's most important - * to be visible; null if there's no + * to be visible; {@code null} if there's no * recommendation for a visible position within current * composed text - * @throws IllegalArgumentException if id is not + * @throws IllegalArgumentException if {@code id} is not * in the range - * INPUT_METHOD_FIRST..INPUT_METHOD_LAST; - * or if id is CARET_POSITION_CHANGED and - * text is not null; - * or if committedCharacterCount is not in the range - * 0..(text.getEndIndex() - text.getBeginIndex()) - * @throws IllegalArgumentException if source is null + * {@code INPUT_METHOD_FIRST}..{@code INPUT_METHOD_LAST}; + * or if id is {@code CARET_POSITION_CHANGED} and + * {@code text} is not {@code null}; + * or if {@code committedCharacterCount} is not in the range + * {@code 0}..{@code (text.getEndIndex() - text.getBeginIndex())} + * @throws IllegalArgumentException if {@code source} is null */ public InputMethodEvent(Component source, int id, AttributedCharacterIterator text, int committedCharacterCount, @@ -228,39 +228,39 @@ public class InputMethodEvent extends AWTEvent { } /** - * Constructs an InputMethodEvent with the + * Constructs an {@code InputMethodEvent} with the * specified source component, type, caret, and visiblePosition. - * The text is set to null, - * committedCharacterCount to 0. + * The text is set to {@code null}, + * {@code committedCharacterCount} to 0. *

          - * The offsets of caret and visiblePosition + * The offsets of {@code caret} and {@code visiblePosition} * are relative to the current composed text; that is, - * the composed text within the text of the - * preceding INPUT_METHOD_TEXT_CHANGED event if the - * event being constructed as a CARET_POSITION_CHANGED event. - * For an INPUT_METHOD_TEXT_CHANGED event without text, - * caret and visiblePosition must be - * null. + * the composed text within the {@code text} of the + * preceding {@code INPUT_METHOD_TEXT_CHANGED} event if the + * event being constructed as a {@code CARET_POSITION_CHANGED} event. + * For an {@code INPUT_METHOD_TEXT_CHANGED} event without text, + * {@code caret} and {@code visiblePosition} must be + * {@code null}. * The time stamp for this event is initialized by invoking * {@link java.awt.EventQueue#getMostRecentEventTime()}. - *

          Note that passing in an invalid id results in + *

          Note that passing in an invalid {@code id} results in * unspecified behavior. This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * * @param source the object where the event originated * @param id the event type * @param caret the caret (a.k.a. insertion point); - * null if there's no caret within current + * {@code null} if there's no caret within current * composed text * @param visiblePosition the position that's most important - * to be visible; null if there's no + * to be visible; {@code null} if there's no * recommendation for a visible position within current * composed text - * @throws IllegalArgumentException if id is not + * @throws IllegalArgumentException if {@code id} is not * in the range - * INPUT_METHOD_FIRST..INPUT_METHOD_LAST - * @throws IllegalArgumentException if source is null + * {@code INPUT_METHOD_FIRST}..{@code INPUT_METHOD_LAST} + * @throws IllegalArgumentException if {@code source} is null */ public InputMethodEvent(Component source, int id, TextHitInfo caret, TextHitInfo visiblePosition) { @@ -271,7 +271,7 @@ public class InputMethodEvent extends AWTEvent { /** * Gets the combined committed and composed text. - * Characters from index 0 to index getCommittedCharacterCount() - 1 are committed + * Characters from index 0 to index {@code getCommittedCharacterCount() - 1} are committed * text, the remaining characters are composed text. * * @return the text. @@ -295,9 +295,9 @@ public class InputMethodEvent extends AWTEvent { *

          * The offset of the caret is relative to the current * composed text; that is, the composed text within getText() - * if this is an INPUT_METHOD_TEXT_CHANGED event, + * if this is an {@code INPUT_METHOD_TEXT_CHANGED} event, * the composed text within getText() of the - * preceding INPUT_METHOD_TEXT_CHANGED event otherwise. + * preceding {@code INPUT_METHOD_TEXT_CHANGED} event otherwise. * * @return the caret (a.k.a. insertion point). * Null if there's no caret within current composed text. @@ -311,9 +311,9 @@ public class InputMethodEvent extends AWTEvent { *

          * The offset of the visible position is relative to the current * composed text; that is, the composed text within getText() - * if this is an INPUT_METHOD_TEXT_CHANGED event, + * if this is an {@code INPUT_METHOD_TEXT_CHANGED} event, * the composed text within getText() of the - * preceding INPUT_METHOD_TEXT_CHANGED event otherwise. + * preceding {@code INPUT_METHOD_TEXT_CHANGED} event otherwise. * * @return the position that's most important to be visible. * Null if there's no recommendation for a visible position within current composed text. @@ -411,7 +411,7 @@ public class InputMethodEvent extends AWTEvent { } /** - * Initializes the when field if it is not present in the + * Initializes the {@code when} field if it is not present in the * object input stream. In that case, the field will be initialized by * invoking {@link java.awt.EventQueue#getMostRecentEventTime()}. */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ItemEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/ItemEvent.java index 34e3b5b01db..37a0c5f0084 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ItemEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ItemEvent.java @@ -32,12 +32,12 @@ import java.awt.ItemSelectable; * A semantic event which indicates that an item was selected or deselected. * This high-level event is generated by an ItemSelectable object (such as a * List) when an item is selected or deselected by the user. - * The event is passed to every ItemListener object which + * The event is passed to every {@code ItemListener} object which * registered to receive such events using the component's - * addItemListener method. + * {@code addItemListener} method. *

          - * The object that implements the ItemListener interface gets - * this ItemEvent when the event occurs. The listener is + * The object that implements the {@code ItemListener} interface gets + * this {@code ItemEvent} when the event occurs. The listener is * spared the details of processing individual mouse movements and mouse * clicks, and can instead process a "meaningful" (semantic) event like * "item selected" or "item deselected". @@ -98,7 +98,7 @@ public class ItemEvent extends AWTEvent { Object item; /** - * stateChange indicates whether the item + * {@code stateChange} indicates whether the {@code item} * was selected or deselected. * * @serial @@ -112,12 +112,12 @@ public class ItemEvent extends AWTEvent { private static final long serialVersionUID = -608708132447206933L; /** - * Constructs an ItemEvent object. + * Constructs an {@code ItemEvent} object. *

          This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The ItemSelectable object + * @param source The {@code ItemSelectable} object * that originated the event * @param id The integer that identifies the event type. * For information on allowable values, see @@ -127,7 +127,7 @@ public class ItemEvent extends AWTEvent { * selected or deselected. * For information on allowable values, see * the class description for {@link ItemEvent} - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getItemSelectable() * @see #getID() * @see #getStateChange() diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/ItemListener.java b/jdk/src/java.desktop/share/classes/java/awt/event/ItemListener.java index 8d2cde627cc..c1533a3c3f8 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/ItemListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/ItemListener.java @@ -32,9 +32,9 @@ import java.util.EventListener; * The class that is interested in processing an item event * implements this interface. The object created with that * class is then registered with a component using the - * component's addItemListener method. When an + * component's {@code addItemListener} method. When an * item-selection event occurs, the listener object's - * itemStateChanged method is invoked. + * {@code itemStateChanged} method is invoked. * * @author Amy Fowler * diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/KeyAdapter.java b/jdk/src/java.desktop/share/classes/java/awt/event/KeyAdapter.java index 846da09af14..12a8a6544a1 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/KeyAdapter.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/KeyAdapter.java @@ -30,17 +30,17 @@ package java.awt.event; * The methods in this class are empty. This class exists as * convenience for creating listener objects. *

          - * Extend this class to create a KeyEvent listener + * Extend this class to create a {@code KeyEvent} listener * and override the methods for the events of interest. (If you implement the - * KeyListener interface, you have to define all of + * {@code KeyListener} interface, you have to define all of * the methods in it. This abstract class defines null methods for them * all, so you can only have to define methods for events you care about.) *

          * Create a listener object using the extended class and then register it with - * a component using the component's addKeyListener + * a component using the component's {@code addKeyListener} * method. When a key is pressed, released, or typed, * the relevant method in the listener object is invoked, - * and the KeyEvent is passed to it. + * and the {@code KeyEvent} is passed to it. * * @author Carl Quinn * diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/KeyEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/KeyEvent.java index b8cbea6052e..f103d525271 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/KeyEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/KeyEvent.java @@ -37,12 +37,12 @@ import sun.awt.AWTAccessor; *

          * This low-level event is generated by a component object (such as a text * field) when a key is pressed, released, or typed. - * The event is passed to every KeyListener - * or KeyAdapter object which registered to receive such - * events using the component's addKeyListener method. - * (KeyAdapter objects implement the - * KeyListener interface.) Each such listener object - * gets this KeyEvent when the event occurs. + * The event is passed to every {@code KeyListener} + * or {@code KeyAdapter} object which registered to receive such + * events using the component's {@code addKeyListener} method. + * ({@code KeyAdapter} objects implement the + * {@code KeyListener} interface.) Each such listener object + * gets this {@code KeyEvent} when the event occurs. *

          * "Key typed" events are higher-level and generally do not depend on * the platform or keyboard layout. They are generated when a Unicode character @@ -974,7 +974,7 @@ public class KeyEvent extends InputEvent { /** * A constant indicating that the keyLocation is indeterminate * or not relevant. - * KEY_TYPED events do not have a keyLocation; this value + * {@code KEY_TYPED} events do not have a keyLocation; this value * is used instead. * @since 1.4 */ @@ -1028,7 +1028,7 @@ public class KeyEvent extends InputEvent { int keyCode; /** - * keyChar is a valid unicode character + * {@code keyChar} is a valid unicode character * that is fired by a key or a key combination on * a keyboard. * @@ -1045,9 +1045,9 @@ public class KeyEvent extends InputEvent { * right shift keys. Additionally, some keys occur on the numeric * keypad. This variable is used to distinguish such keys. * - * The only legal values are KEY_LOCATION_UNKNOWN, - * KEY_LOCATION_STANDARD, KEY_LOCATION_LEFT, - * KEY_LOCATION_RIGHT, and KEY_LOCATION_NUMPAD. + * The only legal values are {@code KEY_LOCATION_UNKNOWN}, + * {@code KEY_LOCATION_STANDARD}, {@code KEY_LOCATION_LEFT}, + * {@code KEY_LOCATION_RIGHT}, and {@code KEY_LOCATION_NUMPAD}. * * @serial * @see #getKeyLocation() @@ -1115,12 +1115,12 @@ public class KeyEvent extends InputEvent { } /** - * Constructs a KeyEvent object. + * Constructs a {@code KeyEvent} object. *

          This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Component that originated the event + * @param source The {@code Component} that originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link KeyEvent} @@ -1142,19 +1142,19 @@ public class KeyEvent extends InputEvent { * CHAR_UNDEFINED (for key-pressed and key-released * events which do not map to a valid Unicode character) * @param keyLocation Identifies the key location. The only legal - * values are KEY_LOCATION_UNKNOWN, - * KEY_LOCATION_STANDARD, KEY_LOCATION_LEFT, - * KEY_LOCATION_RIGHT, and KEY_LOCATION_NUMPAD. + * values are {@code KEY_LOCATION_UNKNOWN}, + * {@code KEY_LOCATION_STANDARD}, {@code KEY_LOCATION_LEFT}, + * {@code KEY_LOCATION_RIGHT}, and {@code KEY_LOCATION_NUMPAD}. * @throws IllegalArgumentException - * if id is KEY_TYPED and - * keyChar is CHAR_UNDEFINED; - * or if id is KEY_TYPED and - * keyCode is not VK_UNDEFINED; - * or if id is KEY_TYPED and - * keyLocation is not KEY_LOCATION_UNKNOWN; - * or if keyLocation is not one of the legal + * if {@code id} is {@code KEY_TYPED} and + * {@code keyChar} is {@code CHAR_UNDEFINED}; + * or if {@code id} is {@code KEY_TYPED} and + * {@code keyCode} is not {@code VK_UNDEFINED}; + * or if {@code id} is {@code KEY_TYPED} and + * {@code keyLocation} is not {@code KEY_LOCATION_UNKNOWN}; + * or if {@code keyLocation} is not one of the legal * values enumerated above. - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code source} is null * @see #getSource() * @see #getID() * @see #getWhen() @@ -1196,12 +1196,12 @@ public class KeyEvent extends InputEvent { } /** - * Constructs a KeyEvent object. + * Constructs a {@code KeyEvent} object. *

          This method throws an - * IllegalArgumentException if source - * is null. + * {@code IllegalArgumentException} if {@code source} + * is {@code null}. * - * @param source The Component that originated the event + * @param source The {@code Component} that originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link KeyEvent} @@ -1222,12 +1222,12 @@ public class KeyEvent extends InputEvent { * @param keyChar The Unicode character generated by this event, or * CHAR_UNDEFINED (for key-pressed and key-released * events which do not map to a valid Unicode character) - * @throws IllegalArgumentException if id is - * KEY_TYPED and keyChar is - * CHAR_UNDEFINED; or if id is - * KEY_TYPED and keyCode is not - * VK_UNDEFINED - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if {@code id} is + * {@code KEY_TYPED} and {@code keyChar} is + * {@code CHAR_UNDEFINED}; or if {@code id} is + * {@code KEY_TYPED} and {@code keyCode} is not + * {@code VK_UNDEFINED} + * @throws IllegalArgumentException if {@code source} is null * @see #getSource() * @see #getID() * @see #getWhen() @@ -1243,7 +1243,7 @@ public class KeyEvent extends InputEvent { /** * @deprecated as of JDK1.1; use {@link #KeyEvent(Component, int, long, int, int, char)} instead - * @param source The Component that originated the event + * @param source The {@code Component} that originated the event * @param id An integer indicating the type of event. * For information on allowable values, see * the class description for {@link KeyEvent} @@ -1272,8 +1272,8 @@ public class KeyEvent extends InputEvent { * Returns the integer keyCode associated with the key in this event. * * @return the integer code for an actual key on the keyboard. - * (For KEY_TYPED events, the keyCode is - * VK_UNDEFINED.) + * (For {@code KEY_TYPED} events, the keyCode is + * {@code VK_UNDEFINED}.) */ public int getKeyCode() { return keyCode; @@ -1290,17 +1290,17 @@ public class KeyEvent extends InputEvent { /** * Returns the character associated with the key in this event. - * For example, the KEY_TYPED event for shift + "a" + * For example, the {@code KEY_TYPED} event for shift + "a" * returns the value for "A". *

          - * KEY_PRESSED and KEY_RELEASED events + * {@code KEY_PRESSED} and {@code KEY_RELEASED} events * are not intended for reporting of character input. Therefore, * the values returned by this method are guaranteed to be - * meaningful only for KEY_TYPED events. + * meaningful only for {@code KEY_TYPED} events. * * @return the Unicode character defined for this key event. * If no valid Unicode character exists for this key event, - * CHAR_UNDEFINED is returned. + * {@code CHAR_UNDEFINED} is returned. */ public char getKeyChar() { return keyChar; @@ -1322,7 +1322,7 @@ public class KeyEvent extends InputEvent { *

          * NOTE: use of this method is not recommended, because many AWT * implementations do not recognize modifier changes. This is - * especially true for KEY_TYPED events where the shift + * especially true for {@code KEY_TYPED} events where the shift * modifier is changed. * * @param modifiers an integer combination of the modifier constants. @@ -1347,8 +1347,8 @@ public class KeyEvent extends InputEvent { * keypad. This provides a way of distinguishing such keys. * * @return the location of the key that was pressed or released. - * Always returns KEY_LOCATION_UNKNOWN for - * KEY_TYPED events. + * Always returns {@code KEY_LOCATION_UNKNOWN} for + * {@code KEY_TYPED} events. * @since 1.4 */ public int getKeyLocation() { @@ -1541,15 +1541,15 @@ public class KeyEvent extends InputEvent { } /** - * Returns a String describing the modifier key(s), + * Returns a {@code String} describing the modifier key(s), * such as "Shift", or "Ctrl+Shift". These strings can be - * localized by changing the awt.properties file. + * localized by changing the {@code awt.properties} file. *

          - * Note that InputEvent.ALT_MASK and - * InputEvent.BUTTON2_MASK have the same value, + * Note that {@code InputEvent.ALT_MASK} and + * {@code InputEvent.BUTTON2_MASK} have the same value, * so the string "Alt" is returned for both modifiers. Likewise, - * InputEvent.META_MASK and - * InputEvent.BUTTON3_MASK have the same value, + * {@code InputEvent.META_MASK} and + * {@code InputEvent.BUTTON3_MASK} have the same value, * so the string "Meta" is returned for both modifiers. * * @param modifiers the modifier mask to be processed @@ -1595,8 +1595,8 @@ public class KeyEvent extends InputEvent { * Typically an action key does not fire a unicode character and is * not a modifier key. * - * @return true if the key is an "action" key, - * false otherwise + * @return {@code true} if the key is an "action" key, + * {@code false} otherwise */ public boolean isActionKey() { switch (keyCode) { diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/KeyListener.java b/jdk/src/java.desktop/share/classes/java/awt/event/KeyListener.java index 1a8ba31bae0..622c6b43991 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/KeyListener.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/KeyListener.java @@ -31,14 +31,14 @@ import java.util.EventListener; * The listener interface for receiving keyboard events (keystrokes). * The class that is interested in processing a keyboard event * either implements this interface (and all the methods it - * contains) or extends the abstract KeyAdapter class + * contains) or extends the abstract {@code KeyAdapter} class * (overriding only the methods of interest). *

          * The listener object created from that class is then registered with a - * component using the component's addKeyListener + * component using the component's {@code addKeyListener} * method. A keyboard event is generated when a key is pressed, released, * or typed. The relevant method in the listener - * object is then invoked, and the KeyEvent is passed to it. + * object is then invoked, and the {@code KeyEvent} is passed to it. * * @author Carl Quinn * diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/MouseEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/MouseEvent.java index de522828a4d..2ae987b8144 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/MouseEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/MouseEvent.java @@ -526,13 +526,15 @@ public class MouseEvent extends InputEvent { * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} * if the mouse has more than three buttons. *

        - * @throws IllegalArgumentException if {@code button} is less then zero + * @throws IllegalArgumentException if {@code button} is less than zero * @throws IllegalArgumentException if {@code source} is null - * @throws IllegalArgumentException if {@code button} is greater then BUTTON3 and the support for extended mouse buttons is + * @throws IllegalArgumentException if {@code button} is greater than BUTTON3 + * and the support for extended mouse buttons is * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java - * @throws IllegalArgumentException if {@code button} is greater then the - * {@link java.awt.MouseInfo#getNumberOfButtons() current number of buttons} and the support - * for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} + * @throws IllegalArgumentException if {@code button} is greater than the + * {@link java.awt.MouseInfo#getNumberOfButtons() current number of buttons} + * and the support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} * by Java * @throws IllegalArgumentException if an invalid {@code button} * value is passed in @@ -701,12 +703,14 @@ public class MouseEvent extends InputEvent { * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} * if the mouse has more than three buttons. *
      - * @throws IllegalArgumentException if {@code button} is less then zero + * @throws IllegalArgumentException if {@code button} is less than zero * @throws IllegalArgumentException if {@code source} is null - * @throws IllegalArgumentException if {@code button} is greater then BUTTON3 and the support for extended mouse buttons is + * @throws IllegalArgumentException if {@code button} is greater than BUTTON3 + * and the support for extended mouse buttons is * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java - * @throws IllegalArgumentException if {@code button} is greater then the - * {@link java.awt.MouseInfo#getNumberOfButtons() current number of buttons} and the support + * @throws IllegalArgumentException if {@code button} is greater than the + * {@link java.awt.MouseInfo#getNumberOfButtons() + * current number of buttons} and the support * for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} * by Java * @throws IllegalArgumentException if an invalid {@code button} @@ -865,7 +869,8 @@ public class MouseEvent extends InputEvent { *
    5. 2 ({@code BUTTON2}) *
    6. 3 ({@code BUTTON3}) * - * Button numbers greater then {@code BUTTON3} have no constant identifier. So if a mouse with five buttons is + * Button numbers greater than {@code BUTTON3} have no constant identifier. + * So if a mouse with five buttons is * installed, this method may return the following values: * *

      * A Java Print Service instance is allowed to support any other doc flavors @@ -390,7 +390,7 @@ import java.io.Serializable; *

      * Class DocFlavor in package javax.print.data is similar to class * {@link java.awt.datatransfer.DataFlavor DataFlavor}. Class - * DataFlavor + * {@code DataFlavor} * is not used in the Java Print Service (JPS) API * for three reasons which are all rooted in allowing the JPS API to be * shared by other print services APIs which may need to run on Java profiles @@ -401,13 +401,13 @@ import java.io.Serializable; * AWT. * *

    7. - * The implementation of class java.awt.datatransfer.DataFlavor + * The implementation of class {@code java.awt.datatransfer.DataFlavor} * does not guarantee that equivalent data flavors will have the same * serialized representation. DocFlavor does, and can be used in services * which need this. * *
    8. - * The implementation of class java.awt.datatransfer.DataFlavor + * The implementation of class {@code java.awt.datatransfer.DataFlavor} * includes a human presentable name as part of the serialized representation. * This is not appropriate as part of a service matching constraint. * @@ -488,10 +488,10 @@ public class DocFlavor implements Serializable, Cloneable { * @param className Fully-qualified representation class name. * * @exception NullPointerException - * (unchecked exception) Thrown if mimeType is null or - * className is null. + * (unchecked exception) Thrown if {@code mimeType} is null or + * {@code className} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if mimeType does not + * (unchecked exception) Thrown if {@code mimeType} does not * obey the syntax for a MIME media type string. */ public DocFlavor(String mimeType, String className) { @@ -528,7 +528,7 @@ public class DocFlavor implements Serializable, Cloneable { } /** - * Returns a String representing a MIME + * Returns a {@code String} representing a MIME * parameter. * Mime types may include parameters which are usually optional. * The charset for text types is a commonly useful example. @@ -555,7 +555,7 @@ public class DocFlavor implements Serializable, Cloneable { } /** - * Converts this DocFlavor to a string. + * Converts this {@code DocFlavor} to a string. * * @return MIME type string based on the canonical form. Each parameter * value is enclosed in quotes. @@ -576,7 +576,7 @@ public class DocFlavor implements Serializable, Cloneable { /** * Determines if this doc flavor object is equal to the given object. * The two are equal if the given object is not null, is an instance - * of DocFlavor, has a MIME type equivalent to this doc + * of {@code DocFlavor}, has a MIME type equivalent to this doc * flavor object's MIME type (that is, the MIME types have the same media * type, media subtype, and parameters), and has the same representation * class name as this doc flavor object. Thus, if two doc flavor objects' @@ -588,7 +588,7 @@ public class DocFlavor implements Serializable, Cloneable { * * @param obj Object to test. * - * @return True if this doc flavor object equals obj, false + * @return True if this doc flavor object equals {@code obj}, false * otherwise. */ public boolean equals(Object obj) { @@ -642,7 +642,7 @@ public class DocFlavor implements Serializable, Cloneable { /** * Class DocFlavor.BYTE_ARRAY provides predefined static constant * DocFlavor objects for example doc flavors using a byte array - * (byte[]) as the print data representation class. + * ({@code byte[]}) as the print data representation class. * * @author Alan Kaminsky */ @@ -652,14 +652,14 @@ public class DocFlavor implements Serializable, Cloneable { /** * Constructs a new doc flavor with the given MIME type and a print - * data representation class name of "[B" (byte array). + * data representation class name of {@code "[B"} (byte array). * * @param mimeType MIME media type string. * * @exception NullPointerException - * (unchecked exception) Thrown if mimeType is null. + * (unchecked exception) Thrown if {@code mimeType} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if mimeType does not + * (unchecked exception) Thrown if {@code mimeType} does not * obey the syntax for a MIME media type string. */ public BYTE_ARRAY (String mimeType) { @@ -667,19 +667,19 @@ public class DocFlavor implements Serializable, Cloneable { } /** - * Doc flavor with MIME type = "text/plain", + * Doc flavor with MIME type = {@code "text/plain"}, * encoded in the host platform encoding. * See {@link DocFlavor#hostEncoding hostEncoding} * Print data representation class name = - * "[B" (byte array). + * {@code "[B"} (byte array). */ public static final BYTE_ARRAY TEXT_PLAIN_HOST = new BYTE_ARRAY ("text/plain; charset="+hostEncoding); /** * Doc flavor with MIME type = - * "text/plain; charset=utf-8", - * print data representation class name = "[B" (byte + * {@code "text/plain; charset=utf-8"}, + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY TEXT_PLAIN_UTF_8 = @@ -687,8 +687,8 @@ public class DocFlavor implements Serializable, Cloneable { /** * Doc flavor with MIME type = - * "text/plain; charset=utf-16", - * print data representation class name = "[B" (byte + * {@code "text/plain; charset=utf-16"}, + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY TEXT_PLAIN_UTF_16 = @@ -697,9 +697,9 @@ public class DocFlavor implements Serializable, Cloneable { /** * Doc flavor with MIME type = - * "text/plain; charset=utf-16be" + * {@code "text/plain; charset=utf-16be"} * (big-endian byte ordering), - * print data representation class name = "[B" (byte + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY TEXT_PLAIN_UTF_16BE = @@ -707,9 +707,9 @@ public class DocFlavor implements Serializable, Cloneable { /** * Doc flavor with MIME type = - * "text/plain; charset=utf-16le" + * {@code "text/plain; charset=utf-16le"} * (little-endian byte ordering), - * print data representation class name = "[B" (byte + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY TEXT_PLAIN_UTF_16LE = @@ -717,28 +717,28 @@ public class DocFlavor implements Serializable, Cloneable { /** * Doc flavor with MIME type = - * "text/plain; charset=us-ascii", + * {@code "text/plain; charset=us-ascii"}, * print data representation class name = - * "[B" (byte array). + * {@code "[B"} (byte array). */ public static final BYTE_ARRAY TEXT_PLAIN_US_ASCII = new BYTE_ARRAY ("text/plain; charset=us-ascii"); /** - * Doc flavor with MIME type = "text/html", + * Doc flavor with MIME type = {@code "text/html"}, * encoded in the host platform encoding. * See {@link DocFlavor#hostEncoding hostEncoding} * Print data representation class name = - * "[B" (byte array). + * {@code "[B"} (byte array). */ public static final BYTE_ARRAY TEXT_HTML_HOST = new BYTE_ARRAY ("text/html; charset="+hostEncoding); /** * Doc flavor with MIME type = - * "text/html; charset=utf-8", - * print data representation class name = "[B" (byte + * {@code "text/html; charset=utf-8"}, + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY TEXT_HTML_UTF_8 = @@ -746,8 +746,8 @@ public class DocFlavor implements Serializable, Cloneable { /** * Doc flavor with MIME type = - * "text/html; charset=utf-16", - * print data representation class name = "[B" (byte + * {@code "text/html; charset=utf-16"}, + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY TEXT_HTML_UTF_16 = @@ -755,9 +755,9 @@ public class DocFlavor implements Serializable, Cloneable { /** * Doc flavor with MIME type = - * "text/html; charset=utf-16be" + * {@code "text/html; charset=utf-16be"} * (big-endian byte ordering), - * print data representation class name = "[B" (byte + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY TEXT_HTML_UTF_16BE = @@ -765,9 +765,9 @@ public class DocFlavor implements Serializable, Cloneable { /** * Doc flavor with MIME type = - * "text/html; charset=utf-16le" + * {@code "text/html; charset=utf-16le"} * (little-endian byte ordering), - * print data representation class name = "[B" (byte + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY TEXT_HTML_UTF_16LE = @@ -775,58 +775,58 @@ public class DocFlavor implements Serializable, Cloneable { /** * Doc flavor with MIME type = - * "text/html; charset=us-ascii", + * {@code "text/html; charset=us-ascii"}, * print data representation class name = - * "[B" (byte array). + * {@code "[B"} (byte array). */ public static final BYTE_ARRAY TEXT_HTML_US_ASCII = new BYTE_ARRAY ("text/html; charset=us-ascii"); /** - * Doc flavor with MIME type = "application/pdf", print - * data representation class name = "[B" (byte array). + * Doc flavor with MIME type = {@code "application/pdf"}, print + * data representation class name = {@code "[B"} (byte array). */ public static final BYTE_ARRAY PDF = new BYTE_ARRAY ("application/pdf"); /** - * Doc flavor with MIME type = "application/postscript", - * print data representation class name = "[B" (byte + * Doc flavor with MIME type = {@code "application/postscript"}, + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY POSTSCRIPT = new BYTE_ARRAY ("application/postscript"); /** - * Doc flavor with MIME type = "application/vnd.hp-PCL", - * print data representation class name = "[B" (byte + * Doc flavor with MIME type = {@code "application/vnd.hp-PCL"}, + * print data representation class name = {@code "[B"} (byte * array). */ public static final BYTE_ARRAY PCL = new BYTE_ARRAY ("application/vnd.hp-PCL"); /** - * Doc flavor with MIME type = "image/gif", print data - * representation class name = "[B" (byte array). + * Doc flavor with MIME type = {@code "image/gif"}, print data + * representation class name = {@code "[B"} (byte array). */ public static final BYTE_ARRAY GIF = new BYTE_ARRAY ("image/gif"); /** - * Doc flavor with MIME type = "image/jpeg", print data - * representation class name = "[B" (byte array). + * Doc flavor with MIME type = {@code "image/jpeg"}, print data + * representation class name = {@code "[B"} (byte array). */ public static final BYTE_ARRAY JPEG = new BYTE_ARRAY ("image/jpeg"); /** - * Doc flavor with MIME type = "image/png", print data - * representation class name = "[B" (byte array). + * Doc flavor with MIME type = {@code "image/png"}, print data + * representation class name = {@code "[B"} (byte array). */ public static final BYTE_ARRAY PNG = new BYTE_ARRAY ("image/png"); /** * Doc flavor with MIME type = - * "application/octet-stream", - * print data representation class name = "[B" (byte + * {@code "application/octet-stream"}, + * print data representation class name = {@code "[B"} (byte * array). The client must determine that data described * using this DocFlavor is valid for the printer. */ @@ -850,14 +850,14 @@ public class DocFlavor implements Serializable, Cloneable { /** * Constructs a new doc flavor with the given MIME type and a print * data representation class name of - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). * * @param mimeType MIME media type string. * * @exception NullPointerException - * (unchecked exception) Thrown if mimeType is null. + * (unchecked exception) Thrown if {@code mimeType} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if mimeType does not + * (unchecked exception) Thrown if {@code mimeType} does not * obey the syntax for a MIME media type string. */ public INPUT_STREAM (String mimeType) { @@ -865,169 +865,169 @@ public class DocFlavor implements Serializable, Cloneable { } /** - * Doc flavor with MIME type = "text/plain", + * Doc flavor with MIME type = {@code "text/plain"}, * encoded in the host platform encoding. * See {@link DocFlavor#hostEncoding hostEncoding} * Print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_PLAIN_HOST = new INPUT_STREAM ("text/plain; charset="+hostEncoding); /** * Doc flavor with MIME type = - * "text/plain; charset=utf-8", + * {@code "text/plain; charset=utf-8"}, * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_PLAIN_UTF_8 = new INPUT_STREAM ("text/plain; charset=utf-8"); /** * Doc flavor with MIME type = - * "text/plain; charset=utf-16", + * {@code "text/plain; charset=utf-16"}, * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_PLAIN_UTF_16 = new INPUT_STREAM ("text/plain; charset=utf-16"); /** * Doc flavor with MIME type = - * "text/plain; charset=utf-16be" + * {@code "text/plain; charset=utf-16be"} * (big-endian byte ordering), * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_PLAIN_UTF_16BE = new INPUT_STREAM ("text/plain; charset=utf-16be"); /** * Doc flavor with MIME type = - * "text/plain; charset=utf-16le" + * {@code "text/plain; charset=utf-16le"} * (little-endian byte ordering), * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_PLAIN_UTF_16LE = new INPUT_STREAM ("text/plain; charset=utf-16le"); /** * Doc flavor with MIME type = - * "text/plain; charset=us-ascii", + * {@code "text/plain; charset=us-ascii"}, * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_PLAIN_US_ASCII = new INPUT_STREAM ("text/plain; charset=us-ascii"); /** - * Doc flavor with MIME type = "text/html", + * Doc flavor with MIME type = {@code "text/html"}, * encoded in the host platform encoding. * See {@link DocFlavor#hostEncoding hostEncoding} * Print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_HTML_HOST = new INPUT_STREAM ("text/html; charset="+hostEncoding); /** * Doc flavor with MIME type = - * "text/html; charset=utf-8", + * {@code "text/html; charset=utf-8"}, * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_HTML_UTF_8 = new INPUT_STREAM ("text/html; charset=utf-8"); /** * Doc flavor with MIME type = - * "text/html; charset=utf-16", + * {@code "text/html; charset=utf-16"}, * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_HTML_UTF_16 = new INPUT_STREAM ("text/html; charset=utf-16"); /** * Doc flavor with MIME type = - * "text/html; charset=utf-16be" + * {@code "text/html; charset=utf-16be"} * (big-endian byte ordering), * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_HTML_UTF_16BE = new INPUT_STREAM ("text/html; charset=utf-16be"); /** * Doc flavor with MIME type = - * "text/html; charset=utf-16le" + * {@code "text/html; charset=utf-16le"} * (little-endian byte ordering), * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_HTML_UTF_16LE = new INPUT_STREAM ("text/html; charset=utf-16le"); /** * Doc flavor with MIME type = - * "text/html; charset=us-ascii", + * {@code "text/html; charset=us-ascii"}, * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM TEXT_HTML_US_ASCII = new INPUT_STREAM ("text/html; charset=us-ascii"); /** - * Doc flavor with MIME type = "application/pdf", print - * data representation class name = "java.io.InputStream" + * Doc flavor with MIME type = {@code "application/pdf"}, print + * data representation class name = {@code "java.io.InputStream"} * (byte stream). */ public static final INPUT_STREAM PDF = new INPUT_STREAM ("application/pdf"); /** - * Doc flavor with MIME type = "application/postscript", + * Doc flavor with MIME type = {@code "application/postscript"}, * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM POSTSCRIPT = new INPUT_STREAM ("application/postscript"); /** - * Doc flavor with MIME type = "application/vnd.hp-PCL", + * Doc flavor with MIME type = {@code "application/vnd.hp-PCL"}, * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM PCL = new INPUT_STREAM ("application/vnd.hp-PCL"); /** - * Doc flavor with MIME type = "image/gif", print data + * Doc flavor with MIME type = {@code "image/gif"}, print data * representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM GIF = new INPUT_STREAM ("image/gif"); /** - * Doc flavor with MIME type = "image/jpeg", print data + * Doc flavor with MIME type = {@code "image/jpeg"}, print data * representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM JPEG = new INPUT_STREAM ("image/jpeg"); /** - * Doc flavor with MIME type = "image/png", print data + * Doc flavor with MIME type = {@code "image/png"}, print data * representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). */ public static final INPUT_STREAM PNG = new INPUT_STREAM ("image/png"); /** * Doc flavor with MIME type = - * "application/octet-stream", + * {@code "application/octet-stream"}, * print data representation class name = - * "java.io.InputStream" (byte stream). + * {@code "java.io.InputStream"} (byte stream). * The client must determine that data described * using this DocFlavor is valid for the printer. */ @@ -1050,14 +1050,14 @@ public class DocFlavor implements Serializable, Cloneable { /** * Constructs a new doc flavor with the given MIME type and a print - * data representation class name of "java.net.URL". + * data representation class name of {@code "java.net.URL"}. * * @param mimeType MIME media type string. * * @exception NullPointerException - * (unchecked exception) Thrown if mimeType is null. + * (unchecked exception) Thrown if {@code mimeType} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if mimeType does not + * (unchecked exception) Thrown if {@code mimeType} does not * obey the syntax for a MIME media type string. */ public URL (String mimeType) { @@ -1065,160 +1065,160 @@ public class DocFlavor implements Serializable, Cloneable { } /** - * Doc flavor with MIME type = "text/plain", + * Doc flavor with MIME type = {@code "text/plain"}, * encoded in the host platform encoding. * See {@link DocFlavor#hostEncoding hostEncoding} * Print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_PLAIN_HOST = new URL ("text/plain; charset="+hostEncoding); /** * Doc flavor with MIME type = - * "text/plain; charset=utf-8", + * {@code "text/plain; charset=utf-8"}, * print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_PLAIN_UTF_8 = new URL ("text/plain; charset=utf-8"); /** * Doc flavor with MIME type = - * "text/plain; charset=utf-16", + * {@code "text/plain; charset=utf-16"}, * print data representation class name = - * java.net.URL"" (byte stream). + * {@code java.net.URL""} (byte stream). */ public static final URL TEXT_PLAIN_UTF_16 = new URL ("text/plain; charset=utf-16"); /** * Doc flavor with MIME type = - * "text/plain; charset=utf-16be" + * {@code "text/plain; charset=utf-16be"} * (big-endian byte ordering), * print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_PLAIN_UTF_16BE = new URL ("text/plain; charset=utf-16be"); /** * Doc flavor with MIME type = - * "text/plain; charset=utf-16le" + * {@code "text/plain; charset=utf-16le"} * (little-endian byte ordering), * print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_PLAIN_UTF_16LE = new URL ("text/plain; charset=utf-16le"); /** * Doc flavor with MIME type = - * "text/plain; charset=us-ascii", + * {@code "text/plain; charset=us-ascii"}, * print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_PLAIN_US_ASCII = new URL ("text/plain; charset=us-ascii"); /** - * Doc flavor with MIME type = "text/html", + * Doc flavor with MIME type = {@code "text/html"}, * encoded in the host platform encoding. * See {@link DocFlavor#hostEncoding hostEncoding} * Print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_HTML_HOST = new URL ("text/html; charset="+hostEncoding); /** * Doc flavor with MIME type = - * "text/html; charset=utf-8", + * {@code "text/html; charset=utf-8"}, * print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_HTML_UTF_8 = new URL ("text/html; charset=utf-8"); /** * Doc flavor with MIME type = - * "text/html; charset=utf-16", + * {@code "text/html; charset=utf-16"}, * print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_HTML_UTF_16 = new URL ("text/html; charset=utf-16"); /** * Doc flavor with MIME type = - * "text/html; charset=utf-16be" + * {@code "text/html; charset=utf-16be"} * (big-endian byte ordering), * print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_HTML_UTF_16BE = new URL ("text/html; charset=utf-16be"); /** * Doc flavor with MIME type = - * "text/html; charset=utf-16le" + * {@code "text/html; charset=utf-16le"} * (little-endian byte ordering), * print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_HTML_UTF_16LE = new URL ("text/html; charset=utf-16le"); /** * Doc flavor with MIME type = - * "text/html; charset=us-ascii", + * {@code "text/html; charset=us-ascii"}, * print data representation class name = - * "java.net.URL" (byte stream). + * {@code "java.net.URL"} (byte stream). */ public static final URL TEXT_HTML_US_ASCII = new URL ("text/html; charset=us-ascii"); /** - * Doc flavor with MIME type = "application/pdf", print - * data representation class name = "java.net.URL". + * Doc flavor with MIME type = {@code "application/pdf"}, print + * data representation class name = {@code "java.net.URL"}. */ public static final URL PDF = new URL ("application/pdf"); /** - * Doc flavor with MIME type = "application/postscript", - * print data representation class name = "java.net.URL". + * Doc flavor with MIME type = {@code "application/postscript"}, + * print data representation class name = {@code "java.net.URL"}. */ public static final URL POSTSCRIPT = new URL ("application/postscript"); /** - * Doc flavor with MIME type = "application/vnd.hp-PCL", - * print data representation class name = "java.net.URL". + * Doc flavor with MIME type = {@code "application/vnd.hp-PCL"}, + * print data representation class name = {@code "java.net.URL"}. */ public static final URL PCL = new URL ("application/vnd.hp-PCL"); /** - * Doc flavor with MIME type = "image/gif", print data - * representation class name = "java.net.URL". + * Doc flavor with MIME type = {@code "image/gif"}, print data + * representation class name = {@code "java.net.URL"}. */ public static final URL GIF = new URL ("image/gif"); /** - * Doc flavor with MIME type = "image/jpeg", print data - * representation class name = "java.net.URL". + * Doc flavor with MIME type = {@code "image/jpeg"}, print data + * representation class name = {@code "java.net.URL"}. */ public static final URL JPEG = new URL ("image/jpeg"); /** - * Doc flavor with MIME type = "image/png", print data - * representation class name = "java.net.URL". + * Doc flavor with MIME type = {@code "image/png"}, print data + * representation class name = {@code "java.net.URL"}. */ public static final URL PNG = new URL ("image/png"); /** * Doc flavor with MIME type = - * "application/octet-stream", - * print data representation class name = "java.net.URL". + * {@code "application/octet-stream"}, + * print data representation class name = {@code "java.net.URL"}. * The client must determine that data described * using this DocFlavor is valid for the printer. */ @@ -1229,7 +1229,7 @@ public class DocFlavor implements Serializable, Cloneable { /** * Class DocFlavor.CHAR_ARRAY provides predefined static constant * DocFlavor objects for example doc flavors using a character array - * (char[]) as the print data representation class. As such, + * ({@code char[]}) as the print data representation class. As such, * the character set is Unicode. * * @author Alan Kaminsky @@ -1241,16 +1241,16 @@ public class DocFlavor implements Serializable, Cloneable { /** * Constructs a new doc flavor with the given MIME type and a print * data representation class name of - * "[C" (character array). + * {@code "[C"} (character array). * * @param mimeType MIME media type string. If it is a text media * type, it is assumed to contain a - * "charset=utf-16" parameter. + * {@code "charset=utf-16"} parameter. * * @exception NullPointerException - * (unchecked exception) Thrown if mimeType is null. + * (unchecked exception) Thrown if {@code mimeType} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if mimeType does not + * (unchecked exception) Thrown if {@code mimeType} does not * obey the syntax for a MIME media type string. */ public CHAR_ARRAY (String mimeType) { @@ -1258,17 +1258,17 @@ public class DocFlavor implements Serializable, Cloneable { } /** - * Doc flavor with MIME type = "text/plain; - * charset=utf-16", print data representation class name = - * "[C" (character array). + * Doc flavor with MIME type = {@code "text/plain; charset=utf-16"}, + * print data representation class name = + * {@code "[C"} (character array). */ public static final CHAR_ARRAY TEXT_PLAIN = new CHAR_ARRAY ("text/plain; charset=utf-16"); /** - * Doc flavor with MIME type = "text/html; - * charset=utf-16", print data representation class name = - * "[C" (character array). + * Doc flavor with MIME type = {@code "text/html; charset=utf-16"}, + * print data representation class name = + * {@code "[C"} (character array). */ public static final CHAR_ARRAY TEXT_HTML = new CHAR_ARRAY ("text/html; charset=utf-16"); @@ -1289,16 +1289,16 @@ public class DocFlavor implements Serializable, Cloneable { /** * Constructs a new doc flavor with the given MIME type and a print - * data representation class name of "java.lang.String". + * data representation class name of {@code "java.lang.String"}. * * @param mimeType MIME media type string. If it is a text media * type, it is assumed to contain a - * "charset=utf-16" parameter. + * {@code "charset=utf-16"} parameter. * * @exception NullPointerException - * (unchecked exception) Thrown if mimeType is null. + * (unchecked exception) Thrown if {@code mimeType} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if mimeType does not + * (unchecked exception) Thrown if {@code mimeType} does not * obey the syntax for a MIME media type string. */ public STRING (String mimeType) { @@ -1306,17 +1306,17 @@ public class DocFlavor implements Serializable, Cloneable { } /** - * Doc flavor with MIME type = "text/plain; - * charset=utf-16", print data representation class name = - * "java.lang.String". + * Doc flavor with MIME type = {@code "text/plain; charset=utf-16"}, + * print data representation class name = + * {@code "java.lang.String"}. */ public static final STRING TEXT_PLAIN = new STRING ("text/plain; charset=utf-16"); /** - * Doc flavor with MIME type = "text/html; - * charset=utf-16", print data representation class name = - * "java.lang.String". + * Doc flavor with MIME type = {@code "text/html; charset=utf-16"}, + * print data representation class name = + * {@code "java.lang.String"}. */ public static final STRING TEXT_HTML = new STRING ("text/html; charset=utf-16"); @@ -1337,16 +1337,16 @@ public class DocFlavor implements Serializable, Cloneable { /** * Constructs a new doc flavor with the given MIME type and a print * data representation class name of\ - * "java.io.Reader" (character stream). + * {@code "java.io.Reader"} (character stream). * * @param mimeType MIME media type string. If it is a text media * type, it is assumed to contain a - * "charset=utf-16" parameter. + * {@code "charset=utf-16"} parameter. * * @exception NullPointerException - * (unchecked exception) Thrown if mimeType is null. + * (unchecked exception) Thrown if {@code mimeType} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if mimeType does not + * (unchecked exception) Thrown if {@code mimeType} does not * obey the syntax for a MIME media type string. */ public READER (String mimeType) { @@ -1354,17 +1354,17 @@ public class DocFlavor implements Serializable, Cloneable { } /** - * Doc flavor with MIME type = "text/plain; - * charset=utf-16", print data representation class name = - * "java.io.Reader" (character stream). + * Doc flavor with MIME type = {@code "text/plain; charset=utf-16"}, + * print data representation class name = + * {@code "java.io.Reader"} (character stream). */ public static final READER TEXT_PLAIN = new READER ("text/plain; charset=utf-16"); /** - * Doc flavor with MIME type = "text/html; - * charset=utf-16", print data representation class name = - * "java.io.Reader" (character stream). + * Doc flavor with MIME type = {@code "text/html; charset=utf-16"}, + * print data representation class name = + * {@code "java.io.Reader"} (character stream). */ public static final READER TEXT_HTML = new READER ("text/html; charset=utf-16"); @@ -1384,14 +1384,14 @@ public class DocFlavor implements Serializable, Cloneable { /** * Constructs a new doc flavor with a MIME type of - * "application/x-java-jvm-local-objectref" indicating + * {@code "application/x-java-jvm-local-objectref"} indicating * service formatted print data and the given print data * representation class name. * * @param className Fully-qualified representation class name. * * @exception NullPointerException - * (unchecked exception) Thrown if className is + * (unchecked exception) Thrown if {@code className} is * null. */ public SERVICE_FORMATTED (String className) { @@ -1401,7 +1401,7 @@ public class DocFlavor implements Serializable, Cloneable { /** * Service formatted print data doc flavor with print data * representation class name = - * "java.awt.image.renderable.RenderableImage" + * {@code "java.awt.image.renderable.RenderableImage"} * (renderable image object). */ public static final SERVICE_FORMATTED RENDERABLE_IMAGE = @@ -1409,7 +1409,7 @@ public class DocFlavor implements Serializable, Cloneable { /** * Service formatted print data doc flavor with print data - * representation class name = "java.awt.print.Printable" + * representation class name = {@code "java.awt.print.Printable"} * (printable object). */ public static final SERVICE_FORMATTED PRINTABLE = @@ -1417,7 +1417,7 @@ public class DocFlavor implements Serializable, Cloneable { /** * Service formatted print data doc flavor with print data - * representation class name = "java.awt.print.Pageable" + * representation class name = {@code "java.awt.print.Pageable"} * (pageable object). */ public static final SERVICE_FORMATTED PAGEABLE = diff --git a/jdk/src/java.desktop/share/classes/javax/print/DocPrintJob.java b/jdk/src/java.desktop/share/classes/javax/print/DocPrintJob.java index 3d504dd6451..3ab15f96664 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/DocPrintJob.java +++ b/jdk/src/java.desktop/share/classes/javax/print/DocPrintJob.java @@ -45,7 +45,7 @@ public interface DocPrintJob { * Determines the {@link PrintService} object to which this print job * object is bound. * - * @return PrintService object. + * @return {@code PrintService} object. * */ public PrintService getPrintService(); @@ -58,7 +58,7 @@ public interface DocPrintJob { * call; that is, the returned attribute set's object's contents will * not be updated if this Print Job's attribute set's contents change * in the future. To detect changes in attribute values, call - * getAttributes() again and compare the new attribute + * {@code getAttributes()} again and compare the new attribute * set to the previous attribute set; alternatively, register a * listener for print job events. * The returned value may be an empty set but should not be null. @@ -96,7 +96,7 @@ public interface DocPrintJob { * If listener is null, no exception is thrown and no action is * performed. * To determine the attribute updates that may be reported by this job, - * a client can call getAttributes() and identify the + * a client can call {@code getAttributes()} and identify the * subset that are interesting and likely to be reported to the * listener. Clients expecting to be updated about changes in a * specific job attribute should verify it is in that set, but @@ -152,7 +152,7 @@ public interface DocPrintJob { * Print service implementors should close any print data streams (ie * Reader or InputStream implementations) that they obtain * from the client doc. Robust clients may still wish to verify this. - * An exception is always generated if a DocFlavor cannot + * An exception is always generated if a {@code DocFlavor} cannot * be printed. * * @param doc The document to be printed. If must be a flavor diff --git a/jdk/src/java.desktop/share/classes/javax/print/MimeType.java b/jdk/src/java.desktop/share/classes/javax/print/MimeType.java index 87891f655b7..c9d1f614af0 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/MimeType.java +++ b/jdk/src/java.desktop/share/classes/javax/print/MimeType.java @@ -195,9 +195,9 @@ class MimeType implements Serializable, Cloneable { * @param s MIME media type string. * * @exception NullPointerException - * (unchecked exception) Thrown if s is null. + * (unchecked exception) Thrown if {@code s} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if s does not obey the + * (unchecked exception) Thrown if {@code s} does not obey the * syntax for a MIME media type string. */ public MimeType(String s) { @@ -271,7 +271,7 @@ class MimeType implements Serializable, Cloneable { * * @param obj Object to test. * - * @return True if this MIME type object equals obj, false + * @return True if this MIME type object equals {@code obj}, false * otherwise. */ public boolean equals (Object obj) { @@ -525,7 +525,7 @@ class MimeType implements Serializable, Cloneable { /** * Parses the given string into canonical pieces and stores the pieces in - * {@link #myPieces myPieces}. + * {@link #myPieces myPieces}. *

      * Special rules applied: *

        @@ -536,9 +536,9 @@ class MimeType implements Serializable, Cloneable { * @param s MIME media type string. * * @exception NullPointerException - * (unchecked exception) Thrown if s is null. + * (unchecked exception) Thrown if {@code s} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if s does not obey the + * (unchecked exception) Thrown if {@code s} does not obey the * syntax for a MIME media type string. */ private void parse(String s) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/PrintService.java b/jdk/src/java.desktop/share/classes/javax/print/PrintService.java index a003e730880..356e8498d01 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/PrintService.java +++ b/jdk/src/java.desktop/share/classes/javax/print/PrintService.java @@ -91,7 +91,7 @@ public interface PrintService { /** * Removes the print-service listener from this print service. * This means the listener is no longer interested in - * PrintService events. + * {@code PrintService} events. * @param listener a PrintServiceAttributeListener object * @see #addPrintServiceAttributeListener */ @@ -103,10 +103,10 @@ public interface PrintService { * giving this Print Service's status. The returned attribute set object * is unmodifiable. The returned attribute set object is a "snapshot" of * this Print Service's attribute set at the time of the - * getAttributes() method call: that is, the returned + * {@code getAttributes()} method call: that is, the returned * attribute set's contents will not be updated if this print * service's attribute set's contents change in the future. To detect - * changes in attribute values, call getAttributes() again + * changes in attribute values, call {@code getAttributes()} again * and compare the new attribute set to the previous attribute set; * alternatively, register a listener for print service events. * @@ -126,8 +126,8 @@ public interface PrintService { * attribute is not supported by this service. * @exception NullPointerException if the category is null. * @exception IllegalArgumentException - * (unchecked exception) if category is not a - * Class that implements interface + * (unchecked exception) if {@code category} is not a + * {@code Class} that implements interface *{@link javax.print.attribute.PrintServiceAttribute PrintServiceAttribute}. */ public @@ -135,13 +135,13 @@ public interface PrintService { /** * Determines the print data formats a client can specify when setting - * up a job for this PrintService. A print data format is + * up a job for this {@code PrintService}. A print data format is * designated by a "doc * flavor" (class {@link javax.print.DocFlavor DocFlavor}) * consisting of a MIME type plus a print data representation class. *

        * Note that some doc flavors may not be supported in combination - * with all attributes. Use getUnsupportedAttributes(..) + * with all attributes. Use {@code getUnsupportedAttributes(..)} * to validate specific combinations. * * @return Array of supported doc flavors, should have at least @@ -152,19 +152,19 @@ public interface PrintService { /** * Determines if this print service supports a specific - * DocFlavor. This is a convenience method to determine - * if the DocFlavor would be a member of the result of - * getSupportedDocFlavors(). + * {@code DocFlavor}. This is a convenience method to determine + * if the {@code DocFlavor} would be a member of the result of + * {@code getSupportedDocFlavors()}. *

        * Note that some doc flavors may not be supported in combination - * with all attributes. Use getUnsupportedAttributes(..) + * with all attributes. Use {@code getUnsupportedAttributes(..)} * to validate specific combinations. * - * @param flavor the DocFlavorto query for support. - * @return true if this print service supports the - * specified DocFlavor; false otherwise. + * @param flavor the {@code DocFlavor} to query for support. + * @return {@code true} if this print service supports the + * specified {@code DocFlavor}; {@code false} otherwise. * @exception NullPointerException - * (unchecked exception) Thrown if flavor is null. + * (unchecked exception) Thrown if {@code flavor} is null. */ public boolean isDocFlavorSupported(DocFlavor flavor); @@ -173,7 +173,7 @@ public interface PrintService { * Determines the printing attribute categories a client can specify * when setting up a job for this print service. * A printing attribute category is - * designated by a Class that implements interface + * designated by a {@code Class} that implements interface * {@link javax.print.attribute.Attribute Attribute}. This method returns * just the attribute categories that are supported; it does not * return the particular attribute values that are supported. @@ -181,10 +181,10 @@ public interface PrintService { * This method returns all the printing attribute * categories this print service supports for any possible job. * Some categories may not be supported in a particular context (ie - * for a particular DocFlavor). - * Use one of the methods that include a DocFlavor to + * for a particular {@code DocFlavor}). + * Use one of the methods that include a {@code DocFlavor} to * validate the request before submitting it, such as - * getSupportedAttributeValues(..). + * {@code getSupportedAttributeValues(..)}. * * @return Array of printing attribute categories that the client can * specify as a doc-level or job-level attribute in a Print @@ -198,37 +198,37 @@ public interface PrintService { /** * Determines whether a client can specify the given printing * attribute category when setting up a job for this print service. A - * printing attribute category is designated by a Class + * printing attribute category is designated by a {@code Class} * that implements interface {@link javax.print.attribute.Attribute * Attribute}. This method tells whether the attribute category is * supported; it does not tell whether a particular attribute value * is supported. *

        * Some categories may not be supported in a particular context (ie - * for a particular DocFlavor). - * Use one of the methods which include a DocFlavor to + * for a particular {@code DocFlavor}). + * Use one of the methods which include a {@code DocFlavor} to * validate the request before submitting it, such as - * getSupportedAttributeValues(..). + * {@code getSupportedAttributeValues(..)}. *

        * This is a convenience method to determine if the category * would be a member of the result of - * getSupportedAttributeCategories(). + * {@code getSupportedAttributeCategories()}. * * @param category Printing attribute category to test. It must be a - * Class that implements + * {@code Class} that implements * interface * {@link javax.print.attribute.Attribute Attribute}. * - * @return true if this print service supports + * @return {@code true} if this print service supports * specifying a doc-level or - * job-level attribute in category in a Print - * Request; false if it doesn't. + * job-level attribute in {@code category} in a Print + * Request; {@code false} if it doesn't. * * @exception NullPointerException - * (unchecked exception) Thrown if category is null. + * (unchecked exception) Thrown if {@code category} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if category is not a - * Class that implements interface + * (unchecked exception) Thrown if {@code category} is not a + * {@code Class} that implements interface * {@link javax.print.attribute.Attribute Attribute}. */ public boolean @@ -244,16 +244,16 @@ public interface PrintService { * default attribute value instead. *

        * Some attributes may not be supported in a particular context (ie - * for a particular DocFlavor). - * Use one of the methods that include a DocFlavor to + * for a particular {@code DocFlavor}). + * Use one of the methods that include a {@code DocFlavor} to * validate the request before submitting it, such as - * getSupportedAttributeValues(..). + * {@code getSupportedAttributeValues(..)}. *

        * Not all attributes have a default value. For example the - * service will not have a defaultvalue for RequestingUser + * service will not have a defaultvalue for {@code RequestingUser} * i.e. a null return for a supported category means there is no * service default value for that category. Use the - * isAttributeCategorySupported(Class) method to + * {@code isAttributeCategorySupported(Class)} method to * distinguish these cases. * * @param category Printing attribute category for which the default @@ -262,16 +262,16 @@ public interface PrintService { * {@link javax.print.attribute.Attribute * Attribute}. * - * @return Default attribute value for category, or null + * @return Default attribute value for {@code category}, or null * if this Print Service does not support specifying a doc-level or - * job-level attribute in category in a Print + * job-level attribute in {@code category} in a Print * Request, or the service does not have a default value * for this attribute. * * @exception NullPointerException - * (unchecked exception) Thrown if category is null. + * (unchecked exception) Thrown if {@code category} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if category is not a + * (unchecked exception) Thrown if {@code category} is not a * {@link java.lang.Class Class} that implements interface {@link * javax.print.attribute.Attribute Attribute}. */ @@ -285,10 +285,10 @@ public interface PrintService { * attribute value is an instance of a class that implements interface * {@link javax.print.attribute.Attribute Attribute}. *

        - * If flavor is null and attributes is null + * If {@code flavor} is null and {@code attributes} is null * or is an empty set, this method returns all the printing attribute * values this Print Service supports for any possible job. If - * flavor is not null or attributes is not + * {@code flavor} is not null or {@code attributes} is not * an empty set, this method returns just the printing attribute values * that are compatible with the given doc flavor and/or set of attributes. * That is, a null return value may indicate that specifying this attribute @@ -296,12 +296,12 @@ public interface PrintService { * Also if DocFlavor is not null it must be a flavor supported by this * PrintService, else IllegalArgumentException will be thrown. *

        - * If the attributes parameter contains an Attribute whose - * category is the same as the category parameter, the service + * If the {@code attributes} parameter contains an Attribute whose + * category is the same as the {@code category} parameter, the service * must ignore this attribute in the AttributeSet. *

        - * DocAttributes which are to be specified on the - * Doc must be included in this set to accurately + * {@code DocAttribute}s which are to be specified on the + * {@code Doc} must be included in this set to accurately * represent the context. *

        * This method returns an Object because different printing attribute @@ -321,7 +321,7 @@ public interface PrintService { * containing the legal values -- used, for example, by an attribute with * a list of enumerated values. The type of the array is an array of the * specified attribute category type as returned by its - * getCategory(Class). + * {@code getCategory(Class)}. *

      • * Return a single object (of some class other than the attribute category) * that indicates bounds on the legal values -- used, for example, by an @@ -337,18 +337,18 @@ public interface PrintService { * (both job-level attributes and document-level * attributes), or null. * - * @return Object indicating supported values for category, + * @return Object indicating supported values for {@code category}, * or null if this Print Service does not support specifying a - * doc-level or job-level attribute in category in + * doc-level or job-level attribute in {@code category} in * a Print Request. * * @exception NullPointerException - * (unchecked exception) Thrown if category is null. + * (unchecked exception) Thrown if {@code category} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if category is not a + * (unchecked exception) Thrown if {@code category} is not a * {@link java.lang.Class Class} that implements interface {@link * javax.print.attribute.Attribute Attribute}, or - * DocFlavor is not supported by this service. + * {@code DocFlavor} is not supported by this service. */ public Object getSupportedAttributeValues(Class category, @@ -362,24 +362,24 @@ public interface PrintService { * attribute value is an instance of a class that implements interface * {@link javax.print.attribute.Attribute Attribute}. *

        - * If flavor is null and attributes is null or + * If {@code flavor} is null and {@code attributes} is null or * is an empty set, this method tells whether this Print Service supports * the given printing attribute value for some possible combination of doc - * flavor and set of attributes. If flavor is not null or - * attributes is not an empty set, this method tells whether + * flavor and set of attributes. If {@code flavor} is not null or + * {@code attributes} is not an empty set, this method tells whether * this Print Service supports the given printing attribute value in * combination with the given doc flavor and/or set of attributes. *

        * Also if DocFlavor is not null it must be a flavor supported by this * PrintService, else IllegalArgumentException will be thrown. *

        - * DocAttributes which are to be specified on the - * Doc must be included in this set to accurately + * {@code DocAttribute}s which are to be specified on the + * {@code Doc} must be included in this set to accurately * represent the context. *

        * This is a convenience method to determine if the value * would be a member of the result of - * getSupportedAttributeValues(...). + * {@code getSupportedAttributeValues(...)}. * * @param attrval Printing attribute value to test. * @param flavor Doc flavor for a supposed job, or null. @@ -388,11 +388,11 @@ public interface PrintService { * attributes), or null. * * @return True if this Print Service supports specifying - * attrval as a doc-level or job-level attribute in a + * {@code attrval} as a doc-level or job-level attribute in a * Print Request, false if it doesn't. * * @exception NullPointerException - * (unchecked exception) if attrval is null. + * (unchecked exception) if {@code attrval} is null. * @exception IllegalArgumentException if flavor is not supported by * this PrintService. */ @@ -410,8 +410,8 @@ public interface PrintService { * IllegalArgumentException will be thrown. If the * return value from this method is null, all attributes are supported. *

        - * DocAttributes which are to be specified on the - * Doc must be included in this set to accurately + * {@code DocAttribute}s which are to be specified on the + * {@code Doc} must be included in this set to accurately * represent the context. *

        * If the return value is non-null, all attributes in the returned @@ -428,7 +428,7 @@ public interface PrintService { * to select the attribute(s) to be identified as the cause of the * conflict. *

        - * Use isDocFlavorSupported() to verify that a DocFlavor + * Use {@code isDocFlavorSupported()} to verify that a DocFlavor * is supported before calling this method. * * @param flavor Doc flavor to test, or null @@ -439,7 +439,7 @@ public interface PrintService { * @return null if this Print Service supports the print request * specification, else the unsupported attributes. * - * @exception IllegalArgumentException ifflavor is + * @exception IllegalArgumentException if {@code flavor} is * not supported by this PrintService. */ public AttributeSet getUnsupportedAttributes(DocFlavor flavor, @@ -453,7 +453,7 @@ public interface PrintService { * an environment with no UI support should ensure that the factory * is not initialised unless the application calls this method to * obtain the factory. - * See ServiceUIFactory for more information. + * See {@code ServiceUIFactory} for more information. * @return null or a factory for UI components. */ public ServiceUIFactory getServiceUIFactory(); @@ -480,7 +480,7 @@ public interface PrintService { /** * This method should be implemented consistently with - * equals(Object). + * {@code equals(Object)}. * @return hash code of this object. */ public int hashCode(); diff --git a/jdk/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java b/jdk/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java index d15a0146287..a6981a1f441 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java +++ b/jdk/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java @@ -113,7 +113,7 @@ public abstract class PrintServiceLookup { * @param attributes attributes that the print service must support. * If null this constraint is not used. * - * @return array of matching PrintService objects + * @return array of matching {@code PrintService} objects * representing print services that support the specified flavor * attributes. If no services match, the array is zero-length. */ @@ -129,9 +129,9 @@ public abstract class PrintServiceLookup { * Locates MultiDoc print Services capable of printing MultiDocs * containing all the specified doc flavors. *

        This method is useful to help locate a service that can print - * a MultiDoc in which the elements may be different + * a {@code MultiDoc} in which the elements may be different * flavors. An application could perform this itself by multiple lookups - * on each DocFlavor in turn and collating the results, + * on each {@code DocFlavor} in turn and collating the results, * but the lookup service may be able to do this more efficiently. * * @param flavors the flavors to print. If null or empty this @@ -201,8 +201,8 @@ public abstract class PrintServiceLookup { * the method returns false. * * @param sp an implementation of a lookup service. - * @return true if the new lookup service is newly - * registered; false otherwise. + * @return {@code true} if the new lookup service is newly + * registered; {@code false} otherwise. */ public static boolean registerServiceProvider(PrintServiceLookup sp) { synchronized (PrintServiceLookup.class) { @@ -232,15 +232,15 @@ public abstract class PrintServiceLookup { * values and classes reported by the service. * This may be less efficient than a lookup * service tuned for that service. - * Therefore registering a PrintServiceLookup instance + * Therefore registering a {@code PrintServiceLookup} instance * instead is recommended. * The method returns true if this service is not previously * registered and is now successfully registered. * This method should not be called with StreamPrintService instances. * They will always fail to register and the method will return false. * @param service an implementation of a print service. - * @return true if the service is newly - * registered; false otherwise. + * @return {@code true} if the service is newly + * registered; {@code false} otherwise. */ public static boolean registerService(PrintService service) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java b/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java index a3960af1816..520d508c3b5 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java +++ b/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java @@ -136,8 +136,8 @@ public class ServiceUI { * @param x location of dialog including border in screen coordinates * @param y location of dialog including border in screen coordinates * @param services to be browsable, must be non-null. - * @param defaultService - initial PrintService to display. - * @param flavor - the flavor to be printed, or null. + * @param defaultService initial PrintService to display. + * @param flavor the flavor to be printed, or null. * @param attributes on input is the initial application supplied * preferences. This cannot be null but may be empty. * On output the attributes reflect changes made by the user. diff --git a/jdk/src/java.desktop/share/classes/javax/print/SimpleDoc.java b/jdk/src/java.desktop/share/classes/javax/print/SimpleDoc.java index f73d794f76b..dfe8dc4a470 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/SimpleDoc.java +++ b/jdk/src/java.desktop/share/classes/javax/print/SimpleDoc.java @@ -35,7 +35,7 @@ import javax.print.attribute.AttributeSetUtilities; import javax.print.attribute.DocAttributeSet; /** - * This class is an implementation of interface Doc that can + * This class is an implementation of interface {@code Doc} that can * be used in many common printing requests. * It can handle all of the presently defined "pre-defined" doc flavors * defined as static variables in the DocFlavor class. @@ -52,7 +52,7 @@ import javax.print.attribute.DocAttributeSet; * or need a MultiDoc will not want to use this class. *

        * If the print data is a stream, or a print job requests data as a - * stream, then SimpleDoc does not monitor if the service + * stream, then {@code SimpleDoc} does not monitor if the service * properly closes the stream after data transfer completion or job * termination. * Clients may prefer to use provide their own implementation of doc that @@ -69,18 +69,18 @@ public final class SimpleDoc implements Doc { private InputStream inStream; /** - * Constructs a SimpleDoc with the specified + * Constructs a {@code SimpleDoc} with the specified * print data, doc flavor and doc attribute set. * @param printData the print data object - * @param flavor the DocFlavor object - * @param attributes a DocAttributeSet, which can - * be null - * @throws IllegalArgumentException if flavor or - * printData is null, or the - * printData does not correspond + * @param flavor the {@code DocFlavor} object + * @param attributes a {@code DocAttributeSet}, which can + * be {@code null} + * @throws IllegalArgumentException if {@code flavor} or + * {@code printData} is {@code null}, or the + * {@code printData} does not correspond * to the specified doc flavor--for example, the data is * not of the type specified as the representation in the - * DocFlavor. + * {@code DocFlavor}. */ public SimpleDoc(Object printData, DocFlavor flavor, DocAttributeSet attributes) { @@ -144,7 +144,7 @@ public final class SimpleDoc implements Doc { * Obtains the print data representation object that contains this doc * object's piece of print data in the format corresponding to the * supported doc flavor. - * The getPrintData() method returns an instance of + * The {@code getPrintData()} method returns an instance of * the representation class whose name is given by * {@link DocFlavor#getRepresentationClassName() getRepresentationClassName}, * and the return value can be cast @@ -161,26 +161,26 @@ public final class SimpleDoc implements Doc { /** * Obtains a reader for extracting character print data from this doc. - * The Doc implementation is required to support this - * method if the DocFlavor has one of the following print - * data representation classes, and return null + * The {@code Doc} implementation is required to support this + * method if the {@code DocFlavor} has one of the following print + * data representation classes, and return {@code null} * otherwise: *

          - *
        • char[] - *
        • java.lang.String - *
        • java.io.Reader + *
        • {@code char[]} + *
        • {@code java.lang.String} + *
        • {@code java.io.Reader} *
        * The doc's print data representation object is used to construct and - * return a Reader for reading the print data as a stream + * return a {@code Reader} for reading the print data as a stream * of characters from the print data representation object. * However, if the print data representation object is itself a - * Reader then the print data representation object is + * {@code Reader} then the print data representation object is * simply returned. * - * @return a Reader for reading the print data + * @return a {@code Reader} for reading the print data * characters from this doc. * If a reader cannot be provided because this doc does not meet - * the criteria stated above, null is returned. + * the criteria stated above, {@code null} is returned. * * @exception IOException if there was an I/O error while creating * the reader. @@ -209,13 +209,13 @@ public final class SimpleDoc implements Doc { /** * Obtains an input stream for extracting byte print data from * this doc. - * The Doc implementation is required to support this - * method if the DocFlavor has one of the following print + * The {@code Doc} implementation is required to support this + * method if the {@code DocFlavor} has one of the following print * data representation classes; otherwise this method - * returns null: + * returns {@code null}: *
          - *
        • byte[] - *
        • java.io.InputStream + *
        • {@code byte[]} + *
        • {@code java.io.InputStream} *
        * The doc's print data representation object is obtained. Then, an * input stream for reading the print data @@ -225,10 +225,10 @@ public final class SimpleDoc implements Doc { * input stream then the print data representation object is simply * returned. * - * @return an InputStream for reading the print data + * @return an {@code InputStream} for reading the print data * bytes from this doc. If an input stream cannot be * provided because this doc does not meet - * the criteria stated above, null is returned. + * the criteria stated above, {@code null} is returned. * * @exception IOException * if there was an I/O error while creating the input stream. diff --git a/jdk/src/java.desktop/share/classes/javax/print/StreamPrintService.java b/jdk/src/java.desktop/share/classes/javax/print/StreamPrintService.java index c1a99229b2e..a735d542a58 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/StreamPrintService.java +++ b/jdk/src/java.desktop/share/classes/javax/print/StreamPrintService.java @@ -37,17 +37,17 @@ import java.io.OutputStream; * The output format must be declared as a mime type. * This is equivalent to an output document flavor where the * representation class is always "java.io.OutputStream" - * An instance of the StreamPrintService class is + * An instance of the {@code StreamPrintService} class is * obtained from a {@link StreamPrintServiceFactory} instance. *

        - * Note that a StreamPrintService is different from a - * PrintService, which supports a + * Note that a {@code StreamPrintService} is different from a + * {@code PrintService}, which supports a * {@link javax.print.attribute.standard.Destination Destination} - * attribute. A StreamPrintService always requires an output - * stream, whereas a PrintService optionally accepts a - * Destination. A StreamPrintService + * attribute. A {@code StreamPrintService} always requires an output + * stream, whereas a {@code PrintService} optionally accepts a + * {@code Destination}. A {@code StreamPrintService} * has no default destination for its formatted output. - * Additionally a StreamPrintService is expected to generate + * Additionally a {@code StreamPrintService} is expected to generate output in * a format useful in other contexts. * StreamPrintService's are not expected to support the Destination attribute. @@ -88,7 +88,7 @@ public abstract class StreamPrintService implements PrintService { public abstract String getOutputFormat(); /** - * Disposes this StreamPrintService. + * Disposes this {@code StreamPrintService}. * If a stream service cannot be re-used, it must be disposed * to indicate this. Typically the client will call this method. * Services which write data which cannot meaningfully be appended to @@ -100,12 +100,12 @@ public abstract class StreamPrintService implements PrintService { } /** - * Returns a boolean indicating whether or not - * this StreamPrintService has been disposed. + * Returns a {@code boolean} indicating whether or not + * this {@code StreamPrintService} has been disposed. * If this object has been disposed, will return true. * Used by services and client applications to recognize streams * to which no further data should be written. - * @return if this StreamPrintService has been disposed + * @return if this {@code StreamPrintService} has been disposed */ public boolean isDisposed() { return disposed; diff --git a/jdk/src/java.desktop/share/classes/javax/print/StreamPrintServiceFactory.java b/jdk/src/java.desktop/share/classes/javax/print/StreamPrintServiceFactory.java index f1f7f28c410..a7da64e61f3 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/StreamPrintServiceFactory.java +++ b/jdk/src/java.desktop/share/classes/javax/print/StreamPrintServiceFactory.java @@ -37,7 +37,7 @@ import java.util.ServiceLoader; import java.util.ServiceConfigurationError; /** - * A StreamPrintServiceFactory is the factory for + * A {@code StreamPrintServiceFactory} is the factory for * {@link StreamPrintService} instances, * which can print to an output stream in a particular * document format described as a mime type. @@ -51,8 +51,8 @@ import java.util.ServiceConfigurationError; * Applications locate instances of this class by calling the * {@link #lookupStreamPrintServiceFactories(DocFlavor, String)} method. *

        - * Applications can use a StreamPrintService obtained from a - * factory in place of a PrintService which represents a + * Applications can use a {@code StreamPrintService} obtained from a + * factory in place of a {@code PrintService} which represents a * physical printer device. */ @@ -101,7 +101,7 @@ public abstract class StreamPrintServiceFactory { * @param outputMimeType representing the required output format, used to * identify suitable stream printer factories. A value of null means * match all formats. - * @return - matching factories for stream print service instance, + * @return matching factories for stream print service instance, * empty if no suitable factories could be located. */ public static StreamPrintServiceFactory[] @@ -127,25 +127,25 @@ public abstract class StreamPrintServiceFactory { public abstract DocFlavor[] getSupportedDocFlavors(); /** - * Returns a StreamPrintService that can print to + * Returns a {@code StreamPrintService} that can print to * the specified output stream. * The output stream is created and managed by the application. * It is the application's responsibility to close the stream and * to ensure that this Printer is not reused. * The application should not close this stream until any print job * created from the printer is complete. Doing so earlier may generate - * a PrinterException and an event indicating that the + * a {@code PrinterException} and an event indicating that the * job failed. *

        - * Whereas a PrintService connected to a physical printer + * Whereas a {@code PrintService} connected to a physical printer * can be reused, - * a StreamPrintService connected to a stream cannot. - * The underlying StreamPrintService may be disposed by + * a {@code StreamPrintService} connected to a stream cannot. + * The underlying {@code StreamPrintService} may be disposed by * the print system with * the {@link StreamPrintService#dispose() dispose} method * before returning from the * {@link DocPrintJob#print(Doc, javax.print.attribute.PrintRequestAttributeSet) print} - * method of DocPrintJob so that the print system knows + * method of {@code DocPrintJob} so that the print system knows * this printer is no longer usable. * This is equivalent to a physical printer going offline - permanently. * Applications may supply a null print stream to create a queryable diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/Attribute.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/Attribute.java index a6c58e6f933..e493b4869de 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/Attribute.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/Attribute.java @@ -52,8 +52,8 @@ public interface Attribute extends Serializable { *

        * Note: This method is intended to provide a default, nonlocalized * string for the attribute's category. If two attribute objects return the - * same category from the getCategory() method, they should - * return the same name from the getName() method. + * same category from the {@code getCategory()} method, they should + * return the same name from the {@code getName()} method. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/AttributeSetUtilities.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/AttributeSetUtilities.java index 2c5896f633f..587a4833501 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/AttributeSetUtilities.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/AttributeSetUtilities.java @@ -206,10 +206,10 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying attribute set. * - * @return Unmodifiable view of attributeSet. + * @return Unmodifiable view of {@code attributeSet}. * * @exception NullPointerException - * Thrown if attributeSet is null. Null is never a + * Thrown if {@code attributeSet} is null. Null is never a */ public static AttributeSet unmodifiableView(AttributeSet attributeSet) { if (attributeSet == null) { @@ -224,10 +224,10 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying doc attribute set. * - * @return Unmodifiable view of attributeSet. + * @return Unmodifiable view of {@code attributeSet}. * * @exception NullPointerException - * Thrown if attributeSet is null. + * Thrown if {@code attributeSet} is null. */ public static DocAttributeSet unmodifiableView (DocAttributeSet attributeSet) { @@ -242,10 +242,10 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying print request attribute set. * - * @return Unmodifiable view of attributeSet. + * @return Unmodifiable view of {@code attributeSet}. * * @exception NullPointerException - * Thrown if attributeSet is null. + * Thrown if {@code attributeSet} is null. */ public static PrintRequestAttributeSet unmodifiableView(PrintRequestAttributeSet attributeSet) { @@ -260,10 +260,10 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying print job attribute set. * - * @return Unmodifiable view of attributeSet. + * @return Unmodifiable view of {@code attributeSet}. * * @exception NullPointerException - * Thrown if attributeSet is null. + * Thrown if {@code attributeSet} is null. */ public static PrintJobAttributeSet unmodifiableView(PrintJobAttributeSet attributeSet) { @@ -278,10 +278,10 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying print service attribute set. * - * @return Unmodifiable view of attributeSet. + * @return Unmodifiable view of {@code attributeSet}. * * @exception NullPointerException - * Thrown if attributeSet is null. + * Thrown if {@code attributeSet} is null. */ public static PrintServiceAttributeSet unmodifiableView(PrintServiceAttributeSet attributeSet) { @@ -417,10 +417,10 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying attribute set. * - * @return Synchronized view of attributeSet. + * @return Synchronized view of {@code attributeSet}. * * @exception NullPointerException - * Thrown if attributeSet is null. + * Thrown if {@code attributeSet} is null. */ public static AttributeSet synchronizedView (AttributeSet attributeSet) { @@ -435,10 +435,10 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying doc attribute set. * - * @return Synchronized view of attributeSet. + * @return Synchronized view of {@code attributeSet}. * * @exception NullPointerException - * Thrown if attributeSet is null. + * Thrown if {@code attributeSet} is null. */ public static DocAttributeSet synchronizedView(DocAttributeSet attributeSet) { @@ -453,10 +453,10 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying print request attribute set. * - * @return Synchronized view of attributeSet. + * @return Synchronized view of {@code attributeSet}. * * @exception NullPointerException - * Thrown if attributeSet is null. + * Thrown if {@code attributeSet} is null. */ public static PrintRequestAttributeSet synchronizedView(PrintRequestAttributeSet attributeSet) { @@ -471,10 +471,10 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying print job attribute set. * - * @return Synchronized view of attributeSet. + * @return Synchronized view of {@code attributeSet}. * * @exception NullPointerException - * Thrown if attributeSet is null. + * Thrown if {@code attributeSet} is null. */ public static PrintJobAttributeSet synchronizedView(PrintJobAttributeSet attributeSet) { @@ -489,7 +489,7 @@ public final class AttributeSetUtilities { * * @param attributeSet Underlying print service attribute set. * - * @return Synchronized view of attributeSet. + * @return Synchronized view of {@code attributeSet}. */ public static PrintServiceAttributeSet synchronizedView(PrintServiceAttributeSet attributeSet) { @@ -508,17 +508,17 @@ public final class AttributeSetUtilities { * @param object Object to test. * @param interfaceName Interface the object must implement. * - * @return If object is a {@link java.lang.Class Class} - * that implements interfaceName, - * object is returned downcast to type {@link + * @return If {@code object} is a {@link java.lang.Class Class} + * that implements {@code interfaceName}, + * {@code object} is returned downcast to type {@link * java.lang.Class Class}; otherwise an exception is thrown. * * @exception NullPointerException - * (unchecked exception) Thrown if object is null. + * (unchecked exception) Thrown if {@code object} is null. * @exception ClassCastException - * (unchecked exception) Thrown if object is not a + * (unchecked exception) Thrown if {@code object} is not a * {@link java.lang.Class Class} that implements - * interfaceName. + * {@code interfaceName}. */ public static Class verifyAttributeCategory(Object object, Class interfaceName) { @@ -540,16 +540,16 @@ public final class AttributeSetUtilities { * @param object Object to test. * @param interfaceName Interface of which the object must be an instance. * - * @return If object is an instance of - * interfaceName, object is returned + * @return If {@code object} is an instance of + * {@code interfaceName}, {@code object} is returned * downcast to type {@link Attribute Attribute}; otherwise an * exception is thrown. * * @exception NullPointerException - * (unchecked exception) Thrown if object is null. + * (unchecked exception) Thrown if {@code object} is null. * @exception ClassCastException - * (unchecked exception) Thrown if object is not an - * instance of interfaceName. + * (unchecked exception) Thrown if {@code object} is not an + * instance of {@code interfaceName}. */ public static Attribute verifyAttributeValue(Object object, Class interfaceName) { @@ -573,11 +573,11 @@ public final class AttributeSetUtilities { * @param attribute Attribute value to test. * * @exception NullPointerException - * (unchecked exception) Thrown if the category is - * null or if the attribute is null. + * (unchecked exception) Thrown if the {@code category} is + * null or if the {@code attribute} is null. * @exception IllegalArgumentException - * (unchecked exception) Thrown if the category is not - * equal to the category of the attribute. + * (unchecked exception) Thrown if the {@code category} is not + * equal to the category of the {@code attribute}. */ public static void verifyCategoryForValue(Class category, Attribute attribute) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/DateTimeSyntax.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/DateTimeSyntax.java index 72e583a0347..0515be6e801 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/DateTimeSyntax.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/DateTimeSyntax.java @@ -34,26 +34,25 @@ import java.util.Date; * Class DateTimeSyntax is an abstract base class providing the common * implementation of all attributes whose value is a date and time. *

        - * Under the hood, a date-time attribute is stored as a value of class - * java.util.Date. You can get a date-time attribute's Date value by + * Under the hood, a date-time attribute is stored as a value of class + * {@code java.util.Date}. You can get a date-time attribute's Date value by * calling {@link #getValue() getValue()}. A date-time attribute's * Date value is established when it is constructed (see {@link * #DateTimeSyntax(Date) DateTimeSyntax(Date)}). Once * constructed, a date-time attribute's value is immutable. *

        * To construct a date-time attribute from separate values of the year, month, - * day, hour, minute, and so on, use a java.util.Calendar - * object to construct a java.util.Date object, then use the - * java.util.Date object to construct the date-time attribute. + * day, hour, minute, and so on, use a {@code java.util.Calendar} + * object to construct a {@code java.util.Date} object, then use the + * {@code java.util.Date} object to construct the date-time attribute. * To convert * a date-time attribute to separate values of the year, month, day, hour, - * minute, and so on, create a java.util.Calendar object and - * set it to the java.util.Date from the date-time attribute. Class - * DateTimeSyntax stores its value in the form of a java.util.Date - * - * rather than a java.util.Calendar because it typically takes - * less memory to store and less time to compare a java.util.Date - * than a java.util.Calendar. + * minute, and so on, create a {@code java.util.Calendar} object and + * set it to the {@code java.util.Date} from the date-time attribute. Class + * DateTimeSyntax stores its value in the form of a {@code java.util.Date} + * rather than a {@code java.util.Calendar} because it typically takes + * less memory to store and less time to compare a {@code java.util.Date} + * than a {@code java.util.Calendar}. * * @author Alan Kaminsky */ @@ -64,7 +63,7 @@ public abstract class DateTimeSyntax implements Serializable, Cloneable { // Hidden data members. /** - * This date-time attribute'sjava.util.Date value. + * This date-time attribute's {@code java.util.Date} value. * @serial */ private Date value; @@ -73,12 +72,12 @@ public abstract class DateTimeSyntax implements Serializable, Cloneable { /** * Construct a new date-time attribute with the given - * java.util.Date value. + * {@code java.util.Date} value. * - * @param value java.util.Date value. + * @param value {@code java.util.Date} value. * * @exception NullPointerException - * (unchecked exception) Thrown if theValue is null. + * (unchecked exception) Thrown if {@code theValue} is null. */ protected DateTimeSyntax(Date value) { if (value == null) { @@ -90,7 +89,7 @@ public abstract class DateTimeSyntax implements Serializable, Cloneable { // Exported operations. /** - * Returns this date-time attribute's java.util.Date + * Returns this date-time attribute's {@code java.util.Date} * value. * @return the Date. */ @@ -105,17 +104,17 @@ public abstract class DateTimeSyntax implements Serializable, Cloneable { * object. To be equivalent, all of the following conditions must be true: *

          *
        1. - * object is not null. + * {@code object} is not null. *
        2. - * object is an instance of class DateTimeSyntax. + * {@code object} is an instance of class DateTimeSyntax. *
        3. - * This date-time attribute's java.util.Date value and - * object's java.util.Date value are + * This date-time attribute's {@code java.util.Date} value and + * {@code object}'s {@code java.util.Date} value are * equal.
        * * @param object Object to compare to. * - * @return True if object is equivalent to this date-time + * @return True if {@code object} is equivalent to this date-time * attribute, false otherwise. */ public boolean equals(Object object) { @@ -126,7 +125,7 @@ public abstract class DateTimeSyntax implements Serializable, Cloneable { /** * Returns a hash code value for this date-time attribute. The hashcode is - * that of this attribute's java.util.Date value. + * that of this attribute's {@code java.util.Date} value. */ public int hashCode() { return value.hashCode(); @@ -135,7 +134,7 @@ public abstract class DateTimeSyntax implements Serializable, Cloneable { /** * Returns a string value corresponding to this date-time attribute. * The string value is just this attribute's - * java.util.Date value + * {@code java.util.Date} value * converted to a string. */ public String toString() { diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/DocAttribute.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/DocAttribute.java index 994208f0a9e..509eee309d4 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/DocAttribute.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/DocAttribute.java @@ -30,7 +30,7 @@ package javax.print.attribute; * Interface DocAttribute is a tagging interface which a printing attribute * class implements to indicate the attribute denotes a setting for a doc. * ("Doc" is a short, easy-to-pronounce term that means "a piece of print - * data.") The client may include a DocAttribute in a Doc's + * data.") The client may include a DocAttribute in a {@code Doc}'s * attribute set to specify a characteristic of * that doc. If an attribute implements {@link PrintRequestAttribute * PrintRequestAttribute} as well as DocAttribute, the client may include the diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/EnumSyntax.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/EnumSyntax.java index f774066e592..2b3470c5da4 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/EnumSyntax.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/EnumSyntax.java @@ -68,7 +68,7 @@ import java.io.Serializable; * } * } * - * You can then write code that uses the == and != + * You can then write code that uses the {@code ==} and {@code !=} * operators to test enumeration values; for example: *
          *     Bach theComposer;
        @@ -77,8 +77,8 @@ import java.io.Serializable;
          *         System.out.println ("The greatest composer of all time!");
          *     }
          * 
        - * The equals() method for an enumeration class just does a test - * for identical objects (==). + * The {@code equals()} method for an enumeration class just does a test + * for identical objects ({@code ==}). *

        * You can convert an enumeration value to a string by calling {@link * #toString() toString()}. The string is obtained from a table @@ -97,8 +97,8 @@ import java.io.Serializable; * You can define a subclass of an enumeration class that extends it with * additional enumeration values. The subclass's enumeration values' integer * values need not be distinct from the superclass's enumeration values' integer - * values; the ==, !=, equals(), and - * toString() methods will still work properly even if the subclass + * values; the {@code ==}, {@code !=}, {@code equals()}, and + * {@code toString()} methods will still work properly even if the subclass * uses some of the same integer values as the superclass. However, the * application in which the enumeration class and subclass are used may need to * have distinct integer values in the superclass and subclass. @@ -182,7 +182,7 @@ public abstract class EnumSyntax implements Serializable, Cloneable { * enumeration value table is null. (Note: {@link * java.io.InvalidObjectException InvalidObjectException} is a subclass * of {@link java.io.ObjectStreamException ObjectStreamException}, which - * readResolve() is declared to throw.) + * {@code readResolve()} is declared to throw.) */ protected Object readResolve() throws ObjectStreamException { diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/HashDocAttributeSet.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/HashDocAttributeSet.java index 0b915ba2ca9..5742a074420 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/HashDocAttributeSet.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/HashDocAttributeSet.java @@ -55,7 +55,7 @@ public class HashDocAttributeSet extends HashAttributeSet * @param attribute Attribute value to add to the set. * * @exception NullPointerException - * (unchecked exception) Thrown if attribute is null. + * (unchecked exception) Thrown if {@code attribute} is null. */ public HashDocAttributeSet(DocAttribute attribute) { super (attribute, DocAttribute.class); @@ -65,7 +65,7 @@ public class HashDocAttributeSet extends HashAttributeSet * Construct a new hash doc attribute set, * initially populated with the values from the given array. * The new attribute set is populated by - * adding the elements of attributes array to the set in + * adding the elements of {@code attributes} array to the set in * sequence, starting at index 0. Thus, later array elements may replace * earlier array elements if the array contains duplicate attribute * values or attribute categories. @@ -75,7 +75,7 @@ public class HashDocAttributeSet extends HashAttributeSet * * @exception NullPointerException * (unchecked exception) - * Thrown if any element of attributes is null. + * Thrown if any element of {@code attributes} is null. */ public HashDocAttributeSet(DocAttribute[] attributes) { super (attributes, DocAttribute.class); @@ -84,15 +84,15 @@ public class HashDocAttributeSet extends HashAttributeSet /** * Construct a new attribute set, initially populated with the * values from the given set where the members of the attribute set - * are restricted to the DocAttribute interface. + * are restricted to the {@code DocAttribute} interface. * * @param attributes set of attribute values to initialise the set. If * null, an empty attribute set is constructed. * * @exception ClassCastException * (unchecked exception) Thrown if any element of - * attributes is not an instance of - * DocAttribute. + * {@code attributes} is not an instance of + * {@code DocAttribute}. */ public HashDocAttributeSet(DocAttributeSet attributes) { super(attributes, DocAttribute.class); diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintJobAttributeSet.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintJobAttributeSet.java index f39c85883d5..e9971e9a45c 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintJobAttributeSet.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintJobAttributeSet.java @@ -55,7 +55,7 @@ public class HashPrintJobAttributeSet extends HashAttributeSet * @param attribute Attribute value to add to the set. * * @exception NullPointerException - * (unchecked exception) Thrown if attribute is null. + * (unchecked exception) Thrown if {@code attribute} is null. */ public HashPrintJobAttributeSet(PrintJobAttribute attribute) { super(attribute, PrintJobAttribute.class); @@ -65,7 +65,7 @@ public class HashPrintJobAttributeSet extends HashAttributeSet * Construct a new hash print job attribute set, * initially populated with the values from the given array. * The new attribute set is populated - * by adding the elements of attributes array to the set in + * by adding the elements of {@code attributes} array to the set in * sequence, starting at index 0. Thus, later array elements may replace * earlier array elements if the array contains duplicate attribute * values or attribute categories. @@ -74,7 +74,7 @@ public class HashPrintJobAttributeSet extends HashAttributeSet * If null, an empty attribute set is constructed. * * @exception NullPointerException (unchecked exception) - * Thrown if any element of attributes is null. + * Thrown if any element of {@code attributes} is null. */ public HashPrintJobAttributeSet(PrintJobAttribute[] attributes) { super (attributes, PrintJobAttribute.class); @@ -83,15 +83,15 @@ public class HashPrintJobAttributeSet extends HashAttributeSet /** * Construct a new attribute set, initially populated with the * values from the given set where the members of the attribute set - * are restricted to the PrintJobAttribute interface. + * are restricted to the {@code PrintJobAttribute} interface. * * @param attributes set of attribute values to initialise the set. If * null, an empty attribute set is constructed. * * @exception ClassCastException * (unchecked exception) Thrown if any element of - * attributes is not an instance of - * PrintJobAttribute. + * {@code attributes} is not an instance of + * {@code PrintJobAttribute}. */ public HashPrintJobAttributeSet(PrintJobAttributeSet attributes) { super(attributes, PrintJobAttribute.class); diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintRequestAttributeSet.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintRequestAttributeSet.java index fde4ebb6945..9ef717500e7 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintRequestAttributeSet.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintRequestAttributeSet.java @@ -55,7 +55,7 @@ public class HashPrintRequestAttributeSet extends HashAttributeSet * @param attribute Attribute value to add to the set. * * @exception NullPointerException - * (unchecked exception) Thrown if attribute is null. + * (unchecked exception) Thrown if {@code attribute} is null. */ public HashPrintRequestAttributeSet(PrintRequestAttribute attribute) { super (attribute, PrintRequestAttribute.class); @@ -64,7 +64,7 @@ public class HashPrintRequestAttributeSet extends HashAttributeSet /** * Construct a new print request attribute set, initially populated with * the values from the given array. The new attribute set is populated - * by adding the elements of attributes array to the set in + * by adding the elements of {@code attributes} array to the set in * sequence, starting at index 0. Thus, later array elements may replace * earlier array elements if the array contains duplicate attribute * values or attribute categories. @@ -74,7 +74,7 @@ public class HashPrintRequestAttributeSet extends HashAttributeSet * * @exception NullPointerException * (unchecked exception) - * Thrown if any element of attributes is null. + * Thrown if any element of {@code attributes} is null. */ public HashPrintRequestAttributeSet(PrintRequestAttribute[] attributes) { super (attributes, PrintRequestAttribute.class); @@ -84,15 +84,15 @@ public class HashPrintRequestAttributeSet extends HashAttributeSet /** * Construct a new attribute set, initially populated with the * values from the given set where the members of the attribute set - * are restricted to the (PrintRequestAttributeSe interface. + * are restricted to the {@code (PrintRequestAttributeSe} interface. * * @param attributes set of attribute values to initialise the set. If * null, an empty attribute set is constructed. * * @exception ClassCastException * (unchecked exception) Thrown if any element of - * attributes is not an instance of - * (PrintRequestAttributeSe. + * {@code attributes} is not an instance of + * {@code (PrintRequestAttributeSe}. */ public HashPrintRequestAttributeSet(PrintRequestAttributeSet attributes) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintServiceAttributeSet.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintServiceAttributeSet.java index d98430d0d75..31bd2ec738c 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintServiceAttributeSet.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/HashPrintServiceAttributeSet.java @@ -55,7 +55,7 @@ public class HashPrintServiceAttributeSet extends HashAttributeSet * @param attribute Attribute value to add to the set. * * @exception NullPointerException - * (unchecked exception) Thrown if attribute is null. + * (unchecked exception) Thrown if {@code attribute} is null. */ public HashPrintServiceAttributeSet(PrintServiceAttribute attribute) { super (attribute, PrintServiceAttribute.class); @@ -64,7 +64,7 @@ public class HashPrintServiceAttributeSet extends HashAttributeSet /** * Construct a new print service attribute set, initially populated with * the values from the given array. The new attribute set is populated - * by adding the elements of attributes array to the set in + * by adding the elements of {@code attributes} array to the set in * sequence, starting at index 0. Thus, later array elements may replace * earlier array elements if the array contains duplicate attribute * values or attribute categories. @@ -74,7 +74,7 @@ public class HashPrintServiceAttributeSet extends HashAttributeSet * * @exception NullPointerException * (unchecked exception) - * Thrown if any element of attributes is null. + * Thrown if any element of {@code attributes} is null. */ public HashPrintServiceAttributeSet(PrintServiceAttribute[] attributes) { super (attributes, PrintServiceAttribute.class); @@ -84,15 +84,15 @@ public class HashPrintServiceAttributeSet extends HashAttributeSet /** * Construct a new attribute set, initially populated with the * values from the given set where the members of the attribute set - * are restricted to the PrintServiceAttribute interface. + * are restricted to the {@code PrintServiceAttribute} interface. * * @param attributes set of attribute values to initialise the set. If * null, an empty attribute set is constructed. * * @exception ClassCastException * (unchecked exception) Thrown if any element of - * attributes is not an instance of - * PrintServiceAttribute. + * {@code attributes} is not an instance of + * {@code PrintServiceAttribute}. */ public HashPrintServiceAttributeSet(PrintServiceAttributeSet attributes) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/IntegerSyntax.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/IntegerSyntax.java index 1fbd3b2556d..a68cb0eac97 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/IntegerSyntax.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/IntegerSyntax.java @@ -69,9 +69,9 @@ public abstract class IntegerSyntax implements Serializable, Cloneable { * @param upperBound Upper bound. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than - * lowerBound or greater than - * upperBound. + * (Unchecked exception) Thrown if {@code value} is less than + * {@code lowerBound} or greater than + * {@code upperBound}. */ protected IntegerSyntax(int value, int lowerBound, int upperBound) { if (lowerBound > value || value > upperBound) { @@ -95,17 +95,17 @@ public abstract class IntegerSyntax implements Serializable, Cloneable { * object. To be equivalent, all of the following conditions must be true: *

          *
        1. - * object is not null. + * {@code object} is not null. *
        2. - * object is an instance of class IntegerSyntax. + * {@code object} is an instance of class IntegerSyntax. *
        3. - * This integer attribute's value and object's value are + * This integer attribute's value and {@code object}'s value are * equal. *
        * * @param object Object to compare to. * - * @return True if object is equivalent to this integer + * @return True if {@code object} is equivalent to this integer * attribute, false otherwise. */ public boolean equals(Object object) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/PrintRequestAttribute.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/PrintRequestAttribute.java index 48249480e60..6acf9ca51ef 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/PrintRequestAttribute.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/PrintRequestAttribute.java @@ -37,7 +37,7 @@ package javax.print.attribute; *

        * If an attribute implements {@link DocAttribute DocAttribute} * as well as PrintRequestAttribute, the client may include the - * attribute in a Doc}'s attribute set to specify + * attribute in a {@code Doc}'s attribute set to specify * a job setting which pertains just to that doc. * * @see DocAttributeSet diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/ResolutionSyntax.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/ResolutionSyntax.java index 7e9c40835b5..c6674707ec0 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/ResolutionSyntax.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/ResolutionSyntax.java @@ -150,13 +150,13 @@ public abstract class ResolutionSyntax implements Serializable, Cloneable { * @param dphi * Value (dphi) to convert. * @param units - * Unit conversion factor, e.g. {@link #DPI DPI} or - * {@link #DPCM DPCM}. + * Unit conversion factor, e.g. {@link #DPI DPI} or + * {@link #DPCM DPCM}. * - * @return The value of dphi converted to the desired units. + * @return The value of {@code dphi} converted to the desired units. * * @exception IllegalArgumentException - * (unchecked exception) Thrown if units < 1. + * (unchecked exception) Thrown if {@code units} < 1. */ private static int convertFromDphi(int dphi, int units) { if (units < 1) { @@ -222,7 +222,7 @@ public abstract class ResolutionSyntax implements Serializable, Cloneable { /** * Returns a string version of this resolution attribute in the given units. - * The string takes the form "CxF U", + * The string takes the form "CxF U", * where C is the cross feed direction resolution, F is the * feed direction resolution, and U is the units name. The values are * rounded to the nearest integer. @@ -231,7 +231,7 @@ public abstract class ResolutionSyntax implements Serializable, Cloneable { * Unit conversion factor, e.g. {@link #DPI CODE>DPI} or {@link * #DPCM DPCM}. * @param unitsName - * Units name string, e.g. "dpi" or "dpcm". If + * Units name string, e.g. {@code "dpi"} or {@code "dpcm"}. If * null, no units name is appended to the result. * * @return String version of this resolution attribute. @@ -259,19 +259,19 @@ public abstract class ResolutionSyntax implements Serializable, Cloneable { *

          *
        • * This attribute's cross feed direction resolution is less than or equal to - * the other attribute's cross feed direction resolution. + * the {@code other} attribute's cross feed direction resolution. *
        • * This attribute's feed direction resolution is less than or equal to the - * other attribute's feed direction resolution. + * {@code other} attribute's feed direction resolution. *
        * * @param other Resolution attribute to compare with. * * @return True if this resolution attribute is less than or equal to the - * other resolution attribute, false otherwise. + * {@code other} resolution attribute, false otherwise. * * @exception NullPointerException - * (unchecked exception) Thrown if other is null. + * (unchecked exception) Thrown if {@code other} is null. */ public boolean lessThanOrEquals(ResolutionSyntax other) { return (this.crossFeedResolution <= other.crossFeedResolution && @@ -284,20 +284,20 @@ public abstract class ResolutionSyntax implements Serializable, Cloneable { * object. To be equivalent, all of the following conditions must be true: *
          *
        1. - * object is not null. + * {@code object} is not null. *
        2. - * object is an instance of class ResolutionSyntax. + * {@code object} is an instance of class ResolutionSyntax. *
        3. * This attribute's cross feed direction resolution is equal to - * object's cross feed direction resolution. + * {@code object}'s cross feed direction resolution. *
        4. * This attribute's feed direction resolution is equal to - * object's feed direction resolution. + * {@code object}'s feed direction resolution. *
        * * @param object Object to compare to. * - * @return True if object is equivalent to this resolution + * @return True if {@code object} is equivalent to this resolution * attribute, false otherwise. */ public boolean equals(Object object) { @@ -320,7 +320,7 @@ public abstract class ResolutionSyntax implements Serializable, Cloneable { /** * Returns a string version of this resolution attribute. The string takes - * the form "CxF dphi", where C is the + * the form "CxF dphi", where C is the * cross feed direction resolution and F is the feed direction * resolution. The values are reported in the internal units of dphi. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/SetOfIntegerSyntax.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/SetOfIntegerSyntax.java index 8ba9303135a..ca1c81a6f31 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/SetOfIntegerSyntax.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/SetOfIntegerSyntax.java @@ -38,19 +38,18 @@ import java.util.Vector; * You can construct an instance of SetOfIntegerSyntax by giving it in "string * form." The string consists of zero or more comma-separated integer groups. * Each integer group consists of either one integer, two integers separated by - * a hyphen (-), or two integers separated by a colon - * (:). Each integer consists of one or more decimal digits - * (0 through 9). Whitespace characters cannot + * a hyphen ({@code -}), or two integers separated by a colon + * ({@code :}). Each integer consists of one or more decimal digits + * ({@code 0} through {@code 9}). Whitespace characters cannot * appear within an integer but are otherwise ignored. For example: - * "", "1", "5-10", "1:2, - * 4". + * {@code ""}, {@code "1"}, {@code "5-10"}, {@code "1:2, 4"}. *

        * You can also construct an instance of SetOfIntegerSyntax by giving it in * "array form." Array form consists of an array of zero or more integer groups * where each integer group is a length-1 or length-2 array of - * ints; for example, int[0][], - * int[][]{{1}}, int[][]{{5,10}}, - * int[][]{{1,2},{4}}. + * {@code int}s; for example, {@code int[0][]}, + * {@code int[][]{{1}}}, {@code int[][]{{5,10}}}, + * {@code int[][]{{1,2},{4}}}. *

        * In both string form and array form, each successive integer group gives a * range of integers to be included in the set. The first integer in each group @@ -68,7 +67,7 @@ import java.util.Vector; * array form." This is the same as array form, except there are no null ranges; * the members of the set are represented in as few ranges as possible (i.e., * overlapping ranges are coalesced); the ranges appear in ascending order; and - * each range is always represented as a length-two array of ints + * each range is always represented as a length-two array of {@code int}s * in the form {lower bound, upper bound}. An empty set is represented as a * zero-length array. *

        @@ -98,7 +97,7 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable { * constructed. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if members does not + * (Unchecked exception) Thrown if {@code members} does not * obey the proper syntax. */ protected SetOfIntegerSyntax(String members) { @@ -305,11 +304,11 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable { * * @exception NullPointerException * (Unchecked exception) Thrown if any element of - * members is null. + * {@code members} is null. * @exception IllegalArgumentException * (Unchecked exception) Thrown if any element of - * members is not a length-one or length-two array or if - * any non-null range in members has a lower bound less + * {@code members} is not a length-one or length-two array or if + * any non-null range in {@code members} has a lower bound less * than zero. */ protected SetOfIntegerSyntax(int[][] members) { @@ -357,7 +356,7 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable { * @param member Set member. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if member is less than + * (Unchecked exception) Thrown if {@code member} is less than * zero. */ protected SetOfIntegerSyntax(int member) { @@ -377,7 +376,7 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable { * * @exception IllegalArgumentException * (Unchecked exception) Thrown if the range is non-null and - * lowerBound is less than zero. + * {@code lowerBound} is less than zero. */ protected SetOfIntegerSyntax(int lowerBound, int upperBound) { if (lowerBound <= upperBound && lowerBound < 0) { @@ -411,7 +410,7 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable { * @param x Integer value. * * @return True if this set-of-integer attribute contains the value - * x, false otherwise. + * {@code x}, false otherwise. */ public boolean contains(int x) { // Do a linear search to find the range that contains x, if any. @@ -433,7 +432,7 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable { * @param attribute Integer attribute. * * @return True if this set-of-integer attribute contains - * theAttribute's value, false otherwise. + * {@code theAttribute}'s value, false otherwise. */ public boolean contains(IntegerSyntax attribute) { return contains (attribute.getValue()); @@ -442,10 +441,10 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable { /** * Determine the smallest integer in this set-of-integer attribute that is * greater than the given value. If there are no integers in this - * set-of-integer attribute greater than the given value, -1 is + * set-of-integer attribute greater than the given value, {@code -1} is * returned. (Since a set-of-integer attribute can only contain nonnegative - * values, -1 will never appear in the set.) You can use the - * next() method to iterate through the integer values in a + * values, {@code -1} will never appear in the set.) You can use the + * {@code next()} method to iterate through the integer values in a * set-of-integer attribute in ascending order, like this: *

              *     SetOfIntegerSyntax attribute = . . .;
        @@ -459,8 +458,8 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable {
              * @param  x  Integer value.
              *
              * @return  The smallest integer in this set-of-integer attribute that is
        -     *          greater than x, or -1 if no integer in
        -     *          this set-of-integer attribute is greater than x.
        +     *          greater than {@code x}, or {@code -1} if no integer in
        +     *          this set-of-integer attribute is greater than {@code x}.
              */
             public int next(int x) {
                 // Do a linear search to find the range that contains x, if any.
        @@ -481,17 +480,17 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable {
              * true:
              * 
          *
        1. - * object is not null. + * {@code object} is not null. *
        2. - * object is an instance of class SetOfIntegerSyntax. + * {@code object} is an instance of class SetOfIntegerSyntax. *
        3. - * This set-of-integer attribute's members and object's + * This set-of-integer attribute's members and {@code object}'s * members are the same. *
        * * @param object Object to compare to. * - * @return True if object is equivalent to this + * @return True if {@code object} is equivalent to this * set-of-integer attribute, false otherwise. */ public boolean equals(Object object) { @@ -534,9 +533,9 @@ public abstract class SetOfIntegerSyntax implements Serializable, Cloneable { * Returns a string value corresponding to this set-of-integer attribute. * The string value is a zero-length string if this set is empty. Otherwise, * the string value is a comma-separated list of the ranges in the canonical - * array form, where each range is represented as "i" if + * array form, where each range is represented as "i" if * the lower bound equals the upper bound or - * "i-j" otherwise. + * "i-j" otherwise. */ public String toString() { StringBuilder result = new StringBuilder(); diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/Size2DSyntax.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/Size2DSyntax.java index 76832508c94..e57c0812d58 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/Size2DSyntax.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/Size2DSyntax.java @@ -172,13 +172,13 @@ public abstract class Size2DSyntax implements Serializable, Cloneable { * @param x * Value (micrometers) to convert. * @param units - * Unit conversion factor, e.g. {@link #INCH INCH} or - * {@link #MM MM}. + * Unit conversion factor, e.g. {@link #INCH INCH} or + * {@link #MM MM}. * - * @return The value of x converted to the desired units. + * @return The value of {@code x} converted to the desired units. * * @exception IllegalArgumentException - * (unchecked exception) Thrown if units < 1. + * (unchecked exception) Thrown if {@code units} < 1. */ private static float convertFromMicrometers(int x, int units) { if (units < 1) { @@ -238,8 +238,8 @@ public abstract class Size2DSyntax implements Serializable, Cloneable { /** * Returns a string version of this two-dimensional size attribute in the - * given units. The string takes the form "XxY - * U", where X is the X dimension, Y is the Y + * given units. The string takes the form "XxY + * U", where X is the X dimension, Y is the Y * dimension, and U is the units name. The values are displayed in * floating point. * @@ -273,20 +273,20 @@ public abstract class Size2DSyntax implements Serializable, Cloneable { * be true: *
          *
        1. - * object is not null. + * {@code object} is not null. *
        2. - * object is an instance of class Size2DSyntax. + * {@code object} is an instance of class Size2DSyntax. *
        3. - * This attribute's X dimension is equal to object's X + * This attribute's X dimension is equal to {@code object}'s X * dimension. *
        4. - * This attribute's Y dimension is equal to object's Y + * This attribute's Y dimension is equal to {@code object}'s Y * dimension. *
        * * @param object Object to compare to. * - * @return True if object is equivalent to this + * @return True if {@code object} is equivalent to this * two-dimensional size attribute, false otherwise. */ public boolean equals(Object object) { @@ -306,7 +306,7 @@ public abstract class Size2DSyntax implements Serializable, Cloneable { /** * Returns a string version of this two-dimensional size attribute. The - * string takes the form "XxY um", where + * string takes the form "XxY um", where * X is the X dimension and Y is the Y dimension. * The values are reported in the internal units of micrometers. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/TextSyntax.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/TextSyntax.java index 7b91de24d0f..fb7a5654364 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/TextSyntax.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/TextSyntax.java @@ -61,10 +61,10 @@ public abstract class TextSyntax implements Serializable, Cloneable { * @param value Text string. * @param locale Natural language of the text string. null * is interpreted to mean the default locale for as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if value is null. + * (unchecked exception) Thrown if {@code value} is null. */ protected TextSyntax(String value, Locale locale) { this.value = verify (value); @@ -115,20 +115,20 @@ public abstract class TextSyntax implements Serializable, Cloneable { * object. To be equivalent, all of the following conditions must be true: *
          *
        1. - * object is not null. + * {@code object} is not null. *
        2. - * object is an instance of class TextSyntax. + * {@code object} is an instance of class TextSyntax. *
        3. - * This text attribute's underlying string and object's + * This text attribute's underlying string and {@code object}'s * underlying string are equal. *
        4. - * This text attribute's locale and object's locale are + * This text attribute's locale and {@code object}'s locale are * equal. *
        * * @param object Object to compare to. * - * @return True if object is equivalent to this text + * @return True if {@code object} is equivalent to this text * attribute, false otherwise. */ public boolean equals(Object object) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/URISyntax.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/URISyntax.java index 770ba8a9592..baee148a778 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/URISyntax.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/URISyntax.java @@ -52,7 +52,7 @@ public abstract class URISyntax implements Serializable, Cloneable { * @param uri URI. * * @exception NullPointerException - * (unchecked exception) Thrown if uri is null. + * (unchecked exception) Thrown if {@code uri} is null. */ protected URISyntax(URI uri) { this.uri = verify (uri); @@ -88,17 +88,17 @@ public abstract class URISyntax implements Serializable, Cloneable { * To be equivalent, all of the following conditions must be true: *
          *
        1. - * object is not null. + * {@code object} is not null. *
        2. - * object is an instance of class URISyntax. + * {@code object} is an instance of class URISyntax. *
        3. - * This URI attribute's underlying URI and object's + * This URI attribute's underlying URI and {@code object}'s * underlying URI are equal. *
        * * @param object Object to compare to. * - * @return True if object is equivalent to this URI + * @return True if {@code object} is equivalent to this URI * attribute, false otherwise. */ public boolean equals(Object object) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Chromaticity.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Chromaticity.java index 0cce5fde315..a9ac9a10c0b 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Chromaticity.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Chromaticity.java @@ -145,7 +145,7 @@ public final class Chromaticity extends EnumSyntax * Get the name of the category of which this attribute value is an * instance. *

        - * For class Chromaticity, the category name is "chromaticity". + * For class Chromaticity, the category name is {@code "chromaticity"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/ColorSupported.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/ColorSupported.java index 53def76bff1..ab5bee83451 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/ColorSupported.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/ColorSupported.java @@ -49,8 +49,8 @@ import javax.print.attribute.PrintServiceAttribute; *

        * IPP Compatibility: The IPP boolean value is "true" for SUPPORTED and * "false" for NOT_SUPPORTED. The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -118,7 +118,7 @@ public final class ColorSupported extends EnumSyntax * Get the name of the category of which this attribute value is an * instance. *

        - * For class ColorSupported, the category name is "color-supported". + * For class ColorSupported, the category name is {@code "color-supported"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Compression.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Compression.java index 80b391ed3bd..c0ba6680aba 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Compression.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Compression.java @@ -37,8 +37,8 @@ import javax.print.attribute.DocAttribute; * NONE}). *

        * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -122,7 +122,7 @@ public class Compression extends EnumSyntax implements DocAttribute { * instance. *

        * For class Compression and any vendor-defined subclasses, the category - * name is "compression". + * name is {@code "compression"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Copies.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Copies.java index 55b8db8489b..67cd5258885 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Copies.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Copies.java @@ -62,7 +62,7 @@ import javax.print.attribute.PrintJobAttribute; *

      *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @author David Mendenhall @@ -79,7 +79,7 @@ public final class Copies extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 1. + * (Unchecked exception) Thrown if {@code value} is less than 1. */ public Copies(int value) { super (value, 1, Integer.MAX_VALUE); @@ -90,17 +90,17 @@ public final class Copies extends IntegerSyntax * object. To be equivalent, all of the following conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class Copies. + * {@code object} is an instance of class Copies. *
      3. - * This copies attribute's value and object's value are + * This copies attribute's value and {@code object}'s value are * equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this copies + * @return True if {@code object} is equivalent to this copies * attribute, false otherwise. */ public boolean equals(Object object) { @@ -124,7 +124,7 @@ public final class Copies extends IntegerSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class Copies, the category name is "copies". + * For class Copies, the category name is {@code "copies"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/CopiesSupported.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/CopiesSupported.java index 4d24577ca7d..96efbb60bac 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/CopiesSupported.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/CopiesSupported.java @@ -39,7 +39,7 @@ import javax.print.attribute.SupportedValuesAttribute; * in an IPP "copies-supported" attribute. See class {@link * javax.print.attribute.SetOfIntegerSyntax SetOfIntegerSyntax} for an * explanation of canonical array form. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -55,7 +55,7 @@ public final class CopiesSupported extends SetOfIntegerSyntax * @param member Set member. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if member is less than 1. + * (Unchecked exception) Thrown if {@code member} is less than 1. */ public CopiesSupported(int member) { super (member); @@ -74,7 +74,7 @@ public final class CopiesSupported extends SetOfIntegerSyntax * * @exception IllegalArgumentException * (Unchecked exception) Thrown if a null range is specified or if a - * non-null range is specified with lowerBound less than + * non-null range is specified with {@code lowerBound} less than * 1. */ public CopiesSupported(int lowerBound, int upperBound) { @@ -93,17 +93,17 @@ public final class CopiesSupported extends SetOfIntegerSyntax * be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class CopiesSupported. + * {@code object} is an instance of class CopiesSupported. *
      3. - * This copies supported attribute's members and object's + * This copies supported attribute's members and {@code object}'s * members are the same. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this copies + * @return True if {@code object} is equivalent to this copies * supported attribute, false otherwise. */ public boolean equals(Object object) { @@ -129,7 +129,7 @@ public final class CopiesSupported extends SetOfIntegerSyntax * instance. *

      * For class CopiesSupported, the category - * name is "copies-supported". + * name is {@code "copies-supported"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtCompleted.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtCompleted.java index c51b2fd32ab..9005e940db1 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtCompleted.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtCompleted.java @@ -45,7 +45,7 @@ import javax.print.attribute.PrintJobAttribute; *

      * IPP Compatibility: The information needed to construct an IPP * "date-time-at-completed" attribute can be obtained as described above. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @author Alan Kaminsky @@ -62,7 +62,7 @@ public final class DateTimeAtCompleted extends DateTimeSyntax * @param dateTime {@link java.util.Date Date} value. * * @exception NullPointerException - * (unchecked exception) Thrown if dateTime is null. + * (unchecked exception) Thrown if {@code dateTime} is null. */ public DateTimeAtCompleted(Date dateTime) { super (dateTime); @@ -74,17 +74,17 @@ public final class DateTimeAtCompleted extends DateTimeSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class DateTimeAtCompleted. + * {@code object} is an instance of class DateTimeAtCompleted. *
      3. * This date-time at completed attribute's {@link java.util.Date Date} value - * and object's {@link java.util.Date Date} value are equal. + * and {@code object}'s {@link java.util.Date Date} value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this date-time + * @return True if {@code object} is equivalent to this date-time * at completed attribute, false otherwise. */ public boolean equals(Object object) { @@ -113,7 +113,7 @@ public final class DateTimeAtCompleted extends DateTimeSyntax * instance. *

      * For class DateTimeAtCompleted, the category name is - * "date-time-at-completed". + * {@code "date-time-at-completed"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtCreation.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtCreation.java index f4c98aaba7d..497398cc3d2 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtCreation.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtCreation.java @@ -45,7 +45,7 @@ import javax.print.attribute.PrintJobAttribute; *

      * IPP Compatibility: The information needed to construct an IPP * "date-time-at-creation" attribute can be obtained as described above. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @author Alan Kaminsky @@ -62,7 +62,7 @@ public final class DateTimeAtCreation extends DateTimeSyntax * @param dateTime {@link java.util.Date Date} value. * * @exception NullPointerException - * (unchecked exception) Thrown if dateTime is null. + * (unchecked exception) Thrown if {@code dateTime} is null. */ public DateTimeAtCreation(Date dateTime) { super (dateTime); @@ -74,17 +74,17 @@ public final class DateTimeAtCreation extends DateTimeSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class DateTimeAtCreation. + * {@code object} is an instance of class DateTimeAtCreation. *
      3. * This date-time at creation attribute's {@link java.util.Date Date} value - * and object's {@link java.util.Date Date} value are equal. + * and {@code object}'s {@link java.util.Date Date} value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this date-time + * @return True if {@code object} is equivalent to this date-time * at creation attribute, false otherwise. */ public boolean equals(Object object) { @@ -111,7 +111,7 @@ public final class DateTimeAtCreation extends DateTimeSyntax * instance. *

      * For class DateTimeAtCreation, the category name is - * "date-time-at-creation". + * {@code "date-time-at-creation"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtProcessing.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtProcessing.java index 821a8453a1a..98ad0d2216d 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtProcessing.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DateTimeAtProcessing.java @@ -45,7 +45,7 @@ import javax.print.attribute.PrintJobAttribute; *

      * IPP Compatibility: The information needed to construct an IPP * "date-time-at-processing" attribute can be obtained as described above. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @author Alan Kaminsky @@ -62,7 +62,7 @@ public final class DateTimeAtProcessing extends DateTimeSyntax * @param dateTime {@link java.util.Date Date} value. * * @exception NullPointerException - * (unchecked exception) Thrown if dateTime is null. + * (unchecked exception) Thrown if {@code dateTime} is null. */ public DateTimeAtProcessing(Date dateTime) { super (dateTime); @@ -74,18 +74,18 @@ public final class DateTimeAtProcessing extends DateTimeSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class DateTimeAtProcessing. + * {@code object} is an instance of class DateTimeAtProcessing. *
      3. * This date-time at processing attribute's {@link java.util.Date Date} - * value and object's {@link java.util.Date Date} value + * value and {@code object}'s {@link java.util.Date Date} value * are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this date-time + * @return True if {@code object} is equivalent to this date-time * at processing attribute, false otherwise. */ public boolean equals(Object object) { @@ -112,7 +112,7 @@ public final class DateTimeAtProcessing extends DateTimeSyntax * instance. *

      * For class DateTimeAtProcessing, the category name is - * "date-time-at-processing". + * {@code "date-time-at-processing"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Destination.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Destination.java index 43e1ea9b150..4c855da4b73 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Destination.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Destination.java @@ -40,7 +40,7 @@ import javax.print.attribute.PrintJobAttribute; * A common use for this attribute will be applications which want * to redirect output to a local disk file : eg."file:out.prn". * Note that proper construction of "file:" scheme URI instances should - * be performed using the toURI() method of class + * be performed using the {@code toURI()} method of class * {@link java.io.File File}. * See the documentation on that class for more information. *

      @@ -64,7 +64,7 @@ public final class Destination extends URISyntax * @param uri URI. * * @exception NullPointerException - * (unchecked exception) Thrown if uri is null. + * (unchecked exception) Thrown if {@code uri} is null. */ public Destination(URI uri) { super (uri); @@ -76,17 +76,17 @@ public final class Destination extends URISyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class Destination. + * {@code object} is an instance of class Destination. *
      3. - * This destination attribute's URI and object's URI + * This destination attribute's URI and {@code object}'s URI * are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this destination + * @return True if {@code object} is equivalent to this destination * attribute, false otherwise. */ public boolean equals(Object object) { @@ -111,7 +111,7 @@ public final class Destination extends URISyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class Destination, the category name is "spool-data-destination". + * For class Destination, the category name is {@code "spool-data-destination"}. * * @return Attribute category name. */ 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 3e567f50973..f4827744815 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 @@ -120,7 +120,7 @@ public final class DialogTypeSelection extends EnumSyntax * instance. *

      * For class DialogTypeSelection the category name is - * "dialog-type-selection". + * {@code "dialog-type-selection"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DocumentName.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DocumentName.java index 68b93bed43c..a2716895cf1 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DocumentName.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DocumentName.java @@ -42,7 +42,7 @@ import javax.print.attribute.DocAttribute; *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -57,10 +57,10 @@ public final class DocumentName extends TextSyntax implements DocAttribute { * @param documentName Document name. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if documentName is null. + * (unchecked exception) Thrown if {@code documentName} is null. */ public DocumentName(String documentName, Locale locale) { super (documentName, locale); @@ -72,20 +72,20 @@ public final class DocumentName extends TextSyntax implements DocAttribute { * To be equivalent, all of the following conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class DocumentName. + * {@code object} is an instance of class DocumentName. *
      3. * This document name attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. - * This document name attribute's locale and object's locale + * This document name attribute's locale and {@code object}'s locale * are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this document + * @return True if {@code object} is equivalent to this document * name attribute, false otherwise. */ public boolean equals(Object object) { @@ -109,7 +109,7 @@ public final class DocumentName extends TextSyntax implements DocAttribute { * Get the name of the category of which this attribute value is an * instance. *

      - * For class DocumentName, the category name is "document-name". + * For class DocumentName, the category name is {@code "document-name"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Fidelity.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Fidelity.java index 8db0c98366b..b77b110d309 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Fidelity.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Fidelity.java @@ -41,8 +41,8 @@ import javax.print.attribute.PrintRequestAttribute; *

      * IPP Compatibility: The IPP boolean value is "true" for FIDELITY_TRUE * and "false" for FIDELITY_FALSE. The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * See RFC 2911 Section 15.1 for * a fuller description of the IPP fidelity attribute. @@ -117,7 +117,7 @@ public final class Fidelity extends EnumSyntax * instance. *

      * For class Fidelity the category name is - * "ipp-attribute-fidelity". + * {@code "ipp-attribute-fidelity"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Finishings.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Finishings.java index cc21389cbaf..8369f7f4da8 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Finishings.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Finishings.java @@ -212,8 +212,8 @@ import javax.print.attribute.PrintJobAttribute; * IPP Compatibility: Class Finishings encapsulates some of the * IPP enum values that can be included in an IPP "finishings" attribute, which * is a set of enums. The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * In IPP Finishings is a multi-value attribute, this API currently allows * only one binding to be specified. @@ -466,7 +466,7 @@ public class Finishings extends EnumSyntax * instance. *

      * For class Finishings and any vendor-defined subclasses, the - * category name is "finishings". + * category name is {@code "finishings"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobHoldUntil.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobHoldUntil.java index 4e3ee705bb7..6c6da671faf 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobHoldUntil.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobHoldUntil.java @@ -77,7 +77,7 @@ import javax.print.attribute.PrintJobAttribute; * converted to one of the standard IPP keywords with some loss of precision; * for example, a JobHoldUntil value with today's date and 9:00pm local time * might be converted to the standard IPP keyword "night". The category name - * returned by getName() gives the IPP attribute name. + * returned by {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -94,7 +94,7 @@ public final class JobHoldUntil extends DateTimeSyntax * @param dateTime {@link java.util.Date Date} value. * * @exception NullPointerException - * (unchecked exception) Thrown if dateTime is null. + * (unchecked exception) Thrown if {@code dateTime} is null. */ public JobHoldUntil(Date dateTime) { super (dateTime); @@ -106,17 +106,17 @@ public final class JobHoldUntil extends DateTimeSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobHoldUntil. + * {@code object} is an instance of class JobHoldUntil. *
      3. * This job hold until attribute's {@link java.util.Date Date} value and - * object's {@link java.util.Date Date} value are equal. + * {@code object}'s {@link java.util.Date Date} value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job hold + * @return True if {@code object} is equivalent to this job hold * until attribute, false otherwise. */ public boolean equals(Object object) { @@ -141,7 +141,7 @@ public final class JobHoldUntil extends DateTimeSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class JobHoldUntil, the category name is "job-hold-until". + * For class JobHoldUntil, the category name is {@code "job-hold-until"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressions.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressions.java index e0b267bae89..8d5a1244327 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressions.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressions.java @@ -63,7 +63,7 @@ import javax.print.attribute.PrintJobAttribute; * than a measure of the number of impressions to be produced by the job. *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @see JobImpressionsSupported @@ -85,7 +85,7 @@ public final class JobImpressions extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public JobImpressions(int value) { super(value, 0, Integer.MAX_VALUE); @@ -97,17 +97,17 @@ public final class JobImpressions extends IntegerSyntax * be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobImpressions. + * {@code object} is an instance of class JobImpressions. *
      3. - * This job impressions attribute's value and object's value + * This job impressions attribute's value and {@code object}'s value * are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job + * @return True if {@code object} is equivalent to this job * impressions attribute, false otherwise. */ public boolean equals(Object object) { @@ -132,7 +132,7 @@ public final class JobImpressions extends IntegerSyntax * instance. *

      * For class JobImpressions, the category name is - * "job-impressions". + * {@code "job-impressions"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressionsCompleted.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressionsCompleted.java index 2ac4f6049d1..ea346435dd6 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressionsCompleted.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressionsCompleted.java @@ -45,7 +45,7 @@ import javax.print.attribute.PrintJobAttribute; * states, the JobImpressionsCompleted value is the final value for the job. *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @see JobImpressions @@ -67,7 +67,7 @@ public final class JobImpressionsCompleted extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public JobImpressionsCompleted(int value) { super (value, 0, Integer.MAX_VALUE); @@ -79,17 +79,17 @@ public final class JobImpressionsCompleted extends IntegerSyntax * conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobImpressionsCompleted. + * {@code object} is an instance of class JobImpressionsCompleted. *
      3. * This job impressions completed attribute's value and - * object's value are equal. + * {@code object}'s value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job + * @return True if {@code object} is equivalent to this job * impressions completed attribute, false otherwise. */ public boolean equals(Object object) { @@ -116,7 +116,7 @@ public final class JobImpressionsCompleted extends IntegerSyntax * instance. *

      * For class JobImpressionsCompleted, the category name is - * "job-impressions-completed". + * {@code "job-impressions-completed"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressionsSupported.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressionsSupported.java index b6804aae2c8..ee53d2a3614 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressionsSupported.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobImpressionsSupported.java @@ -41,7 +41,7 @@ import javax.print.attribute.SupportedValuesAttribute; * included in an IPP "job-impressions-supported" attribute. See class {@link * javax.print.attribute.SetOfIntegerSyntax SetOfIntegerSyntax} for an * explanation of canonical array form. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -61,7 +61,7 @@ public final class JobImpressionsSupported extends SetOfIntegerSyntax * * @exception IllegalArgumentException * (Unchecked exception) Thrown if a null range is specified or if a - * non-null range is specified with lowerBound less than + * non-null range is specified with {@code lowerBound} less than * 0. */ public JobImpressionsSupported(int lowerBound, int upperBound) { @@ -81,17 +81,17 @@ public final class JobImpressionsSupported extends SetOfIntegerSyntax * conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobImpressionsSupported. + * {@code object} is an instance of class JobImpressionsSupported. *
      3. * This job impressions supported attribute's members and - * object's members are the same. + * {@code object}'s members are the same. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job + * @return True if {@code object} is equivalent to this job * impressions supported attribute, false otherwise. */ public boolean equals(Object object) { @@ -118,7 +118,7 @@ public final class JobImpressionsSupported extends SetOfIntegerSyntax * instance. *

      * For class JobImpressionsSupported, the category name is - * "job-impressions-supported". + * {@code "job-impressions-supported"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctets.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctets.java index 383f5fe1e2e..c50dc9f3b7d 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctets.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctets.java @@ -115,7 +115,7 @@ import javax.print.attribute.PrintJobAttribute; * data, replacing any JobKOctets value the client specified. *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @see JobKOctetsSupported @@ -136,7 +136,7 @@ public final class JobKOctets extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public JobKOctets(int value) { super (value, 0, Integer.MAX_VALUE); @@ -148,17 +148,17 @@ public final class JobKOctets extends IntegerSyntax * true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobKOctets. + * {@code object} is an instance of class JobKOctets. *
      3. - * This job K octets attribute's value and object's value + * This job K octets attribute's value and {@code object}'s value * are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job K + * @return True if {@code object} is equivalent to this job K * octets attribute, false otherwise. */ public boolean equals(Object object) { @@ -182,7 +182,7 @@ public final class JobKOctets extends IntegerSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class JobKOctets, the category name is "job-k-octets". + * For class JobKOctets, the category name is {@code "job-k-octets"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctetsProcessed.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctetsProcessed.java index cecd80ddd1b..d3fff73454f 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctetsProcessed.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctetsProcessed.java @@ -57,7 +57,7 @@ import javax.print.attribute.PrintJobAttribute; * JobKOctets} attribute. *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @see JobKOctets @@ -79,7 +79,7 @@ public final class JobKOctetsProcessed extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public JobKOctetsProcessed(int value) { super (value, 0, Integer.MAX_VALUE); @@ -91,17 +91,17 @@ public final class JobKOctetsProcessed extends IntegerSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobKOctetsProcessed. + * {@code object} is an instance of class JobKOctetsProcessed. *
      3. * This job K octets processed attribute's value and - * object's value are equal. + * {@code object}'s value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job K + * @return True if {@code object} is equivalent to this job K * octets processed attribute, false otherwise. */ public boolean equals(Object object) { @@ -128,7 +128,7 @@ public final class JobKOctetsProcessed extends IntegerSyntax * instance. *

      * For class JobKOctetsProcessed, the category name is - * "job-k-octets-processed". + * {@code "job-k-octets-processed"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctetsSupported.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctetsSupported.java index 9a7a8504e00..c4666bee8b1 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctetsSupported.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobKOctetsSupported.java @@ -41,7 +41,7 @@ import javax.print.attribute.SupportedValuesAttribute; * in an IPP "job-k-octets-supported" attribute. See class {@link * javax.print.attribute.SetOfIntegerSyntax SetOfIntegerSyntax} for an * explanation of canonical array form. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -60,7 +60,7 @@ public final class JobKOctetsSupported extends SetOfIntegerSyntax * * @exception IllegalArgumentException * (Unchecked exception) Thrown if a null range is specified or if a - * non-null range is specified with lowerBound less than + * non-null range is specified with {@code lowerBound} less than * 0. */ public JobKOctetsSupported(int lowerBound, int upperBound) { @@ -79,17 +79,17 @@ public final class JobKOctetsSupported extends SetOfIntegerSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobKOctetsSupported. + * {@code object} is an instance of class JobKOctetsSupported. *
      3. * This job K octets supported attribute's members and - * object's members are the same. + * {@code object}'s members are the same. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job K + * @return True if {@code object} is equivalent to this job K * octets supported attribute, false otherwise. */ public boolean equals(Object object) { @@ -116,7 +116,7 @@ public final class JobKOctetsSupported extends SetOfIntegerSyntax * instance. *

      * For class JobKOctetsSupported, the category name is - * "job-k-octets-supported". + * {@code "job-k-octets-supported"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheets.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheets.java index caeb31e996c..ad574753c4e 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheets.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheets.java @@ -55,7 +55,7 @@ import javax.print.attribute.PrintJobAttribute; * with {@link JobMediaSheetsSupported JobMediaSheetsSupported}. *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @see JobMediaSheetsSupported @@ -78,7 +78,7 @@ public class JobMediaSheets extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public JobMediaSheets(int value) { super (value, 0, Integer.MAX_VALUE); @@ -90,17 +90,17 @@ public class JobMediaSheets extends IntegerSyntax * be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobMediaSheets. + * {@code object} is an instance of class JobMediaSheets. *
      3. - * This job media sheets attribute's value and object's + * This job media sheets attribute's value and {@code object}'s * value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job media + * @return True if {@code object} is equivalent to this job media * sheets attribute, false otherwise. */ public boolean equals(Object object) { @@ -126,7 +126,7 @@ public class JobMediaSheets extends IntegerSyntax * instance. *

      * For class JobMediaSheets and any vendor-defined subclasses, the - * category name is "job-media-sheets". + * category name is {@code "job-media-sheets"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheetsCompleted.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheetsCompleted.java index 5b75cdbb89b..ed39a52e122 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheetsCompleted.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheetsCompleted.java @@ -45,7 +45,7 @@ import javax.print.attribute.PrintJobAttribute; * states, the JobMediaSheetsCompleted value is the final value for the job. *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @see JobMediaSheets @@ -68,7 +68,7 @@ public final class JobMediaSheetsCompleted extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public JobMediaSheetsCompleted(int value) { super (value, 0, Integer.MAX_VALUE); @@ -80,17 +80,17 @@ public final class JobMediaSheetsCompleted extends IntegerSyntax * conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobMediaSheetsCompleted. + * {@code object} is an instance of class JobMediaSheetsCompleted. *
      3. * This job media sheets completed attribute's value and - * object's value are equal. + * {@code object}'s value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job media + * @return True if {@code object} is equivalent to this job media * sheets completed attribute, false otherwise. */ public boolean equals(Object object) { @@ -117,7 +117,7 @@ public final class JobMediaSheetsCompleted extends IntegerSyntax * instance. *

      * For class JobMediaSheetsCompleted, the category name is - * "job-media-sheets-completed". + * {@code "job-media-sheets-completed"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheetsSupported.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheetsSupported.java index 47c7b04459a..19d3a6a2084 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheetsSupported.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMediaSheetsSupported.java @@ -41,7 +41,7 @@ import javax.print.attribute.SupportedValuesAttribute; * included in an IPP "job-media-sheets-supported" attribute. See class {@link * javax.print.attribute.SetOfIntegerSyntax SetOfIntegerSyntax} for an * explanation of canonical array form. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -60,7 +60,7 @@ public final class JobMediaSheetsSupported extends SetOfIntegerSyntax * * @exception IllegalArgumentException * (Unchecked exception) Thrown if a null range is specified or if a - * non-null range is specified with lowerBound less than + * non-null range is specified with {@code lowerBound} less than * 0. */ public JobMediaSheetsSupported(int lowerBound, int upperBound) { @@ -79,17 +79,17 @@ public final class JobMediaSheetsSupported extends SetOfIntegerSyntax * conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobMediaSheetsSupported. + * {@code object} is an instance of class JobMediaSheetsSupported. *
      3. * This job media sheets supported attribute's members and - * object's members are the same. + * {@code object}'s members are the same. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job media + * @return True if {@code object} is equivalent to this job media * sheets supported attribute, false otherwise. */ public boolean equals(Object object) { @@ -116,7 +116,7 @@ public final class JobMediaSheetsSupported extends SetOfIntegerSyntax * instance. *

      * For class JobMediaSheetsSupported, the - * category name is "job-media-sheets-supported". + * category name is {@code "job-media-sheets-supported"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMessageFromOperator.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMessageFromOperator.java index c1f4231009c..f52de7d303a 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMessageFromOperator.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobMessageFromOperator.java @@ -46,7 +46,7 @@ import javax.print.attribute.PrintJobAttribute; *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -62,10 +62,10 @@ public final class JobMessageFromOperator extends TextSyntax * @param message Message. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if message is null. + * (unchecked exception) Thrown if {@code message} is null. */ public JobMessageFromOperator(String message, Locale locale) { super (message, locale); @@ -77,20 +77,20 @@ public final class JobMessageFromOperator extends TextSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobMessageFromOperator. + * {@code object} is an instance of class JobMessageFromOperator. *
      3. * This job message from operator attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. * This job message from operator attribute's locale and - * object's locale are equal. + * {@code object}'s locale are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job + * @return True if {@code object} is equivalent to this job * message from operator attribute, false otherwise. */ public boolean equals(Object object) { @@ -117,7 +117,7 @@ public final class JobMessageFromOperator extends TextSyntax * instance. *

      * For class JobMessageFromOperator, the - * category name is "job-message-from-operator". + * category name is {@code "job-message-from-operator"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobName.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobName.java index bb563ceaf75..7be25f02c91 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobName.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobName.java @@ -47,7 +47,7 @@ import javax.print.attribute.PrintJobAttribute; *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -62,10 +62,10 @@ public final class JobName extends TextSyntax * @param jobName Job name. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if jobName is null. + * (unchecked exception) Thrown if {@code jobName} is null. */ public JobName(String jobName, Locale locale) { super (jobName, locale); @@ -76,20 +76,20 @@ public final class JobName extends TextSyntax * object. To be equivalent, all of the following conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobName. + * {@code object} is an instance of class JobName. *
      3. - * This job name attribute's underlying string and object's + * This job name attribute's underlying string and {@code object}'s * underlying string are equal. *
      4. - * This job name attribute's locale and object's locale are + * This job name attribute's locale and {@code object}'s locale are * equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job name + * @return True if {@code object} is equivalent to this job name * attribute, false otherwise. */ public boolean equals(Object object) { @@ -113,7 +113,7 @@ public final class JobName extends TextSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class JobName, the category name is "job-name". + * For class JobName, the category name is {@code "job-name"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobOriginatingUserName.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobOriginatingUserName.java index 61e589c7f64..62a3e20b235 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobOriginatingUserName.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobOriginatingUserName.java @@ -46,7 +46,7 @@ import javax.print.attribute.PrintJobAttribute; *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -62,10 +62,10 @@ public final class JobOriginatingUserName extends TextSyntax * @param userName User name. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if userName is null. + * (unchecked exception) Thrown if {@code userName} is null. */ public JobOriginatingUserName(String userName, Locale locale) { super (userName, locale); @@ -77,20 +77,20 @@ public final class JobOriginatingUserName extends TextSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobOriginatingUserName. + * {@code object} is an instance of class JobOriginatingUserName. *
      3. * This job originating user name attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. * This job originating user name attribute's locale and - * object's locale are equal. + * {@code object}'s locale are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job + * @return True if {@code object} is equivalent to this job * originating user name attribute, false otherwise. */ public boolean equals(Object object) { @@ -117,7 +117,7 @@ public final class JobOriginatingUserName extends TextSyntax * instance. *

      * For class JobOriginatingUserName, the - * category name is "job-originating-user-name". + * category name is {@code "job-originating-user-name"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobPriority.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobPriority.java index b4a77ae5c51..7a03e304f1b 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobPriority.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobPriority.java @@ -52,7 +52,7 @@ import javax.print.attribute.PrintJobAttribute; * among the available job priority levels. *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @author Alan Kaminsky @@ -68,7 +68,7 @@ public final class JobPriority extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 1 + * (Unchecked exception) Thrown if {@code value} is less than 1 * or greater than 100. */ public JobPriority(int value) { @@ -81,17 +81,17 @@ public final class JobPriority extends IntegerSyntax * true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobPriority. + * {@code object} is an instance of class JobPriority. *
      3. - * This job priority attribute's value and object's value + * This job priority attribute's value and {@code object}'s value * are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job + * @return True if {@code object} is equivalent to this job * priority attribute, false otherwise. */ public boolean equals(Object object) { @@ -115,7 +115,7 @@ public final class JobPriority extends IntegerSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class JobPriority, the category name is "job-priority". + * For class JobPriority, the category name is {@code "job-priority"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobPrioritySupported.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobPrioritySupported.java index 80e7b6c54a5..3d7cf55095a 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobPrioritySupported.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobPrioritySupported.java @@ -42,7 +42,7 @@ import javax.print.attribute.SupportedValuesAttribute; * priority values equally among the available job priority levels. *

      * IPP Compatibility: The integer value gives the IPP integer value. - * The category name returned by getName() gives the IPP + * The category name returned by {@code getName()} gives the IPP * attribute name. * * @author Alan Kaminsky @@ -60,7 +60,7 @@ public final class JobPrioritySupported extends IntegerSyntax * @param value Number of different job priority levels supported. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 1 + * (Unchecked exception) Thrown if {@code value} is less than 1 * or greater than 100. */ public JobPrioritySupported(int value) { @@ -73,17 +73,17 @@ public final class JobPrioritySupported extends IntegerSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class JobPrioritySupported. + * {@code object} is an instance of class JobPrioritySupported. *
      3. * This job priority supported attribute's value and - * object's value are equal. + * {@code object}'s value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this job + * @return True if {@code object} is equivalent to this job * priority supported attribute, false otherwise. */ public boolean equals (Object object) { @@ -112,7 +112,7 @@ public final class JobPrioritySupported extends IntegerSyntax * instance. *

      * For class JobPrioritySupported, the - * category name is "job-priority-supported". + * category name is {@code "job-priority-supported"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobSheets.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobSheets.java index cec0f27901a..69579ce6c60 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobSheets.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobSheets.java @@ -44,9 +44,9 @@ import javax.print.attribute.PrintJobAttribute; * particular JobSheets value. *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The + * {@code getName()} is the IPP attribute name. The * enumeration's integer value is the IPP enum value. The - * toString() method returns the IPP string representation of + * {@code toString()} method returns the IPP string representation of * the attribute value. For a subclass, the attribute value must be * localized to give the IPP name and natural language values. * @@ -122,7 +122,7 @@ public class JobSheets extends EnumSyntax * instance. *

      * For class JobSheets and any vendor-defined subclasses, the category - * name is "job-sheets". + * name is {@code "job-sheets"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobState.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobState.java index 0ad1e5997ba..e87de1aab70 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobState.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobState.java @@ -39,8 +39,8 @@ import javax.print.attribute.PrintJobAttribute; * detailed information about the job in the given job state. *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -225,7 +225,7 @@ public class JobState extends EnumSyntax implements PrintJobAttribute { * instance. *

      * For class JobState and any vendor-defined subclasses, the category - * name is "job-state". + * name is {@code "job-state"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobStateReason.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobStateReason.java index 3465eae6204..553236efaeb 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobStateReason.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/JobStateReason.java @@ -48,8 +48,8 @@ import javax.print.attribute.Attribute; * JobState} also changed. *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -259,7 +259,7 @@ public class JobStateReason extends EnumSyntax implements Attribute { * The job was aborted by the system because the document data's document * format (doc flavor) is not among those supported by the printer. If the * client specifies a doc flavor with a MIME type of - * "application/octet-stream", the printer may abort the job if + * {@code "application/octet-stream"}, the printer may abort the job if * the printer cannot determine the document data's actual format through * auto-sensing (even if the printer supports the document format if * specified explicitly). This value must be supported, since a doc flavor @@ -449,7 +449,7 @@ public class JobStateReason extends EnumSyntax implements Attribute { * instance. *

      * For class JobStateReason and any vendor-defined subclasses, the - * category name is "job-state-reason". + * category name is {@code "job-state-reason"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Media.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Media.java index 59dd57b320b..94eec385dfb 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Media.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Media.java @@ -49,8 +49,8 @@ import javax.print.attribute.PrintJobAttribute; * one of the ways in which the Media attribute can be specified. *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Phil Race @@ -74,16 +74,16 @@ public abstract class Media extends EnumSyntax * object. To be equivalent, all of the following conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is of the same subclass of Media as this object. + * {@code object} is of the same subclass of Media as this object. *
      3. * The values are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this media + * @return True if {@code object} is equivalent to this media * attribute, false otherwise. */ public boolean equals(Object object) { @@ -111,7 +111,7 @@ public abstract class Media extends EnumSyntax * instance. *

      * For class Media and any vendor-defined subclasses, the category name is - * "media". + * {@code "media"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MediaPrintableArea.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MediaPrintableArea.java index 232600e88ad..cfe9a34cbf8 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MediaPrintableArea.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MediaPrintableArea.java @@ -54,7 +54,7 @@ import javax.print.attribute.PrintRequestAttribute; * The hardware's minimum margins is not just a property of the printer, * but may be a function of the media size, orientation, media type, and * any specified finishings. - * PrintService provides the method to query the supported + * {@code PrintService} provides the method to query the supported * values of an attribute in a suitable context : * See {@link javax.print.PrintService#getSupportedAttributeValues(Class,DocFlavor, AttributeSet) PrintService.getSupportedAttributeValues()} *

      @@ -236,16 +236,16 @@ public final class MediaPrintableArea * To be equivalent, all of the following conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class MediaPrintableArea. + * {@code object} is an instance of class MediaPrintableArea. *
      3. * The origin and dimensions are the same. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this media margins + * @return True if {@code object} is equivalent to this media margins * attribute, false otherwise. */ public boolean equals(Object object) { @@ -278,7 +278,7 @@ public final class MediaPrintableArea * instance. *

      * For class MediaPrintableArea, - * the category name is "media-printable-area". + * the category name is {@code "media-printable-area"}. *

      This is not an IPP V1.1 attribute. * * @return Attribute category name. @@ -295,7 +295,7 @@ public final class MediaPrintableArea * Unit conversion factor, e.g. {@link #INCH INCH} or * {@link #MM MM}. * @param unitsName - * Units name string, e.g. "in" or "mm". If + * Units name string, e.g. {@code "in"} or {@code "mm"}. If * null, no units name is appended to the result. * * @return String version of this two-dimensional size attribute. diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MediaSize.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MediaSize.java index b6fdbdccb4f..55990097a71 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MediaSize.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MediaSize.java @@ -42,7 +42,7 @@ import javax.print.attribute.Attribute; * MediaSize is not yet used to specify media. Its current role is * as a mapping for named media (see {@link MediaSizeName MediaSizeName}). * Clients can use the mapping method - * MediaSize.getMediaSizeForName(MediaSizeName) + * {@code MediaSize.getMediaSizeForName(MediaSizeName)} * to find the physical dimensions of the MediaSizeName instances * enumerated in this API. This is useful for clients which need this * information to format {@literal &} paginate printing. @@ -66,8 +66,8 @@ public class MediaSize extends Size2DSyntax implements Attribute { * @param x X dimension. * @param y Y dimension. * @param units - * Unit conversion factor, e.g. Size2DSyntax.INCH or - * Size2DSyntax.MM. + * Unit conversion factor, e.g. {@code Size2DSyntax.INCH} or + * {@code Size2DSyntax.MM}. * * @exception IllegalArgumentException * (Unchecked exception) Thrown if {@code x < 0} or {@code y < 0} or @@ -87,8 +87,8 @@ public class MediaSize extends Size2DSyntax implements Attribute { * @param x X dimension. * @param y Y dimension. * @param units - * Unit conversion factor, e.g. Size2DSyntax.INCH or - * Size2DSyntax.MM. + * Unit conversion factor, e.g. {@code Size2DSyntax.INCH} or + * {@code Size2DSyntax.MM}. * * @exception IllegalArgumentException * (Unchecked exception) Thrown if {@code x < 0} or {@code y < 0} or @@ -109,8 +109,8 @@ public class MediaSize extends Size2DSyntax implements Attribute { * @param x X dimension. * @param y Y dimension. * @param units - * Unit conversion factor, e.g. Size2DSyntax.INCH or - * Size2DSyntax.MM. + * Unit conversion factor, e.g. {@code Size2DSyntax.INCH} or + * {@code Size2DSyntax.MM}. * @param media a media name to associate with this MediaSize * * @exception IllegalArgumentException @@ -135,8 +135,8 @@ public class MediaSize extends Size2DSyntax implements Attribute { * @param x X dimension. * @param y Y dimension. * @param units - * Unit conversion factor, e.g. Size2DSyntax.INCH or - * Size2DSyntax.MM. + * Unit conversion factor, e.g. {@code Size2DSyntax.INCH} or + * {@code Size2DSyntax.MM}. * @param media a media name to associate with this MediaSize * * @exception IllegalArgumentException @@ -168,7 +168,7 @@ public class MediaSize extends Size2DSyntax implements Attribute { /** * Get the MediaSize for the specified named media. * - * @param media - the name of the media for which the size is sought + * @param media the name of the media for which the size is sought * @return size of the media, or null if this media is not associated * with any size. */ @@ -187,11 +187,11 @@ public class MediaSize extends Size2DSyntax implements Attribute { *

      * This method is useful for clients which have only dimensions and * want to find a Media which corresponds to the dimensions. - * @param x - X dimension - * @param y - Y dimension. + * @param x X dimension + * @param y Y dimension. * @param units - * Unit conversion factor, e.g. Size2DSyntax.INCH or - * Size2DSyntax.MM + * Unit conversion factor, e.g. {@code Size2DSyntax.INCH} or + * {@code Size2DSyntax.MM} * @return MediaSizeName matching these dimensions, or null. * @exception IllegalArgumentException if {@code x <= 0}, * {@code y <= 0}, or {@code units < 1}. @@ -237,20 +237,20 @@ public class MediaSize extends Size2DSyntax implements Attribute { * To be equivalent, all of the following conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class MediaSize. + * {@code object} is an instance of class MediaSize. *
      3. * This media size attribute's X dimension is equal to - * object's X dimension. + * {@code object}'s X dimension. *
      4. * This media size attribute's Y dimension is equal to - * object's Y dimension. + * {@code object}'s Y dimension. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this media size + * @return True if {@code object} is equivalent to this media size * attribute, false otherwise. */ public boolean equals(Object object) { @@ -276,7 +276,7 @@ public class MediaSize extends Size2DSyntax implements Attribute { * instance. *

      * For class MediaSize and any vendor-defined subclasses, the category - * name is "media-size". + * name is {@code "media-size"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MultipleDocumentHandling.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MultipleDocumentHandling.java index f3e02845159..7f06e953572 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MultipleDocumentHandling.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MultipleDocumentHandling.java @@ -62,53 +62,53 @@ import javax.print.attribute.PrintJobAttribute; * specify two variations of this possibility. * *

      - * In the detailed explanations below, if "a" represents an + * In the detailed explanations below, if "{@code a}" represents an * instance of document data, then the result of processing the data in - * document "a" is a sequence of media sheets represented by - * "a(*)". + * document "{@code a}" is a sequence of media sheets represented by + * "{@code a(*)}". *

      * The standard MultipleDocumentHandling values are: *

        *
      • * {@link #SINGLE_DOCUMENT * SINGLE_DOCUMENT}. If a print job has multiple - * documents -- say, the document data is called a and - * b -- then the result of processing all the document data - * (a and then b) must be treated as a single sequence + * documents -- say, the document data is called {@code a} and + * {@code b} -- then the result of processing all the document data + * ({@code a} and then {@code b}) must be treated as a single sequence * of media sheets for finishing operations; that is, finishing would be - * performed on the concatenation of the sequences a(*),b(*). The + * performed on the concatenation of the sequences {@code a(*),b(*)}. The * printer must not force the data in each document instance to be formatted * onto a new print-stream page, nor to start a new impression on a new media * sheet. If more than one copy is made, the ordering of the sets of media * sheets resulting from processing the document data must be - * a(*),b(*),a(*),b(*),..., and the printer object must force - * each copy (a(*),b(*)) to start on a new media sheet. + * {@code a(*),b(*),a(*),b(*),...}, and the printer object must force + * each copy ({@code a(*),b(*)}) to start on a new media sheet. * *
      • * {@link #SEPARATE_DOCUMENTS_UNCOLLATED_COPIES * SEPARATE_DOCUMENTS_UNCOLLATED_COPIES}. If a print job - * has multiple documents -- say, the document data is called a and - * b -- then the result of processing the data in each document + * has multiple documents -- say, the document data is called {@code a} and + * {@code b} -- then the result of processing the data in each document * instance must be treated as a single sequence of media sheets for finishing - * operations; that is, the sets a(*) and b(*) would + * operations; that is, the sets {@code a(*)} and {@code b(*)} would * each be finished separately. The printer must force each copy of the result * of processing the data in a single document to start on a new media sheet. * If more than one copy is made, the ordering of the sets of media sheets * resulting from processing the document data must be - * a(*),a(*),...,b(*),b(*).... + * {@code a(*),a(*),...,b(*),b(*)...}. * *
      • * {@link #SEPARATE_DOCUMENTS_COLLATED_COPIES * SEPARATE_DOCUMENTS_COLLATED_COPIES}. If a print job - * has multiple documents -- say, the document data is called a and - * b -- then the result of processing the data in each document + * has multiple documents -- say, the document data is called {@code a} and + * {@code b} -- then the result of processing the data in each document * instance must be treated as a single sequence of media sheets for finishing - * operations; that is, the sets a(*) and b(*) would + * operations; that is, the sets {@code a(*)} and {@code b(*)} would * each be finished separately. The printer must force each copy of the result * of processing the data in a single document to start on a new media sheet. * If more than one copy is made, the ordering of the sets of media sheets * resulting from processing the document data must be - * a(*),b(*),a(*),b(*),.... + * {@code a(*),b(*),a(*),b(*),...}. * *
      • * {@link #SINGLE_DOCUMENT_NEW_SHEET @@ -130,18 +130,18 @@ import javax.print.attribute.PrintJobAttribute; * {@link Finishings#STAPLE STAPLE} is specified, then: *
          *
        • - * With SINGLE_DOCUMENT, documents a and b are + * With SINGLE_DOCUMENT, documents {@code a} and {@code b} are * stapled together as a single document with no regard to new sheets. * *
        • - * With SINGLE_DOCUMENT_NEW_SHEET, documents a and b - * are stapled together as a single document, but document b + * With SINGLE_DOCUMENT_NEW_SHEET, documents {@code a} and {@code b} + * are stapled together as a single document, but document {@code b} * starts on a new sheet. * *
        • * With SEPARATE_DOCUMENTS_UNCOLLATED_COPIES and - * SEPARATE_DOCUMENTS_COLLATED_COPIES, documents a and - * b are stapled separately. + * SEPARATE_DOCUMENTS_COLLATED_COPIES, documents {@code a} and + * {@code b} are stapled separately. *
        *

        * Note: None of these values provide means to produce uncollated @@ -150,8 +150,8 @@ import javax.print.attribute.PrintJobAttribute; * To specify that, see the {@link SheetCollate SheetCollate} attribute. *

        * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @see Copies @@ -256,7 +256,7 @@ public class MultipleDocumentHandling extends EnumSyntax * instance. *

        * For class MultipleDocumentHandling and any vendor-defined subclasses, - * the category name is "multiple-document-handling". + * the category name is {@code "multiple-document-handling"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberOfDocuments.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberOfDocuments.java index 73e07e8d124..50e0b10b7c9 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberOfDocuments.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberOfDocuments.java @@ -35,7 +35,7 @@ import javax.print.attribute.PrintJobAttribute; * not. *

        * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @author Alan Kaminsky @@ -53,7 +53,7 @@ public final class NumberOfDocuments extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public NumberOfDocuments(int value) { super (value, 0, Integer.MAX_VALUE); @@ -65,17 +65,17 @@ public final class NumberOfDocuments extends IntegerSyntax * must be true: *

          *
        1. - * object is not null. + * {@code object} is not null. *
        2. - * object is an instance of class NumberOfDocuments. + * {@code object} is an instance of class NumberOfDocuments. *
        3. - * This number of documents attribute's value and object's + * This number of documents attribute's value and {@code object}'s * value are equal. *
        * * @param object Object to compare to. * - * @return True if object is equivalent to this number of + * @return True if {@code object} is equivalent to this number of * documents attribute, false otherwise. */ public boolean equals(Object object) { @@ -102,7 +102,7 @@ public final class NumberOfDocuments extends IntegerSyntax * instance. *

        * For class NumberOfDocuments, the - * category name is "number-of-documents". + * category name is {@code "number-of-documents"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberOfInterveningJobs.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberOfInterveningJobs.java index e73ef00be84..0a01f090bf3 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberOfInterveningJobs.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberOfInterveningJobs.java @@ -35,7 +35,7 @@ import javax.print.attribute.PrintJobAttribute; * scheduled order). *

        * IPP Compatibility: The integer value gives the IPP integer value. - * The category name returned by getName() gives the IPP + * The category name returned by {@code getName()} gives the IPP * attribute name. * * @author Alan Kaminsky @@ -52,7 +52,7 @@ public final class NumberOfInterveningJobs extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public NumberOfInterveningJobs(int value) { super(value, 0, Integer.MAX_VALUE); @@ -64,17 +64,17 @@ public final class NumberOfInterveningJobs extends IntegerSyntax * conditions must be true: *

          *
        1. - * object is not null. + * {@code object} is not null. *
        2. - * object is an instance of class NumberOfInterveningJobs. + * {@code object} is an instance of class NumberOfInterveningJobs. *
        3. * This number of intervening jobs attribute's value and - * object's value are equal. + * {@code object}'s value are equal. *
        * * @param object Object to compare to. * - * @return True if object is equivalent to this number of + * @return True if {@code object} is equivalent to this number of * intervening jobs attribute, false otherwise. */ public boolean equals(Object object) { @@ -101,7 +101,7 @@ public final class NumberOfInterveningJobs extends IntegerSyntax * instance. *

        * For class NumberOfInterveningJobs, the - * category name is "number-of-intervening-jobs". + * category name is {@code "number-of-intervening-jobs"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberUp.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberUp.java index d029d82faa8..b6a965a7c76 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberUp.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberUp.java @@ -118,7 +118,7 @@ import javax.print.attribute.PrintJobAttribute; *

      * * IPP Compatibility: The integer value gives the IPP integer value. - * The category name returned by getName() gives the IPP + * The category name returned by {@code getName()} gives the IPP * attribute name. * * @author Alan Kaminsky @@ -135,7 +135,7 @@ public final class NumberUp extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 1. + * (Unchecked exception) Thrown if {@code value} is less than 1. */ public NumberUp(int value) { super (value, 1, Integer.MAX_VALUE); @@ -146,17 +146,17 @@ public final class NumberUp extends IntegerSyntax * object. To be equivalent, all of the following conditions must be true: *
        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class NumberUp. + * {@code object} is an instance of class NumberUp. *
      3. - * This number up attribute's value and object's value are + * This number up attribute's value and {@code object}'s value are * equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this number up + * @return True if {@code object} is equivalent to this number up * attribute, false otherwise. */ public boolean equals(Object object) { @@ -180,7 +180,7 @@ public final class NumberUp extends IntegerSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class NumberUp, the category name is "number-up". + * For class NumberUp, the category name is {@code "number-up"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberUpSupported.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberUpSupported.java index a7f1b98bc1f..e5107b8ca04 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberUpSupported.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/NumberUpSupported.java @@ -37,7 +37,7 @@ import javax.print.attribute.SupportedValuesAttribute; * included in an IPP "number-up-supported" attribute. See class {@link * javax.print.attribute.SetOfIntegerSyntax SetOfIntegerSyntax} for an * explanation of canonical array form. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -57,12 +57,12 @@ public final class NumberUpSupported extends SetOfIntegerSyntax * @param members Set members in array form. * * @exception NullPointerException - * (unchecked exception) Thrown if members is null or - * any element of members is null. + * (unchecked exception) Thrown if {@code members} is null or + * any element of {@code members} is null. * @exception IllegalArgumentException * (unchecked exception) Thrown if any element of - * members is not a length-one or length-two array. Also - * thrown if members is a zero-length array or if any + * {@code members} is not a length-one or length-two array. Also + * thrown if {@code members} is a zero-length array or if any * member of the set is less than 1. */ public NumberUpSupported(int[][] members) { @@ -91,7 +91,7 @@ public final class NumberUpSupported extends SetOfIntegerSyntax * @param member Set member. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if member is less than + * (Unchecked exception) Thrown if {@code member} is less than * 1. */ public NumberUpSupported(int member) { @@ -111,7 +111,7 @@ public final class NumberUpSupported extends SetOfIntegerSyntax * * @exception IllegalArgumentException * (Unchecked exception) Thrown if a null range is specified or if a - * non-null range is specified with lowerBound less than + * non-null range is specified with {@code lowerBound} less than * 1. */ public NumberUpSupported(int lowerBound, int upperBound) { @@ -130,17 +130,17 @@ public final class NumberUpSupported extends SetOfIntegerSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class NumberUpSupported. + * {@code object} is an instance of class NumberUpSupported. *
      3. - * This number up supported attribute's members and object's + * This number up supported attribute's members and {@code object}'s * members are the same. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this number up + * @return True if {@code object} is equivalent to this number up * supported attribute, false otherwise. */ public boolean equals(Object object) { @@ -167,7 +167,7 @@ public final class NumberUpSupported extends SetOfIntegerSyntax * instance. *

      * For class NumberUpSupported, the - * category name is "number-up-supported". + * category name is {@code "number-up-supported"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/OrientationRequested.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/OrientationRequested.java index a026baac5db..0ce78a5b390 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/OrientationRequested.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/OrientationRequested.java @@ -36,17 +36,17 @@ import javax.print.attribute.PrintJobAttribute; * does not describe the orientation of the client-supplied print-stream * pages. *

      - * For some document formats (such as "application/postscript"), + * For some document formats (such as {@code "application/postscript"}), * the desired orientation of the print-stream pages is specified within the * document data. This information is generated by a device driver prior to * the submission of the print job. Other document formats (such as - * "text/plain") do not include the notion of desired orientation + * {@code "text/plain"}) do not include the notion of desired orientation * within the document data. In the latter case it is possible for the printer * to bind the desired orientation to the document data after it has been * submitted. It is expected that a printer would only support the * OrientationRequested attribute for some document formats (e.g., - * "text/plain" or "text/html") but not others (e.g. - * "application/postscript"). This is no different from any other + * {@code "text/plain"} or {@code "text/html"}) but not others (e.g. + * {@code "application/postscript"}). This is no different from any other * job template attribute, since a print job can always impose constraints * among the values of different job template attributes. * However, a special mention @@ -55,8 +55,8 @@ import javax.print.attribute.PrintJobAttribute; * formats. *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -105,7 +105,7 @@ public final class OrientationRequested extends EnumSyntax * Finishings Finishings} attribute in cases where the * opposite edge is desired for finishing a portrait document on simple * finishing devices that have only one finishing position. Thus a - * "text/plain" portrait document can be stapled "on the + * {@code "text/plain"} portrait document can be stapled "on the * right" by a simple finishing device as is common use with some * Middle Eastern languages such as Hebrew. */ @@ -176,7 +176,7 @@ public final class OrientationRequested extends EnumSyntax * instance. *

      * For class OrientationRequested, the - * category name is "orientation-requested". + * category name is {@code "orientation-requested"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/OutputDeviceAssigned.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/OutputDeviceAssigned.java index 5ebf19378fd..e9411371466 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/OutputDeviceAssigned.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/OutputDeviceAssigned.java @@ -42,7 +42,7 @@ import javax.print.attribute.PrintJobAttribute; *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -58,10 +58,10 @@ public final class OutputDeviceAssigned extends TextSyntax * @param deviceName Device name. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if deviceName is null. + * (unchecked exception) Thrown if {@code deviceName} is null. */ public OutputDeviceAssigned(String deviceName, Locale locale) { @@ -76,20 +76,20 @@ public final class OutputDeviceAssigned extends TextSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class OutputDeviceAssigned. + * {@code object} is an instance of class OutputDeviceAssigned. *
      3. * This output device assigned attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. * This output device assigned attribute's locale and - * object's locale are equal. + * {@code object}'s locale are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this output + * @return True if {@code object} is equivalent to this output * device assigned attribute, false otherwise. */ public boolean equals(Object object) { @@ -116,7 +116,7 @@ public final class OutputDeviceAssigned extends TextSyntax * instance. *

      * For class OutputDeviceAssigned, the - * category name is "output-device-assigned". + * category name is {@code "output-device-assigned"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PDLOverrideSupported.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PDLOverrideSupported.java index b7f75af6ead..e1d31db38c1 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PDLOverrideSupported.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PDLOverrideSupported.java @@ -35,8 +35,8 @@ import javax.print.attribute.PrintServiceAttribute; * specified as attributes outside the print data. *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -116,7 +116,7 @@ public class PDLOverrideSupported extends EnumSyntax * instance. *

      * For class PDLOverrideSupported and any vendor-defined subclasses, the - * category name is "pdl-override-supported". + * category name is {@code "pdl-override-supported"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PageRanges.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PageRanges.java index 6038f0bb534..7e92d6db2c0 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PageRanges.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PageRanges.java @@ -44,13 +44,13 @@ import javax.print.attribute.PrintJobAttribute; * driver and this attribute would not be required. However, when printing an * archived document which has already been formatted, the end user may elect to * print just a subset of the pages contained in the document. In this case, if - * a page range of "n-m" is specified, the first page + * a page range of "n-m" is specified, the first page * to be printed will be page n. All subsequent pages of the document * will be printed through and including page m. *

      * If a PageRanges attribute is not specified for a print job, all pages of * the document will be printed. In other words, the default value for the - * PageRanges attribute is always {{1, Integer.MAX_VALUE}}. + * PageRanges attribute is always {@code {{1, Integer.MAX_VALUE}}}. *

      * The effect of a PageRanges attribute on a multidoc print job (a job with * multiple documents) depends on whether all the docs have the same page ranges @@ -99,7 +99,7 @@ import javax.print.attribute.PrintJobAttribute; * and IPP "page-ranges" attribute. See class {@link * javax.print.attribute.SetOfIntegerSyntax SetOfIntegerSyntax} for an * explanation of canonical array form. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author David Mendenhall * @author Alan Kaminsky @@ -119,12 +119,12 @@ public final class PageRanges extends SetOfIntegerSyntax * @param members Set members in array form. * * @exception NullPointerException - * (unchecked exception) Thrown if members is null or - * any element of members is null. + * (unchecked exception) Thrown if {@code members} is null or + * any element of {@code members} is null. * @exception IllegalArgumentException * (unchecked exception) Thrown if any element of - * members is not a length-one or length-two array. Also - * thrown if members is a zero-length array or if any + * {@code members} is not a length-one or length-two array. Also + * thrown if {@code members} is a zero-length array or if any * member of the set is less than 1. */ public PageRanges(int[][] members) { @@ -144,10 +144,10 @@ public final class PageRanges extends SetOfIntegerSyntax * @param members Set members in string form. * * @exception NullPointerException - * (unchecked exception) Thrown if members is null or - * any element of members is null. + * (unchecked exception) Thrown if {@code members} is null or + * any element of {@code members} is null. * @exception IllegalArgumentException - * (Unchecked exception) Thrown if members does not + * (Unchecked exception) Thrown if {@code members} does not * obey the proper syntax. Also * thrown if the constructed set-of-integer is a * zero-length array or if any @@ -182,7 +182,7 @@ public final class PageRanges extends SetOfIntegerSyntax * @param member Set member. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if member is less than + * (Unchecked exception) Thrown if {@code member} is less than * 1. */ public PageRanges(int member) { @@ -201,7 +201,7 @@ public final class PageRanges extends SetOfIntegerSyntax * * @exception IllegalArgumentException * (Unchecked exception) Thrown if a null range is specified or if a - * non-null range is specified with lowerBound less than + * non-null range is specified with {@code lowerBound} less than * 1. */ public PageRanges(int lowerBound, int upperBound) { @@ -219,17 +219,17 @@ public final class PageRanges extends SetOfIntegerSyntax * true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PageRanges. + * {@code object} is an instance of class PageRanges. *
      3. - * This page ranges attribute's members and object's members + * This page ranges attribute's members and {@code object}'s members * are the same. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this page ranges + * @return True if {@code object} is equivalent to this page ranges * attribute, false otherwise. */ public boolean equals(Object object) { @@ -253,7 +253,7 @@ public final class PageRanges extends SetOfIntegerSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class PageRanges, the category name is "page-ranges". + * For class PageRanges, the category name is {@code "page-ranges"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PagesPerMinute.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PagesPerMinute.java index 37d0ddbd5d7..397ad356837 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PagesPerMinute.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PagesPerMinute.java @@ -37,7 +37,7 @@ import javax.print.attribute.PrintServiceAttribute; * device that takes more than two minutes to process a page. *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @author Alan Kaminsky @@ -54,7 +54,7 @@ public final class PagesPerMinute extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public PagesPerMinute(int value) { super(value, 0, Integer.MAX_VALUE); @@ -66,17 +66,17 @@ public final class PagesPerMinute extends IntegerSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PagesPerMinute. + * {@code object} is an instance of class PagesPerMinute. *
      3. - * This pages per minute attribute's value and object's + * This pages per minute attribute's value and {@code object}'s * value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this pages per + * @return True if {@code object} is equivalent to this pages per * minute attribute, false otherwise. */ public boolean equals(Object object) { @@ -102,7 +102,7 @@ public final class PagesPerMinute extends IntegerSyntax * instance. *

      * For class PagesPerMinute, the - * category name is "pages-per-minute". + * category name is {@code "pages-per-minute"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PagesPerMinuteColor.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PagesPerMinuteColor.java index f139c5964ce..9af138bf5dd 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PagesPerMinuteColor.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PagesPerMinuteColor.java @@ -48,7 +48,7 @@ import javax.print.attribute.PrintServiceAttribute; * attribute must also be present and have a value of SUPPORTED. *

      * IPP Compatibility: The integer value gives the IPP integer value. The - * category name returned by getName() gives the IPP attribute + * category name returned by {@code getName()} gives the IPP attribute * name. * * @author Alan Kaminsky @@ -65,7 +65,7 @@ public final class PagesPerMinuteColor extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public PagesPerMinuteColor(int value) { super(value, 0, Integer.MAX_VALUE); @@ -77,17 +77,17 @@ public final class PagesPerMinuteColor extends IntegerSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PagesPerMinuteColor. + * {@code object} is an instance of class PagesPerMinuteColor. *
      3. - * This pages per minute attribute's value and object's + * This pages per minute attribute's value and {@code object}'s * value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this pages per + * @return True if {@code object} is equivalent to this pages per * minute color attribute, false otherwise. */ public boolean equals(Object object) { @@ -114,7 +114,7 @@ public final class PagesPerMinuteColor extends IntegerSyntax * instance. *

      * For class PagesPerMinuteColor, the - * category name is "pages-per-minute-color". + * category name is {@code "pages-per-minute-color"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PresentationDirection.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PresentationDirection.java index 4b3ff06d073..70d8acff70b 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PresentationDirection.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PresentationDirection.java @@ -42,8 +42,8 @@ import javax.print.attribute.PrintRequestAttribute; * attribute; it is an attribute in the Production Printing Extension * (PDF) * of IPP 1.1. The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Phil Race. @@ -174,7 +174,7 @@ public final class PresentationDirection extends EnumSyntax * instance. *

      * For class PresentationDirection - * the category name is "presentation-direction". + * the category name is {@code "presentation-direction"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrintQuality.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrintQuality.java index 6240965c68a..6ed83ff5842 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrintQuality.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrintQuality.java @@ -35,8 +35,8 @@ import javax.print.attribute.PrintJobAttribute; * that specifies the print quality that the printer uses for the job. *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author David Mendenhall @@ -123,7 +123,7 @@ public class PrintQuality extends EnumSyntax * instance. *

      * For class PrintQuality and any vendor-defined subclasses, the category - * name is "print-quality". + * name is {@code "print-quality"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterInfo.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterInfo.java index 57813ec20b7..13b8ca7c33c 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterInfo.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterInfo.java @@ -33,15 +33,15 @@ import javax.print.attribute.PrintServiceAttribute; /** * Class PrinterInfo is a printing attribute class, a text attribute, that * provides descriptive information about a printer. This could include things - * like: "This printer can be used for printing color transparencies for - * HR presentations", or "Out of courtesy for others, please - * print only small (1-5 page) jobs at this printer", or even \ - * "This printer is going away on July 1, 1997, please find a new - * printer". + * like: {@code "This printer can be used for printing color transparencies for + * HR presentations"}, or {@code "Out of courtesy for others, please + * print only small (1-5 page) jobs at this printer"}, or even + * {@code "This printer is going away on July 1, 1997, please find a new + * printer"}. *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -57,10 +57,10 @@ public final class PrinterInfo extends TextSyntax * @param info Printer information string. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if info is null. + * (unchecked exception) Thrown if {@code info} is null. */ public PrinterInfo(String info, Locale locale) { super (info, locale); @@ -72,20 +72,20 @@ public final class PrinterInfo extends TextSyntax * true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PrinterInfo. + * {@code object} is an instance of class PrinterInfo. *
      3. * This printer info attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. - * This printer info attribute's locale and object's + * This printer info attribute's locale and {@code object}'s * locale are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this printer + * @return True if {@code object} is equivalent to this printer * info attribute, false otherwise. */ public boolean equals(Object object) { @@ -109,7 +109,7 @@ public final class PrinterInfo extends TextSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class PrinterInfo, the category name is "printer-info". + * For class PrinterInfo, the category name is {@code "printer-info"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterIsAcceptingJobs.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterIsAcceptingJobs.java index b04c4bab5ec..39b4961399a 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterIsAcceptingJobs.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterIsAcceptingJobs.java @@ -40,8 +40,8 @@ import javax.print.attribute.PrintServiceAttribute; *

      * IPP Compatibility: The IPP boolean value is "true" for ACCEPTING_JOBS * and "false" for NOT_ACCEPTING_JOBS. The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -116,7 +116,7 @@ public final class PrinterIsAcceptingJobs extends EnumSyntax * instance. *

      * For class PrinterIsAcceptingJobs, the - * category name is "printer-is-accepting-jobs". + * category name is {@code "printer-is-accepting-jobs"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterLocation.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterLocation.java index 7675cb956d4..73056a85820 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterLocation.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterLocation.java @@ -33,11 +33,11 @@ import javax.print.attribute.PrintServiceAttribute; /** * Class PrinterLocation is a printing attribute class, a text attribute, that * identifies the location of the device. This could include things like: - * "in Room 123A, second floor of building XYZ". + * {@code "in Room 123A, second floor of building XYZ"}. *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -53,10 +53,10 @@ public final class PrinterLocation extends TextSyntax * @param location Printer location. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if location is null. + * (unchecked exception) Thrown if {@code location} is null. */ public PrinterLocation(String location, Locale locale) { super (location, locale); @@ -68,20 +68,20 @@ public final class PrinterLocation extends TextSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PrinterLocation. + * {@code object} is an instance of class PrinterLocation. *
      3. * This printer location attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. - * This printer location attribute's locale and object's + * This printer location attribute's locale and {@code object}'s * locale are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this printer + * @return True if {@code object} is equivalent to this printer * location attribute, false otherwise. */ public boolean equals(Object object) { @@ -107,7 +107,7 @@ public final class PrinterLocation extends TextSyntax * instance. *

      * For class PrinterLocation, the - * category name is "printer-location". + * category name is {@code "printer-location"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMakeAndModel.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMakeAndModel.java index c0538fae845..55a61ea44a3 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMakeAndModel.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMakeAndModel.java @@ -35,7 +35,7 @@ import javax.print.attribute.PrintServiceAttribute; *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -51,10 +51,10 @@ public final class PrinterMakeAndModel extends TextSyntax * @param makeAndModel Printer make and model string. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if makeAndModel is null. + * (unchecked exception) Thrown if {@code makeAndModel} is null. */ public PrinterMakeAndModel(String makeAndModel, Locale locale) { super (makeAndModel, locale); @@ -66,20 +66,20 @@ public final class PrinterMakeAndModel extends TextSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PrinterMakeAndModel. + * {@code object} is an instance of class PrinterMakeAndModel. *
      3. * This printer make and model attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. * This printer make and model attribute's locale and - * object's locale are equal. + * {@code object}'s locale are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this printer + * @return True if {@code object} is equivalent to this printer * make and model attribute, false otherwise. */ public boolean equals(Object object) { @@ -106,7 +106,7 @@ public final class PrinterMakeAndModel extends TextSyntax * instance. *

      * For class PrinterMakeAndModel, the - * category name is "printer-make-and-model". + * category name is {@code "printer-make-and-model"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMessageFromOperator.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMessageFromOperator.java index d46412d2f9c..94388ca9469 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMessageFromOperator.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMessageFromOperator.java @@ -50,7 +50,7 @@ import javax.print.attribute.PrintServiceAttribute; *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -66,10 +66,10 @@ public final class PrinterMessageFromOperator extends TextSyntax * @param message Message. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if message is null. + * (unchecked exception) Thrown if {@code message} is null. */ public PrinterMessageFromOperator(String message, Locale locale) { super (message, locale); @@ -81,21 +81,21 @@ public final class PrinterMessageFromOperator extends TextSyntax * following conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class + * {@code object} is an instance of class * PrinterMessageFromOperator. *
      3. * This printer message from operator attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. * This printer message from operator attribute's locale and - * object's locale are equal. + * {@code object}'s locale are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this printer + * @return True if {@code object} is equivalent to this printer * message from operator attribute, false otherwise. */ public boolean equals(Object object) { @@ -122,7 +122,7 @@ public final class PrinterMessageFromOperator extends TextSyntax * instance. *

      * For class PrinterMessageFromOperator, - * the category name is "printer-message-from-operator". + * the category name is {@code "printer-message-from-operator"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMoreInfo.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMoreInfo.java index c982907badf..285a42574b0 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMoreInfo.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMoreInfo.java @@ -46,8 +46,8 @@ import javax.print.attribute.PrintServiceAttribute; * about this general kind of printer rather than this specific printer. *

      * IPP Compatibility: The string form returned by - * toString() gives the IPP uri value. - * The category name returned by getName() + * {@code toString()} gives the IPP uri value. + * The category name returned by {@code getName()} * gives the IPP attribute name. * * @author Alan Kaminsky @@ -63,7 +63,7 @@ public final class PrinterMoreInfo extends URISyntax * @param uri URI. * * @exception NullPointerException - * (unchecked exception) Thrown if uri is null. + * (unchecked exception) Thrown if {@code uri} is null. */ public PrinterMoreInfo(URI uri) { super (uri); @@ -75,17 +75,17 @@ public final class PrinterMoreInfo extends URISyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PrinterMoreInfo. + * {@code object} is an instance of class PrinterMoreInfo. *
      3. - * This printer more info attribute's URI and object's URI + * This printer more info attribute's URI and {@code object}'s URI * are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this printer + * @return True if {@code object} is equivalent to this printer * more info attribute, false otherwise. */ public boolean equals(Object object) { @@ -111,7 +111,7 @@ public final class PrinterMoreInfo extends URISyntax * instance. *

      * For class PrinterMoreInfo, the - * category name is "printer-more-info". + * category name is {@code "printer-more-info"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java index 10b4e9acace..881b5cb8a14 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java @@ -46,8 +46,8 @@ import javax.print.attribute.PrintServiceAttribute; * general kind of printer. *

      * IPP Compatibility: The string form returned by - * toString() gives the IPP uri value. - * The category name returned by getName() + * {@code toString()} gives the IPP uri value. + * The category name returned by {@code getName()} * gives the IPP attribute name. * * @author Alan Kaminsky @@ -64,7 +64,7 @@ public final class PrinterMoreInfoManufacturer extends URISyntax * @param uri URI. * * @exception NullPointerException - * (unchecked exception) Thrown if uri is null. + * (unchecked exception) Thrown if {@code uri} is null. */ public PrinterMoreInfoManufacturer(URI uri) { super (uri); @@ -76,18 +76,18 @@ public final class PrinterMoreInfoManufacturer extends URISyntax * following conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class + * {@code object} is an instance of class * PrinterMoreInfoManufacturer. *
      3. * This printer more info manufacturer attribute's URI and - * object's URI are equal. + * {@code object}'s URI are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this printer + * @return True if {@code object} is equivalent to this printer * more info manufacturer attribute, false otherwise. */ public boolean equals(Object object) { @@ -114,7 +114,7 @@ public final class PrinterMoreInfoManufacturer extends URISyntax * instance. *

      * For class PrinterMoreInfoManufacturer, the category name is - * "printer-more-info-manufacturer". + * {@code "printer-more-info-manufacturer"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterName.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterName.java index a8b2487ad17..3bc293df02b 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterName.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterName.java @@ -40,7 +40,7 @@ import javax.print.attribute.PrintServiceAttribute; *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -55,10 +55,10 @@ public final class PrinterName extends TextSyntax * @param printerName Printer name. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if printerName is null. + * (unchecked exception) Thrown if {@code printerName} is null. */ public PrinterName(String printerName, Locale locale) { super (printerName, locale); @@ -70,20 +70,20 @@ public final class PrinterName extends TextSyntax * true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PrinterName. + * {@code object} is an instance of class PrinterName. *
      3. * This printer name attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. - * This printer name attribute's locale and object's locale + * This printer name attribute's locale and {@code object}'s locale * are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this printer + * @return True if {@code object} is equivalent to this printer * name attribute, false otherwise. */ public boolean equals(Object object) { @@ -109,7 +109,7 @@ public final class PrinterName extends TextSyntax * instance. *

      * For class PrinterName, the category - * name is "printer-name". + * name is {@code "printer-name"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterResolution.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterResolution.java index 67d908103a2..408d2007324 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterResolution.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterResolution.java @@ -61,9 +61,9 @@ import javax.print.attribute.PrintJobAttribute; * PrintQuality attribute which often controls resolution. *

      * IPP Compatibility: The information needed to construct an IPP - * "printer-resolution" attribute can be obtained by calling + * {@code "printer-resolution"} attribute can be obtained by calling * methods on the PrinterResolution object. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author David Mendenhall * @author Alan Kaminsky @@ -81,8 +81,8 @@ public final class PrinterResolution extends ResolutionSyntax * @param feedResolution * Feed direction resolution. * @param units - * Unit conversion factor, e.g. ResolutionSyntax.DPI - * or ResolutionSyntax.DPCM. + * Unit conversion factor, e.g. {@code ResolutionSyntax.DPI} + * or {@code ResolutionSyntax.DPCM}. * * @exception IllegalArgumentException * (unchecked exception) Thrown if {@code crossFeedResolution < 1} or @@ -99,20 +99,20 @@ public final class PrinterResolution extends ResolutionSyntax * must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PrinterResolution. + * {@code object} is an instance of class PrinterResolution. *
      3. * This attribute's cross feed direction resolution is equal to - * object's cross feed direction resolution. + * {@code object}'s cross feed direction resolution. *
      4. * This attribute's feed direction resolution is equal to - * object's feed direction resolution. + * {@code object}'s feed direction resolution. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this printer + * @return True if {@code object} is equivalent to this printer * resolution attribute, false otherwise. */ public boolean equals(Object object) { @@ -138,7 +138,7 @@ public final class PrinterResolution extends ResolutionSyntax * instance. *

      * For class PrinterResolution, the - * category name is "printer-resolution". + * category name is {@code "printer-resolution"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterState.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterState.java index 961d82ec53d..4af01a6cda6 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterState.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterState.java @@ -39,8 +39,8 @@ import javax.print.attribute.PrintServiceAttribute; * in given printer state. *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -130,7 +130,7 @@ implements PrintServiceAttribute { * Get the name of the category of which this attribute value is an * instance. *

      - * For class PrinterState, the category name is "printer-state". + * For class PrinterState, the category name is {@code "printer-state"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterStateReason.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterStateReason.java index ece9a538397..cdcb8e56d88 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterStateReason.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterStateReason.java @@ -56,10 +56,10 @@ import javax.print.attribute.Attribute; *

      * IPP Compatibility: * The string values returned by each individual {@link PrinterStateReason} and - * associated {@link Severity} object's toString() - * methods, concatenated together with a hyphen ("-") in + * associated {@link Severity} object's {@code toString()} + * methods, concatenated together with a hyphen ({@code "-"}) in * between, gives the IPP keyword value for a {@link PrinterStateReasons}. - * The category name returned by getName() gives the IPP + * The category name returned by {@code getName()} gives the IPP * attribute name. * * @author Alan Kaminsky @@ -432,7 +432,7 @@ public class PrinterStateReason extends EnumSyntax implements Attribute { * instance. *

      * For class PrinterStateReason and any vendor-defined subclasses, the - * category name is "printer-state-reason". + * category name is {@code "printer-state-reason"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterURI.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterURI.java index 9471b73481b..b2224d10bfe 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterURI.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/PrinterURI.java @@ -38,8 +38,8 @@ import javax.print.attribute.PrintServiceAttribute; *

      * IPP Compatibility: This implements the * IPP printer-uri attribute. The string form returned by - * toString() gives the IPP printer-uri value. - * The category name returned by getName() + * {@code toString()} gives the IPP printer-uri value. + * The category name returned by {@code getName()} * gives the IPP attribute name. * * @author Robert Herriot @@ -56,7 +56,7 @@ public final class PrinterURI extends URISyntax * @param uri URI of the printer * * @exception NullPointerException - * (unchecked exception) Thrown if uri is null. + * (unchecked exception) Thrown if {@code uri} is null. */ public PrinterURI(URI uri) { super (uri); @@ -68,17 +68,17 @@ public final class PrinterURI extends URISyntax * true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class PrinterURI. + * {@code object} is an instance of class PrinterURI. *
      3. * This PrinterURI attribute's underlying URI and - * object's underlying URI are equal. + * {@code object}'s underlying URI are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this PrinterURI + * @return True if {@code object} is equivalent to this PrinterURI * attribute, false otherwise. */ public boolean equals(Object object) { @@ -104,7 +104,7 @@ public final class PrinterURI extends URISyntax * instance. *

      * For class PrinterURI and any vendor-defined subclasses, the category - * name is "printer-uri". + * name is {@code "printer-uri"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/QueuedJobCount.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/QueuedJobCount.java index f335288bd9c..41a710cb624 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/QueuedJobCount.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/QueuedJobCount.java @@ -34,7 +34,7 @@ import javax.print.attribute.PrintServiceAttribute; * PENDING, PENDING_HELD, PROCESSING, or PROCESSING_STOPPED. *

      * IPP Compatibility: The integer value gives the IPP integer value. - * The category name returned by getName() gives the IPP + * The category name returned by {@code getName()} gives the IPP * attribute name. * * @author Alan Kaminsky @@ -51,7 +51,7 @@ public final class QueuedJobCount extends IntegerSyntax * @param value Integer value. * * @exception IllegalArgumentException - * (Unchecked exception) Thrown if value is less than 0. + * (Unchecked exception) Thrown if {@code value} is less than 0. */ public QueuedJobCount(int value) { super (value, 0, Integer.MAX_VALUE); @@ -63,17 +63,17 @@ public final class QueuedJobCount extends IntegerSyntax * mus be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class QueuedJobCount. + * {@code object} is an instance of class QueuedJobCount. *
      3. - * This queued job count attribute's value and object's + * This queued job count attribute's value and {@code object}'s * value are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this queued job + * @return True if {@code object} is equivalent to this queued job * count attribute, false otherwise. */ public boolean equals(Object object) { @@ -99,7 +99,7 @@ public final class QueuedJobCount extends IntegerSyntax * instance. *

      * For class QueuedJobCount, the - * category name is "queued-job-count". + * category name is {@code "queued-job-count"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java index 8597c3143eb..ac8dcd326b0 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java @@ -32,13 +32,13 @@ import javax.print.attribute.Attribute; * an enumeration, that indicates a "URI scheme," such as "http:" or "ftp:", * that a printer can use to retrieve print data stored at a URI location. * If a printer supports doc flavors with a print data representation class of - * "java.net.URL", the printer uses instances of class + * {@code "java.net.URL"}, the printer uses instances of class * ReferenceUriSchemesSupported to advertise the URI schemes it can accept. * The acceptable URI schemes are included as service attributes in the * lookup service; this lets clients search the * for printers that can get print data using a certain URI scheme. The * acceptable URI schemes can also be queried using the capability methods in - * interface PrintService. However, + * interface {@code PrintService}. However, * ReferenceUriSchemesSupported attributes are used solely for determining * acceptable URI schemes, they are never included in a doc's, * print request's, print job's, or print service's attribute set. @@ -52,8 +52,8 @@ import javax.print.attribute.Attribute; * can define them in a subclass of class ReferenceUriSchemesSupported. *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -171,7 +171,7 @@ public class ReferenceUriSchemesSupported *

      * For class ReferenceUriSchemesSupported and any vendor-defined * subclasses, the category name is - * "reference-uri-schemes-supported". + * {@code "reference-uri-schemes-supported"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/RequestingUserName.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/RequestingUserName.java index 62bd3e03763..c0284c8a041 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/RequestingUserName.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/RequestingUserName.java @@ -47,7 +47,7 @@ import javax.print.attribute.PrintRequestAttribute; *

      * IPP Compatibility: The string value gives the IPP name value. The * locale gives the IPP natural language. The category name returned by - * getName() gives the IPP attribute name. + * {@code getName()} gives the IPP attribute name. * * @author Alan Kaminsky */ @@ -63,10 +63,10 @@ public final class RequestingUserName extends TextSyntax * @param userName User name. * @param locale Natural language of the text string. null * is interpreted to mean the default locale as returned - * by Locale.getDefault() + * by {@code Locale.getDefault()} * * @exception NullPointerException - * (unchecked exception) Thrown if userName is null. + * (unchecked exception) Thrown if {@code userName} is null. */ public RequestingUserName(String userName, Locale locale) { super (userName, locale); @@ -78,20 +78,20 @@ public final class RequestingUserName extends TextSyntax * conditions must be true: *

        *
      1. - * object is not null. + * {@code object} is not null. *
      2. - * object is an instance of class RequestingUserName. + * {@code object} is an instance of class RequestingUserName. *
      3. * This requesting user name attribute's underlying string and - * object's underlying string are equal. + * {@code object}'s underlying string are equal. *
      4. * This requesting user name attribute's locale and - * object's locale are equal. + * {@code object}'s locale are equal. *
      * * @param object Object to compare to. * - * @return True if object is equivalent to this requesting + * @return True if {@code object} is equivalent to this requesting * user name attribute, false otherwise. */ public boolean equals(Object object) { @@ -118,7 +118,7 @@ public final class RequestingUserName extends TextSyntax * instance. *

      * For class RequestingUserName, the - * category name is "requesting-user-name". + * category name is {@code "requesting-user-name"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Severity.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Severity.java index 36df6b6f5d0..d9db96cf299 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Severity.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Severity.java @@ -50,13 +50,13 @@ import javax.print.attribute.Attribute; * {@link PrinterState PrinterState} also changed. *

      * IPP Compatibility: - * Severity.toString() returns either "error", "warning", or + * {@code Severity.toString()} returns either "error", "warning", or * "report". The string values returned by * each individual {@link PrinterStateReason} and - * associated {@link Severity} object's toString() - * methods, concatenated together with a hyphen ("-") in + * associated {@link Severity} object's {@code toString()} + * methods, concatenated together with a hyphen ({@code "-"}) in * between, gives the IPP keyword value for a {@link PrinterStateReasons}. - * The category name returned by getName() gives the IPP + * The category name returned by {@code getName()} gives the IPP * attribute name. * * @author Alan Kaminsky @@ -146,7 +146,7 @@ public final class Severity extends EnumSyntax implements Attribute { * Get the name of the category of which this attribute value is an * instance. *

      - * For class Severit, the category name is "severity". + * For class Severit, the category name is {@code "severity"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/SheetCollate.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/SheetCollate.java index 1d264a5964e..b497791f2a1 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/SheetCollate.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/SheetCollate.java @@ -222,7 +222,7 @@ public final class SheetCollate extends EnumSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class SheetCollate, the category name is "sheet-collate". + * For class SheetCollate, the category name is {@code "sheet-collate"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Sides.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Sides.java index 664f07d03dc..a9c13c11282 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Sides.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/Sides.java @@ -110,8 +110,8 @@ import javax.print.attribute.PrintJobAttribute; * *

      * IPP Compatibility: The category name returned by - * getName() is the IPP attribute name. The enumeration's - * integer value is the IPP enum value. The toString() method + * {@code getName()} is the IPP attribute name. The enumeration's + * integer value is the IPP enum value. The {@code toString()} method * returns the IPP string representation of the attribute value. * * @author Alan Kaminsky @@ -210,7 +210,7 @@ public final class Sides extends EnumSyntax * Get the name of the category of which this attribute value is an * instance. *

      - * For class Sides, the category name is "sides". + * For class Sides, the category name is {@code "sides"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/javax/print/event/PrintEvent.java b/jdk/src/java.desktop/share/classes/javax/print/event/PrintEvent.java index 1f489026149..0732fb37231 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/event/PrintEvent.java +++ b/jdk/src/java.desktop/share/classes/javax/print/event/PrintEvent.java @@ -37,8 +37,8 @@ public class PrintEvent extends java.util.EventObject { /** * Constructs a PrintEvent object. * @param source is the source of the event - * @throws IllegalArgumentException if source is - * null. + * @throws IllegalArgumentException if {@code source} is + * {@code null}. */ public PrintEvent (Object source) { super(source); diff --git a/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobAttributeEvent.java b/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobAttributeEvent.java index d23e4c6a226..efec2a761ca 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobAttributeEvent.java +++ b/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobAttributeEvent.java @@ -45,8 +45,8 @@ public class PrintJobAttributeEvent extends PrintEvent { * Constructs a PrintJobAttributeEvent object. * @param source the print job generating this event * @param attributes the attribute changes being reported - * @throws IllegalArgumentException if source is - * null. + * @throws IllegalArgumentException if {@code source} is + * {@code null}. */ public PrintJobAttributeEvent (DocPrintJob source, PrintJobAttributeSet attributes) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobAttributeListener.java b/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobAttributeListener.java index 64e6b6fa894..0f21e659a9b 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobAttributeListener.java +++ b/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobAttributeListener.java @@ -38,7 +38,7 @@ public interface PrintJobAttributeListener { * One example of an occurrence triggering this event is if the * {@link javax.print.attribute.standard.JobState JobState} * attribute changed from - * PROCESSING to PROCESSING_STOPPED. + * {@code PROCESSING} to {@code PROCESSING_STOPPED}. * @param pjae the event. */ public void attributeUpdate(PrintJobAttributeEvent pjae) ; diff --git a/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobEvent.java b/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobEvent.java index dca9b66640e..77424a07a91 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobEvent.java +++ b/jdk/src/java.desktop/share/classes/javax/print/event/PrintJobEvent.java @@ -29,7 +29,7 @@ import javax.print.DocPrintJob; /** * - * Class PrintJobEvent encapsulates common events a print job + * Class {@code PrintJobEvent} encapsulates common events a print job * reports to let a listener know of progress in the processing of the * {@link DocPrintJob}. * @@ -86,12 +86,12 @@ public class PrintJobEvent extends PrintEvent { public static final int DATA_TRANSFER_COMPLETE = 106; /** - * Constructs a PrintJobEvent object. + * Constructs a {@code PrintJobEvent} object. * - * @param source a DocPrintJob object + * @param source a {@code DocPrintJob} object * @param reason an int specifying the reason. - * @throws IllegalArgumentException if source is - * null. + * @throws IllegalArgumentException if {@code source} is + * {@code null}. */ public PrintJobEvent( DocPrintJob source, int reason) { @@ -109,12 +109,12 @@ public class PrintJobEvent extends PrintEvent { } /** - * Determines the DocPrintJob to which this print job + * Determines the {@code DocPrintJob} to which this print job * event pertains. * - * @return the DocPrintJob object that represents the + * @return the {@code DocPrintJob} object that represents the * print job that reports the events encapsulated by this - * PrintJobEvent. + * {@code PrintJobEvent}. * */ public DocPrintJob getPrintJob() { diff --git a/jdk/src/java.desktop/share/classes/javax/print/event/PrintServiceAttributeEvent.java b/jdk/src/java.desktop/share/classes/javax/print/event/PrintServiceAttributeEvent.java index 9f1b6721854..06998afd354 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/event/PrintServiceAttributeEvent.java +++ b/jdk/src/java.desktop/share/classes/javax/print/event/PrintServiceAttributeEvent.java @@ -47,8 +47,8 @@ public class PrintServiceAttributeEvent extends PrintEvent { * * @param source the print job generating this event * @param attributes the attribute changes being reported - * @throws IllegalArgumentException if source is - * null. + * @throws IllegalArgumentException if {@code source} is + * {@code null}. */ public PrintServiceAttributeEvent(PrintService source, PrintServiceAttributeSet attributes) { diff --git a/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioInputStream.java b/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioInputStream.java index e9e770c0e0d..716b9902331 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioInputStream.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -321,31 +321,48 @@ public class AudioInputStream extends InputStream { */ @Override public long skip(long n) throws IOException { + if (n <= 0) { + return 0; + } // make sure not to skip fractional frames - if( (n%frameSize) != 0 ) { - n -= (n%frameSize); + final long reminder = n % frameSize; + if (reminder != 0) { + n -= reminder; } - if( frameLength != AudioSystem.NOT_SPECIFIED ) { + if (frameLength != AudioSystem.NOT_SPECIFIED) { // don't skip more than our set length in frames. - if( (n/frameSize) > (frameLength-framePos) ) { - n = (frameLength-framePos) * frameSize; + if ((n / frameSize) > (frameLength - framePos)) { + n = (frameLength - framePos) * frameSize; } } - long temp = stream.skip(n); + long remaining = n; + while (remaining > 0) { + // Some input streams like FileInputStream can return more bytes, + // when EOF is reached. + long ret = Math.min(stream.skip(remaining), remaining); + if (ret == 0) { + // EOF or not? we need to check. + if (stream.read() == -1) { + break; + } + ret = 1; + } else if (ret < 0) { + // the skip should not return negative value, but check it also + break; + } + remaining -= ret; + } + final long temp = n - remaining; // if no error, update our position. - if( temp%frameSize != 0 ) { - + if (temp % frameSize != 0) { // Throw an IOException if we've skipped a fractional number of frames throw new IOException("Could not skip an integer number of frames."); } - if( temp >= 0 ) { - framePos += temp/frameSize; - } + framePos += temp/frameSize; return temp; - } /** 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 2a6d98dd158..e567b392102 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,14 @@ package javax.sound.sampled; +import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -688,8 +690,11 @@ public class AudioSystem { } } } - AudioFormat.Encoding encs2[] = encodings.toArray(new AudioFormat.Encoding[0]); - return encs2; + if (!encodings.contains(sourceEncoding)) { + encodings.addElement(sourceEncoding); + } + + return encodings.toArray(new AudioFormat.Encoding[encodings.size()]); } // $$fb 2002-04-12: fix for 4662082: behavior of AudioSystem.getTargetEncodings() methods doesn't match the spec @@ -710,30 +715,18 @@ public class AudioSystem { Objects.requireNonNull(sourceFormat); List codecs = getFormatConversionProviders(); - Vector encodings = new Vector<>(); - - int size = 0; - int index = 0; - AudioFormat.Encoding encs[] = null; + List encs = new ArrayList<>(); // gather from all the codecs - - for(int i=0; i codecs = getFormatConversionProviders(); @@ -781,6 +777,9 @@ public class AudioSystem { AudioInputStream sourceStream) { Objects.requireNonNull(targetEncoding); Objects.requireNonNull(sourceStream); + if (sourceStream.getFormat().getEncoding().equals(targetEncoding)) { + return sourceStream; + } List codecs = getFormatConversionProviders(); @@ -811,31 +810,27 @@ public class AudioSystem { Objects.requireNonNull(sourceFormat); List codecs = getFormatConversionProviders(); - Vector formats = new Vector<>(); - - int size = 0; - int index = 0; - AudioFormat fmts[] = null; + List formats = new ArrayList<>(); + boolean matchFound = false; // gather from all the codecs - - for(int i=0; i codecs = getFormatConversionProviders(); @@ -919,28 +917,17 @@ public class AudioSystem { * @see InputStream#markSupported * @see InputStream#mark */ - public static AudioFileFormat getAudioFileFormat(InputStream stream) + public static AudioFileFormat getAudioFileFormat(final InputStream stream) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(stream); - List providers = getAudioFileReaders(); - AudioFileFormat format = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - format = reader.getAudioFileFormat( stream ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioFileFormat(stream); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( format==null ) { - throw new UnsupportedAudioFileException("file is not a supported file type"); - } else { - return format; - } + throw new UnsupportedAudioFileException("Stream of unsupported format"); } /** @@ -956,28 +943,17 @@ public class AudioSystem { * @throws IOException if an input/output exception occurs * @throws NullPointerException if {@code url} is {@code null} */ - public static AudioFileFormat getAudioFileFormat(URL url) + public static AudioFileFormat getAudioFileFormat(final URL url) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(url); - List providers = getAudioFileReaders(); - AudioFileFormat format = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - format = reader.getAudioFileFormat( url ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioFileFormat(url); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( format==null ) { - throw new UnsupportedAudioFileException("file is not a supported file type"); - } else { - return format; - } + throw new UnsupportedAudioFileException("URL of unsupported format"); } /** @@ -993,28 +969,17 @@ public class AudioSystem { * @throws IOException if an I/O exception occurs * @throws NullPointerException if {@code file} is {@code null} */ - public static AudioFileFormat getAudioFileFormat(File file) + public static AudioFileFormat getAudioFileFormat(final File file) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(file); - List providers = getAudioFileReaders(); - AudioFileFormat format = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - format = reader.getAudioFileFormat( file ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioFileFormat(file); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( format==null ) { - throw new UnsupportedAudioFileException("file is not a supported file type"); - } else { - return format; - } + throw new UnsupportedAudioFileException("File of unsupported format"); } /** @@ -1038,28 +1003,17 @@ public class AudioSystem { * @see InputStream#markSupported * @see InputStream#mark */ - public static AudioInputStream getAudioInputStream(InputStream stream) + public static AudioInputStream getAudioInputStream(final InputStream stream) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(stream); - List providers = getAudioFileReaders(); - AudioInputStream audioStream = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - audioStream = reader.getAudioInputStream( stream ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioInputStream(stream); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( audioStream==null ) { - throw new UnsupportedAudioFileException("could not get audio input stream from input stream"); - } else { - return audioStream; - } + throw new UnsupportedAudioFileException("Stream of unsupported format"); } /** @@ -1075,28 +1029,17 @@ public class AudioSystem { * @throws IOException if an I/O exception occurs * @throws NullPointerException if {@code url} is {@code null} */ - public static AudioInputStream getAudioInputStream(URL url) + public static AudioInputStream getAudioInputStream(final URL url) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(url); - List providers = getAudioFileReaders(); - AudioInputStream audioStream = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - audioStream = reader.getAudioInputStream( url ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioInputStream(url); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( audioStream==null ) { - throw new UnsupportedAudioFileException("could not get audio input stream from input URL"); - } else { - return audioStream; - } + throw new UnsupportedAudioFileException("URL of unsupported format"); } /** @@ -1112,28 +1055,17 @@ public class AudioSystem { * @throws IOException if an I/O exception occurs * @throws NullPointerException if {@code file} is {@code null} */ - public static AudioInputStream getAudioInputStream(File file) + public static AudioInputStream getAudioInputStream(final File file) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(file); - List providers = getAudioFileReaders(); - AudioInputStream audioStream = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - audioStream = reader.getAudioInputStream( file ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioInputStream(file); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( audioStream==null ) { - throw new UnsupportedAudioFileException("could not get audio input stream from input file"); - } else { - return audioStream; - } + throw new UnsupportedAudioFileException("File of unsupported format"); } /** @@ -1255,32 +1187,24 @@ public class AudioSystem { * @see #isFileTypeSupported * @see #getAudioFileTypes */ - public static int write(AudioInputStream stream, AudioFileFormat.Type fileType, - OutputStream out) throws IOException { + public static int write(final AudioInputStream stream, + final AudioFileFormat.Type fileType, + final OutputStream out) throws IOException { Objects.requireNonNull(stream); Objects.requireNonNull(fileType); Objects.requireNonNull(out); - List providers = getAudioFileWriters(); - int bytesWritten = 0; - boolean flag = false; - - for(int i=0; i < providers.size(); i++) { - AudioFileWriter writer = providers.get(i); + for (final AudioFileWriter writer : getAudioFileWriters()) { try { - bytesWritten = writer.write( stream, fileType, out ); // throws IOException - flag = true; - break; - } catch (IllegalArgumentException e) { - // thrown if this provider cannot write the sequence, try the next - continue; + return writer.write(stream, fileType, out); + } catch (final IllegalArgumentException ignored) { + // thrown if this provider cannot write the stream, try next } } - if(!flag) { - throw new IllegalArgumentException("could not write audio file: file type not supported: " + fileType); - } else { - return bytesWritten; - } + // "File type " + type + " not supported." + throw new IllegalArgumentException( + "could not write audio file: file type not supported: " + + fileType); } /** @@ -1300,32 +1224,23 @@ public class AudioSystem { * @see #isFileTypeSupported * @see #getAudioFileTypes */ - public static int write(AudioInputStream stream, AudioFileFormat.Type fileType, - File out) throws IOException { + public static int write(final AudioInputStream stream, + final AudioFileFormat.Type fileType, + final File out) throws IOException { Objects.requireNonNull(stream); Objects.requireNonNull(fileType); Objects.requireNonNull(out); - List providers = getAudioFileWriters(); - int bytesWritten = 0; - boolean flag = false; - - for(int i=0; i < providers.size(); i++) { - AudioFileWriter writer = providers.get(i); + for (final AudioFileWriter writer : getAudioFileWriters()) { try { - bytesWritten = writer.write( stream, fileType, out ); // throws IOException - flag = true; - break; - } catch (IllegalArgumentException e) { - // thrown if this provider cannot write the sequence, try the next - continue; + return writer.write(stream, fileType, out); + } catch (final IllegalArgumentException ignored) { + // thrown if this provider cannot write the stream, try next } } - if (!flag) { - throw new IllegalArgumentException("could not write audio file: file type not supported: " + fileType); - } else { - return bytesWritten; - } + throw new IllegalArgumentException( + "could not write audio file: file type not supported: " + + fileType); } // METHODS FOR INTERNAL IMPLEMENTATION USE diff --git a/jdk/src/java.desktop/share/classes/javax/swing/Action.java b/jdk/src/java.desktop/share/classes/javax/swing/Action.java index b1ebbec40a8..8a7ae6ea1db 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/Action.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/Action.java @@ -356,24 +356,41 @@ public interface Action extends ActionListener { public void putValue(String key, Object value); /** - * Sets the enabled state of the Action. When enabled, + * Sets the enabled state of the {@code Action}. When enabled, * any component associated with this object is active and - * able to fire this object's actionPerformed method. - * If the value has changed, a PropertyChangeEvent is sent + * able to fire this object's {@code actionPerformed} method. + * If the value has changed, a {@code PropertyChangeEvent} is sent * to listeners. * - * @param b true to enable this Action, false to disable it + * @param b true to enable this {@code Action}, false to disable it + * @see #accept */ public void setEnabled(boolean b); /** - * Returns the enabled state of the Action. When enabled, + * Returns the enabled state of the {@code Action}. When enabled, * any component associated with this object is active and - * able to fire this object's actionPerformed method. + * able to fire this object's {@code actionPerformed} method. * - * @return true if this Action is enabled + * @return true if this {@code Action} is enabled + * @see #accept */ public boolean isEnabled(); + /** + * Determines whether the action should be performed with the specified + * sender object. The {@code sender} can be {@code null}. + * The method must return false if the action is disabled. + *

      + * @param sender the object to check, can be null + * @return {@code true} if the action should be performed with the sender + * object, must be false if the action is disabled. + * @see isEnabled + * @see setEnabled + */ + default boolean accept(Object sender) { + return isEnabled(); + } + /** * Adds a PropertyChange listener. Containers and attached * components use these methods to register interest in this diff --git a/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java b/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java index e28f446a5f2..18f30579f4e 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java @@ -197,17 +197,17 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab if (!f.isMaximum()) { f.setNormalBounds(f.getBounds()); } - d.setComponentOrderCheckingEnabled(false); - c.remove(f); - c.add(desktopIcon); - d.setComponentOrderCheckingEnabled(true); - c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight()); if (findNext) { if (d.selectFrame(true) == null) { // The icon is the last frame. f.restoreSubcomponentFocus(); } } + d.setComponentOrderCheckingEnabled(false); + c.remove(f); + c.add(desktopIcon); + d.setComponentOrderCheckingEnabled(true); + c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight()); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JDesktopPane.java b/jdk/src/java.desktop/share/classes/javax/swing/JDesktopPane.java index 99a2fe8ab6a..e5d53e1cda3 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JDesktopPane.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JDesktopPane.java @@ -480,6 +480,7 @@ public class JDesktopPane extends JLayeredPane implements Accessible * @since 1.6 */ protected void addImpl(Component comp, Object constraints, int index) { + checkComponentAttributes(comp); super.addImpl(comp, constraints, index); if (componentOrderCheckingEnabled) { if (comp instanceof JInternalFrame || @@ -489,6 +490,12 @@ public class JDesktopPane extends JLayeredPane implements Accessible } } + private void checkComponentAttributes(Component comp) { + if (comp instanceof JInternalFrame && ((JInternalFrame) comp).isIcon()) { + ((JInternalFrame) comp).putClientProperty("wasIconOnce", Boolean.FALSE); + } + } + /** * {@inheritDoc} * @since 1.6 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 de917a34e00..184ca2c2d0b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java @@ -2156,15 +2156,14 @@ public class JTabbedPane extends JComponent AccessibleStateSet states; states = parent.getAccessibleContext().getAccessibleStateSet(); states.add(AccessibleState.SELECTABLE); - int i = parent.indexOfTabComponent(tabComponent); - if (i == parent.getSelectedIndex()) { + if (getPageIndex() == parent.getSelectedIndex()) { states.add(AccessibleState.SELECTED); } return states; } public int getAccessibleIndexInParent() { - return parent.indexOfTabComponent(tabComponent); + return getPageIndex(); } public int getAccessibleChildrenCount() { @@ -2272,8 +2271,7 @@ public class JTabbedPane extends JComponent } public Rectangle getBounds() { - return parent.getUI(). - getTabBounds(parent, parent.indexOfTabComponent(tabComponent)); + return parent.getUI().getTabBounds(parent, getPageIndex()); } public void setBounds(Rectangle r) { @@ -2343,7 +2341,33 @@ public class JTabbedPane extends JComponent } private String getTitle() { - return getTitleAt(parent.indexOfComponent(component)); + return getTitleAt(getPageIndex()); + } + + /* + * getPageIndex() has three valid scenarios: + * - null component and null tabComponent: use indexOfcomponent + * - non-null component: use indexOfComponent + * - null component and non-null tabComponent: use indexOfTabComponent + * + * Note: It's valid to have have a titled tab with a null component, e.g. + * myPane.add("my title", null); + * but it's only useful to have one of those because indexOfComponent(null) + * will find the first one. + * + * Note: indexofTab(title) is not useful because there are cases, due to + * subclassing, where Page.title is not set and title is managed in a subclass + * and fetched with an overridden JTabbedPane.getTitleAt(index). + */ + private int getPageIndex() { + int index; + if (component != null || (component == null && tabComponent == null)) { + index = parent.indexOfComponent(component); + } else { + // component is null, tabComponent is non-null + index = parent.indexOfTabComponent(tabComponent); + } + return index; } } 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 5c34dffb012..6a48eb423a3 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java @@ -1704,9 +1704,9 @@ public class SwingUtilities implements SwingConstants } /** - * Invokes actionPerformed on action if - * action is enabled (and non-{@code null}). The command for the - * ActionEvent is determined by: + * Invokes {@code actionPerformed} on {@code action} if {@code action} + * is non-{@code null} and accepts the sender object. + * The command for the ActionEvent is determined by: *

        *
      1. If the action was registered via * registerKeyboardAction, then the command string @@ -1725,23 +1725,18 @@ public class SwingUtilities implements SwingConstants * @param modifiers action modifiers * @return {@code true} if {@code action} is non-{@code null} and * actionPerformed is invoked on it. + * @see javax.swing.Action#accept * * @since 1.3 */ public static boolean notifyAction(Action action, KeyStroke ks, KeyEvent event, Object sender, int modifiers) { - if (action == null) { - return false; - } - if (action instanceof UIAction) { - if (!((UIAction)action).isEnabled(sender)) { - return false; - } - } - else if (!action.isEnabled()) { + + if (action == null || !action.accept(sender)) { return false; } + Object commandO; boolean stayNull; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/TransferHandler.java b/jdk/src/java.desktop/share/classes/javax/swing/TransferHandler.java index 5201a0c26a5..70fe30a37be 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/TransferHandler.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/TransferHandler.java @@ -1695,13 +1695,10 @@ public class TransferHandler implements Serializable { super(name); } - public boolean isEnabled(Object sender) { - if (sender instanceof JComponent - && ((JComponent)sender).getTransferHandler() == null) { - return false; - } - - return true; + @Override + public boolean accept(Object sender) { + return !(sender instanceof JComponent + && ((JComponent)sender).getTransferHandler() == null); } private static final JavaSecurityAccess javaSecurityAccess = diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonListener.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonListener.java index 3278d33e4a9..1fda40ee5df 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonListener.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicButtonListener.java @@ -319,13 +319,10 @@ public class BasicButtonListener implements MouseListener, MouseMotionListener, } } - public boolean isEnabled(Object sender) { - if(sender != null && (sender instanceof AbstractButton) && - !((AbstractButton)sender).getModel().isEnabled()) { - return false; - } else { - return true; - } + @Override + public boolean accept(Object sender) { + return !((sender instanceof AbstractButton) && + !((AbstractButton)sender).getModel().isEnabled()); } } -} +} \ No newline at end of file diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java index 5a3f67da230..e08c8a3045f 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -1719,7 +1719,8 @@ public class BasicComboBoxUI extends ComboBoxUI { return comboBox.getSelectedIndex(); } - public boolean isEnabled(Object c) { + @Override + public boolean accept(Object c) { if (getName() == HIDE) { return (c != null && ((JComboBox)c).isPopupVisible()); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java index c8a4d9d0a7a..e784d2d4b2a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java @@ -646,7 +646,8 @@ public class BasicDesktopPaneUI extends DesktopPaneUI { } } - public boolean isEnabled(Object sender) { + @Override + public boolean accept(Object sender) { if (sender instanceof JDesktopPane) { JDesktopPane dp = (JDesktopPane)sender; String action = getName(); 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 8f534ef786a..bcae2e3f8e8 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 @@ -200,7 +200,8 @@ public class BasicInternalFrameUI extends InternalFrameUI } } - public boolean isEnabled(Object sender){ + @Override + public boolean accept(Object sender){ if (sender instanceof JInternalFrame) { JInternalFrame iFrame = (JInternalFrame)sender; if (iFrame.getUI() instanceof BasicInternalFrameUI) { @@ -1709,6 +1710,12 @@ public class BasicInternalFrameUI extends InternalFrameUI } else { parentBounds = null; } + if ((frame.getParent() != null) && frame.isIcon()) { + Boolean value = (Boolean) frame.getClientProperty("wasIconOnce"); + if (Boolean.FALSE.equals(value)) { + iconifyFrame(frame); + } + } if ((frame.getParent() != null) && !componentListenerAdded) { f.getParent().addComponentListener(componentListener); componentListenerAdded = true; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java index ae8827a4f82..39585e86db8 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicListUI.java @@ -2060,7 +2060,8 @@ public class BasicListUI extends ListUI } } - public boolean isEnabled(Object c) { + @Override + public boolean accept(Object c) { Object name = getName(); if (name == SELECT_PREVIOUS_COLUMN_CHANGE_LEAD || name == SELECT_NEXT_COLUMN_CHANGE_LEAD || diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java index 7231ae2a570..98afcc95679 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuUI.java @@ -312,7 +312,8 @@ public class BasicMenuUI extends BasicMenuItemUI } } - public boolean isEnabled(Object c) { + @Override + public boolean accept(Object c) { if (c instanceof JMenu) { return ((JMenu)c).isEnabled(); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRootPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRootPaneUI.java index 300e46a2e7b..714a06396c6 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRootPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicRootPaneUI.java @@ -256,7 +256,8 @@ public class BasicRootPaneUI extends RootPaneUI implements } } - public boolean isEnabled(Object sender) { + @Override + public boolean accept(Object sender) { String key = getName(); if(key == POST_POPUP) { MenuElement[] elems = MenuSelectionManager @@ -278,7 +279,7 @@ public class BasicRootPaneUI extends RootPaneUI implements return false; } - if (sender != null && sender instanceof JRootPane) { + if (sender instanceof JRootPane) { JButton owner = ((JRootPane)sender).getDefaultButton(); return (owner != null && owner.getModel().isEnabled()); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java index 2ec7e11ef71..a02d25f293b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java @@ -855,7 +855,8 @@ public class BasicTableHeaderUI extends TableHeaderUI { super(name); } - public boolean isEnabled(Object sender) { + @Override + public boolean accept(Object sender) { if (sender instanceof JTableHeader) { JTableHeader th = (JTableHeader)sender; TableColumnModel cm = th.getColumnModel(); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java index 73fd9a51340..e6a3d0eb9b5 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java @@ -676,7 +676,8 @@ public class BasicTableUI extends TableUI } } - public boolean isEnabled(Object sender) { + @Override + public boolean accept(Object sender) { String key = getName(); if (sender instanceof JTable && diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java index 7216dfe4a4b..b43423dbc02 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java @@ -4416,7 +4416,8 @@ public class BasicTreeUI extends TreeUI super(key); } - public boolean isEnabled(Object o) { + @Override + public boolean accept(Object o) { if (o instanceof JTree) { if (getName() == CANCEL_EDITING) { return ((JTree)o).isEditing(); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java index 6259171317b..b22941c8f6f 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java @@ -351,12 +351,16 @@ public class SynthDesktopPaneUI extends BasicDesktopPaneUI implements Container c = f.getParent(); JDesktopPane d = f.getDesktopPane(); boolean findNext = f.isSelected(); - - if (c == null) { + if (c == null || d == null) { return; } - desktopIcon = f.getDesktopIcon(); + if (!wasIcon(f)) { + Rectangle r = getBoundsForIconOf(f); + desktopIcon.setBounds(r.x, r.y, r.width, r.height); + desktopIcon.revalidate(); + setWasIcon(f, Boolean.TRUE); + } if (!f.isMaximum()) { f.setNormalBounds(f.getBounds()); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java index bf2b9298973..a36117cda20 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java @@ -471,7 +471,7 @@ public class SynthToolBarUI extends BasicToolBarUI // be distributed among the "glue", if any int extraSpacePerGlue = 0; if (glueCount > 0) { - int minWidth = minimumLayoutSize(parent).width; + int minWidth = preferredLayoutSize(parent).width; extraSpacePerGlue = (tb.getWidth() - minWidth) / glueCount; if (extraSpacePerGlue < 0) extraSpacePerGlue = 0; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractWriter.java b/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractWriter.java index 0ca0fecb5a8..1625964b562 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractWriter.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractWriter.java @@ -441,7 +441,7 @@ public abstract class AbstractWriter { --offsetIndent; } else { - indentLevel--; + indentLevel = indentLevel > 0 ? indentLevel-- : 0; } } diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java index efb0ea50077..a778ca6c769 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java @@ -358,7 +358,7 @@ public class AppletClassLoader extends URLClassLoader { * #getResource(String)}.

        * * @param name the resource name - * @return an input stream for reading the resource, or null + * @return an input stream for reading the resource, or {@code null} * if the resource could not be found * @since 1.1 */ @@ -418,7 +418,7 @@ public class AppletClassLoader extends URLClassLoader { * #getResource(String)}.

        * * @param name the resource name - * @return an input stream for reading the resource, or null + * @return an input stream for reading the resource, or {@code null} * if the resource could not be found * @since 1.1 */ diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java index 0eba476fe82..192c0c84f2e 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java @@ -260,17 +260,17 @@ class AppletSecurity extends AWTSecurityManager { /** - * Throws a SecurityException if the + * Throws a {@code SecurityException} if the * calling thread is not allowed to access the package specified by * the argument. *

        - * This method is used by the loadClass method of class + * This method is used by the {@code loadClass} method of class * loaders. *

        - * The checkPackageAccess method for class - * SecurityManager calls - * checkPermission with the - * RuntimePermission("accessClassInPackage."+ pkgname) + * The {@code checkPackageAccess} method for class + * {@code SecurityManager} calls + * {@code checkPermission} with the + * {@code RuntimePermission("accessClassInPackage."+ pkgname)} * permission. * * @param pkgname the package name. @@ -302,8 +302,8 @@ class AppletSecurity extends AWTSecurityManager { /** * Tests if a client can get access to the AWT event queue. *

        - * This method calls checkPermission with the - * AWTPermission("accessEventQueue") permission. + * This method calls {@code checkPermission} with the + * {@code AWTPermission("accessEventQueue")} permission. * * @since 1.1 * @exception SecurityException if the caller does not have diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletThreadGroup.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletThreadGroup.java index fab6685c1d6..932b517cc0a 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletThreadGroup.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletThreadGroup.java @@ -51,7 +51,7 @@ public class AppletThreadGroup extends ThreadGroup { * @param parent the parent thread group. * @param name the name of the new thread group. * @exception NullPointerException if the thread group argument is - * null. + * {@code null}. * @exception SecurityException if the current thread cannot create a * thread in the specified thread group. * @see java.lang.SecurityException diff --git a/jdk/src/java.desktop/share/classes/sun/applet/Main.java b/jdk/src/java.desktop/share/classes/sun/applet/Main.java index d29ed5ffd23..681fb81c6db 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/Main.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,6 +107,7 @@ public class Main { private int run(String [] args) { // DECODE ARGS try { + System.out.println(lookup("deprecated")); if (args.length == 0) { usage(); return 0; @@ -229,7 +230,7 @@ public class Main { * * @param url a string which represents either a relative or absolute URL. * @return a URL when the passed in string can be interpreted according - * to the RFC, null otherwise. + * to the RFC, {@code null} otherwise. * @exception ParseException * Thrown when we are unable to construct a proper URL from the * passed in string. @@ -270,8 +271,8 @@ public class Main { * Invoke the debugger with the arguments passed in to appletviewer. * * @param args The arguments passed into the debugger. - * @return 0 if the debugger is invoked successfully, - * 1 otherwise. + * @return {@code 0} if the debugger is invoked successfully, + * {@code 1} otherwise. */ private int invokeDebugger(String [] args) { // CONSTRUCT THE COMMAND LINE diff --git a/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java b/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java index af1f3d5a609..f05729b972e 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,6 +73,7 @@ public class MsgAppletViewer extends ListResourceBundle { {"appletviewer.parse.warning.embed.requiresheight", "Warning: tag requires height attribute."}, {"appletviewer.parse.warning.embed.requireswidth", "Warning: tag requires width attribute."}, {"appletviewer.parse.warning.appnotLongersupported", "Warning: tag no longer supported, use instead:"}, + {"appletviewer.deprecated", "AppletViewer is deprecated."}, {"appletviewer.usage", "Usage: appletviewer url(s)\n\nwhere include:\n -debug Start the applet viewer in the Java debugger\n -encoding Specify character encoding used by HTML files\n -J Pass argument to the java interpreter\n\nThe -J option is non-standard and subject to change without notice."}, {"appletviewer.main.err.unsupportedopt", "Unsupported option: {0}"}, {"appletviewer.main.err.unrecognizedarg", "Unrecognized argument: {0}"}, diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java index a025ae85e5f..7d67cd6ae47 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java @@ -85,7 +85,7 @@ public final class AWTAccessor { /* * * Gets the bounds of this component in the form of a - * Rectangle object. The bounds specify this + * {@code Rectangle} object. The bounds specify this * component's width, height, and location relative to * its parent. */ diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java b/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java index 95a1fb9ddb3..1ecef9162ca 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java @@ -41,20 +41,20 @@ import sun.util.logging.PlatformLogger; * This class is to let AWT shutdown automatically when a user is done * with AWT. It tracks AWT state using the following parameters: *
          - *
        • peerMap - the map between the existing peer objects + *
        • {@code peerMap} - the map between the existing peer objects * and their associated targets - *
        • toolkitThreadBusy - whether the toolkit thread + *
        • {@code toolkitThreadBusy} - whether the toolkit thread * is waiting for a new native event to appear in its queue * or is dispatching an event - *
        • busyThreadSet - a set of all the event dispatch + *
        • {@code busyThreadSet} - a set of all the event dispatch * threads that are busy at this moment, i.e. those that are not * waiting for a new event to appear in their event queue. *

        * AWT is considered to be in ready-to-shutdown state when - * peerMap is empty and toolkitThreadBusy - * is false and busyThreadSet is empty. + * {@code peerMap} is empty and {@code toolkitThreadBusy} + * is false and {@code busyThreadSet} is empty. * The internal AWTAutoShutdown logic secures that the single non-daemon - * thread (blockerThread) is running when AWT is not in + * thread ({@code blockerThread}) is running when AWT is not in * ready-to-shutdown state. This blocker thread is to prevent AWT from * exiting since the toolkit thread is now daemon and all the event * dispatch threads are started only when needed. Once it is detected @@ -229,8 +229,8 @@ public final class AWTAutoShutdown implements Runnable { /** * Determine whether AWT is currently in ready-to-shutdown state. * AWT is considered to be in ready-to-shutdown state if - * peerMap is empty and toolkitThreadBusy - * is false and busyThreadSet is empty. + * {@code peerMap} is empty and {@code toolkitThreadBusy} + * is false and {@code busyThreadSet} is empty. * * @return true if AWT is in ready-to-shutdown state. */ diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java b/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java index 9023251171d..b4bc32996b2 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java @@ -71,7 +71,7 @@ import java.util.function.Supplier; * * For example, here we have a Foo service, with its pre-AppContext * code:

        - *

        + * 
        {@code
          *    public class Foo {
          *        private static Foo defaultFoo = new Foo();
          *
        @@ -80,7 +80,8 @@ import java.util.function.Supplier;
          *        }
          *
          *    ... Foo service methods
        - *    }

        + * } + * }

        * * The problem with the above is that the Foo service is global in scope, * so that applets and other untrusted code can execute methods on the @@ -90,7 +91,7 @@ import java.util.function.Supplier; * executes it.

        * * Here's the Foo class written to use the AppContext:

        - *

        + * 
        {@code
          *    public class Foo {
          *        public static Foo getDefaultFoo() {
          *            Foo foo = (Foo)AppContext.getAppContext().get(Foo.class);
        @@ -102,7 +103,8 @@ import java.util.function.Supplier;
          *        }
          *
          *    ... Foo service methods
        - *    }

        + * } + * }

        * * Since a separate AppContext can exist for each ThreadGroup, trusted * and untrusted code have access to different Foo instances. This allows @@ -159,7 +161,7 @@ public final class AppContext { Collections.synchronizedMap(new IdentityHashMap()); /** - * Returns a set containing all AppContexts. + * Returns a set containing all {@code AppContext}s. */ public static Set getAppContexts() { synchronized (threadGroup2appContext) { @@ -187,8 +189,8 @@ public final class AppContext { private final ThreadGroup threadGroup; /** - * If any PropertyChangeListeners have been registered, - * the changeSupport field describes them. + * If any {@code PropertyChangeListeners} have been registered, + * the {@code changeSupport} field describes them. * * @see #addPropertyChangeListener * @see #removePropertyChangeListener @@ -633,7 +635,7 @@ public final class AppContext { * * @param key a key in the AppContext. * @return the value to which the key is mapped in this AppContext; - * null if the key is not mapped to any value. + * {@code null} if the key is not mapped to any value. * @see #put(Object, Object) * @since 1.2 */ @@ -670,19 +672,19 @@ public final class AppContext { } /** - * Maps the specified key to the specified - * value in this AppContext. Neither the key nor the - * value can be null. + * Maps the specified {@code key} to the specified + * {@code value} in this AppContext. Neither the key nor the + * value can be {@code null}. *

        - * The value can be retrieved by calling the get method + * The value can be retrieved by calling the {@code get} method * with a key that is equal to the original key. * * @param key the AppContext key. * @param value the value. * @return the previous value of the specified key in this - * AppContext, or null if it did not have one. + * AppContext, or {@code null} if it did not have one. * @exception NullPointerException if the key or value is - * null. + * {@code null}. * @see #get(Object) * @since 1.2 */ @@ -702,7 +704,7 @@ public final class AppContext { * * @param key the key that needs to be removed. * @return the value to which the key had been mapped in this AppContext, - * or null if the key did not have a mapping. + * or {@code null} if the key did not have a mapping. * @since 1.2 */ public Object remove(Object key) { @@ -746,7 +748,7 @@ public final class AppContext { * Returns an array of all the property change listeners * registered on this component. * - * @return all of this component's PropertyChangeListeners + * @return all of this component's {@code PropertyChangeListener}s * or an empty array if no property change * listeners are currently registered * @@ -825,7 +827,7 @@ public final class AppContext { * Returns an array of all the listeners which have been associated * with the named property. * - * @return all of the PropertyChangeListeners associated with + * @return all of the {@code PropertyChangeListeners} associated with * the named property or an empty array if no listeners have * been added * diff --git a/jdk/src/java.desktop/share/classes/sun/awt/DisplayChangedListener.java b/jdk/src/java.desktop/share/classes/sun/awt/DisplayChangedListener.java index ee0548a2904..747cf9e4124 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/DisplayChangedListener.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/DisplayChangedListener.java @@ -37,7 +37,7 @@ import java.util.EventListener; * screens. * * For win32, the listener object created from that class is then registered - * with the WToolkit object using its addDisplayChangeListener + * with the WToolkit object using its {@code addDisplayChangeListener} * method. When the display resolution is changed (which occurs, * in Windows, either by the user changing the properties of the * display through the control panel or other utility or by diff --git a/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java b/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java index affe2bcb8e7..d096d8c5e7d 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java @@ -348,17 +348,17 @@ public abstract class EmbeddedFrame extends Frame /** * Synthesize native message to activate or deactivate EmbeddedFrame window - * depending on the value of parameter b. + * depending on the value of parameter {@code b}. * Peers should override this method if they are to implement * this functionality. - * @param doActivate if true, activates the window; + * @param doActivate if {@code true}, activates the window; * otherwise, deactivates the window */ public void synthesizeWindowActivation(boolean doActivate) {} /** * Moves this embedded frame to a new location. The top-left corner of - * the new location is specified by the x and y + * the new location is specified by the {@code x} and {@code y} * parameters relative to the native parent component. *

        * setLocation() and setBounds() for EmbeddedFrame really don't move it @@ -418,9 +418,9 @@ public abstract class EmbeddedFrame extends Frame /** * Moves and resizes this embedded frame. The new location of the top-left - * corner is specified by x and y parameters + * corner is specified by {@code x} and {@code y} parameters * relative to the native parent component. The new size is specified by - * width and height. + * {@code width} and {@code height}. *

        * setLocation() and setBounds() for EmbeddedFrame really don't move it * within the native parent. These methods always put embedded frame to @@ -437,8 +437,8 @@ public abstract class EmbeddedFrame extends Frame *

        * @param x the new x-coordinate relative to the parent component * @param y the new y-coordinate relative to the parent component - * @param width the new width of this embedded frame - * @param height the new height of this embedded frame + * @param width the new {@code width} of this embedded frame + * @param height the new {@code height} of this embedded frame * @see java.awt.Component#setBounds * @see #setLocationPrivate * @see #getLocationPrivate diff --git a/jdk/src/java.desktop/share/classes/sun/awt/FwDispatcher.java b/jdk/src/java.desktop/share/classes/sun/awt/FwDispatcher.java index 8ceb67e05b1..8131834b3c7 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/FwDispatcher.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/FwDispatcher.java @@ -48,7 +48,7 @@ public interface FwDispatcher { /** * Forwards a runnable to the delegate, which executes it on an appropriate thread. - * @param r - a runnable calling {@link EventQueue#dispatchEventImpl(java.awt.AWTEvent, Object)} + * @param r a runnable calling {@link EventQueue#dispatchEventImpl(java.awt.AWTEvent, Object)} */ void scheduleDispatch(Runnable r); diff --git a/jdk/src/java.desktop/share/classes/sun/awt/GlobalCursorManager.java b/jdk/src/java.desktop/share/classes/sun/awt/GlobalCursorManager.java index 5337b1956ea..67305e77efd 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/GlobalCursorManager.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/GlobalCursorManager.java @@ -153,7 +153,7 @@ public abstract class GlobalCursorManager { * updates:

        * * (1) InputEvent updates which are outdated are discarded by - * updateCursorImmediately(InputEvent).

        + * {@code updateCursorImmediately(InputEvent)}.

        * * (2) If 'useCache' is true, the native code is free to use a cached * value to determine the most specific, visible, enabled heavyweight diff --git a/jdk/src/java.desktop/share/classes/sun/awt/LightweightFrame.java b/jdk/src/java.desktop/share/classes/sun/awt/LightweightFrame.java index 1a203b83700..5ddeca23ef4 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/LightweightFrame.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/LightweightFrame.java @@ -112,7 +112,7 @@ public abstract class LightweightFrame extends Frame { * frame. Peers should override this method if they are to implement * this functionality. * - * @param activate if true, activates the frame; + * @param activate if {@code true}, activates the frame; * otherwise, deactivates the frame */ public void emulateActivation(boolean activate) { diff --git a/jdk/src/java.desktop/share/classes/sun/awt/PaintEventDispatcher.java b/jdk/src/java.desktop/share/classes/sun/awt/PaintEventDispatcher.java index 7a6312aa99e..eec1fc93c66 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/PaintEventDispatcher.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/PaintEventDispatcher.java @@ -40,7 +40,7 @@ public class PaintEventDispatcher { private static PaintEventDispatcher dispatcher; /** - * Sets the current PaintEventDispatcher. + * Sets the current {@code PaintEventDispatcher}. * * @param dispatcher PaintEventDispatcher */ @@ -52,7 +52,7 @@ public class PaintEventDispatcher { } /** - * Returns the currently active PaintEventDispatcher. This + * Returns the currently active {@code PaintEventDispatcher}. This * will never return null. * * @return PaintEventDispatcher @@ -67,9 +67,9 @@ public class PaintEventDispatcher { } /** - * Creates and returns the PaintEvent that should be + * Creates and returns the {@code PaintEvent} that should be * dispatched for the specified component. If this returns null - * no PaintEvent is dispatched. + * no {@code PaintEvent} is dispatched. *

        * WARNING: This is invoked from the native thread, be careful * what methods you end up invoking here. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/RepaintArea.java b/jdk/src/java.desktop/share/classes/sun/awt/RepaintArea.java index 86723c5d015..e2624f26a0b 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/RepaintArea.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/RepaintArea.java @@ -31,7 +31,7 @@ import java.awt.Rectangle; import java.awt.event.PaintEvent; /** - * The RepaintArea is a geometric construct created for the + * The {@code RepaintArea} is a geometric construct created for the * purpose of holding the geometry of several coalesced paint events. * This geometry is accessed synchronously, although it is written such * that painting may still be executed asynchronously. @@ -59,17 +59,17 @@ public class RepaintArea { /** - * Constructs a new RepaintArea + * Constructs a new {@code RepaintArea} * @since 1.3 */ public RepaintArea() { } /** - * Constructs a new RepaintArea initialized to match + * Constructs a new {@code RepaintArea} initialized to match * the values of the specified RepaintArea. * - * @param ra the RepaintArea from which to copy initial + * @param ra the {@code RepaintArea} from which to copy initial * values to a newly constructed RepaintArea * @since 1.3 */ @@ -82,12 +82,12 @@ public class RepaintArea { } /** - * Adds a Rectangle to this RepaintArea. + * Adds a {@code Rectangle} to this {@code RepaintArea}. * PAINT Rectangles are divided into mostly vertical and mostly horizontal. * Each group is unioned together. * UPDATE Rectangles are unioned. * - * @param r the specified Rectangle + * @param r the specified {@code Rectangle} * @param id possible values PaintEvent.UPDATE or PaintEvent.PAINT * @since 1.3 */ @@ -109,11 +109,11 @@ public class RepaintArea { /** - * Creates a new RepaintArea with the same geometry as this + * Creates a new {@code RepaintArea} with the same geometry as this * RepaintArea, then removes all of the geometry from this * RepaintArea and restores it to an empty RepaintArea. * - * @return ra a new RepaintArea having the same geometry as + * @return ra a new {@code RepaintArea} having the same geometry as * this RepaintArea. * @since 1.3 */ @@ -186,7 +186,7 @@ public class RepaintArea { * MAX_BENEFIT_RATIO times the benefit, then the vertical and horizontal unions are * painted separately. Otherwise the entire bounding rectangle is painted. * - * @param target Component to paint or update + * @param target Component to {@code paint} or {@code update} * @since 1.4 */ public void paint(Object target, boolean shouldClearRectBeforePaint) { @@ -248,7 +248,7 @@ public class RepaintArea { } /** - * Calls Component.update(Graphics) with given Graphics. + * Calls {@code Component.update(Graphics)} with given Graphics. */ protected void updateComponent(Component comp, Graphics g) { if (comp != null) { @@ -257,7 +257,7 @@ public class RepaintArea { } /** - * Calls Component.paint(Graphics) with given Graphics. + * Calls {@code Component.paint(Graphics)} with given Graphics. */ protected void paintComponent(Component comp, Graphics g) { if (comp != null) { diff --git a/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java b/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java index 8130198e0d2..a1c89a41067 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java @@ -339,9 +339,9 @@ public abstract class SunToolkit extends Toolkit /** * Sets the synchronous status of focus requests on lightweight * components in the specified window to the specified value. - * If the boolean parameter is true then the focus + * If the boolean parameter is {@code true} then the focus * requests on lightweight components will be performed - * synchronously, if it is false, then asynchronously. + * synchronously, if it is {@code false}, then asynchronously. * By default, all windows have their lightweight request status * set to asynchronous. *

        @@ -521,7 +521,7 @@ public abstract class SunToolkit extends Toolkit /* * Execute a chunk of code on the Java event handler thread. The * method takes into account provided AppContext and sets - * SunToolkit.getDefaultToolkit() as a target of the + * {@code SunToolkit.getDefaultToolkit()} as a target of the * event. See 6451487 for detailes. * Does not wait for the execution to occur before returning to * the caller. @@ -1159,21 +1159,10 @@ public abstract class SunToolkit extends Toolkit return getStartupLocale(); } - private static DefaultMouseInfoPeer mPeer = null; - - @Override - public synchronized MouseInfoPeer getMouseInfoPeer() { - if (mPeer == null) { - mPeer = new DefaultMouseInfoPeer(); - } - return mPeer; - } - - /** * Returns whether default toolkit needs the support of the xembed * from embedding host(if any). - * @return true, if XEmbed is needed, false otherwise + * @return {@code true}, if XEmbed is needed, {@code false} otherwise */ public static boolean needsXEmbed() { String noxembed = AccessController. @@ -1196,7 +1185,7 @@ public abstract class SunToolkit extends Toolkit /** * Returns whether this toolkit needs the support of the xembed * from embedding host(if any). - * @return true, if XEmbed is needed, false otherwise + * @return {@code true}, if XEmbed is needed, {@code false} otherwise */ protected boolean needsXEmbedImpl() { return false; @@ -1215,8 +1204,8 @@ public abstract class SunToolkit extends Toolkit /** * Returns whether the modal exclusion API is supported by the current toolkit. - * When it isn't supported, calling setModalExcluded has no - * effect, and isModalExcluded returns false for all windows. + * When it isn't supported, calling {@code setModalExcluded} has no + * effect, and {@code isModalExcluded} returns false for all windows. * * @return true if modal exclusion is supported by the toolkit, false otherwise * @@ -1249,7 +1238,7 @@ public abstract class SunToolkit extends Toolkit * events, focus transfer and z-order will continue to work for the * window, it's owned windows and child components, even in the * presence of a modal dialog. - * For details on which Windows are normally blocked + * For details on which {@code Window}s are normally blocked * by modal dialog, see {@link java.awt.Dialog}. * Invoking this method when the modal exclusion API is not supported by * the current toolkit has no effect. @@ -1438,23 +1427,23 @@ public abstract class SunToolkit extends Toolkit * *

        This method allows to write tests without explicit timeouts * or wait for some event. Example: - * + *

        {@code
              * Frame f = ...;
              * f.setVisible(true);
              * ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
        -     * 
        +     * }
        * - *

        After realSync, f will be completely visible + *

        After realSync, {@code f} will be completely visible * on the screen, its getLocationOnScreen will be returning the * right result and it will be the focus owner. * *

        Another example: - * + *

        {@code
              * b.requestFocus();
              * ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
        -     * 
        +     * }
        * - *

        After realSync, b will be focus owner. + *

        After realSync, {@code b} will be focus owner. * *

        Notice that realSync isn't guaranteed to work if recurring * actions occur, such as if during processing of some event @@ -1529,8 +1518,8 @@ public abstract class SunToolkit extends Toolkit * sync of the native queue. The method should wait until native * requests are processed, all native events are processed and * corresponding Java events are generated. Should return - * true if some events were processed, - * false otherwise. + * {@code true} if some events were processed, + * {@code false} otherwise. */ protected abstract boolean syncNativeQueue(final long timeout); @@ -1547,8 +1536,8 @@ public abstract class SunToolkit extends Toolkit * Waits for the Java event queue to empty. Ensures that all * events are processed (including paint events), and that if * recursive events were generated, they are also processed. - * Should return true if more processing is - * necessary, false otherwise. + * Should return {@code true} if more processing is + * necessary, {@code false} otherwise. */ @SuppressWarnings("serial") protected final boolean waitForIdle(final long timeout) { @@ -1813,7 +1802,7 @@ public abstract class SunToolkit extends Toolkit } /** - * Returns the Window ancestor of the component comp. + * Returns the {@code Window} ancestor of the component {@code comp}. * @return Window ancestor of the component or component by itself if it is Window; * null, if component is not a part of window hierarchy */ diff --git a/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java b/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java index 1714fea6113..e90e6004ad7 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java @@ -124,7 +124,7 @@ import java.util.stream.Stream; */ public abstract class DataTransferer { /** - * The DataFlavor representing a Java text encoding String + * The {@code DataFlavor} representing a Java text encoding String * encoded in UTF-8, where *

              *     representationClass = [B
        @@ -323,7 +323,7 @@ public abstract class DataTransferer {
              * @param flavors the data flavors
              * @param map the FlavorTable which contains mappings between
              *            DataFlavors and data formats
        -     * @throws NullPointerException if flavors or map is null
        +     * @throws NullPointerException if flavors or map is {@code null}
              */
             public SortedMap getFormatsForFlavors(DataFlavor[] flavors,
                                                                     FlavorTable map)
        @@ -478,7 +478,7 @@ public abstract class DataTransferer {
              * @param formats the data formats
              * @param map the FlavorTable which contains mappings between
              *            DataFlavors and data formats
        -     * @throws NullPointerException if formats or map is null
        +     * @throws NullPointerException if formats or map is {@code null}
              */
             public Set getFlavorsForFormatsAsSet(long[] formats, FlavorTable map) {
                 Set flavorSet = new HashSet<>(formats.length);
        @@ -509,13 +509,13 @@ public abstract class DataTransferer {
              * 2) the data translation for this mapping can be performed by the data
              * transfer subsystem.
              * The array will be sorted according to a
        -     * DataFlavorComparator created with the specified
        +     * {@code DataFlavorComparator} created with the specified
              * map as an argument.
              *
              * @param formats the data formats
              * @param map the FlavorTable which contains mappings between
              *            DataFlavors and data formats
        -     * @throws NullPointerException if formats or map is null
        +     * @throws NullPointerException if formats or map is {@code null}
              */
             public DataFlavor[] getFlavorsForFormatsAsArray(long[] formats,
                                                             FlavorTable map) {
        @@ -1805,21 +1805,21 @@ search:
         
             /**
              * Concatenates the data represented by two objects. Objects can be either
        -     * byte arrays or instances of InputStream. If both arguments
        +     * byte arrays or instances of {@code InputStream}. If both arguments
              * are byte arrays byte array will be returned. Otherwise an
        -     * InputStream will be returned.
        +     * {@code InputStream} will be returned.
              * 

        * Currently is only called from native code to prepend palette data to * platform-specific image data during image transfer on Win32. * * @param obj1 the first object to be concatenated. * @param obj2 the second object to be concatenated. - * @return a byte array or an InputStream which represents + * @return a byte array or an {@code InputStream} which represents * a logical concatenation of the two arguments. * @throws NullPointerException is either of the arguments is - * null + * {@code null} * @throws ClassCastException is either of the arguments is - * neither byte array nor an instance of InputStream. + * neither byte array nor an instance of {@code InputStream}. */ private Object concatData(Object obj1, Object obj2) { InputStream str1 = null; @@ -1962,7 +1962,7 @@ search: /** * Helper function to convert a Set of DataFlavors to a sorted array. - * The array will be sorted according to DataFlavorComparator. + * The array will be sorted according to {@code DataFlavorComparator}. */ public static DataFlavor[] setToSortedDataFlavorArray(Set flavorsSet) { DataFlavor[] flavors = new DataFlavor[flavorsSet.size()]; @@ -1993,7 +1993,7 @@ search: /** * Returns platform-specific mappings for the specified native. * If there are no platform-specific mappings for this native, the method - * returns an empty List. + * returns an empty {@code List}. */ public LinkedHashSet getPlatformMappingsForNative(String nat) { return new LinkedHashSet<>(); @@ -2002,7 +2002,7 @@ search: /** * Returns platform-specific mappings for the specified flavor. * If there are no platform-specific mappings for this flavor, the method - * returns an empty List. + * returns an empty {@code List}. */ public LinkedHashSet getPlatformMappingsForFlavor(DataFlavor df) { return new LinkedHashSet<>(); diff --git a/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java b/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java index 3b743cbbaab..fe1baa3e631 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/datatransfer/SunClipboard.java @@ -68,8 +68,8 @@ public abstract class SunClipboard extends Clipboard private final Object CLIPBOARD_FLAVOR_LISTENER_KEY; /** - * A number of FlavorListeners currently registered - * on this clipboard across all AppContexts. + * A number of {@code FlavorListener}s currently registered + * on this clipboard across all {@code AppContext}s. */ private volatile int numberOfFlavorListeners = 0; @@ -262,11 +262,11 @@ public abstract class SunClipboard extends Clipboard /** * Clears the clipboard state (contents, owner and contents context) and * notifies the current owner that ownership is lost. Does nothing if the - * argument is not null and is not equal to the current + * argument is not {@code null} and is not equal to the current * contents context. * * @param disposedContext the AppContext that is disposed or - * null if the ownership is lost because another + * {@code null} if the ownership is lost because another * application acquired ownership. */ protected void lostOwnershipLater(final AppContext disposedContext) { @@ -405,10 +405,10 @@ public abstract class SunClipboard extends Clipboard protected abstract void unregisterClipboardViewerChecked(); /** - * Checks change of the DataFlavors and, if necessary, - * posts notifications on FlavorEvents to the + * Checks change of the {@code DataFlavor}s and, if necessary, + * posts notifications on {@code FlavorEvent}s to the * AppContexts' EDTs. - * The parameter formats is null iff we have just + * The parameter {@code formats} is null iff we have just * failed to get formats available on the clipboard. * * @param formats data formats that have just been retrieved from diff --git a/jdk/src/java.desktop/share/classes/sun/awt/event/IgnorePaintEvent.java b/jdk/src/java.desktop/share/classes/sun/awt/event/IgnorePaintEvent.java index 1f59869027d..78a316b0700 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/event/IgnorePaintEvent.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/event/IgnorePaintEvent.java @@ -32,7 +32,7 @@ import java.awt.event.PaintEvent; * PaintEvents that are effectively ignored. This class is used only for * tagging. If a heavy weight peer is asked to handle an event of this * class it'll ignore it. This class is used by Swing. - * Look at javax.swing.SwingPaintEventDispatcher for more. + * Look at {@code javax.swing.SwingPaintEventDispatcher} for more. * */ @SuppressWarnings("serial") // JDK-implementation class diff --git a/jdk/src/java.desktop/share/classes/sun/awt/geom/Order2.java b/jdk/src/java.desktop/share/classes/sun/awt/geom/Order2.java index 64d37c88e27..82a0dc1ef38 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/geom/Order2.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/geom/Order2.java @@ -89,7 +89,7 @@ final class Order2 extends Curve { /* * Return the count of the number of horizontal sections of the * specified quadratic Bezier curve. Put the parameters for the - * horizontal sections into the specified ret array. + * horizontal sections into the specified {@code ret} array. *

        * If we examine the parametric equation in t, we have: * Py(t) = C0*(1-t)^2 + 2*CP*t*(1-t) + C1*t^2 diff --git a/jdk/src/java.desktop/share/classes/sun/awt/geom/Order3.java b/jdk/src/java.desktop/share/classes/sun/awt/geom/Order3.java index 9c9e5962aea..21363f63b1c 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/geom/Order3.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/geom/Order3.java @@ -123,7 +123,7 @@ final class Order3 extends Curve { /* * Return the count of the number of horizontal sections of the * specified cubic Bezier curve. Put the parameters for the - * horizontal sections into the specified ret array. + * horizontal sections into the specified {@code ret} array. *

        * If we examine the parametric equation in t, we have: * Py(t) = C0(1-t)^3 + 3CP0 t(1-t)^2 + 3CP1 t^2(1-t) + C1 t^3 diff --git a/jdk/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java b/jdk/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java index 88ee71163b1..fe533f4cbe0 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/im/ExecutableInputMethodManager.java @@ -57,11 +57,11 @@ import sun.awt.InputMethodSupport; import sun.awt.SunToolkit; /** - * ExecutableInputMethodManager is the implementation of the - * InputMethodManager class. It is runnable as a separate + * {@code ExecutableInputMethodManager} is the implementation of the + * {@code InputMethodManager} class. It is runnable as a separate * thread in the AWT environment.  - * InputMethodManager.getInstance() creates an instance of - * ExecutableInputMethodManager and executes it as a deamon + * {@code InputMethodManager.getInstance()} creates an instance of + * {@code ExecutableInputMethodManager} and executes it as a deamon * thread. * * @see InputMethodManager diff --git a/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java b/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java index a5000b9836d..8b479d20957 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java @@ -59,10 +59,10 @@ import sun.misc.InnocuousThread; import sun.misc.ManagedLocalsThread; /** - * InputMethodManager is an abstract class that manages the input - * method environment of JVM. There is only one InputMethodManager + * {@code InputMethodManager} is an abstract class that manages the input + * method environment of JVM. There is only one {@code InputMethodManager} * instance in JVM that is executed under a separate daemon thread. - * InputMethodManager performs the following: + * {@code InputMethodManager} performs the following: *

          *
        • * Keeps track of the current input context.
        • @@ -87,7 +87,7 @@ import sun.misc.ManagedLocalsThread; * When more than one input method descriptor can be found or the only input * method descriptor found supports multiple locales, a menu item * is added to the window (manager) menu. This item label is obtained invoking - * getTriggerMenuString(). If null is returned by this method, it + * {@code getTriggerMenuString()}. If null is returned by this method, it * means that there is only input method or none in the environment. Frame and Dialog * invoke this method. * @@ -97,15 +97,15 @@ import sun.misc.ManagedLocalsThread; * *
        • * When the menu item of the window (manager) menu has been selected by the - * user, Frame/Dialog invokes notifyChangeRequest() to notify - * InputMethodManager that the user wants to switch input methods.
        • + * user, Frame/Dialog invokes {@code notifyChangeRequest()} to notify + * {@code InputMethodManager} that the user wants to switch input methods. * *
        • - * InputMethodManager displays a pop-up menu to choose an input method.
        • + * {@code InputMethodManager} displays a pop-up menu to choose an input method. * *
        • - * InputMethodManager notifies the current InputContext of - * the selected InputMethod.
        • + * {@code InputMethodManager} notifies the current {@code InputContext} of + * the selected {@code InputMethod}. *
        * *
          @@ -116,8 +116,8 @@ import sun.misc.ManagedLocalsThread; * *
        • * When the hot key combination is typed by the user, the component which has the input - * focus invokes notifyChangeRequestByHotKey() to notify - * InputMethodManager that the user wants to switch input methods.
        • + * focus invokes {@code notifyChangeRequestByHotKey()} to notify + * {@code InputMethodManager} that the user wants to switch input methods. * *
        • * This results in a popup menu and notification to the current input context, diff --git a/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodPopupMenu.java b/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodPopupMenu.java index d64a5f06f7a..7a2c975918e 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodPopupMenu.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodPopupMenu.java @@ -46,7 +46,7 @@ import javax.swing.JMenu; import javax.swing.JMenuItem; /** - * InputMethodPopupMenu provides the popup selection menu + * {@code InputMethodPopupMenu} provides the popup selection menu */ abstract class InputMethodPopupMenu implements ActionListener { diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/BufferedImageDevice.java b/jdk/src/java.desktop/share/classes/sun/awt/image/BufferedImageDevice.java index 95dd69f1ff9..a91ffbc5d29 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/BufferedImageDevice.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/BufferedImageDevice.java @@ -37,8 +37,8 @@ public class BufferedImageDevice extends GraphicsDevice } /** - * Returns the type of this GraphicsDevice. - * @return the type of this GraphicsDevice, which can + * Returns the type of this {@code GraphicsDevice}. + * @return the type of this {@code GraphicsDevice}, which can * either be TYPE_RASTER_SCREEN, TYPE_PRINTER or TYPE_IMAGE_BUFFER. * @see #TYPE_RASTER_SCREEN * @see #TYPE_PRINTER @@ -50,30 +50,30 @@ public class BufferedImageDevice extends GraphicsDevice /** * Returns the identification string associated with this - * GraphicsDevice. - * @return a String that is the identification - * of this GraphicsDevice. + * {@code GraphicsDevice}. + * @return a {@code String} that is the identification + * of this {@code GraphicsDevice}. */ public String getIDstring() { return ("BufferedImage"); } /** - * Returns all of the GraphicsConfiguration - * objects associated with this GraphicsDevice. - * @return an array of GraphicsConfiguration + * Returns all of the {@code GraphicsConfiguration} + * objects associated with this {@code GraphicsDevice}. + * @return an array of {@code GraphicsConfiguration} * objects that are associated with this - * GraphicsDevice. + * {@code GraphicsDevice}. */ public GraphicsConfiguration[] getConfigurations() { return new GraphicsConfiguration[] { gc }; } /** - * Returns the default GraphicsConfiguration - * associated with this GraphicsDevice. - * @return the default GraphicsConfiguration - * of this GraphicsDevice. + * Returns the default {@code GraphicsConfiguration} + * associated with this {@code GraphicsDevice}. + * @return the default {@code GraphicsConfiguration} + * of this {@code GraphicsDevice}. */ public GraphicsConfiguration getDefaultConfiguration() { return gc; diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/DataBufferNative.java b/jdk/src/java.desktop/share/classes/sun/awt/image/DataBufferNative.java index bb152835f55..c8f33d8d169 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/DataBufferNative.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/DataBufferNative.java @@ -31,7 +31,7 @@ import sun.java2d.SurfaceData; import java.awt.Rectangle; /** - * This class extends DataBuffer and allows access to + * This class extends {@code DataBuffer} and allows access to * native data via the DataBuffer methods. Note that, unlike other * DataBuffer classes, the data is not stored in this class but * has been created and stored elsewhere and this class is used diff --git a/jdk/src/java.desktop/share/classes/sun/awt/shell/DefaultShellFolder.java b/jdk/src/java.desktop/share/classes/sun/awt/shell/DefaultShellFolder.java index fe349dc90b2..e20d40b2e47 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/shell/DefaultShellFolder.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/shell/DefaultShellFolder.java @@ -46,9 +46,9 @@ class DefaultShellFolder extends ShellFolder { /** * This method is implemented to make sure that no instances - * of ShellFolder are ever serialized. An instance of + * of {@code ShellFolder} are ever serialized. An instance of * this default implementation can always be represented with a - * java.io.File object instead. + * {@code java.io.File} object instead. * * @return a java.io.File replacement object. */ diff --git a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java index cf1878a0a7a..90bf4d02389 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java @@ -62,9 +62,9 @@ public abstract class ShellFolder extends File { /** * This method must be implemented to make sure that no instances - * of ShellFolder are ever serialized. If isFileSystem() returns - * true, then the object should be representable with an instance of - * java.io.File instead. If not, then the object is most likely + * of {@code ShellFolder} are ever serialized. If {@code isFileSystem()} returns + * {@code true}, then the object should be representable with an instance of + * {@code java.io.File} instead. If not, then the object is most likely * depending on some internal (native) state and cannot be serialized. * * @return a java.io.File replacement object, or null @@ -74,11 +74,11 @@ public abstract class ShellFolder extends File { /** * Returns the path for this object's parent, - * or null if this object does not name a parent + * or {@code null} if this object does not name a parent * folder. * * @return the path as a String for this object's parent, - * or null if this object does not name a parent + * or {@code null} if this object does not name a parent * folder * * @see java.io.File#getParent() @@ -97,11 +97,11 @@ public abstract class ShellFolder extends File { /** * Returns a File object representing this object's parent, - * or null if this object does not name a parent + * or {@code null} if this object does not name a parent * folder. * * @return a File object representing this object's parent, - * or null if this object does not name a parent + * or {@code null} if this object does not name a parent * folder * * @see java.io.File#getParentFile() @@ -250,8 +250,8 @@ public abstract class ShellFolder extends File { } /** - * @param key a String - * @return An Object matching the string key. + * @param key a {@code String} + * @return An Object matching the string {@code key}. * @see ShellFolderManager#get(String) */ public static Object get(String key) { @@ -259,7 +259,7 @@ public abstract class ShellFolder extends File { } /** - * Does dir represent a "computer" such as a node on the network, or + * Does {@code dir} represent a "computer" such as a node on the network, or * "My Computer" on the desktop. */ public static boolean isComputerNode(File dir) { diff --git a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderColumnInfo.java b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderColumnInfo.java index 3926b558ba3..eba6b3af1d1 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderColumnInfo.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderColumnInfo.java @@ -40,8 +40,8 @@ public class ShellFolderColumnInfo { private SortOrder sortOrder; private Comparator comparator; /** - * false (default) if the {@link #comparator} expects folders as arguments, - * and true if folder's column values. The first option is used default for comparison + * {@code false} (default) if the {@link #comparator} expects folders as arguments, + * and {@code true} if folder's column values. The first option is used default for comparison * on Windows and also for separating files from directories when sorting using * ShellFolderManager's inner comparator. */ diff --git a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderManager.java b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderManager.java index 955ba3be986..e61b8122d0a 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderManager.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolderManager.java @@ -44,21 +44,21 @@ class ShellFolderManager { } /** - * @param key a String + * @param key a {@code String} * "fileChooserDefaultFolder": - * Returns a File - the default shellfolder for a new filechooser + * Returns a {@code File} - the default shellfolder for a new filechooser * "roots": - * Returns a File[] - containing the root(s) of the displayable hierarchy + * Returns a {@code File[]} - containing the root(s) of the displayable hierarchy * "fileChooserComboBoxFolders": - * Returns a File[] - an array of shellfolders representing the list to + * Returns a {@code File[]} - an array of shellfolders representing the list to * show by default in the file chooser's combobox * "fileChooserShortcutPanelFolders": - * Returns a File[] - an array of shellfolders representing well-known + * Returns a {@code File[]} - an array of shellfolders representing well-known * folders, such as Desktop, Documents, History, Network, Home, etc. * This is used in the shortcut panel of the filechooser on Windows 2000 * and Windows Me. * "fileChooserIcon ": - * Returns an Image - icon can be ListView, DetailsView, UpFolder, NewFolder or + * Returns an {@code Image} - icon can be ListView, DetailsView, UpFolder, NewFolder or * ViewMenu (Windows only). * * @return An Object matching the key string. @@ -90,7 +90,7 @@ class ShellFolderManager { } /** - * Does dir represent a "computer" such as a node on the network, or + * Does {@code dir} represent a "computer" such as a node on the network, or * "My Computer" on the desktop. */ public boolean isComputerNode(File dir) { diff --git a/jdk/src/java.desktop/share/classes/sun/font/BidiUtils.java b/jdk/src/java.desktop/share/classes/sun/font/BidiUtils.java index 45dcf92aef5..285245ed381 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/BidiUtils.java +++ b/jdk/src/java.desktop/share/classes/sun/font/BidiUtils.java @@ -48,8 +48,8 @@ public final class BidiUtils { * * @param levels the array to receive the character levels * @param start the starting offset into the array - * @throws IndexOutOfBoundsException if start is less than 0 or - * start + getLength() is greater than levels.length. + * @throws IndexOutOfBoundsException if {@code start} is less than 0 or + * {@code start + getLength()} is greater than {@code levels.length}. */ public static void getLevels(Bidi bidi, byte[] levels, int start) { int limit = start + bidi.getLength(); @@ -87,7 +87,7 @@ public final class BidiUtils { * Given level data, compute a a visual to logical mapping. * The leftmost (or topmost) character is at visual index zero. The * logical index of the character is derived from the visual index - * by the expression li = map[vi];. + * by the expression {@code li = map[vi];}. * @param levels the levels array * @return the mapping array from visual to logical */ @@ -148,7 +148,7 @@ public final class BidiUtils { /** * Return the inverse position map. The source array must map one-to-one (each value * is distinct and the values run from zero to the length of the array minus one). - * For example, if values[i] = j, then inverse[j] = i. + * For example, if {@code values[i] = j}, then {@code inverse[j] = i}. * @param values the source ordering array * @return the inverse array */ diff --git a/jdk/src/java.desktop/share/classes/sun/font/FileFont.java b/jdk/src/java.desktop/share/classes/sun/font/FileFont.java index 6b84a5fe288..60b2377c9da 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/FileFont.java +++ b/jdk/src/java.desktop/share/classes/sun/font/FileFont.java @@ -80,7 +80,7 @@ public abstract class FileFont extends PhysicalFont { protected NativeFont[] nativeFonts; protected char[] glyphToCharMap; /* - * @throws FontFormatException - if the font can't be opened + * @throws FontFormatException if the font can't be opened */ FileFont(String platname, Object nativeNames) throws FontFormatException { diff --git a/jdk/src/java.desktop/share/classes/sun/font/FileFontStrike.java b/jdk/src/java.desktop/share/classes/sun/font/FileFontStrike.java index f5c478fb517..5ea5095ace4 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/FileFontStrike.java +++ b/jdk/src/java.desktop/share/classes/sun/font/FileFontStrike.java @@ -734,8 +734,8 @@ public class FileFontStrike extends PhysicalStrike { but if we eventually allow scalers to return NULL pointers this check might be actually useful. */ if (ptr == 0L) { - result.x = (int) Math.floor(pt.x); - result.y = (int) Math.floor(pt.y); + result.x = (int) Math.floor(pt.x+0.5f); + result.y = (int) Math.floor(pt.y+0.5f); result.width = result.height = 0; return; } @@ -743,8 +743,8 @@ public class FileFontStrike extends PhysicalStrike { topLeftX = StrikeCache.unsafe.getFloat(ptr+StrikeCache.topLeftXOffset); topLeftY = StrikeCache.unsafe.getFloat(ptr+StrikeCache.topLeftYOffset); - result.x = (int)Math.floor(pt.x + topLeftX); - result.y = (int)Math.floor(pt.y + topLeftY); + result.x = (int)Math.floor(pt.x + topLeftX + 0.5f); + result.y = (int)Math.floor(pt.y + topLeftY + 0.5f); result.width = StrikeCache.unsafe.getShort(ptr+StrikeCache.widthOffset) &0x0ffff; result.height = diff --git a/jdk/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java b/jdk/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java index 750e5022ca1..15174561c03 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java +++ b/jdk/src/java.desktop/share/classes/sun/font/FontDesignMetrics.java @@ -520,14 +520,14 @@ public final class FontDesignMetrics extends FontMetrics { /** * Gets the advance widths of the first 256 characters in the - * Font. The advance is the + * {@code Font}. The advance is the * distance from the leftmost point to the rightmost point on the * character's baseline. Note that the advance of a - * String is not necessarily the sum of the advances + * {@code String} is not necessarily the sum of the advances * of its characters. * @return an array storing the advance widths of the - * characters in the Font - * described by this FontMetrics object. + * characters in the {@code Font} + * described by this {@code FontMetrics} object. */ // More efficient than base class implementation - reuses existing cache public int[] getWidths() { diff --git a/jdk/src/java.desktop/share/classes/sun/font/PhysicalFont.java b/jdk/src/java.desktop/share/classes/sun/font/PhysicalFont.java index a3c7378265d..1ca522e3517 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/PhysicalFont.java +++ b/jdk/src/java.desktop/share/classes/sun/font/PhysicalFont.java @@ -52,7 +52,7 @@ public abstract class PhysicalFont extends Font2D { /** * Opens the file (temporarily) and does basic verification. * Initializes the CMAP - * @throws FontFormatException - if the font can't be opened + * @throws FontFormatException if the font can't be opened * or fails verification, or there's no usable cmap */ PhysicalFont(String platname, Object nativeNames) diff --git a/jdk/src/java.desktop/share/classes/sun/font/ScriptRun.java b/jdk/src/java.desktop/share/classes/sun/font/ScriptRun.java index 485002ded79..52029dcc074 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/ScriptRun.java +++ b/jdk/src/java.desktop/share/classes/sun/font/ScriptRun.java @@ -35,10 +35,10 @@ package sun.font; /** - * ScriptRun is used to find runs of characters in - * the same script, as defined in the Script class. + * {@code ScriptRun} is used to find runs of characters in + * the same script, as defined in the {@code Script} class. * It implements a simple iterator over an array of characters. - * The iterator will assign COMMON and INHERITED + * The iterator will assign {@code COMMON} and {@code INHERITED} * characters to the same script as the preceding characters. If the * COMMON and INHERITED characters are first, they will be assigned to * the same script as the following characters. @@ -88,7 +88,7 @@ public final class ScriptRun } /** - * Construct a ScriptRun object which iterates over a subrange + * Construct a {@code ScriptRun} object which iterates over a subrange * of the given characetrs. * * @param chars the array of characters over which to iterate. @@ -145,10 +145,10 @@ public final class ScriptRun } /** - * Find the next script run. Returns false if there - * isn't another run, returns true if there is. + * Find the next script run. Returns {@code false} if there + * isn't another run, returns {@code true} if there is. * - * @return false if there isn't another run, true if there is. + * @return {@code false} if there isn't another run, {@code true} if there is. */ public boolean next() { int startSP = parenSP; // used to find the first new open character @@ -273,7 +273,7 @@ public final class ScriptRun * * @param scriptOne one of the script codes. * @param scriptTwo the other script code. - * @return true if the two scripts are the same. + * @return {@code true} if the two scripts are the same. * @see Script */ private static boolean sameScript(int scriptOne, int scriptTwo) { diff --git a/jdk/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java b/jdk/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java index 69f1d4babc2..92a7c306cdc 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java +++ b/jdk/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java @@ -1261,20 +1261,20 @@ public class StandardGlyphVector extends GlyphVector { // internal use only for possible future extension /** - * A flag used with getLayoutFlags that indicates whether this GlyphVector uses + * A flag used with getLayoutFlags that indicates whether this {@code GlyphVector} uses * a vertical baseline. */ public static final int FLAG_USES_VERTICAL_BASELINE = 128; /** - * A flag used with getLayoutFlags that indicates whether this GlyphVector uses - * vertical glyph metrics. A GlyphVector can use vertical metrics on a + * A flag used with getLayoutFlags that indicates whether this {@code GlyphVector} uses + * vertical glyph metrics. A {@code GlyphVector} can use vertical metrics on a * horizontal line, or vice versa. */ public static final int FLAG_USES_VERTICAL_METRICS = 256; /** - * A flag used with getLayoutFlags that indicates whether this GlyphVector uses + * A flag used with getLayoutFlags that indicates whether this {@code GlyphVector} uses * the 'alternate orientation.' Glyphs have a default orientation given a * particular baseline and metrics orientation, this is the orientation appropriate * for left-to-right text. For example, the letter 'A' can have four orientations, diff --git a/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java b/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java index 7668b6572a8..c04bfb9431f 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java +++ b/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java @@ -189,7 +189,7 @@ public class TrueTypeFont extends FileFont { * - reads the names (full, family). * - determines the style of the font. * - initializes the CMAP - * @throws FontFormatException - if the font can't be opened + * @throws FontFormatException if the font can't be opened * or fails verification, or there's no usable cmap */ public TrueTypeFont(String platname, Object nativeNames, int fIndex, diff --git a/jdk/src/java.desktop/share/classes/sun/font/Type1Font.java b/jdk/src/java.desktop/share/classes/sun/font/Type1Font.java index 39a1c08d0e0..44f4f58e334 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/Type1Font.java +++ b/jdk/src/java.desktop/share/classes/sun/font/Type1Font.java @@ -161,7 +161,7 @@ public class Type1Font extends FileFont { * - does basic verification of the file * - reads the names (full, family). * - determines the style of the font. - * @throws FontFormatException - if the font can't be opened + * @throws FontFormatException if the font can't be opened * or fails verification, or there's no usable cmap */ public Type1Font(String platname, Object nativeNames, boolean createdCopy) diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/Spans.java b/jdk/src/java.desktop/share/classes/sun/java2d/Spans.java index abd1eda118f..c7be5d5ab36 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/Spans.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/Spans.java @@ -41,7 +41,7 @@ public class Spans { /** * This class will sort and collapse its span * entries after this many span additions via - * the add method. + * the {@code add} method. */ private static final int kMaxAddsSinceSort = 256; @@ -52,7 +52,7 @@ public class Spans { private List mSpans = new Vector<>(kMaxAddsSinceSort); /** - * The number of Span + * The number of {@code Span} * instances that have been added * to this object without a sort * and collapse taking place. @@ -65,8 +65,8 @@ public class Spans { /** * Add a span covering the half open interval - * including start up to - * but not including end. + * including {@code start} up to + * but not including {@code end}. */ public void add(float start, float end) { @@ -82,10 +82,10 @@ public class Spans { /** * Add a span which covers the entire range. * This call is logically equivalent to - * add(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY) + * {@code add(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY)} * The result of making this call is that - * all future add calls are ignored - * and the intersects method always + * all future {@code add} calls are ignored + * and the {@code intersects} method always * returns true. */ public void addInfinite() { @@ -94,8 +94,8 @@ public class Spans { /** * Returns true if the span defined by the half-open - * interval from start up to, - * but not including, end intersects + * interval from {@code start} up to, + * but not including, {@code end} intersects * any of the spans defined by this instance. */ public boolean intersects(float start, float end) { @@ -231,8 +231,8 @@ public class Spans { /** * Create a half-open interval including - * start but not including - * end. + * {@code start} but not including + * {@code end}. */ Span(float start, float end) { mStart = start; @@ -240,7 +240,7 @@ public class Spans { } /** - * Return the start of the Span. + * Return the start of the {@code Span}. * The start is considered part of the * half-open interval. */ @@ -249,7 +249,7 @@ public class Spans { } /** - * Return the end of the Span. + * Return the end of the {@code Span}. * The end is not considered part of the * half-open interval. */ @@ -259,7 +259,7 @@ public class Spans { /** * Change the initial position of the - * Span. + * {@code Span}. */ final void setStart(float start) { mStart = start; @@ -267,18 +267,18 @@ public class Spans { /** * Change the terminal position of the - * Span. + * {@code Span}. */ final void setEnd(float end) { mEnd = end; } /** - * Attempt to alter this Span - * to include otherSpan without + * Attempt to alter this {@code Span} + * to include {@code otherSpan} without * altering this span's starting position. - * If otherSpan can be so consumed - * by this Span then true + * If {@code otherSpan} can be so consumed + * by this {@code Span} then {@code true} * is returned. */ boolean subsume(Span otherSpan) { @@ -304,7 +304,7 @@ public class Spans { /** * Return true if the passed in position * lies in the half-open interval defined - * by this Span. + * by this {@code Span}. */ boolean contains(float pos) { return mStart <= pos && pos < mEnd; @@ -337,11 +337,11 @@ public class Spans { } /** - * This class ranks a pair of Span + * This class ranks a pair of {@code Span} * instances. If the instances intersect they * are deemed equal otherwise they are ranked * by their relative position. Use - * SpanIntersection.instance to + * {@code SpanIntersection.instance} to * get the single instance of this class. */ static class SpanIntersection implements Comparator { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/StateTrackable.java b/jdk/src/java.desktop/share/classes/sun/java2d/StateTrackable.java index 01f0d00cb8f..53896a81894 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/StateTrackable.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/StateTrackable.java @@ -129,9 +129,9 @@ package sun.java2d; * time period of the modifications would be small in most cases * and the 2 changes of state would each require synchronization. *

          - * In comparison the act of setting the curTracker + * In comparison the act of setting the {@code curTracker} * reference to null in the usage pattern above effectively invalidates - * all outstanding Tracker objects as soon as possible + * all outstanding {@code Tracker} objects as soon as possible * after the change to the data and requires very little code and no * synchronization to implement. *

          diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index 3cb7207ad2b..869271d1e0c 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -2759,8 +2759,8 @@ public final class SunGraphics2D } /** - * Intersects destRect with clip and - * overwrites destRect with the result. + * Intersects {@code destRect} with {@code clip} and + * overwrites {@code destRect} with the result. * Returns false if the intersection was empty, true otherwise. */ private boolean clipTo(Rectangle destRect, Rectangle clip) { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java index 679f801d2e4..ce14dfa569d 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java @@ -166,7 +166,7 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment /** * Create and return the screen device with the specified number. The - * device with number 0 will be the default device (returned + * device with number {@code 0} will be the default device (returned * by {@link #getDefaultScreenDevice()}. * * @param screennum the number of the screen to create diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java b/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java index 8250d09a43d..4de1a1fc576 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/SurfaceData.java @@ -922,8 +922,8 @@ public abstract class SurfaceData } /** - * Returns the type of this Transparency. - * @return the field type of this Transparency, which is + * Returns the type of this {@code Transparency}. + * @return the field type of this {@code Transparency}, which is * either OPAQUE, BITMASK or TRANSLUCENT. */ public int getTransparency() { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java index 9aa35132772..18cb441c571 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java @@ -110,7 +110,7 @@ public final class MarlinCache implements MarlinConst { MarlinCache(final RendererContext rdrCtx) { this.rdrCtx = rdrCtx; - rowAAChunk = new OffHeapArray(rdrCtx, INITIAL_CHUNK_ARRAY); + rowAAChunk = new OffHeapArray(rdrCtx.cleanerObj, INITIAL_CHUNK_ARRAY); // 64K touchedTile = touchedTile_initial; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/OffHeapArray.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/OffHeapArray.java index 43dee2477ed..96437cd2f56 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/OffHeapArray.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/OffHeapArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,9 @@ package sun.java2d.marlin; -import java.lang.ref.PhantomReference; -import java.lang.ref.ReferenceQueue; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Vector; import static sun.java2d.marlin.MarlinConst.logUnsafeMalloc; -import sun.awt.util.ThreadGroupUtils; import jdk.internal.misc.Unsafe; +import jdk.internal.ref.CleanerFactory; /** * @@ -45,36 +40,9 @@ final class OffHeapArray { // size of int / float static final int SIZE_INT; - // RendererContext reference queue - private static final ReferenceQueue rdrQueue - = new ReferenceQueue(); - // reference list - private static final Vector refList - = new Vector(32); - static { unsafe = Unsafe.getUnsafe(); SIZE_INT = Unsafe.ARRAY_INT_INDEX_SCALE; - - // Mimics Java2D Disposer: - AccessController.doPrivileged( - (PrivilegedAction) () -> { - /* - * The thread must be a member of a thread group - * which will not get GCed before VM exit. - * Make its parent the top-level thread group. - */ - final ThreadGroup rootTG - = ThreadGroupUtils.getRootThreadGroup(); - final Thread t = new Thread(rootTG, new OffHeapDisposer(), - "MarlinRenderer Disposer"); - t.setContextClassLoader(null); - t.setDaemon(true); - t.setPriority(Thread.MAX_PRIORITY); - t.start(); - return null; - } - ); } /* members */ @@ -89,12 +57,12 @@ final class OffHeapArray { this.used = 0; if (logUnsafeMalloc) { MarlinUtils.logInfo(System.currentTimeMillis() - + ": OffHeapArray.allocateMemory = " + + ": OffHeapArray.allocateMemory = " + len + " to addr = " + this.address); } - // Create the phantom reference to ensure freeing off-heap memory: - refList.add(new OffHeapReference(parent, this)); + // Register a cleaning function to ensure freeing off-heap memory: + CleanerFactory.cleaner().register(parent, () -> this.free()); } /* @@ -117,7 +85,7 @@ final class OffHeapArray { unsafe.freeMemory(this.address); if (logUnsafeMalloc) { MarlinUtils.logInfo(System.currentTimeMillis() - + ": OffHeapEdgeArray.free = " + + ": OffHeapArray.freeMemory = " + this.length + " at addr = " + this.address); } @@ -126,41 +94,4 @@ final class OffHeapArray { void fill(final byte val) { unsafe.setMemory(this.address, this.length, val); } - - static final class OffHeapReference extends PhantomReference { - - private final OffHeapArray array; - - OffHeapReference(final Object parent, final OffHeapArray edges) { - super(parent, rdrQueue); - this.array = edges; - } - - void dispose() { - // free off-heap blocks - this.array.free(); - } - } - - static final class OffHeapDisposer implements Runnable { - @Override - public void run() { - final Thread currentThread = Thread.currentThread(); - OffHeapReference ref; - - // check interrupted: - for (; !currentThread.isInterrupted();) { - try { - ref = (OffHeapReference)rdrQueue.remove(); - ref.dispose(); - - refList.remove(ref); - - } catch (InterruptedException ie) { - MarlinUtils.logException("OffHeapDisposer interrupted:", - ie); - } - } - } - } } diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java index f59785cd92f..aacd8b2062d 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java @@ -514,7 +514,7 @@ final class Renderer implements PathConsumer2D, MarlinConst { Renderer(final RendererContext rdrCtx) { this.rdrCtx = rdrCtx; - this.edges = new OffHeapArray(rdrCtx, INITIAL_EDGES_CAPACITY); // 96K + this.edges = new OffHeapArray(rdrCtx.cleanerObj, INITIAL_EDGES_CAPACITY); // 96K this.curve = rdrCtx.curve; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java index a767651f5d5..f9524c88870 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java @@ -68,6 +68,8 @@ final class RendererContext implements MarlinConst { * @see MarlinRenderingEngine#REF_TYPE */ final Object reference; + // Smallest object used as Cleaner's parent reference + final Object cleanerObj = new Object(); // dirty flag indicating an exception occured during pipeline in pathTo() boolean dirty = false; // dynamic array caches kept using weak reference (low memory footprint) @@ -187,10 +189,10 @@ final class RendererContext implements MarlinConst { if (USE_CACHE_HARD_REF) { // update hard reference: hardRefArrayCaches = holder; + } else { + // update weak reference: + refArrayCaches = new WeakReference(holder); } - - // update weak reference: - refArrayCaches = new WeakReference(holder); } } return holder; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java index 1aa48411f04..2946eda28f0 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java @@ -87,6 +87,7 @@ final class Stroker implements PathConsumer2D, MarlinConst { private int joinStyle; private float lineWidth2; + private float invHalfLineWidth2Sq; private final float[] offset0 = new float[2]; private final float[] offset1 = new float[2]; @@ -158,6 +159,7 @@ final class Stroker implements PathConsumer2D, MarlinConst { this.out = pc2d; this.lineWidth2 = lineWidth / 2f; + this.invHalfLineWidth2Sq = 1f / (2f * lineWidth2 * lineWidth2); this.capStyle = capStyle; this.joinStyle = joinStyle; @@ -252,11 +254,11 @@ final class Stroker implements PathConsumer2D, MarlinConst { // The sign of the dot product of mx,my and omx,omy is equal to the // the sign of the cosine of ext // (ext is the angle between omx,omy and mx,my). - double cosext = omx * mx + omy * my; + final float cosext = omx * mx + omy * my; // If it is >=0, we know that abs(ext) is <= 90 degrees, so we only // need 1 curve to approximate the circle section that joins omx,omy // and mx,my. - final int numCurves = cosext >= 0 ? 1 : 2; + final int numCurves = (cosext >= 0f) ? 1 : 2; switch (numCurves) { case 1: @@ -302,14 +304,22 @@ final class Stroker implements PathConsumer2D, MarlinConst { final float mx, final float my, boolean rev) { - float cosext2 = (omx * mx + omy * my) / (2f * lineWidth2 * lineWidth2); + final float cosext2 = (omx * mx + omy * my) * invHalfLineWidth2Sq; + + // check round off errors producing cos(ext) > 1 and a NaN below + // cos(ext) == 1 implies colinear segments and an empty join anyway + if (cosext2 >= 0.5f) { + // just return to avoid generating a flat curve: + return; + } + // cv is the length of P1-P0 and P2-P3 divided by the radius of the arc // (so, cv assumes the arc has radius 1). P0, P1, P2, P3 are the points that // define the bezier curve we're computing. // It is computed using the constraints that P1-P0 and P3-P2 are parallel // to the arc tangents at the endpoints, and that |P1-P0|=|P3-P2|. - float cv = (float) ((4.0 / 3.0) * sqrt(0.5-cosext2) / - (1.0 + sqrt(cosext2+0.5))); + float cv = (float) ((4.0 / 3.0) * sqrt(0.5 - cosext2) / + (1.0 + sqrt(cosext2 + 0.5))); // if clockwise, we need to negate cv. if (rev) { // rev is equivalent to isCW(omx, omy, mx, my) cv = -cv; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java index 16f719a0cbf..94b0e2f1e59 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java @@ -27,7 +27,7 @@ package sun.java2d.marlin; public final class Version { - private static final String version = "marlin-0.7.2-Unsafe-OpenJDK"; + private static final String version = "marlin-0.7.3-Unsafe-OpenJDK"; public static String getVersion() { return version; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLUtilities.java b/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLUtilities.java index 02f9b4cef29..601658b11f5 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLUtilities.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLUtilities.java @@ -81,7 +81,7 @@ class OGLUtilities { * * In order to avoid deadlock, it is important that the given Runnable * does not attempt to acquire the AWT lock, as that will be handled - * automatically as part of the rq.flushAndInvokeNow() step. + * automatically as part of the {@code rq.flushAndInvokeNow()} step. * * @param g the Graphics object for the corresponding destination surface; * if null, the step making a context current to the destination surface @@ -134,7 +134,7 @@ class OGLUtilities { * * In order to avoid deadlock, it is important that the given Runnable * does not attempt to acquire the AWT lock, as that will be handled - * automatically as part of the rq.flushAndInvokeNow() step. + * automatically as part of the {@code rq.flushAndInvokeNow()} step. * * @param config the GraphicsConfiguration object whose "shared" * context will be made current during this operation; if this value is @@ -297,7 +297,7 @@ class OGLUtilities { * @return a constant that describes the surface associated with the * given Graphics object; if the given Graphics object is invalid (i.e. * is not associated with an OpenGL surface) this method will return - * OGLUtilities.UNDEFINED + * {@code OGLUtilities.UNDEFINED} */ public static int getOGLSurfaceType(Graphics g) { if (!(g instanceof SunGraphics2D)) { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/DrawImage.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/DrawImage.java index a7e181e9d2a..728a5823e4d 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/DrawImage.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/DrawImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -955,6 +955,12 @@ public class DrawImage implements DrawImagePipe { comp = CompositeType.SrcNoEa; } + if (srcData == dstData && sx == dx && sy == dy + && CompositeType.SrcNoEa.equals(comp)) { + // Performance optimization. We skip the Blit/BlitBG if we know that + // it will be noop. + return; + } if (!isBgOperation(srcData, bgColor)) { Blit blit = Blit.getFromCache(srcType, comp, dstType); blit.Blit(srcData, dstData, sg.composite, clipRegion, diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/Region.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/Region.java index 723fdaaf97e..95a7aa46674 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/Region.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/Region.java @@ -104,11 +104,11 @@ public class Region { } /** - * Adds the dimension dim to the coordinate - * start with appropriate clipping. If - * dim is non-positive then the method returns + * Adds the dimension {@code dim} to the coordinate + * {@code start} with appropriate clipping. If + * {@code dim} is non-positive then the method returns * the start coordinate. If the sum overflows an integer - * data type then the method returns Integer.MAX_VALUE. + * data type then the method returns {@code Integer.MAX_VALUE}. */ public static int dimAdd(int start, int dim) { if (dim <= 0) return start; @@ -179,9 +179,9 @@ public class Region { * * @param s a non-null Shape object specifying the geometry enclosing * the pixels of interest - * @param at an optional AffineTransform to be applied to the + * @param at an optional {@code AffineTransform} to be applied to the * coordinates as they are returned in the iteration, or - * null if untransformed coordinates are desired + * {@code null} if untransformed coordinates are desired */ public static Region getInstance(Shape s, AffineTransform at) { return getInstance(WHOLE_REGION, false, s, at); @@ -205,9 +205,9 @@ public class Region { * clip the geometry to * @param s a non-null Shape object specifying the geometry enclosing * the pixels of interest - * @param at an optional AffineTransform to be applied to the + * @param at an optional {@code AffineTransform} to be applied to the * coordinates as they are returned in the iteration, or - * null if untransformed coordinates are desired + * {@code null} if untransformed coordinates are desired */ public static Region getInstance(Region devBounds, Shape s, AffineTransform at) @@ -238,9 +238,9 @@ public class Region { * normalization * @param s a non-null Shape object specifying the geometry enclosing * the pixels of interest - * @param at an optional AffineTransform to be applied to the + * @param at an optional {@code AffineTransform} to be applied to the * coordinates as they are returned in the iteration, or - * null if untransformed coordinates are desired + * {@code null} if untransformed coordinates are desired */ public static Region getInstance(Region devBounds, boolean normalize, Shape s, AffineTransform at) @@ -363,7 +363,7 @@ public class Region { * Sets the rectangle of interest for storing and returning * region bands. The rectangle is specified in x, y, width, height * format and appropriate clipping is performed as per the method - * dimAdd. + * {@code dimAdd}. *

          * This method can also be used to initialize a simple rectangular * region. @@ -637,7 +637,7 @@ public class Region { * object with the specified Region object. *

          * If {@code A} and {@code B} are both Region Objects and - * C = A.getIntersection(B); then a point will + * {@code C = A.getIntersection(B);} then a point will * be contained in {@code C} iff it is contained in both * {@code A} and {@code B}. *

          @@ -666,7 +666,7 @@ public class Region { * object with the specified Region object. *

          * If {@code A} and {@code B} are both Region Objects and - * C = A.getUnion(B); then a point will + * {@code C = A.getUnion(B);} then a point will * be contained in {@code C} iff it is contained in either * {@code A} or {@code B}. *

          @@ -693,7 +693,7 @@ public class Region { * specified Region object subtracted from this object. *

          * If {@code A} and {@code B} are both Region Objects and - * C = A.getDifference(B); then a point will + * {@code C = A.getDifference(B);} then a point will * be contained in {@code C} iff it is contained in * {@code A} but not contained in {@code B}. *

          @@ -717,7 +717,7 @@ public class Region { * object with the specified Region object. *

          * If {@code A} and {@code B} are both Region Objects and - * C = A.getExclusiveOr(B); then a point will + * {@code C = A.getExclusiveOr(B);} then a point will * be contained in {@code C} iff it is contained in either * {@code A} or {@code B}, but not if it is contained in both. *

          diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderQueue.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderQueue.java index f9dc262f17c..d33db33ec5c 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderQueue.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderQueue.java @@ -115,7 +115,7 @@ public abstract class RenderQueue { /** * Attempts to lock the queue. If successful, this method returns true, * indicating that the caller is responsible for calling - * unlock; otherwise this method returns false. + * {@code unlock}; otherwise this method returns false. */ public final boolean tryLock() { return SunToolkit.awtTryLock(); diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Dasher.java b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Dasher.java index 386e4ea4377..c7855d6b9e9 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Dasher.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Dasher.java @@ -28,9 +28,9 @@ package sun.java2d.pisces; import sun.awt.geom.PathConsumer2D; /** - * The Dasher class takes a series of linear commands - * (moveTo, lineTo, close and - * end) and breaks them into smaller segments according to a + * The {@code Dasher} class takes a series of linear commands + * ({@code moveTo}, {@code lineTo}, {@code close} and + * {@code end}) and breaks them into smaller segments according to a * dash pattern array and a starting dash phase. * *

          Issues: in J2Se, a zero length dash segment as drawn as a very @@ -60,11 +60,11 @@ final class Dasher implements sun.awt.geom.PathConsumer2D { private float[] curCurvepts; /** - * Constructs a Dasher. + * Constructs a {@code Dasher}. * - * @param out an output PathConsumer2D. - * @param dash an array of floats containing the dash pattern - * @param phase a float containing the dash phase + * @param out an output {@code PathConsumer2D}. + * @param dash an array of {@code float}s containing the dash pattern + * @param phase a {@code float} containing the dash phase */ public Dasher(PathConsumer2D out, float[] dash, float phase) { if (phase < 0) { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Helpers.java b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Helpers.java index 38a7fc2baf6..592348c0043 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Helpers.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Helpers.java @@ -239,18 +239,18 @@ final class Helpers { // QuadCurve2D don't provide them. /** * Subdivides the cubic curve specified by the coordinates - * stored in the src array at indices srcoff - * through (srcoff + 7) and stores the + * stored in the {@code src} array at indices {@code srcoff} + * through ({@code srcoff} + 7) and stores the * resulting two subdivided curves into the two result arrays at the * corresponding indices. - * Either or both of the left and right - * arrays may be null or a reference to the same array - * as the src array. + * Either or both of the {@code left} and {@code right} + * arrays may be {@code null} or a reference to the same array + * as the {@code src} array. * Note that the last point in the first subdivided curve is the * same as the first point in the second subdivided curve. Thus, - * it is possible to pass the same array for left - * and right and to use offsets, such as rightoff - * equals (leftoff + 6), in order + * it is possible to pass the same array for {@code left} + * and {@code right} and to use offsets, such as {@code rightoff} + * equals ({@code leftoff} + 6), in order * to avoid allocating extra storage for this common point. * @param src the array holding the coordinates for the source curve * @param srcoff the offset into the array of the beginning of the diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Stroker.java b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Stroker.java index 6d4a4c75ac5..4480286fae8 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Stroker.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pisces/Stroker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,16 +99,16 @@ final class Stroker implements PathConsumer2D { private final PolyStack reverse = new PolyStack(); /** - * Constructs a Stroker. + * Constructs a {@code Stroker}. * - * @param pc2d an output PathConsumer2D. + * @param pc2d an output {@code PathConsumer2D}. * @param lineWidth the desired line width in pixels * @param capStyle the desired end cap style, one of - * CAP_BUTT, CAP_ROUND or - * CAP_SQUARE. + * {@code CAP_BUTT}, {@code CAP_ROUND} or + * {@code CAP_SQUARE}. * @param joinStyle the desired line join style, one of - * JOIN_MITER, JOIN_ROUND or - * JOIN_BEVEL. + * {@code JOIN_MITER}, {@code JOIN_ROUND} or + * {@code JOIN_BEVEL}. * @param miterLimit the desired miter limit */ public Stroker(PathConsumer2D pc2d, @@ -193,11 +193,11 @@ final class Stroker implements PathConsumer2D { // The sign of the dot product of mx,my and omx,omy is equal to the // the sign of the cosine of ext // (ext is the angle between omx,omy and mx,my). - double cosext = omx * mx + omy * my; + final float cosext = omx * mx + omy * my; // If it is >=0, we know that abs(ext) is <= 90 degrees, so we only // need 1 curve to approximate the circle section that joins omx,omy // and mx,my. - final int numCurves = cosext >= 0 ? 1 : 2; + final int numCurves = (cosext >= 0f) ? 1 : 2; switch (numCurves) { case 1: @@ -242,14 +242,22 @@ final class Stroker implements PathConsumer2D { final float mx, final float my, boolean rev) { - float cosext2 = (omx * mx + omy * my) / (2 * lineWidth2 * lineWidth2); + final float cosext2 = (omx * mx + omy * my) / (2f * lineWidth2 * lineWidth2); + + // check round off errors producing cos(ext) > 1 and a NaN below + // cos(ext) == 1 implies colinear segments and an empty join anyway + if (cosext2 >= 0.5f) { + // just return to avoid generating a flat curve: + return; + } + // cv is the length of P1-P0 and P2-P3 divided by the radius of the arc // (so, cv assumes the arc has radius 1). P0, P1, P2, P3 are the points that // define the bezier curve we're computing. // It is computed using the constraints that P1-P0 and P3-P2 are parallel // to the arc tangents at the endpoints, and that |P1-P0|=|P3-P2|. - float cv = (float) ((4.0 / 3.0) * sqrt(0.5-cosext2) / - (1.0 + sqrt(cosext2+0.5))); + float cv = (float) ((4.0 / 3.0) * sqrt(0.5 - cosext2) / + (1.0 + sqrt(cosext2 + 0.5))); // if clockwise, we need to negate cv. if (rev) { // rev is equivalent to isCW(omx, omy, mx, my) cv = -cv; diff --git a/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java b/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java index a08c06bac58..3b29183e2f4 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java +++ b/jdk/src/java.desktop/share/classes/sun/print/DialogOwner.java @@ -82,7 +82,7 @@ public final class DialogOwner * instance. *

          * For class DialogOwner the category name is - * "dialog-owner". + * {@code "dialog-owner"}. * * @return Attribute category name. */ diff --git a/jdk/src/java.desktop/share/classes/sun/print/PSPathGraphics.java b/jdk/src/java.desktop/share/classes/sun/print/PSPathGraphics.java index 1b00d4b7851..2e4bea56f55 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PSPathGraphics.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PSPathGraphics.java @@ -72,8 +72,8 @@ class PSPathGraphics extends PathGraphics { } /** - * Creates a new Graphics object that is - * a copy of this Graphics object. + * Creates a new {@code Graphics} object that is + * a copy of this {@code Graphics} object. * @return a new graphics context that is a copy of * this graphics context. * @since 1.0 @@ -115,19 +115,19 @@ class PSPathGraphics extends PathGraphics { } /** - * Renders the text specified by the specified String, - * using the current Font and Paint attributes - * in the Graphics2D context. + * Renders the text specified by the specified {@code String}, + * using the current {@code Font} and {@code Paint} attributes + * in the {@code Graphics2D} context. * The baseline of the first character is at position * (xy) in the User Space. - * The rendering attributes applied include the Clip, - * Transform, Paint, Font and - * Composite attributes. For characters in script systems + * The rendering attributes applied include the {@code Clip}, + * {@code Transform}, {@code Paint}, {@code Font} and + * {@code Composite} attributes. For characters in script systems * such as Hebrew and Arabic, the glyphs can be rendered from right to * left, in which case the coordinate supplied is the location of the * leftmost character on the baseline. - * @param str the String to be rendered - * @param x, y the coordinates where the String + * @param str the {@code String} to be rendered + * @param x, y the coordinates where the {@code String} * should be rendered * @see #setPaint * @see java.awt.Graphics#setColor @@ -248,16 +248,16 @@ class PSPathGraphics extends PathGraphics { } /** - * The various drawImage() methods for - * WPathGraphics are all decomposed - * into an invocation of drawImageToPlatform. + * The various {@code drawImage()} methods for + * {@code WPathGraphics} are all decomposed + * into an invocation of {@code drawImageToPlatform}. * The portion of the passed in image defined by - * srcX, srcY, srcWidth, and srcHeight + * {@code srcX, srcY, srcWidth, and srcHeight} * is transformed by the supplied AffineTransform and * drawn using PS to the printer context. * * @param image The image to be drawn. - * This method does nothing if img is null. + * This method does nothing if {@code img} is null. * @param xform Used to transform the image before drawing. * This can be null. * @param bgcolor This color is drawn where the image has transparent @@ -730,7 +730,7 @@ class PSPathGraphics extends PathGraphics { /* - * Fill the path defined by pathIter + * Fill the path defined by {@code pathIter} * with the specified color. * The path is provided in current user space. */ diff --git a/jdk/src/java.desktop/share/classes/sun/print/PSPrinterJob.java b/jdk/src/java.desktop/share/classes/sun/print/PSPrinterJob.java index ad30841d0a7..b22fe72880d 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PSPrinterJob.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PSPrinterJob.java @@ -116,14 +116,14 @@ public class PSPrinterJob extends RasterPrinterJob { /* Class Constants */ /** - * Passed to the setFillMode + * Passed to the {@code setFillMode} * method this value forces fills to be * done using the even-odd fill rule. */ protected static final int FILL_EVEN_ODD = 1; /** - * Passed to the setFillMode + * Passed to the {@code setFillMode} * method this value forces fills to be * done using the non-zero winding rule. */ @@ -294,14 +294,14 @@ public class PSPrinterJob extends RasterPrinterJob { /** * This string holds the PostScript operator to * be used to fill a path. It can be changed - * by the setFillMode method. + * by the {@code setFillMode} method. */ private String mFillOpStr = WINDING_FILL_STR; /** * This string holds the PostScript operator to * be used to clip to a path. It can be changed - * by the setFillMode method. + * by the {@code setFillMode} method. */ private String mClipOpStr = WINDING_CLIP_STR; @@ -876,14 +876,14 @@ public class PSPrinterJob extends RasterPrinterJob { /** * Convert the 24 bit BGR image buffer represented by - * image to PostScript. The image is drawn at - * (destX, destY) in device coordinates. + * {@code image} to PostScript. The image is drawn at + * {@code (destX, destY)} in device coordinates. * The image is scaled into a square of size - * specified by destWidth and - * destHeight. The portion of the + * specified by {@code destWidth} and + * {@code destHeight}. The portion of the * source image copied into that square is specified - * by srcX, srcY, - * srcWidth, and srcHeight. + * by {@code srcX}, {@code srcY}, + * {@code srcWidth}, and srcHeight. */ protected void drawImageBGR(byte[] bgrData, float destX, float destY, @@ -1026,14 +1026,14 @@ public class PSPrinterJob extends RasterPrinterJob { /** * Examine the metrics captured by the - * PeekGraphics instance and + * {@code PeekGraphics} instance and * if capable of directly converting this * print job to the printer's control language * or the native OS's graphics primitives, then - * return a PSPathGraphics to perform + * return a {@code PSPathGraphics} to perform * that conversion. If there is not an object * capable of the conversion then return - * null. Returning null + * {@code null}. Returning {@code null} * causes the print job to be rasterized. */ @@ -1349,8 +1349,8 @@ public class PSPrinterJob extends RasterPrinterJob { } /** * Set the current path rule to be either - * FILL_EVEN_ODD (using the - * even-odd file rule) or FILL_WINDING + * {@code FILL_EVEN_ODD} (using the + * even-odd file rule) or {@code FILL_WINDING} * (using the non-zero winding rule.) */ protected void setFillMode(int fillRule) { @@ -1375,7 +1375,7 @@ public class PSPrinterJob extends RasterPrinterJob { /** * Set the printer's current color to be that - * defined by color + * defined by {@code color} */ protected void setColor(Color color) { mLastColor = color; @@ -1418,7 +1418,7 @@ public class PSPrinterJob extends RasterPrinterJob { /** * Generate PostScript to move the current pen - * position to (x, y). + * position to {@code (x, y)}. */ protected void moveTo(float x, float y) { @@ -1437,7 +1437,7 @@ public class PSPrinterJob extends RasterPrinterJob { } /** * Generate PostScript to draw a line from the - * current pen position to (x, y). + * current pen position to {@code (x, y)}. */ protected void lineTo(float x, float y) { @@ -1861,7 +1861,7 @@ public class PSPrinterJob extends RasterPrinterJob { } /** - * Given a Java2D PathIterator instance, + * Given a Java2D {@code PathIterator} instance, * this method translates that into a PostScript path.. */ void convertToPSPath(PathIterator pathIter) { @@ -1926,7 +1926,7 @@ public class PSPrinterJob extends RasterPrinterJob { } /* - * Fill the path defined by pathIter + * Fill the path defined by {@code pathIter} * with the specified color. * The path is provided in current user space. */ diff --git a/jdk/src/java.desktop/share/classes/sun/print/PathGraphics.java b/jdk/src/java.desktop/share/classes/sun/print/PathGraphics.java index 467ed39fe9d..c36f8cb9f78 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PathGraphics.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PathGraphics.java @@ -177,9 +177,9 @@ public abstract class PathGraphics extends ProxyGraphics2D { /** * Draws the outline of the specified rectangle. * The left and right edges of the rectangle are at - * x and x + width. + * {@code x} and x + width. * The top and bottom edges are at - * y and y + height. + * {@code y} and y + height. * The rectangle is drawn using the graphics context's current color. * @param x the x coordinate * of the rectangle to be drawn. @@ -211,12 +211,12 @@ public abstract class PathGraphics extends ProxyGraphics2D { /** * Fills the specified rectangle. * The left and right edges of the rectangle are at - * x and x + width - 1. + * {@code x} and x + width - 1. * The top and bottom edges are at - * y and y + height - 1. + * {@code y} and y + height - 1. * The resulting rectangle covers an area - * width pixels wide by - * height pixels tall. + * {@code width} pixels wide by + * {@code height} pixels tall. * The rectangle is filled using the graphics context's current color. * @param x the x coordinate * of the rectangle to be filled. @@ -251,7 +251,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { *

          * Beginning with Java 1.1, the background color * of offscreen images may be system dependent. Applications should - * use setColor followed by fillRect to + * use {@code setColor} followed by {@code fillRect} to * ensure that an offscreen image is cleared to a specific color. * @param x the x coordinate of the rectangle to clear. * @param y the y coordinate of the rectangle to clear. @@ -271,9 +271,9 @@ public abstract class PathGraphics extends ProxyGraphics2D { /** * Draws an outlined round-cornered rectangle using this graphics * context's current color. The left and right edges of the rectangle - * are at x and x + width, + * are at {@code x} and x + width, * respectively. The top and bottom edges of the rectangle are at - * y and y + height. + * {@code y} and y + height. * @param x the x coordinate of the rectangle to be drawn. * @param y the y coordinate of the rectangle to be drawn. * @param width the width of the rectangle to be drawn. @@ -296,9 +296,9 @@ public abstract class PathGraphics extends ProxyGraphics2D { /** * Fills the specified rounded corner rectangle with the current color. * The left and right edges of the rectangle - * are at x and x + width - 1, + * are at {@code x} and x + width - 1, * respectively. The top and bottom edges of the rectangle are at - * y and y + height - 1. + * {@code y} and y + height - 1. * @param x the x coordinate of the rectangle to be filled. * @param y the y coordinate of the rectangle to be filled. * @param width the width of the rectangle to be filled. @@ -320,8 +320,8 @@ public abstract class PathGraphics extends ProxyGraphics2D { /** * Draws the outline of an oval. * The result is a circle or ellipse that fits within the - * rectangle specified by the x, y, - * width, and height arguments. + * rectangle specified by the {@code x}, {@code y}, + * {@code width}, and {@code height} arguments. *

          * The oval covers an area that is * width + 1 pixels wide @@ -359,8 +359,8 @@ public abstract class PathGraphics extends ProxyGraphics2D { * Draws the outline of a circular or elliptical arc * covering the specified rectangle. *

          - * The resulting arc begins at startAngle and extends - * for arcAngle degrees, using the current color. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees, using the current color. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -368,7 +368,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { *

          * The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

          * The resulting arc covers an area * width + 1 pixels wide @@ -403,8 +403,8 @@ public abstract class PathGraphics extends ProxyGraphics2D { /** * Fills a circular or elliptical arc covering the specified rectangle. *

          - * The resulting arc begins at startAngle and extends - * for arcAngle degrees. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -412,7 +412,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { *

          * The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

          * The resulting arc covers an area * width + 1 pixels wide @@ -478,16 +478,16 @@ public abstract class PathGraphics extends ProxyGraphics2D { * arrays of x and y coordinates. * Each pair of (xy) coordinates defines a point. *

          - * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#fillPolygon * @see java.awt.Graphics#drawPolyline @@ -500,7 +500,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { /** * Draws the outline of a polygon defined by the specified - * Polygon object. + * {@code Polygon} object. * @param p the polygon to draw. * @see java.awt.Graphics#fillPolygon * @see java.awt.Graphics#drawPolyline @@ -513,19 +513,19 @@ public abstract class PathGraphics extends ProxyGraphics2D { * Fills a closed polygon defined by * arrays of x and y coordinates. *

          - * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. *

          * The area inside the polygon is defined using an * even-odd fill rule, also known as the alternating rule. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#drawPolygon(int[], int[], int) */ @@ -1089,7 +1089,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { } /** - * Fill the path defined by pathIter + * Fill the path defined by {@code pathIter} * with the specified color. * The path is provided in device coordinates. */ @@ -1097,7 +1097,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { /* * Set the clipping path to that defined by - * the passed in PathIterator. + * the passed in {@code PathIterator}. */ protected abstract void deviceClip(PathIterator pathIter); @@ -1326,16 +1326,16 @@ public abstract class PathGraphics extends ProxyGraphics2D { /** - * The various drawImage() methods for - * PathGraphics are all decomposed - * into an invocation of drawImageToPlatform. + * The various {@code drawImage()} methods for + * {@code PathGraphics} are all decomposed + * into an invocation of {@code drawImageToPlatform}. * The portion of the passed in image defined by - * srcX, srcY, srcWidth, and srcHeight + * {@code srcX, srcY, srcWidth, and srcHeight} * is transformed by the supplied AffineTransform and * drawn using PS to the printer context. * * @param img The image to be drawn. - * This method does nothing if img is null. + * This method does nothing if {@code img} is null. * @param xform Used to transform the image before drawing. * This can be null. * @param bgcolor This color is drawn where the image has transparent @@ -1373,7 +1373,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { * and converted for the current output device. *

          * If the image has not yet been completely loaded, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. * @param img the specified image to be drawn. @@ -1405,9 +1405,9 @@ public abstract class PathGraphics extends ProxyGraphics2D { * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies - * the image observer by calling its imageUpdate method. + * the image observer by calling its {@code imageUpdate} method. *

          * A scaled version of an image will not necessarily be * available immediately just because an unscaled version of the @@ -1450,11 +1450,11 @@ public abstract class PathGraphics extends ProxyGraphics2D { * and converted for the current output device. *

          * If the image has not yet been completely loaded, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. * @param img the specified image to be drawn. - * This method does nothing if img is null. + * This method does nothing if {@code img} is null. * @param x the x coordinate. * @param y the y coordinate. * @param bgcolor the background color to paint under the @@ -1507,7 +1507,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1517,7 +1517,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { * the image may be cached separately and generated from the original * data in a separate image production sequence. * @param img the specified image to be drawn. - * This method does nothing if img is null. + * This method does nothing if {@code img} is null. * @param x the x coordinate. * @param y the y coordinate. * @param width the width of the rectangle. @@ -1566,7 +1566,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1628,7 +1628,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1642,7 +1642,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { * mapped to the second destination coordinate. The subimage is * scaled and flipped as needed to preserve those mappings. * @param img the specified image to be drawn - * This method does nothing if img is null. + * This method does nothing if {@code img} is null. * @param dx1 the x coordinate of the first corner of the * destination rectangle. * @param dy1 the y coordinate of the first corner of the @@ -1767,7 +1767,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { * and composite attributes. Note that the result is * undefined, if the given transform is noninvertible. * @param img The image to be drawn. - * This method does nothing if img is null. + * This method does nothing if {@code img} is null. * @param xform The transformation from image space into user space. * @param obs The image observer to be notified as more of the image * is converted. @@ -1809,7 +1809,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { * * @param op The filter to be applied to the image before drawing. * @param img The BufferedImage to be drawn. - * This method does nothing if img is null. + * This method does nothing if {@code img} is null. * @param x,y The location in user space where the image should be drawn. * @see #transform * @see #setTransform @@ -1853,7 +1853,7 @@ public abstract class PathGraphics extends ProxyGraphics2D { * and composite attributes. Note that the result is * undefined, if the given transform is noninvertible. * @param img The image to be drawn. - * This method does nothing if img is null. + * This method does nothing if {@code img} is null. * @param xform The transformation from image space into user space. * @see #transform * @see #setTransform diff --git a/jdk/src/java.desktop/share/classes/sun/print/PeekGraphics.java b/jdk/src/java.desktop/share/classes/sun/print/PeekGraphics.java index 0e33bf191eb..b76321d84a3 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PeekGraphics.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PeekGraphics.java @@ -162,8 +162,8 @@ public class PeekGraphics extends Graphics2D /* The Delegated Graphics Methods */ /** - * Creates a new Graphics object that is - * a copy of this Graphics object. + * Creates a new {@code Graphics} object that is + * a copy of this {@code Graphics} object. * @return a new graphics context that is a copy of * this graphics context. * @since 1.0 @@ -444,7 +444,7 @@ public class PeekGraphics extends Graphics2D /** * Gets the current clipping area. - * @return a Shape object representing the + * @return a {@code Shape} object representing the * current clipping area. * @see java.awt.Graphics#getClipBounds * @see java.awt.Graphics#clipRect @@ -459,12 +459,12 @@ public class PeekGraphics extends Graphics2D /** * Sets the current clipping area to an arbitrary clip shape. - * Not all objects which implement the Shape + * Not all objects which implement the {@code Shape} * interface can be used to set the clip. The only - * Shape objects which are guaranteed to be - * supported are Shape objects which are - * obtained via the getClip method and via - * Rectangle objects. + * {@code Shape} objects which are guaranteed to be + * supported are {@code Shape} objects which are + * obtained via the {@code getClip} method and via + * {@code Rectangle} objects. * @see java.awt.Graphics#getClip() * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(int, int, int, int) @@ -477,16 +477,16 @@ public class PeekGraphics extends Graphics2D /** * Copies an area of the component by a distance specified by - * dx and dy. From the point specified - * by x and y, this method + * {@code dx} and {@code dy}. From the point specified + * by {@code x} and {@code y}, this method * copies downwards and to the right. To copy an area of the * component to the left or upwards, specify a negative value for - * dx or dy. + * {@code dx} or {@code dy}. * If a portion of the source rectangle lies outside the bounds * of the component, or is obscured by another window or component, - * copyArea will be unable to copy the associated + * {@code copyArea} will be unable to copy the associated * pixels. The area that is omitted can be refreshed by calling - * the component's paint method. + * the component's {@code paint} method. * @param x the x coordinate of the source rectangle. * @param y the y coordinate of the source rectangle. * @param width the width of the source rectangle. @@ -520,12 +520,12 @@ public class PeekGraphics extends Graphics2D /** * Fills the specified rectangle. * The left and right edges of the rectangle are at - * x and x + width - 1. + * {@code x} and x + width - 1. * The top and bottom edges are at - * y and y + height - 1. + * {@code y} and y + height - 1. * The resulting rectangle covers an area - * width pixels wide by - * height pixels tall. + * {@code width} pixels wide by + * {@code height} pixels tall. * The rectangle is filled using the graphics context's current color. * @param x the x coordinate * of the rectangle to be filled. @@ -551,7 +551,7 @@ public class PeekGraphics extends Graphics2D *

          * Beginning with Java 1.1, the background color * of offscreen images may be system dependent. Applications should - * use setColor followed by fillRect to + * use {@code setColor} followed by {@code fillRect} to * ensure that an offscreen image is cleared to a specific color. * @param x the x coordinate of the rectangle to clear. * @param y the y coordinate of the rectangle to clear. @@ -573,9 +573,9 @@ public class PeekGraphics extends Graphics2D /** * Draws an outlined round-cornered rectangle using this graphics * context's current color. The left and right edges of the rectangle - * are at x and x + width, + * are at {@code x} and x + width, * respectively. The top and bottom edges of the rectangle are at - * y and y + height. + * {@code y} and y + height. * @param x the x coordinate of the rectangle to be drawn. * @param y the y coordinate of the rectangle to be drawn. * @param width the width of the rectangle to be drawn. @@ -597,9 +597,9 @@ public class PeekGraphics extends Graphics2D /** * Fills the specified rounded corner rectangle with the current color. * The left and right edges of the rectangle - * are at x and x + width - 1, + * are at {@code x} and x + width - 1, * respectively. The top and bottom edges of the rectangle are at - * y and y + height - 1. + * {@code y} and y + height - 1. * @param x the x coordinate of the rectangle to be filled. * @param y the y coordinate of the rectangle to be filled. * @param width the width of the rectangle to be filled. @@ -621,8 +621,8 @@ public class PeekGraphics extends Graphics2D /** * Draws the outline of an oval. * The result is a circle or ellipse that fits within the - * rectangle specified by the x, y, - * width, and height arguments. + * rectangle specified by the {@code x}, {@code y}, + * {@code width}, and {@code height} arguments. *

          * The oval covers an area that is * width + 1 pixels wide @@ -665,8 +665,8 @@ public class PeekGraphics extends Graphics2D * Draws the outline of a circular or elliptical arc * covering the specified rectangle. *

          - * The resulting arc begins at startAngle and extends - * for arcAngle degrees, using the current color. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees, using the current color. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -674,7 +674,7 @@ public class PeekGraphics extends Graphics2D *

          * The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

          * The resulting arc covers an area * width + 1 pixels wide @@ -701,8 +701,8 @@ public class PeekGraphics extends Graphics2D /** * Fills a circular or elliptical arc covering the specified rectangle. *

          - * The resulting arc begins at startAngle and extends - * for arcAngle degrees. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -710,7 +710,7 @@ public class PeekGraphics extends Graphics2D *

          * The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

          * The resulting arc covers an area * width + 1 pixels wide @@ -767,16 +767,16 @@ public class PeekGraphics extends Graphics2D * arrays of x and y coordinates. * Each pair of (xy) coordinates defines a point. *

          - * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#fillPolygon * @see java.awt.Graphics#drawPolyline @@ -796,19 +796,19 @@ public class PeekGraphics extends Graphics2D * Fills a closed polygon defined by * arrays of x and y coordinates. *

          - * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. *

          * The area inside the polygon is defined using an * even-odd fill rule, also known as the alternating rule. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#drawPolygon(int[], int[], int) * @since 1.0 @@ -931,7 +931,7 @@ public class PeekGraphics extends Graphics2D * and converted for the current output device. *

          * If the image has not yet been completely loaded, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. * @param img the specified image to be drawn. @@ -976,9 +976,9 @@ public class PeekGraphics extends Graphics2D * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies - * the image observer by calling its imageUpdate method. + * the image observer by calling its {@code imageUpdate} method. *

          * A scaled version of an image will not necessarily be * available immediately just because an unscaled version of the @@ -1027,7 +1027,7 @@ public class PeekGraphics extends Graphics2D * and converted for the current output device. *

          * If the image has not yet been completely loaded, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. * @param img the specified image to be drawn. @@ -1078,7 +1078,7 @@ public class PeekGraphics extends Graphics2D * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1127,7 +1127,7 @@ public class PeekGraphics extends Graphics2D * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1199,7 +1199,7 @@ public class PeekGraphics extends Graphics2D * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1304,10 +1304,10 @@ public class PeekGraphics extends Graphics2D /** * Disposes of this graphics context and releases * any system resources that it is using. - * A Graphics object cannot be used after - * disposehas been called. + * A {@code Graphics} object cannot be used after + * {@code dispose} has been called. *

          - * When a Java program runs, a large number of Graphics + * When a Java program runs, a large number of {@code Graphics} * objects can be created within a short time frame. * Although the finalization process of the garbage collector * also disposes of the same system resources, it is preferable @@ -1316,12 +1316,12 @@ public class PeekGraphics extends Graphics2D * may not run to completion for a long period of time. *

          * Graphics objects which are provided as arguments to the - * paint and update methods + * {@code paint} and {@code update} methods * of components are automatically released by the system when * those methods return. For efficiency, programmers should - * call dispose when finished using - * a Graphics object only if it was created - * directly from a component or another Graphics object. + * call {@code dispose} when finished using + * a {@code Graphics} object only if it was created + * directly from a component or another {@code Graphics} object. * @see java.awt.Graphics#finalize * @see java.awt.Component#paint * @see java.awt.Component#update @@ -1735,7 +1735,7 @@ public class PeekGraphics extends Graphics2D } /** - * Return true if the Rectangle rect + * Return true if the Rectangle {@code rect} * intersects the area into which the application * has drawn. */ diff --git a/jdk/src/java.desktop/share/classes/sun/print/PeekMetrics.java b/jdk/src/java.desktop/share/classes/sun/print/PeekMetrics.java index 9b5aae6899d..7f023f30d1d 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PeekMetrics.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PeekMetrics.java @@ -52,9 +52,9 @@ public class PeekMetrics { private boolean mHasImages; /** - * Return true if the application + * Return {@code true} if the application * has done any drawing with a Paint that - * is not an instance of Color + * is not an instance of {@code Color} */ public boolean hasNonSolidColors() { return mHasNonSolidColors; @@ -119,7 +119,7 @@ public class PeekMetrics { /** * The application is drawing text - * defined by TextLayout + * defined by {@code TextLayout} * so record the needed information. */ public void drawText(Graphics2D g, TextLayout textLayout) { @@ -164,7 +164,7 @@ public class PeekMetrics { /** * Record information about drawing done - * with the supplied Paint. + * with the supplied {@code Paint}. */ private void checkPaint(Paint paint) { @@ -179,7 +179,7 @@ public class PeekMetrics { /** * Record information about drawing done - * with the supplied Composite. + * with the supplied {@code Composite}. */ private void checkAlpha(Composite composite) { diff --git a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java index 9b7de159322..975e52ab86d 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java @@ -928,23 +928,23 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { /** * Prints the page at the specified index into the specified * {@link Graphics} context in the specified - * format. A PrinterJob calls the - * Printable interface to request that a page be + * format. A {@code PrinterJob} calls the + * {@code Printable} interface to request that a page be * rendered into the context specified by - * graphics. The format of the page to be drawn is - * specified by pageFormat. The zero based index - * of the requested page is specified by pageIndex. + * {@code graphics}. The format of the page to be drawn is + * specified by {@code pageFormat}. The zero based index + * of the requested page is specified by {@code pageIndex}. * If the requested page does not exist then this method returns * NO_SUCH_PAGE; otherwise PAGE_EXISTS is returned. - * The Graphics class or subclass implements the + * The {@code Graphics} class or subclass implements the * {@link java.awt.PrintGraphics} interface to provide additional - * information. If the Printable object + * information. If the {@code Printable} object * aborts the print job then it throws a {@link PrinterException}. * @param graphics the context into which the page is drawn * @param pageFormat the size and orientation of the page being drawn * @param pageIndex the zero based index of the page to be drawn * @return PAGE_EXISTS if the page is rendered successfully - * or NO_SUCH_PAGE if pageIndex specifies a + * or NO_SUCH_PAGE if {@code pageIndex} specifies a * non-existent page. * @exception java.awt.print.PrinterException * thrown when the print job is terminated. diff --git a/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics.java b/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics.java index 9bb3bd254c1..eefb49ee75a 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics.java +++ b/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics.java @@ -63,8 +63,8 @@ public class ProxyGraphics extends Graphics { } /** - * Creates a new Graphics object that is - * a copy of this Graphics object. + * Creates a new {@code Graphics} object that is + * a copy of this {@code Graphics} object. * @return a new graphics context that is a copy of * this graphics context. */ @@ -73,28 +73,28 @@ public class ProxyGraphics extends Graphics { } /** - * Creates a new Graphics object based on this - * Graphics object, but with a new translation and clip area. - * The new Graphics object has its origin + * Creates a new {@code Graphics} object based on this + * {@code Graphics} object, but with a new translation and clip area. + * The new {@code Graphics} object has its origin * translated to the specified point (xy). * Its clip area is determined by the intersection of the original * clip area with the specified rectangle. The arguments are all * interpreted in the coordinate system of the original - * Graphics object. The new graphics context is + * {@code Graphics} object. The new graphics context is * identical to the original, except in two respects: *

          *

            *
          • * The new graphics context is translated by (xy). - * That is to say, the point (00) in the + * That is to say, the point ({@code 0}, {@code 0}) in the * new graphics context is the same as (xy) in * the original graphics context. *
          • * The new graphics context has an additional clipping rectangle, in * addition to whatever (translated) clipping rectangle it inherited * from the original graphics context. The origin of the new clipping - * rectangle is at (00), and its size - * is specified by the width and height + * rectangle is at ({@code 0}, {@code 0}), and its size + * is specified by the {@code width} and {@code height} * arguments. *
          *

          @@ -231,12 +231,12 @@ public class ProxyGraphics extends Graphics { * This method refers to the user clip, which is independent of the * clipping associated with device bounds and window visibility. * If no clip has previously been set, or if the clip has been - * cleared using setClip(null), this method returns - * null. + * cleared using {@code setClip(null)}, this method returns + * {@code null}. * The coordinates in the rectangle are relative to the coordinate * system origin of this graphics context. * @return the bounding rectangle of the current clipping area, - * or null if no clip is set. + * or {@code null} if no clip is set. * @see java.awt.Graphics#getClip * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(int, int, int, int) @@ -252,7 +252,7 @@ public class ProxyGraphics extends Graphics { * The resulting clipping area is the intersection of the current * clipping area and the specified rectangle. If there is no * current clipping area, either because the clip has never been - * set, or the clip has been cleared using setClip(null), + * set, or the clip has been cleared using {@code setClip(null)}, * the specified rectangle becomes the new clip. * This method sets the user clip, which is independent of the * clipping associated with device bounds and window visibility. @@ -293,10 +293,10 @@ public class ProxyGraphics extends Graphics { * This method returns the user clip, which is independent of the * clipping associated with device bounds and window visibility. * If no clip has previously been set, or if the clip has been - * cleared using setClip(null), this method returns - * null. - * @return a Shape object representing the - * current clipping area, or null if + * cleared using {@code setClip(null)}, this method returns + * {@code null}. + * @return a {@code Shape} object representing the + * current clipping area, or {@code null} if * no clip is set. * @see java.awt.Graphics#getClipBounds * @see java.awt.Graphics#clipRect @@ -310,15 +310,15 @@ public class ProxyGraphics extends Graphics { /** * Sets the current clipping area to an arbitrary clip shape. - * Not all objects that implement the Shape + * Not all objects that implement the {@code Shape} * interface can be used to set the clip. The only - * Shape objects that are guaranteed to be - * supported are Shape objects that are - * obtained via the getClip method and via - * Rectangle objects. This method sets the + * {@code Shape} objects that are guaranteed to be + * supported are {@code Shape} objects that are + * obtained via the {@code getClip} method and via + * {@code Rectangle} objects. This method sets the * user clip, which is independent of the clipping associated * with device bounds and window visibility. - * @param clip the Shape to use to set the clip + * @param clip the {@code Shape} to use to set the clip * @see java.awt.Graphics#getClip() * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(int, int, int, int) @@ -330,16 +330,16 @@ public class ProxyGraphics extends Graphics { /** * Copies an area of the component by a distance specified by - * dx and dy. From the point specified - * by x and y, this method + * {@code dx} and {@code dy}. From the point specified + * by {@code x} and {@code y}, this method * copies downwards and to the right. To copy an area of the * component to the left or upwards, specify a negative value for - * dx or dy. + * {@code dx} or {@code dy}. * If a portion of the source rectangle lies outside the bounds * of the component, or is obscured by another window or component, - * copyArea will be unable to copy the associated + * {@code copyArea} will be unable to copy the associated * pixels. The area that is omitted can be refreshed by calling - * the component's paint method. + * the component's {@code paint} method. * @param x the x coordinate of the source rectangle. * @param y the y coordinate of the source rectangle. * @param width the width of the source rectangle. @@ -368,12 +368,12 @@ public class ProxyGraphics extends Graphics { /** * Fills the specified rectangle. * The left and right edges of the rectangle are at - * x and x + width - 1. + * {@code x} and x + width - 1. * The top and bottom edges are at - * y and y + height - 1. + * {@code y} and y + height - 1. * The resulting rectangle covers an area - * width pixels wide by - * height pixels tall. + * {@code width} pixels wide by + * {@code height} pixels tall. * The rectangle is filled using the graphics context's current color. * @param x the x coordinate * of the rectangle to be filled. @@ -391,9 +391,9 @@ public class ProxyGraphics extends Graphics { /** * Draws the outline of the specified rectangle. * The left and right edges of the rectangle are at - * x and x + width. + * {@code x} and x + width. * The top and bottom edges are at - * y and y + height. + * {@code y} and y + height. * The rectangle is drawn using the graphics context's current color. * @param x the x coordinate * of the rectangle to be drawn. @@ -415,7 +415,7 @@ public class ProxyGraphics extends Graphics { *

          * Beginning with Java 1.1, the background color * of offscreen images may be system dependent. Applications should - * use setColor followed by fillRect to + * use {@code setColor} followed by {@code fillRect} to * ensure that an offscreen image is cleared to a specific color. * @param x the x coordinate of the rectangle to clear. * @param y the y coordinate of the rectangle to clear. @@ -434,9 +434,9 @@ public class ProxyGraphics extends Graphics { /** * Draws an outlined round-cornered rectangle using this graphics * context's current color. The left and right edges of the rectangle - * are at x and x + width, + * are at {@code x} and x + width, * respectively. The top and bottom edges of the rectangle are at - * y and y + height. + * {@code y} and y + height. * @param x the x coordinate of the rectangle to be drawn. * @param y the y coordinate of the rectangle to be drawn. * @param width the width of the rectangle to be drawn. @@ -455,9 +455,9 @@ public class ProxyGraphics extends Graphics { /** * Fills the specified rounded corner rectangle with the current color. * The left and right edges of the rectangle - * are at x and x + width - 1, + * are at {@code x} and x + width - 1, * respectively. The top and bottom edges of the rectangle are at - * y and y + height - 1. + * {@code y} and y + height - 1. * @param x the x coordinate of the rectangle to be filled. * @param y the y coordinate of the rectangle to be filled. * @param width the width of the rectangle to be filled. @@ -520,8 +520,8 @@ public class ProxyGraphics extends Graphics { /** * Draws the outline of an oval. * The result is a circle or ellipse that fits within the - * rectangle specified by the x, y, - * width, and height arguments. + * rectangle specified by the {@code x}, {@code y}, + * {@code width}, and {@code height} arguments. *

          * The oval covers an area that is * width + 1 pixels wide @@ -557,8 +557,8 @@ public class ProxyGraphics extends Graphics { * Draws the outline of a circular or elliptical arc * covering the specified rectangle. *

          - * The resulting arc begins at startAngle and extends - * for arcAngle degrees, using the current color. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees, using the current color. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -566,7 +566,7 @@ public class ProxyGraphics extends Graphics { *

          * The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

          * The resulting arc covers an area * width + 1 pixels wide @@ -598,8 +598,8 @@ public class ProxyGraphics extends Graphics { /** * Fills a circular or elliptical arc covering the specified rectangle. *

          - * The resulting arc begins at startAngle and extends - * for arcAngle degrees. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -607,7 +607,7 @@ public class ProxyGraphics extends Graphics { *

          * The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

          * The resulting arc covers an area * width + 1 pixels wide @@ -659,16 +659,16 @@ public class ProxyGraphics extends Graphics { * arrays of x and y coordinates. * Each pair of (xy) coordinates defines a point. *

          - * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#fillPolygon * @see java.awt.Graphics#drawPolyline @@ -680,7 +680,7 @@ public class ProxyGraphics extends Graphics { /** * Draws the outline of a polygon defined by the specified - * Polygon object. + * {@code Polygon} object. * @param p the polygon to draw. * @see java.awt.Graphics#fillPolygon * @see java.awt.Graphics#drawPolyline @@ -693,19 +693,19 @@ public class ProxyGraphics extends Graphics { * Fills a closed polygon defined by * arrays of x and y coordinates. *

          - * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. *

          * The area inside the polygon is defined using an * even-odd fill rule, also known as the alternating rule. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#drawPolygon(int[], int[], int) */ @@ -805,7 +805,7 @@ public class ProxyGraphics extends Graphics { * and converted for the current output device. *

          * If the image has not yet been completely loaded, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. * @param img the specified image to be drawn. @@ -835,9 +835,9 @@ public class ProxyGraphics extends Graphics { * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies - * the image observer by calling its imageUpdate method. + * the image observer by calling its {@code imageUpdate} method. *

          * A scaled version of an image will not necessarily be * available immediately just because an unscaled version of the @@ -877,7 +877,7 @@ public class ProxyGraphics extends Graphics { * and converted for the current output device. *

          * If the image has not yet been completely loaded, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. * @param img the specified image to be drawn. @@ -913,7 +913,7 @@ public class ProxyGraphics extends Graphics { * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -953,7 +953,7 @@ public class ProxyGraphics extends Graphics { * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1014,7 +1014,7 @@ public class ProxyGraphics extends Graphics { * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1068,10 +1068,10 @@ public class ProxyGraphics extends Graphics { /** * Disposes of this graphics context and releases * any system resources that it is using. - * A Graphics object cannot be used after - * disposehas been called. + * A {@code Graphics} object cannot be used after + * {@code dispose} has been called. *

          - * When a Java program runs, a large number of Graphics + * When a Java program runs, a large number of {@code Graphics} * objects can be created within a short time frame. * Although the finalization process of the garbage collector * also disposes of the same system resources, it is preferable @@ -1080,12 +1080,12 @@ public class ProxyGraphics extends Graphics { * may not run to completion for a long period of time. *

          * Graphics objects which are provided as arguments to the - * paint and update methods + * {@code paint} and {@code update} methods * of components are automatically released by the system when * those methods return. For efficiency, programmers should - * call dispose when finished using - * a Graphics object only if it was created - * directly from a component or another Graphics object. + * call {@code dispose} when finished using + * a {@code Graphics} object only if it was created + * directly from a component or another {@code Graphics} object. * @see java.awt.Graphics#finalize * @see java.awt.Component#paint * @see java.awt.Component#update @@ -1103,8 +1103,8 @@ public class ProxyGraphics extends Graphics { } /** - * Returns a String object representing this - * Graphics object's value. + * Returns a {@code String} object representing this + * {@code Graphics} object's value. * @return a string representation of this graphics context. */ public String toString() { @@ -1113,7 +1113,7 @@ public class ProxyGraphics extends Graphics { /** * @deprecated As of JDK version 1.1, - * replaced by getClipBounds(). + * replaced by {@code getClipBounds()}. */ @Deprecated public Rectangle getClipRect() { @@ -1144,8 +1144,8 @@ public class ProxyGraphics extends Graphics { * This method refers to the user clip, which is independent of the * clipping associated with device bounds and window visibility. * If no clip has previously been set, or if the clip has been - * cleared using setClip(null), this method returns the - * specified Rectangle. + * cleared using {@code setClip(null)}, this method returns the + * specified {@code Rectangle}. * @param r the rectangle where the current clipping area is * copied to. Any current values in this rectangle are * overwritten. diff --git a/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java b/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java index 57f8ec876b3..6ded8e98eab 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java +++ b/jdk/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java @@ -111,8 +111,8 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /* The Delegated Graphics Methods */ /** - * Creates a new Graphics object that is - * a copy of this Graphics object. + * Creates a new {@code Graphics} object that is + * a copy of this {@code Graphics} object. * @return a new graphics context that is a copy of * this graphics context. * @since 1.0 @@ -380,7 +380,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Gets the current clipping area. - * @return a Shape object representing the + * @return a {@code Shape} object representing the * current clipping area. * @see java.awt.Graphics#getClipBounds * @see java.awt.Graphics#clipRect @@ -395,12 +395,12 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Sets the current clipping area to an arbitrary clip shape. - * Not all objects which implement the Shape + * Not all objects which implement the {@code Shape} * interface can be used to set the clip. The only - * Shape objects which are guaranteed to be - * supported are Shape objects which are - * obtained via the getClip method and via - * Rectangle objects. + * {@code Shape} objects which are guaranteed to be + * supported are {@code Shape} objects which are + * obtained via the {@code getClip} method and via + * {@code Rectangle} objects. * @see java.awt.Graphics#getClip() * @see java.awt.Graphics#clipRect * @see java.awt.Graphics#setClip(int, int, int, int) @@ -413,16 +413,16 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Copies an area of the component by a distance specified by - * dx and dy. From the point specified - * by x and y, this method + * {@code dx} and {@code dy}. From the point specified + * by {@code x} and {@code y}, this method * copies downwards and to the right. To copy an area of the * component to the left or upwards, specify a negative value for - * dx or dy. + * {@code dx} or {@code dy}. * If a portion of the source rectangle lies outside the bounds * of the component, or is obscured by another window or component, - * copyArea will be unable to copy the associated + * {@code copyArea} will be unable to copy the associated * pixels. The area that is omitted can be refreshed by calling - * the component's paint method. + * the component's {@code paint} method. * @param x the x coordinate of the source rectangle. * @param y the y coordinate of the source rectangle. * @param width the width of the source rectangle. @@ -454,12 +454,12 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Fills the specified rectangle. * The left and right edges of the rectangle are at - * x and x + width - 1. + * {@code x} and x + width - 1. * The top and bottom edges are at - * y and y + height - 1. + * {@code y} and y + height - 1. * The resulting rectangle covers an area - * width pixels wide by - * height pixels tall. + * {@code width} pixels wide by + * {@code height} pixels tall. * The rectangle is filled using the graphics context's current color. * @param x the x coordinate * of the rectangle to be filled. @@ -482,7 +482,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { *

          * Beginning with Java 1.1, the background color * of offscreen images may be system dependent. Applications should - * use setColor followed by fillRect to + * use {@code setColor} followed by {@code fillRect} to * ensure that an offscreen image is cleared to a specific color. * @param x the x coordinate of the rectangle to clear. * @param y the y coordinate of the rectangle to clear. @@ -502,9 +502,9 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Draws an outlined round-cornered rectangle using this graphics * context's current color. The left and right edges of the rectangle - * are at x and x + width, + * are at {@code x} and x + width, * respectively. The top and bottom edges of the rectangle are at - * y and y + height. + * {@code y} and y + height. * @param x the x coordinate of the rectangle to be drawn. * @param y the y coordinate of the rectangle to be drawn. * @param width the width of the rectangle to be drawn. @@ -524,9 +524,9 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Fills the specified rounded corner rectangle with the current color. * The left and right edges of the rectangle - * are at x and x + width - 1, + * are at {@code x} and x + width - 1, * respectively. The top and bottom edges of the rectangle are at - * y and y + height - 1. + * {@code y} and y + height - 1. * @param x the x coordinate of the rectangle to be filled. * @param y the y coordinate of the rectangle to be filled. * @param width the width of the rectangle to be filled. @@ -546,8 +546,8 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Draws the outline of an oval. * The result is a circle or ellipse that fits within the - * rectangle specified by the x, y, - * width, and height arguments. + * rectangle specified by the {@code x}, {@code y}, + * {@code width}, and {@code height} arguments. *

          * The oval covers an area that is * width + 1 pixels wide @@ -585,8 +585,8 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * Draws the outline of a circular or elliptical arc * covering the specified rectangle. *

          - * The resulting arc begins at startAngle and extends - * for arcAngle degrees, using the current color. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees, using the current color. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -594,7 +594,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { *

          * The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

          * The resulting arc covers an area * width + 1 pixels wide @@ -619,8 +619,8 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Fills a circular or elliptical arc covering the specified rectangle. *

          - * The resulting arc begins at startAngle and extends - * for arcAngle degrees. + * The resulting arc begins at {@code startAngle} and extends + * for {@code arcAngle} degrees. * Angles are interpreted such that 0 degrees * is at the 3 o'clock position. * A positive value indicates a counter-clockwise rotation @@ -628,7 +628,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { *

          * The center of the arc is the center of the rectangle whose origin * is (xy) and whose size is specified by the - * width and height arguments. + * {@code width} and {@code height} arguments. *

          * The resulting arc covers an area * width + 1 pixels wide @@ -672,16 +672,16 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * arrays of x and y coordinates. * Each pair of (xy) coordinates defines a point. *

          - * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#fillPolygon * @see java.awt.Graphics#drawPolyline @@ -696,19 +696,19 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * Fills a closed polygon defined by * arrays of x and y coordinates. *

          - * This method draws the polygon defined by nPoint line + * This method draws the polygon defined by {@code nPoint} line * segments, where the first nPoint - 1 * line segments are line segments from * (xPoints[i - 1], yPoints[i - 1]) * to (xPoints[i], yPoints[i]), for - * 1 ≤ i ≤ nPoints. + * 1 ≤ i ≤ {@code nPoints}. * The figure is automatically closed by drawing a line connecting * the final point to the first point, if those points are different. *

          * The area inside the polygon is defined using an * even-odd fill rule, also known as the alternating rule. - * @param xPoints a an array of x coordinates. - * @param yPoints a an array of y coordinates. + * @param xPoints a an array of {@code x} coordinates. + * @param yPoints a an array of {@code y} coordinates. * @param nPoints a the total number of points. * @see java.awt.Graphics#drawPolygon(int[], int[], int) * @since 1.0 @@ -796,7 +796,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * and converted for the current output device. *

          * If the image has not yet been completely loaded, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. * @param img the specified image to be drawn. @@ -828,9 +828,9 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies - * the image observer by calling its imageUpdate method. + * the image observer by calling its {@code imageUpdate} method. *

          * A scaled version of an image will not necessarily be * available immediately just because an unscaled version of the @@ -872,7 +872,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * and converted for the current output device. *

          * If the image has not yet been completely loaded, then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. * @param img the specified image to be drawn. @@ -923,7 +923,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * entire image has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -978,7 +978,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1038,7 +1038,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * image area to be drawn has not yet been scaled, dithered, and converted * for the current output device. * If the current output representation is not yet complete then - * drawImage returns false. As more of + * {@code drawImage} returns {@code false}. As more of * the image becomes available, the process that draws the image notifies * the specified image observer. *

          @@ -1106,7 +1106,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { } /** - * Return true if drawing img will + * Return true if drawing {@code img} will * invoke a Java2D bug (#4258675). The bug in question * occurs when a draw image call with a background color * parameter tries to render a sheared @@ -1126,14 +1126,14 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { } /** - * Return a new BufferedImage + * Return a new {@code BufferedImage} * that contains a copy of the provided - * Image where its + * {@code Image} where its * transparent pixels have been replaced by - * bgcolor. If the new - * BufferedImage can not be created, + * {@code bgcolor}. If the new + * {@code BufferedImage} can not be created, * probably because the original image has not - * finished loading, then null is + * finished loading, then {@code null} is * returned. */ private BufferedImage getBufferedImageCopy(Image img, Color bgcolor) { @@ -1232,10 +1232,10 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Disposes of this graphics context and releases * any system resources that it is using. - * A Graphics object cannot be used after - * disposehas been called. + * A {@code Graphics} object cannot be used after + * {@code dispose} has been called. *

          - * When a Java program runs, a large number of Graphics + * When a Java program runs, a large number of {@code Graphics} * objects can be created within a short time frame. * Although the finalization process of the garbage collector * also disposes of the same system resources, it is preferable @@ -1244,12 +1244,12 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { * may not run to completion for a long period of time. *

          * Graphics objects which are provided as arguments to the - * paint and update methods + * {@code paint} and {@code update} methods * of components are automatically released by the system when * those methods return. For efficiency, programmers should - * call dispose when finished using - * a Graphics object only if it was created - * directly from a component or another Graphics object. + * call {@code dispose} when finished using + * a {@code Graphics} object only if it was created + * directly from a component or another {@code Graphics} object. * @see java.awt.Graphics#finalize * @see java.awt.Component#paint * @see java.awt.Component#update diff --git a/jdk/src/java.desktop/share/classes/sun/print/ProxyPrintGraphics.java b/jdk/src/java.desktop/share/classes/sun/print/ProxyPrintGraphics.java index f46caed3ea3..49480707019 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/ProxyPrintGraphics.java +++ b/jdk/src/java.desktop/share/classes/sun/print/ProxyPrintGraphics.java @@ -54,8 +54,8 @@ public class ProxyPrintGraphics extends ProxyGraphics } /** - * Creates a new Graphics object that is - * a copy of this Graphics object. + * Creates a new {@code Graphics} object that is + * a copy of this {@code Graphics} object. * @return a new graphics context that is a copy of * this graphics context. */ @@ -65,8 +65,8 @@ public class ProxyPrintGraphics extends ProxyGraphics /** - * Creates a new Graphics object based on this - * Graphics object, but with a new translation and + * Creates a new {@code Graphics} object based on this + * {@code Graphics} object, but with a new translation and * clip area. * Refer to * {@link sun.print.ProxyGraphics#create(int, int, int, int)} diff --git a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index 585e6e495b8..1ffb6a18e1d 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -431,7 +431,7 @@ public abstract class RasterPrinterJob extends PrinterJob { /* * A convenience method which returns the default service - * for 2D PrinterJobs. + * for 2D {@code PrinterJob}s. * May return null if there is no suitable default (although there * may still be 2D services available). * @return default 2D print service, or null. @@ -495,9 +495,9 @@ public abstract class RasterPrinterJob extends PrinterJob { /** * Associate this PrinterJob with a new PrintService. * - * Throws PrinterException if the specified service - * cannot support the Pageable and - * Printable interfaces necessary to support 2D printing. + * Throws {@code PrinterException} if the specified service + * cannot support the {@code Pageable} and + * {@code Printable} interfaces necessary to support 2D printing. * @param service print service which supports 2D printing. * * @throws PrinterException if the specified service does not support @@ -694,17 +694,17 @@ public abstract class RasterPrinterJob extends PrinterJob { /** * Display a dialog to the user allowing the modification of a * PageFormat instance. - * The page argument is used to initialize controls + * The {@code page} argument is used to initialize controls * in the page setup dialog. * If the user cancels the dialog, then the method returns the - * original page object unmodified. + * original {@code page} object unmodified. * If the user okays the dialog then the method returns a new * PageFormat object with the indicated changes. - * In either case the original page object will + * In either case the original {@code page} object will * not be modified. * @param page the default PageFormat presented to the user * for modification - * @return the original page object if the dialog + * @return the original {@code page} object if the dialog * is cancelled, or a new PageFormat object containing * the format indicated by the user if the dialog is * acknowledged @@ -2350,14 +2350,14 @@ public abstract class RasterPrinterJob extends PrinterJob { /** * Examine the metrics captured by the - * PeekGraphics instance and + * {@code PeekGraphics} instance and * if capable of directly converting this * print job to the printer's control language * or the native OS's graphics primitives, then - * return a PathGraphics to perform + * return a {@code PathGraphics} to perform * that conversion. If there is not an object * capable of the conversion then return - * null. Returning null + * {@code null}. Returning {@code null} * causes the print job to be rasterized. */ protected Graphics2D createPathGraphics(PeekGraphics graphics, @@ -2372,11 +2372,11 @@ public abstract class RasterPrinterJob extends PrinterJob { /** * Create and return an object that will * gather and hold metrics about the print - * job. This method is passed a Graphics2D + * job. This method is passed a {@code Graphics2D} * object that can be used as a proxy for the * object gathering the print job matrics. The * method is also supplied with the instance - * controlling the print job, printerJob. + * controlling the print job, {@code printerJob}. */ protected PeekGraphics createPeekGraphics(Graphics2D graphics, PrinterJob printerJob) { diff --git a/jdk/src/java.desktop/share/classes/sun/swing/UIAction.java b/jdk/src/java.desktop/share/classes/sun/swing/UIAction.java index 98aa04c06c4..d87801fc683 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/UIAction.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/UIAction.java @@ -87,7 +87,7 @@ public abstract class UIAction implements Action { * Cover method for isEnabled(null). */ public final boolean isEnabled() { - return isEnabled(null); + return accept(null); } /** @@ -96,7 +96,8 @@ public abstract class UIAction implements Action { * * @param sender Widget enabled state is being asked for, may be null. */ - public boolean isEnabled(Object sender) { + @Override + public boolean accept(Object sender) { return true; } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java index 42dd34e6943..ecee8ade0bc 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java @@ -118,8 +118,8 @@ public abstract class UNIXToolkit extends SunToolkit * Load a native Gtk stock icon. * * @param longname a desktop property name. This contains icon name, size - * and orientation, e.g. "gtk.icon.gtk-add.4.rtl" - * @return an Image for the icon, or null if the + * and orientation, e.g. {@code "gtk.icon.gtk-add.4.rtl"} + * @return an {@code Image} for the icon, or {@code null} if the * icon could not be loaded */ protected Object lazilyLoadGTKIcon(String longname) { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java index a476628e7c5..72aeb67a3f9 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java @@ -55,7 +55,7 @@ class MotifDnDDragSourceProtocol extends XDragSourceProtocol /** * Creates an instance associated with the specified listener. * - * @throws NullPointerException if listener is null. + * @throws NullPointerException if listener is {@code null}. */ static XDragSourceProtocol createInstance(XDragSourceProtocolListener listener) { return new MotifDnDDragSourceProtocol(listener); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java index e71236a6ff9..8d63906a664 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java @@ -62,7 +62,7 @@ class MotifDnDDropTargetProtocol extends XDropTargetProtocol { /** * Creates an instance associated with the specified listener. * - * @throws NullPointerException if listener is null. + * @throws NullPointerException if listener is {@code null}. */ static XDropTargetProtocol createInstance(XDropTargetProtocolListener listener) { return new MotifDnDDropTargetProtocol(listener); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java index e4d5b23ca76..470da61093f 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java @@ -63,7 +63,7 @@ class Native { /** * Set of helper function to read data of different PLATFORM types - * from memory pointer by ptr + * from memory pointer by {@code ptr} * Note, names of types in function are NATIVE PLATFORM types * and they have the same size as they would have in C compiler * on the same platform. @@ -93,7 +93,7 @@ class Native { putByte(ptr+index, data); } /** - * Converts length bytes of data pointed by data into byte array + * Converts length bytes of data pointed by {@code data} into byte array * Returns null if data is zero * @param data native pointer to native memory * @param length size in bytes of native memory @@ -143,7 +143,7 @@ class Native { } /** - * Converts length usnigned bytes of data pointed by data into + * Converts length usnigned bytes of data pointed by {@code data} into * short array * Returns null if data is zero * @param data native pointer to native memory @@ -297,8 +297,8 @@ class Native { } /** * Stores to C long data(four bytes) - * Note: data has long type - * to be able to keep 64-bit C long data + * Note: {@code data} has {@code long} type + * to be able to keep 64-bit C {@code long} data */ static void putLong(long ptr, long data) { if (XlibWrapper.dataModel == 32) { @@ -320,7 +320,7 @@ class Native { } /** * Stores Java long[] array into memory. Memory location is treated as array - * of native longs + * of native {@code long}s */ static void put(long ptr, long[] arr) { for (int i = 0; i < arr.length; i ++, ptr += getLongSize()) { @@ -330,7 +330,7 @@ class Native { /** * Stores Java Vector of Longs into memory. Memory location is treated as array - * of native longs + * of native {@code long}s */ static void putLong(long ptr, Vector arr) { for (int i = 0; i < arr.size(); i ++, ptr += getLongSize()) { @@ -340,7 +340,7 @@ class Native { /** * Stores Java Vector of Longs into memory. Memory location is treated as array - * of native longs. Array is stored in reverse order + * of native {@code long}s. Array is stored in reverse order */ static void putLongReverse(long ptr, Vector arr) { for (int i = arr.size()-1; i >= 0; i--, ptr += getLongSize()) { @@ -348,7 +348,7 @@ class Native { } } /** - * Converts length bytes of data pointed by data into byte array + * Converts length bytes of data pointed by {@code data} into byte array * Returns null if data is zero * @param data native pointer to native memory * @param length size in longs(platform dependent) of native memory @@ -393,7 +393,7 @@ class Native { } /** - * Allocates memory for array of native longs of the size length + * Allocates memory for array of native {@code long}s of the size {@code length} */ static long allocateLongArray(int length) { return unsafe.allocateMemory(getLongSize() * length); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java index eeb46347b56..117e3865241 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java @@ -29,28 +29,31 @@ package sun.awt.X11; * XAtom is a class that allows you to create and modify X Window properties. * An X Atom is an identifier for a property that you can set on any X Window. * Standard X Atom are defined by X11 and these atoms are defined in this class - * for convenience. Common X Atoms like XA_WM_NAME are used to communicate with the + * for convenience. Common X Atoms like {@code XA_WM_NAME} are used to communicate with the * Window manager to let it know the Window name. The use and protocol for these * atoms are defined in the Inter client communications converntions manual. * User specified XAtoms are defined by specifying a name that gets Interned - * by the XServer and an XAtom object is returned. An XAtom can also be created - * by using a pre-exisiting atom like XA_WM_CLASS. A display has to be specified - * in order to create an XAtom.

          + * by the XServer and an {@code XAtom} object is returned. An {@code XAtom} can also be created + * by using a pre-exisiting atom like {@code XA_WM_CLASS}. A {@code display} has to be specified + * in order to create an {@code XAtom}.

          * - * Once an XAtom instance is created, you can call get and set property methods to + * Once an {@code XAtom} instance is created, you can call get and set property methods to * set the values for a particular window.

          * * * Example usage : To set the window name for a top level:

          - * - * XAtom xa = new XAtom(display,XAtom.XA_WM_NAME);

          - * xa.setProperty(window,"Hello World");

          - *

          - *

          - * To get the cut buffer :

          - *

          - * XAtom xa = new XAtom(display,XAtom.XA_CUT_BUFFER0);

          - * String selection = xa.getProperty(root_window);

          + *

          {@code
          + * XAtom xa = new XAtom(display,XAtom.XA_WM_NAME);
          + * xa.setProperty(window,"Hello World");
          + * }
          + *

          + *

          + * To get the cut buffer: + *

          {@code
          + * XAtom xa = new XAtom(display,XAtom.XA_CUT_BUFFER0);
          + * String selection = xa.getProperty(root_window);
          + * }
          + * * @author Bino George * @since 1.5 */ @@ -237,7 +240,7 @@ public final class XAtom { } /** This constructor will create an instance of XAtom that is specified - * by the predefined XAtom specified by u latom + * by the predefined XAtom specified by u {@code latom} * * @param display X display to use. * @param atom a predefined XAtom. @@ -250,7 +253,7 @@ public final class XAtom { } /** This constructor will create the instance, - * and if autoIntern is true intern a new XAtom that is specified + * and if {@code autoIntern} is true intern a new XAtom that is specified * by the supplied name. * * @param display X display to use @@ -450,7 +453,7 @@ public final class XAtom { /** * Gets uninterpreted set of data from property and stores them in data_ptr. - * Property type is type, property is current atom. + * Property type is {@code type}, property is current atom. * Property format is 32. Property 'delete' is false. * Returns boolean if requested type, format, length match returned values * and returned data pointer is not null. @@ -505,7 +508,7 @@ public final class XAtom { /** * Sets uninterpreted set of data into property from data_ptr. - * Property type is type, property is current atom. + * Property type is {@code type}, property is current atom. * Property format is 32. Mode is PropModeReplace. length is a number * of items pointer by data_ptr. */ @@ -526,7 +529,7 @@ public final class XAtom { /** * Sets uninterpreted set of data into property from data_ptr. - * Property type is type, property is current atom. + * Property type is {@code type}, property is current atom. * Property format is 8. Mode is PropModeReplace. length is a number * of bytes pointer by data_ptr. */ @@ -784,7 +787,7 @@ public final class XAtom { } /** - * Sets property on the window to the value window_value + * Sets property on the {@code window} to the value {@code window_value} * Property is assumed to be of type WINDOW/32 */ public void setWindowProperty(long window, long window_value) { @@ -807,7 +810,7 @@ public final class XAtom { } /** - * Gets property on the window. Property is assumed to be + * Gets property on the {@code window}. Property is assumed to be * of type WINDOW/32. */ public long getWindowProperty(long window) { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtomList.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtomList.java index a998850eb4c..624c7040694 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtomList.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtomList.java @@ -41,7 +41,7 @@ class XAtomList { /** * Creates instance of XAtomList and initializes it with - * the contents pointer by data. + * the contents pointer by {@code data}. * Uses default display to initialize atoms. */ public XAtomList(long data, int count) { @@ -90,7 +90,7 @@ class XAtomList { } /** - * Returns true if this list contains the atom atom + * Returns true if this list contains the atom {@code atom} */ public boolean contains(XAtom atom) { return atoms.contains(atom); @@ -119,8 +119,8 @@ class XAtomList { } /** - * Returns a subset of a list which is intersection of this set and set build by mapping mask in - * mapping. + * Returns a subset of a list which is intersection of this set and set build by mapping {@code mask} in + * {@code mapping}. */ public XAtomList subset(int mask, Map mapping) { XAtomList res = new XAtomList(); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java index 94cb9fdacaf..c8534aa36e3 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseWindow.java @@ -170,7 +170,7 @@ public class XBaseWindow { } /** - * Creates window using parameters params + * Creates window using parameters {@code params} * If params contain flag DELAYED doesn't do anything. * Note: Descendants can call this method to create the window * at the time different to instance construction. @@ -316,7 +316,7 @@ public class XBaseWindow { } /** - * Creates window with parameters specified by params + * Creates window with parameters specified by {@code params} * @see #init */ private final void create(XCreateWindowParams params) { @@ -691,7 +691,7 @@ public class XBaseWindow { XToolkit.awtLock(); try { XAtom xa = XAtom.get(XAtom.XA_WM_CLASS); - xa.setProperty8(getWindow(), cl[0] + '\0' + cl[1]); + xa.setProperty8(getWindow(), cl[0] + '\0' + cl[1] + '\0'); } finally { XToolkit.awtUnlock(); } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java index e1331c7fdd0..82715e73ff2 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java @@ -680,7 +680,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget * Gets the font metrics for the specified font. * @param font the font for which font metrics is to be * obtained - * @return the font metrics for font + * @return the font metrics for {@code font} * @see #getFont * @see java.awt.peer.ComponentPeer#getFontMetrics(Font) * @see Toolkit#getFontMetrics(Font) @@ -724,8 +724,8 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget /* * The method changes the cursor. - * @param cursor - a new cursor to change to. - * @param ignoreSubComponents - if {@code true} is passed then + * @param cursor a new cursor to change to. + * @param ignoreSubComponents if {@code true} is passed then * the new cursor will be installed on window. * if {@code false} is passed then * subsequent components will try to handle diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java index abe706a3652..72a34cf85f8 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java @@ -39,7 +39,7 @@ import java.util.List; /** - * Concrete implementation of the interface DesktopPeer for + * Concrete implementation of the interface {@code DesktopPeer} for * the Gnome desktop on Linux and Unix platforms. * * @see DesktopPeer diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java index 26265be30bc..fc60ec97fa8 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java @@ -55,7 +55,7 @@ class XDnDDragSourceProtocol extends XDragSourceProtocol { /** * Creates an instance associated with the specified listener. * - * @throws NullPointerException if listener is null. + * @throws NullPointerException if listener is {@code null}. */ static XDragSourceProtocol createInstance(XDragSourceProtocolListener listener) { return new XDnDDragSourceProtocol(listener); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java index e1698a424b8..f2e7b62c9f1 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java @@ -70,7 +70,7 @@ class XDnDDropTargetProtocol extends XDropTargetProtocol { /** * Creates an instance associated with the specified listener. * - * @throws NullPointerException if listener is null. + * @throws NullPointerException if listener is {@code null}. */ static XDropTargetProtocol createInstance(XDropTargetProtocolListener listener) { return new XDnDDropTargetProtocol(listener); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDragSourceProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDragSourceProtocol.java index 48e611b627a..c8ecb422611 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDragSourceProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDragSourceProtocol.java @@ -74,7 +74,7 @@ abstract class XDragSourceProtocol { * Initializes a drag operation with the specified supported drop actions, * contents and data formats. * - * @param actions a bitwise mask of DnDConstants that represent + * @param actions a bitwise mask of {@code DnDConstants} that represent * the supported drop actions. * @param contents the contents for the drag operation. * @param formats an array of Atoms that represent the supported data formats. diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedServerTester.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedServerTester.java index 9b37a429125..1bbae4f91f9 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedServerTester.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedServerTester.java @@ -570,7 +570,7 @@ public class XEmbedServerTester implements XEventDispatcher { } } /** - * Checks if the event is already in a list at position >= position + * Checks if the {@code event} is already in a list at position >= {@code position} */ private int checkEventList(int position, int event) { if (position == -1) { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRepaintArea.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRepaintArea.java index 97a997958ec..6f7b733c82f 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRepaintArea.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRepaintArea.java @@ -33,7 +33,7 @@ import sun.awt.AWTAccessor; import sun.awt.RepaintArea; /** - * The RepaintArea is a geometric construct created for the + * The {@code RepaintArea} is a geometric construct created for the * purpose of holding the geometry of several coalesced paint events. * This geometry is accessed synchronously, although it is written such * that painting may still be executed asynchronously. @@ -43,7 +43,7 @@ import sun.awt.RepaintArea; final class XRepaintArea extends RepaintArea { /** - * Calls Component.update(Graphics) with given Graphics. + * Calls {@code Component.update(Graphics)} with given Graphics. */ protected void updateComponent(Component comp, Graphics g) { if (comp != null) { @@ -54,7 +54,7 @@ final class XRepaintArea extends RepaintArea { } /** - * Calls Component.paint(Graphics) with given Graphics. + * Calls {@code Component.paint(Graphics)} with given Graphics. */ protected void paintComponent(Component comp, Graphics g) { if (comp != null) { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java index 6d8473cb47c..368d034687e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XRobotPeer.java @@ -31,6 +31,7 @@ import sun.awt.AWTAccessor; import sun.awt.SunToolkit; import sun.awt.UNIXToolkit; import sun.awt.X11GraphicsConfig; +import sun.awt.X11GraphicsEnvironment; class XRobotPeer implements RobotPeer { @@ -64,7 +65,14 @@ class XRobotPeer implements RobotPeer { @Override public void mouseMove(int x, int y) { - mouseMoveImpl(xgc, xgc.scaleUp(x), xgc.scaleUp(y)); + X11GraphicsEnvironment x11ge = (X11GraphicsEnvironment) + GraphicsEnvironment.getLocalGraphicsEnvironment(); + if(x11ge.runningXinerama()) { + Rectangle sb = xgc.getBounds(); + mouseMoveImpl(xgc, xgc.scaleUp(x + sb.x), xgc.scaleUp(y + sb.y)); + } else { + mouseMoveImpl(xgc, xgc.scaleUp(x), xgc.scaleUp(y)); + } } @Override diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XSelection.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XSelection.java index 2fb074855d5..0a9a70487df 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XSelection.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XSelection.java @@ -110,7 +110,7 @@ final class XSelection { /* * Returns the XSelection object for the specified selection atom or - * null if none exists. + * {@code null} if none exists. */ static XSelection getSelection(XAtom atom) { return table.get(atom); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XStateProtocol.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XStateProtocol.java index 72bbc348045..84defe3a912 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XStateProtocol.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XStateProtocol.java @@ -30,7 +30,7 @@ public interface XStateProtocol { /** * Returns whether or not the protocol supports the transition to the state - * represented by state. State contains encoded state + * represented by {@code state}. {@code State} contains encoded state * as a bit mask of state defined in java.awt.Frame */ boolean supportsState(int state); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java index 428d1d27d55..9efe70b17c4 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java @@ -127,7 +127,7 @@ final class XTextAreaPeer extends XComponentPeer implements TextAreaPeer { int end = target.getSelectionEnd(); // Fix for 5100200 // Restoring Motif behaviour - // Since the end position of the selected text can be greater then the length of the text, + // Since the end position of the selected text can be greater than the length of the text, // so we should set caret to max position of the text setCaretPosition(Math.min(end, text.length())); if (end > start) { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java index b936b6bb26a..9df078e9d1f 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java @@ -83,7 +83,7 @@ final class XTextFieldPeer extends XComponentPeer implements TextFieldPeer { int end = target.getSelectionEnd(); // Fix for 5100200 // Restoring Motif behaviour - // Since the end position of the selected text can be greater then the length of the text, + // Since the end position of the selected text can be greater than the length of the text, // so we should set caret to max position of the text setCaretPosition(Math.min(end, text.length())); if (end > start) { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index 7297ef72287..d79df149f6d 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -407,7 +407,7 @@ public final class XToolkit extends UNIXToolkit implements Runnable { /** * Returns whether there is last remembered cursor position. The * position is remembered from X mouse events on our peers. The - * position is stored in p. + * position is stored in {@code p}. * @return true, if there is remembered last cursor position, * false otherwise */ @@ -1680,11 +1680,11 @@ public final class XToolkit extends UNIXToolkit implements Runnable { /** * Callback from the native side indicating some, or all, of the * desktop properties have changed and need to be reloaded. - * data is the byte array directly from the x server and + * {@code data} is the byte array directly from the x server and * may be in little endian format. *

          * NB: This could be called from any thread if triggered by - * loadXSettings. It is called from the System EDT + * {@code loadXSettings}. It is called from the System EDT * if triggered by an XSETTINGS change. */ void parseXSettings(int screen_XXX_ignored,Map updatedSettings) { @@ -1941,16 +1941,16 @@ public final class XToolkit extends UNIXToolkit implements Runnable { static native void wakeup_poll(); /** - * Registers a Runnable which run() method will be called + * Registers a Runnable which {@code run()} method will be called * once on the toolkit thread when a specified interval of time elapses. * - * @param task a Runnable which run method will be called - * on the toolkit thread when interval milliseconds + * @param task a Runnable which {@code run} method will be called + * on the toolkit thread when {@code interval} milliseconds * elapse * @param interval an interal in milliseconds * - * @throws NullPointerException if task is null - * @throws IllegalArgumentException if interval is not positive + * @throws NullPointerException if {@code task} is {@code null} + * @throws IllegalArgumentException if {@code interval} is not positive */ static void schedule(Runnable task, long interval) { if (task == null) { diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java index 77fb29d3a97..862508ccfcf 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java @@ -1622,7 +1622,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, * @param transientForWindow the top-level window * @param updateChain specifies if next/prevTransientFor fields are * to be updated - * @param allStates if set to true then TRANSIENT_FOR hint + * @param allStates if set to {@code true} then TRANSIENT_FOR hint * is set regardless of the state of window and transientForWindow, * otherwise it is set only if both are in the same state */ diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/XSettings.java b/jdk/src/java.desktop/unix/classes/sun/awt/XSettings.java index 59fb9a08ad2..812255ea850 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/XSettings.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/XSettings.java @@ -44,13 +44,13 @@ public class XSettings { /** - * Update these settings with data obtained from + * Update these settings with {@code data} obtained from * XSETTINGS manager. * * @param data settings data obtained from - * _XSETTINGS_SETTINGS window property of the + * {@code _XSETTINGS_SETTINGS} window property of the * settings manager. - * @return a Map of changed settings. + * @return a {@code Map} of changed settings. */ public Map update(byte[] data) { return (new Update(data)).update(); @@ -84,10 +84,10 @@ public class XSettings { /** * Construct an Update object for the data read from - * _XSETTINGS_SETTINGS property of the XSETTINGS + * {@code _XSETTINGS_SETTINGS} property of the XSETTINGS * selection owner. * - * @param data _XSETTINGS_SETTINGS contents. + * @param data {@code _XSETTINGS_SETTINGS} contents. */ Update(byte[] data) { this.data = data; diff --git a/jdk/src/java.desktop/unix/classes/sun/font/NativeFont.java b/jdk/src/java.desktop/unix/classes/sun/font/NativeFont.java index ca225f6df5a..b30b6459c3b 100644 --- a/jdk/src/java.desktop/unix/classes/sun/font/NativeFont.java +++ b/jdk/src/java.desktop/unix/classes/sun/font/NativeFont.java @@ -64,7 +64,7 @@ public class NativeFont extends PhysicalFont { /** * Verifies native font is accessible. - * @throws FontFormatException - if the font can't be located. + * @throws FontFormatException if the font can't be located. */ public NativeFont(String platName, boolean bitmapDelegate) throws FontFormatException { diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c index 07588c80f5e..00d04814e86 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c @@ -221,8 +221,10 @@ wcstombsdmp(wchar_t *wcs, int len) } /* TODO: check return values... Handle invalid characters properly... */ - if (wcstombs(mbs, wcs, n) == (size_t)-1) + if (wcstombs(mbs, wcs, n) == (size_t)-1) { + free(mbs); return NULL; + } return mbs; } diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java b/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java index 4773934e39e..a13c1ff1d50 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/Win32GraphicsConfig.java @@ -94,7 +94,7 @@ public class Win32GraphicsConfig extends GraphicsConfiguration /** * @deprecated as of JDK version 1.3 - * replaced by getConfig() + * replaced by {@code getConfig()} */ @Deprecated public Win32GraphicsConfig(GraphicsDevice device, int visualnum) { diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java index 8e32e39acc8..dab4129ade5 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java @@ -350,12 +350,12 @@ final class Win32ShellFolder2 extends ShellFolder { /** * This method is implemented to make sure that no instances - * of ShellFolder are ever serialized. If isFileSystem() returns - * true, then the object is representable with an instance of - * java.io.File instead. If not, then the object depends + * of {@code ShellFolder} are ever serialized. If {@code isFileSystem()} returns + * {@code true}, then the object is representable with an instance of + * {@code java.io.File} instead. If not, then the object depends * on native PIDL state and should not be serialized. * - * @return a java.io.File replacement object. If the folder + * @return a {@code java.io.File} replacement object. If the folder * is a not a normal directory, then returns the first non-removable * drive (normally "C:\"). */ @@ -718,7 +718,7 @@ final class Win32ShellFolder2 extends ShellFolder { /** * @return An array of shell folders that are children of this shell folder * object. The array will be empty if the folder is empty. Returns - * null if this shellfolder does not denote a directory. + * {@code null} if this shellfolder does not denote a directory. */ public File[] listFiles(final boolean includeHiddenFiles) { SecurityManager security = System.getSecurityManager(); @@ -1091,7 +1091,7 @@ final class Win32ShellFolder2 extends ShellFolder { } /** - * Gets an icon from the Windows system icon list as an Image + * Gets an icon from the Windows system icon list as an {@code Image} */ static Image getSystemIcon(SystemIcon iconType) { long hIcon = getSystemIcon(iconType.getIconID()); @@ -1101,7 +1101,7 @@ final class Win32ShellFolder2 extends ShellFolder { } /** - * Gets an icon from the Windows system icon list as an Image + * Gets an icon from the Windows system icon list as an {@code Image} */ static Image getShell32Icon(int iconID, boolean getLargeIcon) { boolean useVGAColors = true; // Will be ignored on XP and later diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index e87379a58f0..b01d04443df 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -225,24 +225,24 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { private static File[] roots; /** - * @param key a String + * @param key a {@code String} * "fileChooserDefaultFolder": - * Returns a File - the default shellfolder for a new filechooser + * Returns a {@code File} - the default shellfolder for a new filechooser * "roots": - * Returns a File[] - containing the root(s) of the displayable hierarchy + * Returns a {@code File[]} - containing the root(s) of the displayable hierarchy * "fileChooserComboBoxFolders": - * Returns a File[] - an array of shellfolders representing the list to + * Returns a {@code File[]} - an array of shellfolders representing the list to * show by default in the file chooser's combobox * "fileChooserShortcutPanelFolders": - * Returns a File[] - an array of shellfolders representing well-known + * Returns a {@code File[]} - an array of shellfolders representing well-known * folders, such as Desktop, Documents, History, Network, Home, etc. * This is used in the shortcut panel of the filechooser on Windows 2000 * and Windows Me. * "fileChooserIcon ": - * Returns an Image - icon can be ListView, DetailsView, UpFolder, NewFolder or + * Returns an {@code Image} - icon can be ListView, DetailsView, UpFolder, NewFolder or * ViewMenu (Windows only). * "optionPaneIcon iconName": - * Returns an Image - icon from the system icon list + * Returns an {@code Image} - icon from the system icon list * * @return An Object matching the key string. */ @@ -415,7 +415,7 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { } /** - * Does dir represent a "computer" such as a node on the network, or + * Does {@code dir} represent a "computer" such as a node on the network, or * "My Computer" on the desktop. */ public boolean isComputerNode(final File dir) { diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WDesktopPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WDesktopPeer.java index c3d68c7442c..b745e9d41ae 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WDesktopPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WDesktopPeer.java @@ -34,7 +34,7 @@ import java.net.URI; /** - * Concrete implementation of the interface DesktopPeer for + * Concrete implementation of the interface {@code DesktopPeer} for * the Windows platform. * * @see DesktopPeer diff --git a/jdk/src/java.desktop/share/classes/sun/awt/DefaultMouseInfoPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMouseInfoPeer.java similarity index 82% rename from jdk/src/java.desktop/share/classes/sun/awt/DefaultMouseInfoPeer.java rename to jdk/src/java.desktop/windows/classes/sun/awt/windows/WMouseInfoPeer.java index 9ac06c4b8bf..e5bef4fe1b9 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/DefaultMouseInfoPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WMouseInfoPeer.java @@ -23,18 +23,24 @@ * questions. */ -package sun.awt; +package sun.awt.windows; +import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Window; import java.awt.peer.MouseInfoPeer; -public final class DefaultMouseInfoPeer implements MouseInfoPeer { +public final class WMouseInfoPeer implements MouseInfoPeer { + + static { + // initialize screen devices for the mouse coordinates scaling + GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); + } /** * Package-private constructor to prevent instantiation. */ - DefaultMouseInfoPeer() { + WMouseInfoPeer() { } public native int fillPointWithCoords(Point point); diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java index f892a88bf6c..b7508fc290e 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java @@ -116,8 +116,8 @@ final class WPathGraphics extends PathGraphics { } /** - * Creates a new Graphics object that is - * a copy of this Graphics object. + * Creates a new {@code Graphics} object that is + * a copy of this {@code Graphics} object. * @return a new graphics context that is a copy of * this graphics context. * @since 1.0 @@ -375,19 +375,19 @@ final class WPathGraphics extends PathGraphics { } /** - * Renders the text specified by the specified String, - * using the current Font and Paint attributes - * in the Graphics2D context. + * Renders the text specified by the specified {@code String}, + * using the current {@code Font} and {@code Paint} attributes + * in the {@code Graphics2D} context. * The baseline of the first character is at position * (xy) in the User Space. - * The rendering attributes applied include the Clip, - * Transform, Paint, Font and - * Composite attributes. For characters in script systems + * The rendering attributes applied include the {@code Clip}, + * {@code Transform}, {@code Paint}, {@code Font} and + * {@code Composite} attributes. For characters in script systems * such as Hebrew and Arabic, the glyphs can be rendered from right to * left, in which case the coordinate supplied is the location of the * leftmost character on the baseline. - * @param str the String to be rendered - * @param x, y the coordinates where the String + * @param str the {@code String} to be rendered + * @param x, y the coordinates where the {@code String} * should be rendered * @see #setPaint * @see java.awt.Graphics#setColor @@ -914,11 +914,11 @@ final class WPathGraphics extends PathGraphics { } /** - * The various drawImage() methods for - * WPathGraphics are all decomposed - * into an invocation of drawImageToPlatform. + * The various {@code drawImage()} methods for + * {@code WPathGraphics} are all decomposed + * into an invocation of {@code drawImageToPlatform}. * The portion of the passed in image defined by - * srcX, srcY, srcWidth, and srcHeight + * {@code srcX, srcY, srcWidth, and srcHeight} * is transformed by the supplied AffineTransform and * drawn using GDI to the printer context. * @@ -1379,7 +1379,7 @@ final class WPathGraphics extends PathGraphics { /** * Have the printing application redraw everything that falls - * within the page bounds defined by region. + * within the page bounds defined by {@code region}. */ @Override public void redrawRegion(Rectangle2D region, double scaleX, double scaleY, @@ -1479,7 +1479,7 @@ final class WPathGraphics extends PathGraphics { } /* - * Fill the path defined by pathIter + * Fill the path defined by {@code pathIter} * with the specified color. * The path is provided in device coordinates. */ @@ -1495,7 +1495,7 @@ final class WPathGraphics extends PathGraphics { /* * Set the printer device's clip to be the - * path defined by pathIter + * path defined by {@code pathIter} * The path is provided in device coordinates. */ @Override @@ -1719,7 +1719,7 @@ final class WPathGraphics extends PathGraphics { /** - * Given a Java2D PathIterator instance, + * Given a Java2D {@code PathIterator} instance, * this method translates that into a Window's path * in the printer device context. */ diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java index 3506e4e6331..89c28502411 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java @@ -336,13 +336,13 @@ public final class WPrinterJob extends RasterPrinterJob /** * The last color set into the print device context or - * null if no color has been set. + * {@code null} if no color has been set. */ private Color mLastColor; /** * The last text color set into the print device context or - * null if no color has been set. + * {@code null} if no color has been set. */ private Color mLastTextColor; @@ -402,17 +402,17 @@ public final class WPrinterJob extends RasterPrinterJob /** * Display a dialog to the user allowing the modification of a * PageFormat instance. - * The page argument is used to initialize controls + * The {@code page} argument is used to initialize controls * in the page setup dialog. * If the user cancels the dialog, then the method returns the - * original page object unmodified. + * original {@code page} object unmodified. * If the user okays the dialog then the method returns a new * PageFormat object with the indicated changes. - * In either case the original page object will + * In either case the original {@code page} object will * not be modified. * @param page the default PageFormat presented to the user * for modification - * @return the original page object if the dialog + * @return the original {@code page} object if the dialog * is cancelled, or a new PageFormat object containing * the format indicated by the user if the dialog is * acknowledged @@ -588,8 +588,8 @@ public final class WPrinterJob extends RasterPrinterJob /** * Associate this PrinterJob with a new PrintService. * - * Throws PrinterException if the specified service - * cannot support the Pageable and + * Throws {@code PrinterException} if the specified service + * cannot support the {@code Pageable} and * Printable interfaces necessary to support 2D printing. * @param service print service which supports 2D printing. * @@ -763,14 +763,14 @@ public final class WPrinterJob extends RasterPrinterJob /** * Examine the metrics captured by the - * PeekGraphics instance and + * {@code PeekGraphics} instance and * if capable of directly converting this * print job to the printer's control language * or the native OS's graphics primitives, then - * return a PathGraphics to perform + * return a {@code PathGraphics} to perform * that conversion. If there is not an object * capable of the conversion then return - * null. Returning null + * {@code null}. Returning {@code null} * causes the print job to be rasterized. */ @@ -976,9 +976,9 @@ public final class WPrinterJob extends RasterPrinterJob /** * Set the current polgon fill rule into the printer device context. - * The fillRule should + * The {@code fillRule} should * be one of the following Windows constants: - * ALTERNATE or WINDING. + * {@code ALTERNATE} or {@code WINDING}. */ protected void setPolyFillMode(int fillRule) { setPolyFillMode(getPrintDC(), fillRule); @@ -986,7 +986,7 @@ public final class WPrinterJob extends RasterPrinterJob /* * Create a Window's solid brush for the color specified - * by (red, green, blue). Once the brush + * by {@code (red, green, blue)}. Once the brush * is created, select it in the current printing device * context and free the old brush. */ @@ -1146,7 +1146,7 @@ public final class WPrinterJob extends RasterPrinterJob } /** - * Draw the string text to the printer's + * Draw the string {@code text} to the printer's * device context at the specified position. */ protected void textOut(String str, float x, float y, @@ -1166,7 +1166,7 @@ public final class WPrinterJob extends RasterPrinterJob } /** - * Draw the glyphs glyphs to the printer's + * Draw the glyphs {@code glyphs} to the printer's * device context at the specified position. */ protected void glyphsOut(int []glyphs, float x, float y, @@ -1208,15 +1208,15 @@ public final class WPrinterJob extends RasterPrinterJob /** * Draw the 24 bit BGR image buffer represented by - * image to the GDI device context - * printDC. The image is drawn at - * (destX, destY) in device coordinates. + * {@code image} to the GDI device context + * {@code printDC}. The image is drawn at + * {@code (destX, destY)} in device coordinates. * The image is scaled into a square of size - * specified by destWidth and - * destHeight. The portion of the + * specified by {@code destWidth} and + * {@code destHeight}. The portion of the * source image copied into that square is specified - * by srcX, srcY, - * srcWidth, and srcHeight. + * by {@code srcX}, {@code srcY}, + * {@code srcWidth}, and srcHeight. */ protected void drawImage3ByteBGR(byte[] image, float destX, float destY, @@ -1412,37 +1412,37 @@ public final class WPrinterJob extends RasterPrinterJob /** * Begin a Window's rendering path in the device - * context printDC. + * context {@code printDC}. */ protected native void beginPath(long printDC); /** * End a Window's rendering path in the device - * context printDC. + * context {@code printDC}. */ protected native void endPath(long printDC); /** * Close a subpath in a Window's rendering path in the device - * context printDC. + * context {@code printDC}. */ protected native void closeFigure(long printDC); /** * Fill a defined Window's rendering path in the device - * context printDC. + * context {@code printDC}. */ protected native void fillPath(long printDC); /** - * Move the Window's pen position to (x,y) - * in the device context printDC. + * Move the Window's pen position to {@code (x,y)} + * in the device context {@code printDC}. */ protected native void moveTo(long printDC, float x, float y); /** * Draw a line from the current pen position to - * (x,y) in the device context printDC. + * {@code (x,y)} in the device context {@code printDC}. */ protected native void lineTo(long printDC, float x, float y); @@ -1453,17 +1453,17 @@ public final class WPrinterJob extends RasterPrinterJob /** * Set the current polgon fill rule into the device context - * printDC. The fillRule should + * {@code printDC}. The {@code fillRule} should * be one of the following Windows constants: - * ALTERNATE or WINDING. + * {@code ALTERNATE} or {@code WINDING}. */ protected native void setPolyFillMode(long printDC, int fillRule); /** * Create a Window's solid brush for the color specified - * by (red, green, blue). Once the brush + * by {@code (red, green, blue)}. Once the brush * is created, select it in the device - * context printDC and free the old brush. + * context {@code printDC} and free the old brush. */ protected native void selectSolidBrush(long printDC, int red, int green, int blue); @@ -1471,14 +1471,14 @@ public final class WPrinterJob extends RasterPrinterJob /** * Return the x coordinate of the current pen * position in the device context - * printDC. + * {@code printDC}. */ protected native int getPenX(long printDC); /** * Return the y coordinate of the current pen * position in the device context - * printDC. + * {@code printDC}. */ protected native int getPenY(long printDC); @@ -1537,8 +1537,8 @@ public final class WPrinterJob extends RasterPrinterJob /** - * Draw the string text into the device - * context printDC at the specified + * Draw the string {@code text} into the device + * context {@code printDC} at the specified * position. */ protected native void textOut(long printDC, String text, @@ -1550,15 +1550,15 @@ public final class WPrinterJob extends RasterPrinterJob /** * Draw the DIB compatible image buffer represented by - * image to the GDI device context - * printDC. The image is drawn at - * (destX, destY) in device coordinates. + * {@code image} to the GDI device context + * {@code printDC}. The image is drawn at + * {@code (destX, destY)} in device coordinates. * The image is scaled into a square of size - * specified by destWidth and - * destHeight. The portion of the + * specified by {@code destWidth} and + * {@code destHeight}. The portion of the * source image copied into that square is specified - * by srcX, srcY, - * srcWidth, and srcHeight. + * by {@code srcX}, {@code srcY}, + * {@code srcWidth}, and srcHeight. * Note that the image isn't completely compatible with DIB format. * At the very least it needs to be padded so each scanline is * DWORD aligned. Also we "flip" the image to make it a bottom-up DIB. diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java index fed3e231731..c7c463a8754 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java @@ -558,6 +558,16 @@ public final class WToolkit extends SunToolkit implements Runnable { return WKeyboardFocusManagerPeer.getInstance(); } + private static WMouseInfoPeer wPeer = null; + + @Override + public synchronized MouseInfoPeer getMouseInfoPeer() { + if (wPeer == null) { + wPeer = new WMouseInfoPeer(); + } + return wPeer; + } + private native void setDynamicLayoutNative(boolean b); @Override @@ -587,7 +597,7 @@ public final class WToolkit extends SunToolkit implements Runnable { } /** - * Returns true if this frame state is supported. + * Returns {@code true} if this frame state is supported. */ @Override public boolean isFrameStateSupported(int state) { diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WTrayIconPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WTrayIconPeer.java index 09b564f194e..b2828e2503f 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WTrayIconPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WTrayIconPeer.java @@ -180,7 +180,7 @@ final class WTrayIconPeer extends WObjectPeer implements TrayIconPeer { /* * Updates/adds the icon in/to the system tray. - * @param doUpdate if true, updates the icon, + * @param doUpdate if {@code true}, updates the icon, * otherwise, adds the icon */ native void updateNativeIcon(boolean doUpdate); diff --git a/jdk/src/java.desktop/windows/classes/sun/font/NativeFont.java b/jdk/src/java.desktop/windows/classes/sun/font/NativeFont.java index 9b9be888933..7a5c29c7c73 100644 --- a/jdk/src/java.desktop/windows/classes/sun/font/NativeFont.java +++ b/jdk/src/java.desktop/windows/classes/sun/font/NativeFont.java @@ -41,7 +41,7 @@ public class NativeFont extends PhysicalFont { /** * Verifies native font is accessible. - * @throws FontFormatException - if the font can't be located. + * @throws FontFormatException if the font can't be located. */ public NativeFont(String platName, boolean isBitmapDelegate) throws FontFormatException { diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java index 48f1dce490c..4b112b9fcc7 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java @@ -140,8 +140,8 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager * method returns GDI surface (we don't want to have two swap chains) * @param isResize whether this surface is being created in response to * a component resize event. This determines whether a repaint event will - * be issued after a surface is created: it will be if isResize - * is true. + * be issued after a surface is created: it will be if {@code isResize} + * is {@code true}. * @return surface data to be use for onscreen rendering */ @Override diff --git a/jdk/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBlitLoops.cpp b/jdk/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBlitLoops.cpp index ac1acd491dd..0b670639783 100644 --- a/jdk/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBlitLoops.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBlitLoops.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -508,8 +508,10 @@ D3DBlitTextureToSurface(D3DContext *d3dc, RETURN_STATUS_IF_NULL(srcOps->pResource, E_FAIL); RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL); - if ((pSrc = srcOps->pResource->GetTexture()) == NULL || - FAILED(res = d3dc->BeginScene(STATE_TEXTUREOP) || + pSrc = srcOps->pResource->GetTexture(); + RETURN_STATUS_IF_NULL(pSrc, E_FAIL); + + if (FAILED(res = d3dc->BeginScene(STATE_TEXTUREOP) || FAILED(res = d3dc->SetTexture(pSrc)))) { J2dRlsTraceLn(J2D_TRACE_ERROR, diff --git a/jdk/src/java.desktop/windows/native/libawt/java2d/d3d/D3DTextRenderer.cpp b/jdk/src/java.desktop/windows/native/libawt/java2d/d3d/D3DTextRenderer.cpp index 7bd843b93e6..4dde51b98e4 100644 --- a/jdk/src/java.desktop/windows/native/libawt/java2d/d3d/D3DTextRenderer.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/java2d/d3d/D3DTextRenderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -355,7 +355,7 @@ D3DTR_UpdateCachedDestination(D3DContext *d3dc, D3DSDOps *dstOps, jint dx1, dy1, dx2, dy2; D3DResource *pCachedDestTexRes; IDirect3DSurface9 *pCachedDestSurface, *pDst; - HRESULT res; + HRESULT res = S_OK; if (isCachedDestValid && INSIDE(gx1, gy1, gx2, gy2, cachedDestBounds)) { // glyph is already within the cached destination bounds; no need diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp index e43f6ea3f5f..90cef5303cf 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp @@ -33,12 +33,12 @@ extern "C" { /* - * Class: sun_awt_DefaultMouseInfoPeer + * Class: sun_awt_windows_WMouseInfoPeer * Method: isWindowUnderMouse * Signature: (Ljava/awt/Window)Z */ JNIEXPORT jboolean JNICALL -Java_sun_awt_DefaultMouseInfoPeer_isWindowUnderMouse(JNIEnv *env, jclass cls, +Java_sun_awt_windows_WMouseInfoPeer_isWindowUnderMouse(JNIEnv *env, jclass cls, jobject window) { POINT pt; @@ -73,12 +73,12 @@ Java_sun_awt_DefaultMouseInfoPeer_isWindowUnderMouse(JNIEnv *env, jclass cls, } /* - * Class: sun_awt_DefaultMouseInfoPeer + * Class: sun_awt_windows_WMouseInfoPeer * Method: fillPointWithCoords * Signature: (Ljava/awt/Point)I */ JNIEXPORT jint JNICALL -Java_sun_awt_DefaultMouseInfoPeer_fillPointWithCoords(JNIEnv *env, jclass cls, jobject point) +Java_sun_awt_windows_WMouseInfoPeer_fillPointWithCoords(JNIEnv *env, jclass cls, jobject point) { static jclass pointClass = NULL; static jfieldID xID, yID; @@ -95,7 +95,8 @@ Java_sun_awt_DefaultMouseInfoPeer_fillPointWithCoords(JNIEnv *env, jclass cls, j env->DeleteLocalRef(pointClassLocal); } - int screen = AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); + HMONITOR monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); + int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(monitor); Devices::InstanceAccess devices; AwtWin32GraphicsDevice *device = devices->GetDevice(screen); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp index b70048a9122..05273d41bad 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp @@ -686,6 +686,9 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getLinkLocation case STRRET_WSTR : wstr = strret.pOleStr; break; + + default: + return NULL; } IShellLinkW* psl; diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index a36db45b72f..d5224df0b62 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -2605,6 +2605,9 @@ AwtComponent::GetJavaModifiers() if (HIBYTE(::GetKeyState(VK_MENU)) != 0) { modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK; } + if (HIBYTE(::GetKeyState(VK_RMENU)) != 0) { + modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK; + } if (HIBYTE(::GetKeyState(VK_MBUTTON)) != 0) { modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK; } @@ -5231,6 +5234,8 @@ void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent) message = WM_MBUTTONDOWN; break; case java_awt_event_MouseEvent_BUTTON2: message = WM_RBUTTONDOWN; break; + default: + return; } break; } @@ -5242,6 +5247,8 @@ void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent) message = WM_MBUTTONUP; break; case java_awt_event_MouseEvent_BUTTON2: message = WM_RBUTTONUP; break; + default: + return; } break; } @@ -7302,4 +7309,4 @@ void ReleaseDCList(HWND hwnd, DCList &list) { removedDCs = removedDCs->next; delete tmpDCList; } -} \ No newline at end of file +} diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp index 21a4b0074ce..454a2fe74e4 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_DesktopProperties.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -388,7 +388,7 @@ void CheckFontSmoothingSettings(HWND hWnd) { } BOOL fontSmoothing = FALSE, settingsChanged; - UINT fontSmoothingType=0, fontSmoothingContrast=0, subPixelOrder; + UINT fontSmoothingType=0, fontSmoothingContrast=0, subPixelOrder=0; if (firstTime) { SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothing, 0); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp index a8d7fd1bcb6..6a7e49dcce3 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -270,7 +270,7 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) cfnum = 0; } - LPCWSTR wName; + LPCWSTR wName = NULL; awtFont = new AwtFont(cfnum, env, font); @@ -1202,7 +1202,7 @@ void AwtFontCache::IncRefCount(HFONT hFont){ } LONG AwtFontCache::IncRefCount(Item* item){ - LONG newVal; + LONG newVal = 0; if(NULL != item){ newVal = InterlockedIncrement((long*)&item->refCount); @@ -1211,7 +1211,7 @@ LONG AwtFontCache::IncRefCount(Item* item){ } LONG AwtFontCache::DecRefCount(Item* item){ - LONG newVal; + LONG newVal = 0; if(NULL != item){ newVal = InterlockedDecrement((long*)&item->refCount); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index e9a4167a6e1..ed8311ff3b3 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -156,7 +156,7 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) PDATA pData; HWND hwndParent = NULL; - AwtFrame* frame; + AwtFrame* frame = NULL; jclass cls = NULL; jclass inputMethodWindowCls = NULL; jobject target = NULL; @@ -993,7 +993,9 @@ MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) AwtComponent::SetFocusedWindow(GetHWnd()); } else { - if (!::IsWindow(AwtWindow::GetModalBlocker(opposite))) { + if (::IsWindow(AwtWindow::GetModalBlocker(opposite))) { + return mrConsume; + } else { // If deactivation happens because of press on grabbing // window - this is nonsense, since grabbing window is // assumed to have focus and watch for deactivation. But diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Label.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Label.cpp index d755d5fc68d..722151cd864 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Label.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Label.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,15 +146,16 @@ void AwtLabel::DoPaint(HDC hDC, RECT& r) jint alignment = env->GetIntField(target, AwtLabel::alignmentID); switch (alignment) { - case java_awt_Label_LEFT: - x = r.left + 2; - break; case java_awt_Label_CENTER: x = (r.left + r.right - size.cx) / 2; break; case java_awt_Label_RIGHT: x = r.right - 2 - size.cx; break; + case java_awt_Label_LEFT: + default: + x = r.left + 2; + break; } /* draw string */ if (isEnabled()) { diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp index d904da8774b..53057bb4dbd 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1108,7 +1108,7 @@ Java_sun_awt_windows_WPrinterJob_initPrinter(JNIEnv *env, jobject self) { // check for collation HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, self); if (hDevNames != NULL) { - DWORD dmFields; + DWORD dmFields = 0; DEVNAMES *devnames = (DEVNAMES *)::GlobalLock(hDevNames); if (devnames != NULL) { diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp index eaa8bca03d4..de60f0ed702 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,6 +129,7 @@ AwtTextComponent* AwtTextComponent::Create(jobject peer, jobject parent, BOOL is scroll_style = WS_HSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL; break; case java_awt_TextArea_SCROLLBARS_BOTH: + default: scroll_style = WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | ES_AUTOHSCROLL; break; diff --git a/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java b/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java index 24c848800fd..8d0083ff807 100644 --- a/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java +++ b/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java @@ -519,9 +519,13 @@ public class ManagementFactory { * {@code MBeanServerConnection} where * {@link java.io.IOException IOException} may be thrown * when the communication problem occurs with the connector server. - * An application remotely accesses the platform MXBeans using - * proxy should prepare to catch {@code IOException} as if - * accessing with the {@code MBeanServerConnector} interface. + * If thrown, {@link java.io.IOException IOException} will be wrappped in + * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}. + * An application remotely accessing the platform MXBeans using + * proxy should prepare to catch {@code UndeclaredThrowableException} and + * handle its {@linkplain java.lang.reflect.UndeclaredThrowableException#getCause() cause} + * as if that cause had been thrown by the {@code MBeanServerConnection} + * interface. * *

        • When a client application is designed to remotely access MXBeans * for a running virtual machine whose version is different than @@ -530,7 +534,11 @@ public class ManagementFactory { * {@link java.io.InvalidObjectException InvalidObjectException} * which is thrown when an MXBean proxy receives a name of an * enum constant which is missing in the enum class loaded in - * the client application.
        • + * the client application. If thrown, + * {@link java.io.InvalidObjectException InvalidObjectException} will be + * wrappped in + * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}. + * * *
        • {@link javax.management.MBeanServerInvocationHandler * MBeanServerInvocationHandler} or its diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 08a1eb94c28..1b7cc2da8b5 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -315,6 +315,9 @@ javax/sound/midi/Gervill/SoftProvider/GetDevice.java generic-all ############################################################################ # jdk_imageio +javax/imageio/plugins/shared/CanWriteSequence.java generic-all +javax/imageio/plugins/tiff/MultiPageTest/MultiPageTest.java generic-all +javax/imageio/plugins/tiff/WriteToSequenceAfterAbort.java generic-all ############################################################################ @@ -372,9 +375,6 @@ com/sun/jdi/GetLocalVariables4Test.sh windows-all # 8062512 java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.java generic-all -# 8076458 -java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java generic-all - # 8130337 java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java generic-all diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index e608d9d98b5..f621295f82d 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -78,6 +78,7 @@ jdk_lang = \ sun/reflect \ jdk/lambda \ jdk/internal/misc \ + jdk/internal/ref \ vm # All of the java.util package diff --git a/jdk/test/java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java b/jdk/test/java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java index 5512e4febb5..bf2252832f8 100644 --- a/jdk/test/java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java +++ b/jdk/test/java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java @@ -23,12 +23,12 @@ /* @test - @bug 6562853 - @summary Tests that focus transfered directy to window w/o transfering it to frame. - @author Oleg Sukhodolsky: area=awt.focus - @library ../../regtesthelpers - @build Util - @run main TranserFocusToWindow + @bug 6562853 7035459 + @summary Tests that focus transfered directy to window w/o transfering it to frame. + @author Oleg Sukhodolsky: area=awt.focus + @library ../../regtesthelpers + @build Util + @run main TranserFocusToWindow */ import java.awt.Button; @@ -44,10 +44,13 @@ import test.java.awt.regtesthelpers.Util; public class TranserFocusToWindow { + private static final int WIDTH = 300; + private static final int HEIGHT = 200; + public static void main(String[] args) { Robot robot = Util.createRobot(); Frame owner_frame = new Frame("Owner frame"); - owner_frame.setBounds(0, 0, 200, 200); + owner_frame.setBounds(0, 0, WIDTH, HEIGHT); owner_frame.setVisible(true); Util.waitForIdle(robot); @@ -55,7 +58,7 @@ public class TranserFocusToWindow Button btn1 = new Button("button for focus"); window.add(btn1); window.pack(); - window.setLocation(0, 300); + window.setLocation(0, HEIGHT + 100); window.setVisible(true); Util.waitForIdle(robot); @@ -63,17 +66,10 @@ public class TranserFocusToWindow Button btn2 = new Button("button in a frame"); another_frame.add(btn2); another_frame.pack(); - another_frame.setLocation(300, 0); + another_frame.setLocation(WIDTH + 100, 0); another_frame.setVisible(true); Util.waitForIdle(robot); - Util.clickOnTitle(owner_frame, robot); - Util.waitForIdle(robot); - - setFocus(btn1, robot); - - setFocus(btn2, robot); - owner_frame.addWindowFocusListener(new WindowFocusListener() { public void windowLostFocus(WindowEvent we) { System.out.println(we); @@ -100,6 +96,10 @@ public class TranserFocusToWindow } }); + Util.clickOnTitle(owner_frame, robot); + Util.waitForIdle(robot); + setFocus(btn1, robot); + setFocus(btn2, robot); // we need this delay so WM can not treat two clicks on title as double click robot.delay(500); Util.clickOnTitle(owner_frame, robot); diff --git a/jdk/test/java/awt/FontClass/DrawStringWithInfiniteXform.java b/jdk/test/java/awt/FontClass/DrawStringWithInfiniteXform.java new file mode 100644 index 00000000000..bd23226cb54 --- /dev/null +++ b/jdk/test/java/awt/FontClass/DrawStringWithInfiniteXform.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 8023213 + * @summary Font/Text APIs should not crash/takes long time + * if transform includes INIFINITY + * @run main DrawStringWithInfiniteXform + */ +import java.awt.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.util.Timer; +import java.util.TimerTask; + +public class DrawStringWithInfiniteXform { + Timer timer; + boolean done; + class ScheduleTask extends TimerTask { + public void run() { + timer.cancel(); + if (!done) { + throw new + RuntimeException("drawString with InfiniteXform transform takes long time"); + } + } + } + public DrawStringWithInfiniteXform() { + timer = new Timer(); + timer.schedule(new ScheduleTask(), 10000); + } + + public static void main(String [] args) { + DrawStringWithInfiniteXform test = new DrawStringWithInfiniteXform(); + test.start(); + } + + private void start() { + float[] vals = new float[6]; + for (int i=0;i<6;i++) vals[i]=Float.POSITIVE_INFINITY; + AffineTransform nanTX = new AffineTransform(vals); + + BufferedImage bi = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = bi.createGraphics(); + + g2d.rotate(Float.POSITIVE_INFINITY); + Font font = g2d.getFont(); + Font xfiniteFont; + for (int i=0; i<2000; i++) { + xfiniteFont = font.deriveFont(Float.POSITIVE_INFINITY); + g2d.setFont(xfiniteFont); + g2d.drawString("abc", 20, 20); + } + done = true; + System.out.println("Test passed"); + } +} diff --git a/jdk/test/java/awt/FontClass/NaNTransform.java b/jdk/test/java/awt/FontClass/NaNTransform.java new file mode 100644 index 00000000000..ab525ec2d2c --- /dev/null +++ b/jdk/test/java/awt/FontClass/NaNTransform.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/** + * @test + * @bug 6357987 6513889 8023213 + * @summary Font/Text APIs should not crash if transform includes NaN + * @author prr + * @run main NaNTransform + */ +import java.awt.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.awt.image.*; + +public class NaNTransform { + + private static void testShape(String msg, Shape s) { + if (!(new Area(s).isEmpty())) { + System.out.println(msg+"="+s); + throw new RuntimeException("Warning: expected this to be empty"); + } + } + + public static void main(String [] args) { + + float NaN=0f/0f; + float[] vals = new float[6]; + for (int i=0;i<6;i++) vals[i]=NaN; + AffineTransform nanTX = new AffineTransform(vals); + + BufferedImage bi = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = bi.createGraphics(); + + g2d.rotate(NaN); + + Font font = g2d.getFont(); + FontMetrics fm = g2d.getFontMetrics(); + FontRenderContext frc = g2d.getFontRenderContext(); + + int adv = fm.stringWidth("ABCDEF"); + if (adv != 0) { + System.out.println("strWidth="+adv); + throw new RuntimeException("Warning: expected this to be zero"); + } + testShape("strBounds", font.getStringBounds("12345", frc)); + + TextLayout tl = new TextLayout("Some text", font, frc); + testShape("tl PixelBounds 1", tl.getPixelBounds(frc, 20, 10)); + testShape("tl PixelBounds 2", tl.getPixelBounds(frc, NaN, NaN)); + testShape("tl Outline", tl.getOutline(nanTX)); + + GlyphVector gv = font.createGlyphVector(frc, "abcdef"); + testShape("gv PixelBounds 1", gv.getPixelBounds(frc, 0, 0)); + testShape("gv PixelBounds 2", gv.getPixelBounds(frc, NaN, NaN)); + testShape("gv Outline", gv.getOutline(NaN, NaN)); + + gv.setGlyphTransform(0, nanTX); + testShape("gv PixelBounds 1A", gv.getPixelBounds(frc, 0, 0)); + testShape("gv PixelBounds 2A", gv.getPixelBounds(frc, NaN, NaN)); + testShape("gv Outline A", gv.getOutline(NaN, NaN)); + + g2d.drawString("BOO!", 20, 20); + + Font nanFont; + for (int i=0; i<5000; i++) { + nanFont = font.deriveFont(Float.NaN); + g2d.setFont(nanFont); + g2d.drawString("abc", 20, 20); + } + System.out.println("Test passed (no crash)"); + } +} diff --git a/jdk/test/java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java b/jdk/test/java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java index e0da056b035..0b295470328 100644 --- a/jdk/test/java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java +++ b/jdk/test/java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java @@ -32,7 +32,7 @@ import java.awt.Robot; /** * @test - * @bug 8007219 + * @bug 8007219 8146168 * @author Alexander Scherbatiy * @summary Frame size reverts meaning of maximized attribute * @run main MaximizedToMaximized @@ -41,7 +41,8 @@ public class MaximizedToMaximized { public static void main(String[] args) throws Exception { - Frame frame = new Frame(); + Frame frame = new Frame(); + Robot robot = new Robot(); final Toolkit toolkit = Toolkit.getDefaultToolkit(); final GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment(); @@ -62,13 +63,15 @@ public class MaximizedToMaximized { frame.setBounds(availableScreenBounds.x, availableScreenBounds.y, availableScreenBounds.width, availableScreenBounds.height); frame.setVisible(true); + robot.waitForIdle(); Rectangle frameBounds = frame.getBounds(); frame.setExtendedState(Frame.MAXIMIZED_BOTH); - Robot robot = new Robot(); robot.waitForIdle(); Rectangle maximizedFrameBounds = frame.getBounds(); + + frame.dispose(); if (maximizedFrameBounds.width < frameBounds.width || maximizedFrameBounds.height < frameBounds.height) { throw new RuntimeException("Maximized frame is smaller than non maximized"); diff --git a/jdk/test/java/awt/Graphics2D/MTGraphicsAccessTest/MTGraphicsAccessTest.java b/jdk/test/java/awt/Graphics2D/MTGraphicsAccessTest/MTGraphicsAccessTest.java index 39117195a65..9545c57c220 100644 --- a/jdk/test/java/awt/Graphics2D/MTGraphicsAccessTest/MTGraphicsAccessTest.java +++ b/jdk/test/java/awt/Graphics2D/MTGraphicsAccessTest/MTGraphicsAccessTest.java @@ -23,7 +23,7 @@ /* @test - @bug 5089429 6982632 + @bug 5089429 6982632 8145808 @summary Checks that we don't crash if rendering operations and state changes are performed on a graphics context from different threads. @@ -34,6 +34,7 @@ import java.awt.*; import java.awt.image.*; import java.awt.geom.*; +import java.util.concurrent.atomic.AtomicInteger; public class MTGraphicsAccessTest { @@ -46,7 +47,7 @@ public class MTGraphicsAccessTest { static long testRunTime; volatile boolean done; - volatile int stillRunning; + AtomicInteger stillRunning = new AtomicInteger(0); volatile int numexceptions; Graphics2D sharedGraphics; @@ -108,7 +109,7 @@ public class MTGraphicsAccessTest { mysleep(testRunTime); done = true; - while (stillRunning > 0) { mysleep(500); } + while (stillRunning.get() > 0) { mysleep(500); } if (numexceptions == 0) { System.err.println("Test passed"); @@ -187,7 +188,7 @@ public class MTGraphicsAccessTest { Runnable testRunnable; public TesterThread(Runnable testRunnable) { - stillRunning++; + stillRunning.incrementAndGet(); this.testRunnable = testRunnable; } @@ -203,7 +204,7 @@ public class MTGraphicsAccessTest { } } } finally { - stillRunning--; + stillRunning.decrementAndGet(); } } } diff --git a/jdk/test/java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.java b/jdk/test/java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.java index 832713d187f..e52b6b95f13 100644 --- a/jdk/test/java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.java +++ b/jdk/test/java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.java @@ -23,7 +23,7 @@ /* test - @bug 5039416 6404008 + @bug 5039416 6404008 7087869 @summary REGRESSION: Extra mouse click dispatched after press-drag- release sequence. @library ../../regtesthelpers @build Util @@ -32,8 +32,16 @@ */ import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; import test.java.awt.regtesthelpers.Util; //** @@ -141,7 +149,12 @@ public class ExtraMouseClick extends Applet smallWin32Drag(dragWidth, dragHeight); clearFlags(); } - }else{ + } else if ("sun.lwawt.macosx.LWCToolkit".equals(sToolkit)) { + // On MacOS X every mouse move event is MOUSE_DRAGGED event and + // MOUSE_DRAGGED is sent back form the Native code to the java code + // for every mouse move. Therefore 'smallDrag test should be + // disabled for toolkit 'sun.lwawt.macosx.LWCToolkit'. + } else { for (int i = 0; i< TRIALS; i++){ smallDrag(SMUDGE_WIDTH - 1, SMUDGE_HEIGHT - 1); //on Motif and XAWT SMUDGE area is 4-pixels wide clearFlags(); @@ -157,8 +170,10 @@ public class ExtraMouseClick extends Applet for (int i = 1; i=0; --k) { + for (int k = keys.length - 1; k >= 0; --k) { robot.keyRelease(keys[k]); - robot.delay(keyDelay); + robot.delay(KEY_DELAY); } - - assertEQ(modifiersEx, modEx, "invalid extended modifiers"); + assertEQ(expectedMask, modEx, "invalid extended modifiers"); for (int k = 0; k < keys.length; ++k) { String keyText = KeyEvent.getKeyText(keys[k]).toLowerCase(); - assertTrue(exText.toLowerCase().contains(keyText), "invalid extended modifier keys description"); + assertTrue(exText.toLowerCase().contains(keyText), + "invalid extended modifier keys description"); } System.out.println(exText + " : passed"); robot.type(KeyEvent.VK_ESCAPE); - - robot.delay(robotDelay); + robot.waitForIdle(); } private void doTest() throws Exception { @@ -201,7 +209,7 @@ public class ExtendedModifiersTest implements KeyListener { String OS = System.getProperty("os.name").toLowerCase(); System.out.println(OS); - for (Component c: components) { + for (Component c : components) { String className = c.getClass().getName(); System.out.println("component class : " + className); @@ -211,18 +219,19 @@ public class ExtendedModifiersTest implements KeyListener { int yc = origin.y + c.getHeight() / 2; Point center = new Point(xc, yc); - robot.delay(robotDelay); + robot.waitForIdle(); robot.glide(origin, center); robot.click(); - robot.delay(robotDelay); + robot.waitForIdle(); // 1. shift + control runScenario(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL}, InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK); // 2. alt + shift + control - runScenario(new int[]{KeyEvent.VK_ALT, KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL}, - InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK); + runScenario(new int[]{KeyEvent.VK_ALT, KeyEvent.VK_SHIFT, + KeyEvent.VK_CONTROL}, InputEvent.ALT_DOWN_MASK + | InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK); // 3. shift runScenario(new int[]{KeyEvent.VK_SHIFT}, @@ -236,26 +245,31 @@ public class ExtendedModifiersTest implements KeyListener { runScenario(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_ALT}, InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK); - if (OS.contains("os x") || OS.contains("sunos")) { // 6. meta - runScenario(new int[]{KeyEvent.VK_META}, InputEvent.META_DOWN_MASK); + runScenario(new int[]{KeyEvent.VK_META}, + InputEvent.META_DOWN_MASK); // 7. shift + ctrl + alt + meta - runScenario(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL, KeyEvent.VK_ALT, KeyEvent.VK_META}, - InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.META_DOWN_MASK); + runScenario(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL, + KeyEvent.VK_ALT, KeyEvent.VK_META}, + InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK + | InputEvent.ALT_DOWN_MASK | InputEvent.META_DOWN_MASK); // 8. meta + shift + ctrl - runScenario(new int[]{KeyEvent.VK_META, KeyEvent.VK_SHIFT, KeyEvent.VK_CONTROL}, - InputEvent.META_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK); + runScenario(new int[]{KeyEvent.VK_META, KeyEvent.VK_SHIFT, + KeyEvent.VK_CONTROL}, InputEvent.META_DOWN_MASK + | InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK); // 9. meta + shift + alt - runScenario(new int[]{KeyEvent.VK_META, KeyEvent.VK_SHIFT, KeyEvent.VK_ALT}, - InputEvent.META_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK); + runScenario(new int[]{KeyEvent.VK_META, KeyEvent.VK_SHIFT, + KeyEvent.VK_ALT}, InputEvent.META_DOWN_MASK + | InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK); // 10. meta + ctrl + alt - runScenario(new int[]{KeyEvent.VK_META, KeyEvent.VK_CONTROL, KeyEvent.VK_ALT}, - InputEvent.META_DOWN_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK); + runScenario(new int[]{KeyEvent.VK_META, KeyEvent.VK_CONTROL, + KeyEvent.VK_ALT}, InputEvent.META_DOWN_MASK + | InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK); } } @@ -267,5 +281,4 @@ public class ExtendedModifiersTest implements KeyListener { ExtendedModifiersTest test = new ExtendedModifiersTest(); test.doTest(); } -} - +} \ No newline at end of file diff --git a/jdk/test/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java b/jdk/test/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java new file mode 100644 index 00000000000..92dcc214376 --- /dev/null +++ b/jdk/test/java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 8041928 + @summary Confirm that the Alt-Gr Modifier bit is set correctly. + @run main/manual AltGraphModifierTest + */ +import java.awt.Button; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class AltGraphModifierTest { + private static void init() throws Exception { + String[] instructions + = { + "This test is for verifying Alt-Gr modifier of an event.", + "Windows :-", + "1. Please check if Alt-Gr key is present on keyboard.", + "2. If present, press the Alt-Gr key and perform", + " mouse click on the TestWindow.", + "3. If Alt-Gr key is not present, press Ctrl+Alt keys &", + " perform mouse click on the TestWindow.", + "4. Test will exit by itself with appropriate result.", + "", + "Linux :-", + "1. Please check if Alt-Gr key is present on keyboard.", + "2. If present, press the Alt-Gr key and perform", + " mouse click on the TestWindow.", + "3. Navigate to System Settings-> Keyboard-> Shortcuts->", + " Typing.", + "4. Select an option for the Alternative Characters Key", + " For example. Right Alt", + "5. Close the settings and navigate to test", + "6. Press Right Alt Key & perform mouse click on the", + " TestWindow", + "7. Test will exit by itself with appropriate result.", + "", + "Mac :-", + " Mac fix is under progress, & will be fixed soon.", + " Please click Fail" + }; + + Sysout.createDialog(); + Sysout.printInstructions(instructions); + } + + static Frame mainFrame; + public static void initTestWindow() { + mainFrame = new Frame(); + mainFrame.setTitle("TestWindow"); + mainFrame.setSize(300, 200); + mainFrame.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + int ex = e.getModifiersEx(); + if ((ex & InputEvent.ALT_GRAPH_DOWN_MASK) == 0) { + AltGraphModifierTest.fail("Alt-Gr Modifier bit is not set."); + } else { + AltGraphModifierTest.pass(); + } + } + }); + mainFrame.setVisible(true); + } + + public static void dispose() { + Sysout.dispose(); + mainFrame.dispose(); + } + + /** + * *************************************************** + * Standard Test Machinery Section DO NOT modify anything in this section -- + * it's a standard chunk of code which has all of the synchronisation + * necessary for the test harness. By keeping it the same in all tests, it + * is easier to read and understand someone else's test, as well as insuring + * that all tests behave correctly with the test harness. There is a section + * following this for test-defined classes + * **************************************************** + */ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + private static Thread mainThread = null; + final private static int sleepTime = 300000; + + public static void main(String args[]) throws Exception { + mainThread = Thread.currentThread(); + try { + init(); + initTestWindow(); + } catch (Exception e) { + e.printStackTrace(); + } + try { + mainThread.sleep(sleepTime); + } catch (InterruptedException e) { + dispose(); + if (testGeneratedInterrupt && !theTestPassed) { + throw new Exception(failureMessage); + } + } + if (!testGeneratedInterrupt) { + dispose(); + throw new RuntimeException("Timed out after " + sleepTime / 1000 + + " seconds"); + } + } + + public static synchronized void pass() { + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail(String whyFailed) { + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + } +} + +// *********** End Standard Test Machinery Section ********** +/** + * ************************************************** + * Standard Test Machinery DO NOT modify anything below -- it's a standard chunk + * of code whose purpose is to make user interaction uniform, and thereby make + * it simpler to read and understand someone else's test. + * ************************************************** + */ +/** + * This is part of the standard test machinery. It creates a dialog (with the + * instructions), and is the interface for sending text messages to the user. To + * print the instructions, send an array of strings to Sysout.createDialog + * WithInstructions method. Put one line of instructions per array entry. To + * display a message for the tester to see, simply call Sysout.println with the + * string to be displayed. This mimics System.out.println but works within the + * test harness as well as standalone. + */ +class Sysout { + private static TestDialog dialog; + private static Frame frame; + + public static void createDialog() { + frame = new Frame(); + dialog = new TestDialog(frame, "Instructions"); + String[] defInstr = {"Instructions will appear here. ", ""}; + dialog.printInstructions(defInstr); + dialog.show(); + println("Any messages for the tester will display here."); + } + + public static void printInstructions(String[] instructions) { + dialog.printInstructions(instructions); + } + + public static void println(String messageIn) { + dialog.displayMessage(messageIn); + } + + public static void dispose() { + dialog.dispose(); + frame.dispose(); + } +} + +/** + * This is part of the standard test machinery. It provides a place for the test + * instructions to be displayed, and a place for interactive messages to the + * user to be displayed. To have the test instructions displayed, see Sysout. To + * have a message to the user be displayed, see Sysout. Do not call anything in + * this dialog directly. + */ +class TestDialog extends Dialog implements ActionListener { + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP; + Button failB; + + // DO NOT call this directly, go through Sysout + public TestDialog(Frame frame, String name) { + super(frame, name); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea("", 15, maxStringLength, scrollBoth); + add("North", instructionsText); + + messageText = new TextArea("", 5, maxStringLength, scrollBoth); + add("Center", messageText); + + buttonP = new Panel(); + failB = new Button("Fail"); + failB.setActionCommand("fail"); + failB.addActionListener(this); + buttonP.add("Center", failB); + + add("South", buttonP); + pack(); + setVisible(true); + } + + // DO NOT call this directly, go through Sysout + public void printInstructions(String[] instructions) { + instructionsText.setText(""); + String printStr, remainingStr; + for (int i = 0; i < instructions.length; i++) { + remainingStr = instructions[i]; + while (remainingStr.length() > 0) { + if (remainingStr.length() >= maxStringLength) { + int posOfSpace = remainingStr. + lastIndexOf(' ', maxStringLength - 1); + + if (posOfSpace <= 0) { + posOfSpace = maxStringLength - 1; + } + + printStr = remainingStr.substring(0, posOfSpace + 1); + remainingStr = remainingStr.substring(posOfSpace + 1); + } + else { + printStr = remainingStr; + remainingStr = ""; + } + instructionsText.append(printStr + "\n"); + } + } + } + + public void displayMessage(String messageIn) { + messageText.append(messageIn + "\n"); + } + + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand() == "fail") { + AltGraphModifierTest.fail("User Clicked Fail"); + } + } +} \ No newline at end of file diff --git a/jdk/test/java/awt/font/TextLayout/TestGetPixelBounds.java b/jdk/test/java/awt/font/TextLayout/TestGetPixelBounds.java new file mode 100644 index 00000000000..459ff695bf3 --- /dev/null +++ b/jdk/test/java/awt/font/TextLayout/TestGetPixelBounds.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6271221 8145584 + * @summary ask a text layout for its pixel bounds, then render it and + * compute the actual pixel bounds when rendering-- the actual pixel bounds + * must be contained within the bounds reported by the text layout, or there + * will be an exception. + */ + +/* + * Copyright 2005 IBM Corp. All Rights Reserved. + */ + +import java.awt.*; +import java.awt.font.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.text.*; +import java.util.*; + +import static java.awt.Font.*; +import static java.awt.font.GraphicAttribute.*; +import static java.awt.font.ShapeGraphicAttribute.*; +import static java.awt.font.TextAttribute.*; + +public class TestGetPixelBounds { + static final boolean DEBUG; + static final boolean DUMP; + static { + String dbg = null; + String dmp = null; + try { + dbg = System.getProperty("DEBUG"); + dmp = System.getProperty("DUMP"); + } + catch (SecurityException e) { + dbg = dmp = null; + } + + DEBUG = dbg != null; + DUMP = dmp != null; + } + + public static void main(String[] args) { + float x = 0; + float y = 0; + boolean rotate = false; + boolean underline = false; + boolean graphic = false; + String text = "Ping"; + for (int i = 0; i < args.length; ++i) { + String arg = args[i]; + if (arg.startsWith("-x")) { + x = Float.parseFloat(args[++i]); + } else if (arg.startsWith("-y")) { + y = Float.parseFloat(args[++i]); + } else if (arg.startsWith("-r")) { + rotate = true; + } else if (arg.startsWith("-u")) { + underline = true; + } else if (arg.startsWith("-g")) { + graphic = true; + } else if (arg.startsWith("-t")) { + text = args[++i]; + } + } + FontRenderContext frc = new FontRenderContext(null, true, true); + Map m = new HashMap(); + m.put(FAMILY, SANS_SERIF); + m.put(SIZE, 16); + if (underline) { + m.put(UNDERLINE, UNDERLINE_ON); + } + if (rotate) { + m.put(TRANSFORM, AffineTransform.getRotateInstance(Math.PI/4)); + } + Font font = Font.getFont(m); + + AttributedString as; + if (graphic) { + GraphicAttribute sga = new ShapeGraphicAttribute( + new Ellipse2D.Float(0,-10,10,20), TOP_ALIGNMENT, STROKE); + as = new AttributedString(text + '*' + text, m); + as.addAttribute(CHAR_REPLACEMENT, sga, text.length(), text.length() + 1); + } else { + as = new AttributedString(text, m); + } + TextLayout tl = new TextLayout(as.getIterator(), frc); + System.out.println("tl bounds: " + tl.getBounds()); + System.out.println("tl compute: " + computeLayoutBounds(tl, x, y, frc)); + System.out.println("tl pixel bounds: " + tl.getPixelBounds(frc, x, y)); + System.out.println(" again int off: " + tl.getPixelBounds(frc, x+2, y - 2)); + System.out.println(" again frac off: " + tl.getPixelBounds(frc, x+.5f, y + .2f)); + System.out.println(" again frc: " + tl.getPixelBounds( + new FontRenderContext(AffineTransform.getScaleInstance(100, 100), true, true), x, y)); + System.out.println(" again int off: " + tl.getPixelBounds(frc, x-2, y+2)); + + GlyphVector gv = font.createGlyphVector(frc, text); + System.out.println("gv bounds: " + gv.getPixelBounds(frc, x, y)); + System.out.println("gv compute: " + computeLayoutBounds(gv, x, y, frc)); + + if (!tl.getPixelBounds(frc, x, y).contains(computeLayoutBounds(tl, x, y, frc))) { + throw new RuntimeException("error, tl.bounds does not contain computed bounds"); + } + } + + static Rectangle computeLayoutBounds(TextLayout tl, float x, float y, FontRenderContext frc) { + Rectangle bounds = tl.getBounds().getBounds(); + BufferedImage im = new BufferedImage(bounds.width + 4, bounds.height + 4, + BufferedImage.TYPE_INT_ARGB); + + Graphics2D g2d = im.createGraphics(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, im.getWidth(), im.getHeight()); + + float fx = (float)Math.IEEEremainder(x,1); + float fy = (float)Math.IEEEremainder(y,1); + g2d.setColor(Color.BLACK); + tl.draw(g2d, fx + 2 - bounds.x, fy + 2 - bounds.y); + + Rectangle r = computePixelBounds(im); + r.x += (int)Math.floor(x) - 2 + bounds.x; + r.y += (int)Math.floor(y) - 2 + bounds.y; + + return r; + } + + static Rectangle computeLayoutBounds(GlyphVector gv, float x, float y, FontRenderContext frc) { + Rectangle bounds = gv.getVisualBounds().getBounds(); + BufferedImage im = new BufferedImage(bounds.width + 4, bounds.height + 4, + BufferedImage.TYPE_INT_ARGB); + + Graphics2D g2d = im.createGraphics(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, im.getWidth(), im.getHeight()); + + float fx = (float)Math.IEEEremainder(x,1); + float fy = (float)Math.IEEEremainder(y,1); + g2d.setColor(Color.BLACK); + g2d.drawGlyphVector(gv, fx + 2 - bounds.x, fy + 2 - bounds.y); + + Rectangle r = computePixelBounds(im); + r.x += (int)Math.floor(x) - 2 + bounds.x; + r.y += (int)Math.floor(y) - 2 + bounds.y; + + return r; + } + + static Rectangle computePixelBounds(BufferedImage im) { + int w = im.getWidth(); + int h = im.getHeight(); + + Formatter fmt = DEBUG ? new Formatter(System.err) : null; + + // dump + if (DUMP && DEBUG) { + fmt.format(" "); + for (int j = 0; j < w; ++j) { + fmt.format("%2d", j); + } + for (int i = 0; i < h; ++i) { + fmt.format("\n[%2d] ", i); + for (int j = 0; j < w; ++j) { + fmt.format("%c ", im.getRGB(j, i) == -1 ? ' ' : '*'); + } + } + fmt.format("\n"); + } + + int l = -1, t = -1, r = w, b = h; + + { + // get top + int[] buf = new int[w]; + loop: + while (++t < h) { + im.getRGB(0, t, buf.length, 1, buf, 0, w); // w ignored + for (int i = 0; i < buf.length; i++) { + if (buf[i] != -1) { + if (DEBUG) fmt.format("top pixel at %d,%d = 0x%08x\n", i, t, buf[i]); + break loop; + } + } + } + if (DEBUG) fmt.format("t: %d\n", t); + } + + // get bottom + { + int[] buf = new int[w]; + loop: + while (--b > t) { + im.getRGB(0, b, buf.length, 1, buf, 0, w); // w ignored + for (int i = 0; i < buf.length; ++i) { + if (buf[i] != -1) { + if (DEBUG) fmt.format("bottom pixel at %d,%d = 0x%08x\n", i, b, buf[i]); + break loop; + } + } + } + ++b; + if (DEBUG) fmt.format("b: %d\n", b); + } + + // get left + { + loop: + while (++l < r) { + for (int i = t; i < b; ++i) { + int v = im.getRGB(l, i); + if (v != -1) { + if (DEBUG) fmt.format("left pixel at %d,%d = 0x%08x\n", l, i, v); + break loop; + } + } + } + if (DEBUG) fmt.format("l: %d\n", l); + } + + // get right + { + loop: + while (--r > l) { + for (int i = t; i < b; ++i) { + int v = im.getRGB(r, i); + if (v != -1) { + if (DEBUG) fmt.format("right pixel at %d,%d = 0x%08x\n", r, i, v); + break loop; + } + } + } + ++r; + if (DEBUG) fmt.format("r: %d\n", r); + } + + return new Rectangle(l, t, r-l, b-t); + } +} diff --git a/jdk/test/java/awt/image/multiresolution/MultiResolutionImagePropertiesTest.java b/jdk/test/java/awt/image/multiresolution/MultiResolutionImagePropertiesTest.java new file mode 100644 index 00000000000..67bdf08c606 --- /dev/null +++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionImagePropertiesTest.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; +import java.awt.image.*; +import java.util.*; + +/* @test + * @bug 8147966 + * @summary test multiresolution image properties + * @author a.stepanov + * + * @run main MultiResolutionImagePropertiesTest + */ + +public class MultiResolutionImagePropertiesTest { + + private final static Map PROPS; + static { + PROPS = new HashMap<>(); + PROPS.put("one", "ONE"); + PROPS.put("two", "TWO"); + PROPS.put("three", "THREE"); + PROPS.put("other", "OTHER"); + PROPS.put("test", "TEST"); + } + + private final static int SZ = 100; + private final static Object UNDEF = Image.UndefinedProperty; + + private static BufferedImage generateImage(int scale, Properties p) { + + int x = (int) (SZ * scale); + BufferedImage tmp = new BufferedImage(x, x, BufferedImage.TYPE_INT_RGB); + + return new BufferedImage(tmp.getColorModel(), + tmp.getRaster(), + tmp.isAlphaPremultiplied(), + p); + } + + private static void checkProperties(BufferedImage img, + String keys[], + String undefined[]) { + boolean numOK = true; + + if (keys.length == 0) { + numOK = (img.getPropertyNames() == null); + } else { + numOK = (img.getPropertyNames().length == keys.length); + } + + if (!numOK) { + throw new RuntimeException("invalid number of properties"); + } + + for (String k: keys) { + if (!img.getProperty(k).equals(PROPS.get(k))) { + throw new RuntimeException("invalid property for name " + k); + } + } + + for (String k: undefined) { + if (!img.getProperty(k).equals(UNDEF)) { + throw new RuntimeException("property for name " + k + + " must be undefined"); + } + } + } + + private static void checkProperties(BaseMultiResolutionImage img, + String keys[], + String undefined[]) { + for (String k: keys) { + if (!img.getProperty(k, null).equals(PROPS.get(k))) { + throw new RuntimeException("invalid property for name " + k); + } + } + + for (String k: undefined) { + if (!img.getProperty(k, null).equals(UNDEF)) { + throw new RuntimeException("property for name " + k + + " must be undefined"); + } + } + } + + + public static void main(String[] args) throws Exception { + + String keys[] = new String[]{"one", "two", "three"}; + String otherKeys[] = new String[]{"other", "test"}; + String empty[] = new String[]{}; + + Properties props = new Properties(); + for (String k: keys) { props.setProperty(k, PROPS.get(k)); } + + Properties otherProps = new Properties(); + for (String k: otherKeys) { otherProps.setProperty(k, PROPS.get(k)); } + + Properties defaultProps = new Properties(); + + + // === check the default state === + BaseMultiResolutionImage image = + new BaseMultiResolutionImage(new BufferedImage[]{ + generateImage(1, defaultProps), + generateImage(2, defaultProps), + generateImage(3, defaultProps) + }); + + for (Image var: image.getResolutionVariants()) { + if (((BufferedImage) var).getPropertyNames() != null) { + throw new RuntimeException("PropertyNames should be null"); + } + } + + // === default: base image is the 1st one === + image = + new BaseMultiResolutionImage(new BufferedImage[]{ + generateImage(1, props), + generateImage(2, otherProps), + generateImage(3, defaultProps) + }); + + checkProperties(image, keys, otherKeys); + + BufferedImage var = (BufferedImage) image.getResolutionVariant(SZ, SZ); + checkProperties(var, keys, otherKeys); + + var = (BufferedImage) image.getResolutionVariant(2 * SZ, 2 * SZ); + checkProperties(var, otherKeys, keys); + + var = (BufferedImage) image.getResolutionVariant(3 * SZ, 3 * SZ); + checkProperties(var, empty, keys); + checkProperties(var, empty, otherKeys); + + // === let the 2nd image be a base one === + image = + new BaseMultiResolutionImage(1, new BufferedImage[]{ + generateImage(1, props), + generateImage(2, otherProps), + generateImage(3, defaultProps) + }); + + checkProperties(image, otherKeys, keys); + + var = (BufferedImage) image.getResolutionVariant(SZ, SZ); + checkProperties(var, keys, otherKeys); + + var = (BufferedImage) image.getResolutionVariant(2 * SZ, 2 * SZ); + checkProperties(var, otherKeys, keys); + + var = (BufferedImage) image.getResolutionVariant(3 * SZ, 3 * SZ); + checkProperties(var, empty, keys); + checkProperties(var, empty, otherKeys); + + // === let the 3rd image be a base one === + image = + new BaseMultiResolutionImage(2, new BufferedImage[]{ + generateImage(1, defaultProps), + generateImage(2, defaultProps), + generateImage(3, props) + }); + + checkProperties(image, keys, otherKeys); + + var = (BufferedImage) image.getResolutionVariant(SZ, SZ); + checkProperties(var, empty, keys); + checkProperties(var, empty, otherKeys); + + var = (BufferedImage) image.getResolutionVariant(2 * SZ, 2 * SZ); + checkProperties(var, empty, keys); + checkProperties(var, empty, otherKeys); + + var = (BufferedImage) image.getResolutionVariant(3 * SZ, 3 * SZ); + checkProperties(var, keys, otherKeys); + + // === check the other properties don't affect base === + checkProperties( + new BaseMultiResolutionImage(new BufferedImage[]{ + generateImage(1, defaultProps), + generateImage(2, props), + generateImage(3, props) + }), + empty, keys); + + checkProperties( + new BaseMultiResolutionImage(2, new BufferedImage[]{ + generateImage(1, props), + generateImage(2, props), + generateImage(3, defaultProps) + }), + empty, keys); + } +} diff --git a/jdk/test/java/lang/String/concat/CompactStringsInitialCoder.java b/jdk/test/java/lang/String/concat/CompactStringsInitialCoder.java new file mode 100644 index 00000000000..6f566c33eb9 --- /dev/null +++ b/jdk/test/java/lang/String/concat/CompactStringsInitialCoder.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary StringConcatFactory MH_INLINE_SIZED_EXACT strategy does not work with -XX:-CompactStrings + * @bug 8148869 + * + * @compile -XDstringConcat=indy -source 1.9 -target 1.9 CompactStringsInitialCoder.java + * + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -XX:+CompactStrings CompactStringsInitialCoder + * + * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 CompactStringsInitialCoder.java + * + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -XX:+CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -XX:+CompactStrings CompactStringsInitialCoder + * + * @compile -XDstringConcat=indy -source 1.9 -target 1.9 CompactStringsInitialCoder.java + * + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -XX:-CompactStrings CompactStringsInitialCoder + * + * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 CompactStringsInitialCoder.java + * + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -XX:-CompactStrings CompactStringsInitialCoder + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -XX:-CompactStrings CompactStringsInitialCoder +*/ +import java.lang.StringBuilder; + +public class CompactStringsInitialCoder { + + static String strEmpty = ""; + static String strLatin1 = "\u0042"; + static String strUTF16 = "\u4242"; + static char charLatin1 = '\u0042'; + static char charUTF16 = '\u4242'; + + public static void main(String[] args) throws Exception { + test("\u0042", "" + '\u0042'); + test("\u4242", "" + '\u4242'); + + test("\u0042", "" + charLatin1); + test("\u4242", "" + charUTF16); + + test("\u0042", strEmpty + '\u0042'); + test("\u4242", strEmpty + '\u4242'); + + test("\u0042\u0042", strLatin1 + '\u0042'); + test("\u0042\u4242", strLatin1 + '\u4242'); + test("\u4242\u0042", strUTF16 + '\u0042'); + test("\u4242\u4242", strUTF16 + '\u4242'); + + test("\u0042\u0042", "\u0042" + charLatin1); + test("\u0042\u4242", "\u0042" + charUTF16); + test("\u4242\u0042", "\u4242" + charLatin1); + test("\u4242\u4242", "\u4242" + charUTF16); + + test("\u0042\u0042", "" + charLatin1 + charLatin1); + test("\u0042\u4242", "" + charLatin1 + charUTF16); + test("\u4242\u0042", "" + charUTF16 + charLatin1); + test("\u4242\u4242", "" + charUTF16 + charUTF16); + } + + public static void test(String expected, String actual) { + if (!expected.equals(actual)) { + StringBuilder sb = new StringBuilder(); + sb.append("Expected = "); + sb.append(expected); + sb.append(", actual = "); + sb.append(actual); + throw new IllegalStateException(sb.toString()); + } + } + + +} diff --git a/jdk/test/java/lang/String/concat/ImplicitStringConcat.java b/jdk/test/java/lang/String/concat/ImplicitStringConcat.java index 5eb78602498..f0ef90d02db 100644 --- a/jdk/test/java/lang/String/concat/ImplicitStringConcat.java +++ b/jdk/test/java/lang/String/concat/ImplicitStringConcat.java @@ -26,70 +26,70 @@ * @summary test implicit String concatenations * * @compile ImplicitStringConcat.java - * @run main/othervm ImplicitStringConcat + * @run main/othervm -Xverify:all ImplicitStringConcat * * @compile -XDstringConcat=inline ImplicitStringConcat.java - * @run main/othervm ImplicitStringConcat + * @run main/othervm -Xverify:all ImplicitStringConcat * * @compile -XDstringConcat=indy -source 1.9 -target 1.9 ImplicitStringConcat.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcat * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat * * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 ImplicitStringConcat.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcat * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcat * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcat */ import java.lang.StringBuilder; diff --git a/jdk/test/java/lang/String/concat/ImplicitStringConcatArgCount.java b/jdk/test/java/lang/String/concat/ImplicitStringConcatArgCount.java index 0cc0a2a7887..108cce0b23b 100644 --- a/jdk/test/java/lang/String/concat/ImplicitStringConcatArgCount.java +++ b/jdk/test/java/lang/String/concat/ImplicitStringConcatArgCount.java @@ -26,70 +26,70 @@ * @summary Test multiple number of arguments to concatenate. * * @compile ImplicitStringConcatArgCount.java - * @run main/othervm ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all ImplicitStringConcatArgCount * * @compile -XDallowStringFolding=false -XDstringConcat=inline ImplicitStringConcatArgCount.java - * @run main/othervm ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all ImplicitStringConcatArgCount * * @compile -XDallowStringFolding=false -XDstringConcat=indy -source 1.9 -target 1.9 ImplicitStringConcatArgCount.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatArgCount * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount * * @compile -XDallowStringFolding=false -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 ImplicitStringConcatArgCount.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatArgCount * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatArgCount * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatArgCount */ public class ImplicitStringConcatArgCount { static final String s = "f"; diff --git a/jdk/test/java/lang/String/concat/ImplicitStringConcatBoundaries.java b/jdk/test/java/lang/String/concat/ImplicitStringConcatBoundaries.java index f8e677b12bb..0ae6137e9fe 100644 --- a/jdk/test/java/lang/String/concat/ImplicitStringConcatBoundaries.java +++ b/jdk/test/java/lang/String/concat/ImplicitStringConcatBoundaries.java @@ -26,70 +26,70 @@ * @summary Test the boundary values for concatenation arguments. * * @compile ImplicitStringConcatBoundaries.java - * @run main/othervm ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all ImplicitStringConcatBoundaries * * @compile -XDstringConcat=inline ImplicitStringConcatBoundaries.java - * @run main/othervm ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all ImplicitStringConcatBoundaries * * @compile -XDstringConcat=indy -source 1.9 -target 1.9 ImplicitStringConcatBoundaries.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatBoundaries * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries * * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 ImplicitStringConcatBoundaries.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatBoundaries * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatBoundaries * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatBoundaries */ diff --git a/jdk/test/java/lang/String/concat/ImplicitStringConcatMany.java b/jdk/test/java/lang/String/concat/ImplicitStringConcatMany.java index 7af7e7d5e05..00780b0758a 100644 --- a/jdk/test/java/lang/String/concat/ImplicitStringConcatMany.java +++ b/jdk/test/java/lang/String/concat/ImplicitStringConcatMany.java @@ -26,70 +26,70 @@ * @summary Test implicit String concatenations with lots of arguments. * * @compile ImplicitStringConcatMany.java - * @run main/othervm ImplicitStringConcatMany + * @run main/othervm -Xverify:all ImplicitStringConcatMany * * @compile -XDstringConcat=inline ImplicitStringConcatMany.java - * @run main/othervm ImplicitStringConcatMany + * @run main/othervm -Xverify:all ImplicitStringConcatMany * * @compile -XDstringConcat=indy -source 1.9 -target 1.9 ImplicitStringConcatMany.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatMany * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany * * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 ImplicitStringConcatMany.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatMany * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatMany * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatMany */ import java.lang.reflect.Field; diff --git a/jdk/test/java/lang/String/concat/ImplicitStringConcatManyLongs.java b/jdk/test/java/lang/String/concat/ImplicitStringConcatManyLongs.java index cc14a100cec..bea78ca8693 100644 --- a/jdk/test/java/lang/String/concat/ImplicitStringConcatManyLongs.java +++ b/jdk/test/java/lang/String/concat/ImplicitStringConcatManyLongs.java @@ -26,70 +26,70 @@ * @summary Test implicit String concatenations with lots of arguments (two-slot version) * * @compile ImplicitStringConcatManyLongs.java - * @run main/othervm ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all ImplicitStringConcatManyLongs * * @compile -XDstringConcat=inline ImplicitStringConcatManyLongs.java - * @run main/othervm ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all ImplicitStringConcatManyLongs * * @compile -XDstringConcat=indy -source 1.9 -target 1.9 ImplicitStringConcatManyLongs.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatManyLongs * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs * * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 ImplicitStringConcatManyLongs.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatManyLongs * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatManyLongs * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatManyLongs */ import java.lang.reflect.Field; diff --git a/jdk/test/java/lang/String/concat/ImplicitStringConcatShapes-head.template b/jdk/test/java/lang/String/concat/ImplicitStringConcatShapes-head.template index 10fd57f0616..f832cef1f03 100644 --- a/jdk/test/java/lang/String/concat/ImplicitStringConcatShapes-head.template +++ b/jdk/test/java/lang/String/concat/ImplicitStringConcatShapes-head.template @@ -26,70 +26,70 @@ * @summary Test implicit String concatenations, multiple shapes. * * @compile ImplicitStringConcatShapes.java - * @run main/othervm ImplicitStringConcatShapes + * @run main/othervm -Xverify:all ImplicitStringConcatShapes * * @compile -XDstringConcat=inline ImplicitStringConcatShapes.java - * @run main/othervm ImplicitStringConcatShapes + * @run main/othervm -Xverify:all ImplicitStringConcatShapes * * @compile -XDstringConcat=indy -source 1.9 -target 1.9 ImplicitStringConcatShapes.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes * * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 ImplicitStringConcatShapes.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes */ public class ImplicitStringConcatShapes { public static void test(String expected, String actual) { diff --git a/jdk/test/java/lang/String/concat/ImplicitStringConcatShapes.java b/jdk/test/java/lang/String/concat/ImplicitStringConcatShapes.java index c4a673721ae..5ed9d863810 100644 --- a/jdk/test/java/lang/String/concat/ImplicitStringConcatShapes.java +++ b/jdk/test/java/lang/String/concat/ImplicitStringConcatShapes.java @@ -26,70 +26,70 @@ * @summary Test implicit String concatenations, multiple shapes. * * @compile ImplicitStringConcatShapes.java - * @run main/othervm ImplicitStringConcatShapes + * @run main/othervm -Xverify:all ImplicitStringConcatShapes * * @compile -XDstringConcat=inline ImplicitStringConcatShapes.java - * @run main/othervm ImplicitStringConcatShapes + * @run main/othervm -Xverify:all ImplicitStringConcatShapes * * @compile -XDstringConcat=indy -source 1.9 -target 1.9 ImplicitStringConcatShapes.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes * * @compile -XDstringConcat=indyWithConstants -source 1.9 -target 1.9 ImplicitStringConcatShapes.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true ImplicitStringConcatShapes */ public class ImplicitStringConcatShapes { public static void test(String expected, String actual) { diff --git a/jdk/test/java/lang/String/concat/StringConcatFactoryEmptyMethods.java b/jdk/test/java/lang/String/concat/StringConcatFactoryEmptyMethods.java new file mode 100644 index 00000000000..31b29cd30fd --- /dev/null +++ b/jdk/test/java/lang/String/concat/StringConcatFactoryEmptyMethods.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.Serializable; +import java.lang.invoke.*; +import java.util.concurrent.Callable; + +/** + * @test + * @summary StringConcatFactory exactness check produces bad bytecode when a non-arg concat is requested + * @bug 8148787 + * + * @compile StringConcatFactoryEmptyMethods.java + * + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryEmptyMethods + * +*/ +public class StringConcatFactoryEmptyMethods { + + public static void main(String[] args) throws Throwable { + StringConcatFactory.makeConcat( + MethodHandles.lookup(), + "foo", + MethodType.methodType(String.class) + ); + + StringConcatFactory.makeConcatWithConstants( + MethodHandles.lookup(), + "foo", + MethodType.methodType(String.class), + "" + ); + } + +} diff --git a/jdk/test/java/lang/String/concat/StringConcatFactoryInvariants.java b/jdk/test/java/lang/String/concat/StringConcatFactoryInvariants.java index e1a3e8085c6..a174e3e4ffe 100644 --- a/jdk/test/java/lang/String/concat/StringConcatFactoryInvariants.java +++ b/jdk/test/java/lang/String/concat/StringConcatFactoryInvariants.java @@ -31,33 +31,33 @@ import java.util.concurrent.Callable; * * @compile StringConcatFactoryInvariants.java * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT StringConcatFactoryInvariants * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true StringConcatFactoryInvariants * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants * - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants - * @run main/othervm -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT -Djava.lang.invoke.stringConcat.debug=true -Djava.lang.invoke.stringConcat.cache=true StringConcatFactoryInvariants * */ public class StringConcatFactoryInvariants { diff --git a/jdk/test/java/lang/ref/CleanerTest.java b/jdk/test/java/lang/ref/CleanerTest.java index fedcaf88713..396fbed88bd 100644 --- a/jdk/test/java/lang/ref/CleanerTest.java +++ b/jdk/test/java/lang/ref/CleanerTest.java @@ -41,14 +41,17 @@ import jdk.internal.ref.CleanerFactory; import sun.hotspot.WhiteBox; +import jdk.test.lib.Utils; + import org.testng.Assert; import org.testng.TestNG; import org.testng.annotations.Test; /* * @test - * @library /lib/testlibrary /test/lib + * @library /test/lib/share/classes /lib/testlibrary /test/lib * @build sun.hotspot.WhiteBox + * @build jdk.test.lib.Utils * @modules java.base/jdk.internal.misc java.base/jdk.internal.ref * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run testng/othervm @@ -88,8 +91,7 @@ public class CleanerTest { CleanableCase s = setupPhantom(COMMON, cleaner); cleaner = null; - Assert.assertTrue(checkCleaned(s.getSemaphore()), - "Cleaner cleanup should have occurred"); + checkCleaned(s.getSemaphore(), true, "Cleaner was cleaned:"); } /** @@ -124,8 +126,7 @@ public class CleanerTest { CleanableCase s = setupPhantom(COMMON, cleaner); cleaner = null; - Assert.assertTrue(checkCleaned(s.getSemaphore()), - "Cleaner cleanup should have occurred"); + checkCleaned(s.getSemaphore(), true, "Cleaner was cleaned:"); } /** @@ -213,16 +214,11 @@ public class CleanerTest { CleanableCase cc = setupPhantom(COMMON, test.getCleanable()); test.clearCleanable(); // release this hard reference - boolean result = checkCleaned(test.getSemaphore()); - if (result) { - Assert.assertEquals(r, CleanableCase.EV_CLEAN, - "cleaned; but not expected"); - } else { - Assert.assertNotEquals(r, CleanableCase.EV_CLEAN, - "not cleaned; expected cleaning"); - } - Assert.assertTrue(checkCleaned(cc.getSemaphore()), - "The reference to the Cleanable should have been freed"); + checkCleaned(test.getSemaphore(), + r == CleanableCase.EV_CLEAN, + "Cleanable was cleaned:"); + checkCleaned(cc.getSemaphore(), true, + "The reference to the Cleanable was freed:"); } /** @@ -278,27 +274,32 @@ public class CleanerTest { * Check a semaphore having been released by cleanup handler. * Force a number of GC cycles to give the GC a chance to process * the Reference and for the cleanup action to be run. + * Use a larger number of cycles to wait for an expected cleaning to occur. * * @param semaphore a Semaphore - * @return true if the semaphores has 1 permit, false otherwise. + * @param expectCleaned true if cleaning should occur + * @param msg a message to explain the error */ - static boolean checkCleaned(Semaphore semaphore) { - int cycle = 0; - for (; cycle < 3; cycle++) { + static void checkCleaned(Semaphore semaphore, boolean expectCleaned, + String msg) { + long max_cycles = expectCleaned ? 10 : 3; + long cycle = 0; + for (; cycle < max_cycles; cycle++) { + // Force GC + whitebox.fullGC(); + try { - if (semaphore.tryAcquire(10L, TimeUnit.MILLISECONDS)) { + if (semaphore.tryAcquire(Utils.adjustTimeout(10L), TimeUnit.MILLISECONDS)) { System.out.printf(" Cleanable cleaned in cycle: %d%n", cycle); - return true; + Assert.assertEquals(true, expectCleaned, msg); + return; } } catch (InterruptedException ie) { // retry in outer loop } - // Force GC - whitebox.fullGC(); } // Object has not been cleaned - System.out.printf(" Cleanable not cleaned%n"); - return false; // Failing result + Assert.assertEquals(false, expectCleaned, msg); } /** @@ -622,7 +623,7 @@ public class CleanerTest { System.gc(); Assert.assertNotEquals(map.get(k2), data, "value should not be found in the map"); - final int CYCLE_MAX = 30; + final long CYCLE_MAX = Utils.adjustTimeout(30L); for (int i = 1; map.size() > 0 && i < CYCLE_MAX; i++) { map.forEach( (k, v) -> System.out.printf(" k: %s, v: %s%n", k, v)); try { @@ -699,7 +700,7 @@ public class CleanerTest { } obj = null; - Assert.assertTrue(checkCleaned(s1), "reference should be cleaned;"); + checkCleaned(s1, true, "reference was cleaned:"); cleaner = null; } @@ -713,7 +714,7 @@ public class CleanerTest { Object obj = new Object(); CleanableCase s = setupPhantom(cleaner, obj); obj = null; - Assert.assertTrue(checkCleaned(s.getSemaphore()), - "Object cleaning should have occurred using CleanerFactor.cleaner()"); + checkCleaned(s.getSemaphore(), true, + "Object was cleaned using CleanerFactor.cleaner():"); } } diff --git a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java index ef97aa3f225..6659cd861d2 100644 --- a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java +++ b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ * @build java.util.stream.OpTestCase * @run testng/othervm NetworkInterfaceStreamTest * @run testng/othervm -Djava.net.preferIPv4Stack=true NetworkInterfaceStreamTest + * @key intermittent */ import org.testng.annotations.Test; diff --git a/jdk/test/java/net/URI/URItoURLTest.java b/jdk/test/java/net/URI/URItoURLTest.java index e1a5577bb74..05fadebf8f9 100644 --- a/jdk/test/java/net/URI/URItoURLTest.java +++ b/jdk/test/java/net/URI/URItoURLTest.java @@ -23,13 +23,16 @@ /** * @test - * @bug 4768755 4677045 - * @summary URL.equal(URL) is inconsistant for opaque URI.toURL() - * and new URL(URI.toString) + * @bug 4768755 4677045 8147462 + * @summary URL.equal(URL) is inconsistent for opaque URI.toURL() + * and new URL(URI.toString) * URI.toURL() does not always work as specified + * Ensure URIs representing invalid/malformed URLs throw similar + * exception with new URL(URI.toString()) and URI.toURL() */ import java.net.*; +import java.util.Objects; public class URItoURLTest { @@ -39,19 +42,43 @@ public class URItoURLTest { URL classUrl = testClass.getClass(). getResource("/java/lang/Object.class"); - String[] uris = { "mailto:xyz@abc.de", + String[] uris = { + "mailto:xyz@abc.de", "file:xyz#ab", "http:abc/xyz/pqr", + "http:abc/xyz/pqr?id=x%0a&ca=true", "file:/C:/v700/dev/unitTesting/tests/apiUtil/uri", "http:///p", + "file:/C:/v700/dev/unitTesting/tests/apiUtil/uri", + "file:/C:/v700/dev%20src/unitTesting/tests/apiUtil/uri", + "file:/C:/v700/dev%20src/./unitTesting/./tests/apiUtil/uri", + "http://localhost:80/abc/./xyz/../pqr?id=x%0a&ca=true", + "file:./test/./x", + "file:./././%20#i=3", + "file:?hmm", + "file:.#hmm", classUrl.toExternalForm(), }; + // Strings that represent valid URIs but invalid URLs that should throw + // MalformedURLException both when calling toURL and new URL(String) + String[] malformedUrls = { + "test:/test", + "fiel:test", + }; + + // Non-absolute URIs should throw IAE when calling toURL but will throw + // MalformedURLException when calling new URL + String[] illegalUris = { + "./test", + "/test", + }; + boolean isTestFailed = false; boolean isURLFailed = false; - for (int i = 0; i < uris.length; i++) { - URI uri = URI.create(uris[i]); + for (String uriString : uris) { + URI uri = URI.create(uriString); URL url1 = new URL(uri.toString()); URL url2 = uri.toURL(); @@ -107,6 +134,42 @@ public class URItoURLTest { System.out.println(); isURLFailed = false; } + for (String malformedUrl : malformedUrls) { + Exception toURLEx = null; + Exception newURLEx = null; + try { + new URI(malformedUrl).toURL(); + } catch (Exception e) { + // expected + toURLEx = e; + } + try { + new URL(new URI(malformedUrl).toString()); + } catch (Exception e) { + // expected + newURLEx = e; + } + if (!(toURLEx instanceof MalformedURLException) || + !(newURLEx instanceof MalformedURLException) || + !toURLEx.getMessage().equals(newURLEx.getMessage())) { + isTestFailed = true; + System.out.println("Expected the same MalformedURLException: " + + newURLEx + " vs " + toURLEx); + } + } + for (String illegalUri : illegalUris) { + try { + new URI(illegalUri).toURL(); + } catch (IllegalArgumentException e) { + // pass + } + + try { + new URL(illegalUri); + } catch (MalformedURLException e) { + // pass + } + } if (isTestFailed) { throw new Exception("URI.toURL() test failed"); } diff --git a/jdk/test/java/rmi/Naming/DefaultRegistryPort.java b/jdk/test/java/rmi/Naming/DefaultRegistryPort.java index a1f2b7adfc6..0c5efcb55d8 100644 --- a/jdk/test/java/rmi/Naming/DefaultRegistryPort.java +++ b/jdk/test/java/rmi/Naming/DefaultRegistryPort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ * java.rmi/sun.rmi.transport.tcp * @build TestLibrary * @run main/othervm DefaultRegistryPort + * @key intermittent */ /* diff --git a/jdk/test/java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java b/jdk/test/java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java index 7016e00f43c..eb4d408227b 100644 --- a/jdk/test/java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java +++ b/jdk/test/java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ * java.rmi/sun.rmi.transport.tcp * @build TestLibrary Legal LegalRegistryNames_Stub * @run main/othervm LegalRegistryNames + * @key intermittent */ import java.net.InetAddress; diff --git a/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java index 7f36832e98a..12188414001 100644 --- a/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java +++ b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java @@ -58,7 +58,7 @@ public class AltSecurityManager implements Runnable { public AltSecurityManager(int port) { if (port <= 0) { - TestLibrary.bomb("Port must be greater then 0."); + TestLibrary.bomb("Port must be greater than 0."); } this.regPort = port; diff --git a/jdk/test/java/rmi/transport/closeServerSocket/CloseServerSocket.java b/jdk/test/java/rmi/transport/closeServerSocket/CloseServerSocket.java index 4209bdccc57..9525535447c 100644 --- a/jdk/test/java/rmi/transport/closeServerSocket/CloseServerSocket.java +++ b/jdk/test/java/rmi/transport/closeServerSocket/CloseServerSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ * java.rmi/sun.rmi.transport.tcp * @build TestLibrary * @run main/othervm CloseServerSocket + * @key intermittent */ import java.io.IOException; diff --git a/jdk/test/java/time/tck/java/time/TCKLocalDate.java b/jdk/test/java/time/tck/java/time/TCKLocalDate.java index 96290401c97..2b5832465c9 100644 --- a/jdk/test/java/time/tck/java/time/TCKLocalDate.java +++ b/jdk/test/java/time/tck/java/time/TCKLocalDate.java @@ -119,6 +119,8 @@ import java.time.temporal.UnsupportedTemporalTypeException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -2385,4 +2387,204 @@ public class TCKLocalDate extends AbstractDateTimeTest { assertSame(isoEra,IsoEra.CE); assertSame(LocalDate.MIN.getEra(),IsoEra.BCE); } + + //----------------------------------------------------------------- + // datesUntil() + // ---------------------------------------------------------------- + @Test + public void test_datesUntil() { + assertEquals( + date(2015, 9, 29).datesUntil(date(2015, 10, 3)).collect( + Collectors.toList()), Arrays.asList(date(2015, 9, 29), + date(2015, 9, 30), date(2015, 10, 1), date(2015, 10, 2))); + assertEquals(date(2015, 9, 29).datesUntil(date(2015, 10, 3), Period.ofDays(2)) + .collect(Collectors.toList()), Arrays.asList(date(2015, 9, 29), + date(2015, 10, 1))); + assertEquals(date(2015, 1, 31).datesUntil(date(2015, 6, 1), Period.ofMonths(1)) + .collect(Collectors.toList()), Arrays.asList(date(2015, 1, 31), + date(2015, 2, 28), date(2015, 3, 31), date(2015, 4, 30), + date(2015, 5, 31))); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_datesUntil_nullEnd() { + LocalDate date = date(2015, 1, 31); + date.datesUntil(null); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_datesUntil_nullEndStep() { + LocalDate date = date(2015, 1, 31); + date.datesUntil(null, Period.ofDays(1)); + } + + @Test(expectedExceptions=NullPointerException.class) + public void test_datesUntil_nullStep() { + LocalDate date = date(2015, 1, 31); + date.datesUntil(date, null); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void test_datesUntil_endBeforeStart() { + date(2015, 1, 31).datesUntil(date(2015, 1, 30)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void test_datesUntil_endBeforeStartPositiveStep() { + date(2015, 1, 31).datesUntil(date(2015, 1, 30), Period.of(1, 0, 0)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void test_datesUntil_endAfterStartNegativeStep() { + date(2015, 1, 30).datesUntil(date(2015, 1, 31), Period.of(0, -1, -1)); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_datesUntil_zeroStep() { + LocalDate date = date(2015, 1, 31); + date.datesUntil(date, Period.ZERO); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_datesUntil_oppositeSign() { + LocalDate date = date(2015, 1, 31); + date.datesUntil(date, Period.of(1, 0, -1)); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void test_datesUntil_oppositeSign2() { + LocalDate date = date(2015, 1, 31); + date.datesUntil(date, Period.of(0, -1, 1)); + } + + @DataProvider(name="datesUntil") + public Object[][] provider_datesUntil() { + return new Object[][] { + {MIN_DATE, MIN_DATE}, + {MIN_DATE, MAX_DATE}, + {MAX_DATE, MAX_DATE}, + {date(2015,10,1), date(2015,10,2)}, + {date(2015,10,1), date(2015,11,1)}, + {date(2015,10,31), date(2015,11,1)}, + {date(2015,10,1), MAX_DATE}, + {MIN_DATE, date(2015,10,1)} + }; + } + + @Test(dataProvider = "datesUntil") + public void test_datesUntil_count(LocalDate start, LocalDate end) { + assertEquals(start.datesUntil(end).count(), start.until(end, ChronoUnit.DAYS)); + assertEquals(start.datesUntil(end, Period.ofDays(1)).count(), + start.until(end, ChronoUnit.DAYS)); + } + + @DataProvider(name="datesUntilSteps") + public Object[][] provider_datesUntil_steps() { + List data = new ArrayList<>(Arrays.asList(new Object[][] { + {MIN_DATE, MAX_DATE, Period.ofYears(Year.MAX_VALUE)}, + {MIN_DATE, MAX_DATE, Period.ofDays(2)}, + {MIN_DATE, MAX_DATE, Period.of(1,2,3)}, + {MIN_DATE, MAX_DATE, Period.of(1,2,1000000)}, + {MIN_DATE, MAX_DATE, Period.of(1,1000000,3)}, + {MIN_DATE, MAX_DATE, Period.of(1000000,2,3)}, + {MIN_DATE, MIN_DATE.plusMonths(1), Period.ofMonths(1)}, + {MIN_DATE, date(Year.MIN_VALUE, 2, 2), Period.ofMonths(1)}, + {MIN_DATE, date(Year.MIN_VALUE, 8, 9), Period.of(0, 1, 1)}, + {MIN_DATE, MAX_DATE.minusYears(1), Period.ofYears(Year.MAX_VALUE)}, + {MAX_DATE.minusMonths(1), MAX_DATE, Period.ofMonths(1)}, + {date(Year.MAX_VALUE, 2, 20), MAX_DATE, Period.of(0, 1, 1)}, + {date(2015,1,1), date(2016,1,1), Period.ofYears(1)}, + {date(2015,1,1), date(2016,1,1), Period.ofDays(365)}, + {date(2015,1,1), date(2016,1,1), Period.ofDays(366)}, + {date(2015,1,1), date(2016,1,1), Period.ofDays(4)}, + {date(2015,1,1), date(2016,1,1), Period.of(0,1,2)}, + {date(2015,1,1), date(2016,1,1), Period.ofMonths(1)}, + {date(2015,1,1), date(2016,1,1), Period.ofMonths(12)}, + {date(2015,1,1), date(2016,1,2), Period.ofMonths(12)}, + {date(2015,1,1), date(2016,1,1), Period.of(0, 11, 30)}, + {date(2015,1,1), date(2015,12,31), Period.of(0, 11, 30)}, + {date(2015,1,31), date(2015,12,31), Period.ofMonths(2)}, + {date(2015,1,31), date(2015,12,1), Period.ofMonths(2)}, + {date(2015,1,31), date(2015,11,30), Period.ofMonths(2)}, + {date(2015,1,31), date(2030,11,30), Period.of(1,30,365)}, + {date(2015,1,31), date(2043,1,31), Period.of(4,0,0)}, + {date(2015,1,31), date(2043,2,1), Period.of(4,0,0)}, + {date(2015,1,31), date(2043,1,31), Period.of(3,11,30)}, + {date(2015,1,31), date(2043,2,1), Period.of(3,11,30)}, + {date(2015,1,31), date(2043,1,31), Period.of(0,0,1460)}, + {date(2015,1,31), date(2043,1,31), Period.of(0,0,1461)}, + {date(2015,1,31), date(2043,2,1), Period.of(0,0,1461)}, + {date(2015,1,31), MAX_DATE, Period.of(10,100,1000)}, + {date(2015,1,31), MAX_DATE, Period.of(1000000,10000,100000)}, + {date(2015,1,31), MAX_DATE, Period.ofDays(10000000)}, + {date(2015,1,31), MAX_DATE, Period.ofDays(Integer.MAX_VALUE)}, + {date(2015,1,31), MAX_DATE, Period.ofMonths(Integer.MAX_VALUE)}, + {date(2015,1,31), MAX_DATE, Period.ofYears(Integer.MAX_VALUE)} + })); + LocalDate start = date(2014, 1, 15); + LocalDate end = date(2015, 3, 4); + for (int months : new int[] { 0, 1, 2, 3, 5, 7, 12, 13 }) { + for (int days : new int[] { 0, 1, 2, 3, 5, 10, 17, 27, 28, 29, 30, 31, 32, 57, 58, 59, + 60, 61, 62, 70, 80, 90 }) { + if (months > 0 || days > 0) + data.add(new Object[] { start, end, Period.of(0, months, days) }); + } + } + for (int days = 27; days < 100; days++) { + data.add(new Object[] { start, start.plusDays(days), Period.ofMonths(1) }); + } + return data.toArray(new Object[data.size()][]); + } + + @Test(dataProvider="datesUntilSteps") + public void test_datesUntil_step(LocalDate start, LocalDate end, Period step) { + assertEquals(start.datesUntil(start, step).count(), 0); + long count = start.datesUntil(end, step).count(); + assertTrue(count > 0); + // the last value must be before the end date + assertTrue(start.plusMonths(step.toTotalMonths()*(count-1)).plusDays(step.getDays()*(count-1)).isBefore(end)); + try { + // the next after the last value must be either invalid or not before the end date + assertFalse(start.plusMonths(step.toTotalMonths()*count).plusDays(step.getDays()*count).isBefore(end)); + } catch (ArithmeticException | DateTimeException e) { + // ignore: possible overflow for the next value is ok + } + if(count < 1000) { + assertTrue(start.datesUntil(end, step).allMatch(date -> !date.isBefore(start) && date.isBefore(end))); + List list = new ArrayList<>(); + for(long i=0; i 0); + // the last value must be after the start date + assertTrue(end.minusMonths(step.toTotalMonths()*(count-1)).minusDays(step.getDays()*(count-1)).isAfter(start)); + try { + // the next after the last value must be either invalid or not after the start date + assertFalse(end.minusMonths(step.toTotalMonths()*count).minusDays(step.getDays()*count).isAfter(start)); + } catch (ArithmeticException | DateTimeException e) { + // ignore: possible overflow for the next value is ok + } + if(count < 1000) { + assertTrue(end.datesUntil(start, step.negated()).allMatch(date -> date.isAfter(start) && !date.isAfter(end))); + List list = new ArrayList<>(); + for(long i=0; i stream = date.datesUntil(date.plusDays(5)); + long sum = stream.mapToInt(LocalDate::getDayOfMonth).sum(); + assertEquals(sum, 60, "sum of 10, 11, 12, 13, 14 is wrong"); + } } diff --git a/jdk/test/java/time/tck/java/time/format/TCKDTFParsedInstant.java b/jdk/test/java/time/tck/java/time/format/TCKDTFParsedInstant.java index 11f103dd317..ec60f0f586d 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDTFParsedInstant.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDTFParsedInstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.util.Locale; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; @@ -194,7 +195,7 @@ public class TCKDTFParsedInstant { @Test(dataProvider="parseWithZoneWithoutOffset") public void testWithZoneWithoutOffset(String withZoneWithoutOffset, ZonedDateTime expectedZDT) { - dtFormatter = DateTimeFormatter.ofPattern("d MMM HH:mm:ss uuuu VV"); + dtFormatter = DateTimeFormatter.ofPattern("d MMM HH:mm:ss uuuu VV").withLocale(Locale.ENGLISH); zdt1 = ZonedDateTime.parse(withZoneWithoutOffset, dtFormatter); assertEquals(expectedZDT, zdt1); } diff --git a/jdk/test/java/time/test/java/time/TestClock_System.java b/jdk/test/java/time/test/java/time/TestClock_System.java index b311dad6e6c..55ef1cd851e 100644 --- a/jdk/test/java/time/test/java/time/TestClock_System.java +++ b/jdk/test/java/time/test/java/time/TestClock_System.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -179,11 +179,17 @@ public class TestClock_System { int count=0; // let's preheat the system a bit: + int lastNanos = 0; for (int i = 0; i < 1000 ; i++) { system1 = Instant.ofEpochMilli(System.currentTimeMillis()); - highest1 = highestUTC.instant(); final int sysnan = system1.getNano(); - final int nanos = highest1.getNano(); + int nanos; + do { + highest1 = highestUTC.instant(); + nanos = highest1.getNano(); + } while (nanos == lastNanos); // Repeat to get a different value + lastNanos = nanos; + if ((nanos % 1000000) > 0) { count++; // we have micro seconds } diff --git a/jdk/test/java/util/Collections/EmptyNavigableMap.java b/jdk/test/java/util/Collections/EmptyNavigableMap.java index 306f05657b9..5daf055786a 100644 --- a/jdk/test/java/util/Collections/EmptyNavigableMap.java +++ b/jdk/test/java/util/Collections/EmptyNavigableMap.java @@ -265,7 +265,7 @@ public class EmptyNavigableMap { navigableMap.subMap(last, true, first, false); }, IllegalArgumentException.class, description - + ": Must throw IllegalArgumentException when fromElement is not less then then toElement."); + + ": Must throw IllegalArgumentException when fromElement is not less than toElement."); navigableMap.subMap(first, true, last, false); } diff --git a/jdk/test/java/util/Collections/EmptyNavigableSet.java b/jdk/test/java/util/Collections/EmptyNavigableSet.java index fa28e097006..7541f3d363b 100644 --- a/jdk/test/java/util/Collections/EmptyNavigableSet.java +++ b/jdk/test/java/util/Collections/EmptyNavigableSet.java @@ -284,7 +284,7 @@ public class EmptyNavigableSet { navigableSet.subSet(last, true, first, false); }, IllegalArgumentException.class, description - + ": Must throw IllegalArgumentException when fromElement is not less then then toElement."); + + ": Must throw IllegalArgumentException when fromElement is not less than toElement."); navigableSet.subSet(first, true, last, false); } diff --git a/jdk/test/java/util/Map/Defaults.java b/jdk/test/java/util/Map/Defaults.java index 37c2fad21dc..7b2956f8846 100644 --- a/jdk/test/java/util/Map/Defaults.java +++ b/jdk/test/java/util/Map/Defaults.java @@ -48,11 +48,14 @@ import java.util.WeakHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiFunction; +import java.util.function.Function; import java.util.function.Supplier; import org.testng.annotations.Test; import org.testng.annotations.DataProvider; +import static java.util.Objects.requireNonNull; import static org.testng.Assert.fail; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -533,6 +536,191 @@ public class Defaults { "Should throw NPE"); } + /** A function that flipflops between running two other functions. */ + static BiFunction twoStep(AtomicBoolean b, + BiFunction first, + BiFunction second) { + return (t, u) -> { + boolean bb = b.get(); + try { + return (b.get() ? first : second).apply(t, u); + } finally { + b.set(!bb); + }}; + } + + /** + * Simulates races by modifying the map within the mapping function. + */ + @Test + public void testConcurrentMap_computeIfAbsent_racy() { + final ConcurrentMap map = new ImplementsConcurrentMap<>(); + final Long two = 2L; + Function f, g; + + // race not detected if function returns null + f = (k) -> { map.put(two, 42L); return null; }; + assertNull(map.computeIfAbsent(two, f)); + assertEquals(42L, (long)map.get(two)); + + map.clear(); + f = (k) -> { map.put(two, 42L); return 86L; }; + assertEquals(42L, (long)map.computeIfAbsent(two, f)); + assertEquals(42L, (long)map.get(two)); + + // mapping function ignored if value already exists + map.put(two, 99L); + assertEquals(99L, (long)map.computeIfAbsent(two, f)); + assertEquals(99L, (long)map.get(two)); + } + + /** + * Simulates races by modifying the map within the remapping function. + */ + @Test + public void testConcurrentMap_computeIfPresent_racy() { + final AtomicBoolean b = new AtomicBoolean(true); + final ConcurrentMap map = new ImplementsConcurrentMap<>(); + final Long two = 2L; + BiFunction f, g; + + for (Long val : new Long[] { null, 86L }) { + map.clear(); + + // Function not invoked if no mapping exists + f = (k, v) -> { map.put(two, 42L); return val; }; + assertNull(map.computeIfPresent(two, f)); + assertNull(map.get(two)); + + map.put(two, 42L); + f = (k, v) -> { map.put(two, 86L); return val; }; + g = (k, v) -> { + assertSame(two, k); + assertEquals(86L, (long)v); + return null; + }; + assertNull(map.computeIfPresent(two, twoStep(b, f, g))); + assertFalse(map.containsKey(two)); + assertTrue(b.get()); + + map.put(two, 42L); + f = (k, v) -> { map.put(two, 86L); return val; }; + g = (k, v) -> { + assertSame(two, k); + assertEquals(86L, (long)v); + return 99L; + }; + assertEquals(99L, (long)map.computeIfPresent(two, twoStep(b, f, g))); + assertTrue(map.containsKey(two)); + assertTrue(b.get()); + } + } + + @Test + public void testConcurrentMap_compute_simple() { + final ConcurrentMap map = new ImplementsConcurrentMap<>(); + BiFunction fun = (k, v) -> ((v == null) ? 0L : k + v); + assertEquals(Long.valueOf(0L), map.compute(3L, fun)); + assertEquals(Long.valueOf(3L), map.compute(3L, fun)); + assertEquals(Long.valueOf(6L), map.compute(3L, fun)); + assertNull(map.compute(3L, (k, v) -> null)); + assertTrue(map.isEmpty()); + + assertEquals(Long.valueOf(0L), map.compute(new Long(3L), fun)); + assertEquals(Long.valueOf(3L), map.compute(new Long(3L), fun)); + assertEquals(Long.valueOf(6L), map.compute(new Long(3L), fun)); + assertNull(map.compute(3L, (k, v) -> null)); + assertTrue(map.isEmpty()); + } + + /** + * Simulates races by modifying the map within the remapping function. + */ + @Test + public void testConcurrentMap_compute_racy() { + final AtomicBoolean b = new AtomicBoolean(true); + final ConcurrentMap map = new ImplementsConcurrentMap<>(); + final Long two = 2L; + BiFunction f, g; + + // null -> null is a no-op; race not detected + f = (k, v) -> { map.put(two, 42L); return null; }; + assertNull(map.compute(two, f)); + assertEquals(42L, (long)map.get(two)); + + for (Long val : new Long[] { null, 86L }) { + map.clear(); + + f = (k, v) -> { map.put(two, 42L); return 86L; }; + g = (k, v) -> { + assertSame(two, k); + assertEquals(42L, (long)v); + return k + v; + }; + assertEquals(44L, (long)map.compute(two, twoStep(b, f, g))); + assertEquals(44L, (long)map.get(two)); + assertTrue(b.get()); + + f = (k, v) -> { map.remove(two); return val; }; + g = (k, v) -> { + assertSame(two, k); + assertNull(v); + return 44L; + }; + assertEquals(44L, (long)map.compute(two, twoStep(b, f, g))); + assertEquals(44L, (long)map.get(two)); + assertTrue(map.containsKey(two)); + assertTrue(b.get()); + + f = (k, v) -> { map.remove(two); return val; }; + g = (k, v) -> { + assertSame(two, k); + assertNull(v); + return null; + }; + assertNull(map.compute(two, twoStep(b, f, g))); + assertNull(map.get(two)); + assertFalse(map.containsKey(two)); + assertTrue(b.get()); + } + } + + /** + * Simulates races by modifying the map within the remapping function. + */ + @Test + public void testConcurrentMap_merge_racy() { + final AtomicBoolean b = new AtomicBoolean(true); + final ConcurrentMap map = new ImplementsConcurrentMap<>(); + final Long two = 2L; + BiFunction f, g; + + for (Long val : new Long[] { null, 86L }) { + map.clear(); + + f = (v, w) -> { throw new AssertionError(); }; + assertEquals(99L, (long)map.merge(two, 99L, f)); + assertEquals(99L, (long)map.get(two)); + + f = (v, w) -> { map.put(two, 42L); return val; }; + g = (v, w) -> { + assertEquals(42L, (long)v); + assertEquals(3L, (long)w); + return v + w; + }; + assertEquals(45L, (long)map.merge(two, 3L, twoStep(b, f, g))); + assertEquals(45L, (long)map.get(two)); + assertTrue(b.get()); + + f = (v, w) -> { map.remove(two); return val; }; + g = (k, v) -> { throw new AssertionError(); }; + assertEquals(55L, (long)map.merge(two, 55L, twoStep(b, f, g))); + assertEquals(55L, (long)map.get(two)); + assertTrue(map.containsKey(two)); + assertFalse(b.get()); b.set(true); + } + } + public enum IntegerEnum { e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, @@ -838,13 +1026,13 @@ public class Defaults { protected ExtendsAbstractMap(M map) { this.map = map; } - public Set> entrySet() { + @Override public Set> entrySet() { return new AbstractSet>() { - public int size() { + @Override public int size() { return map.size(); } - public Iterator> iterator() { + @Override public Iterator> iterator() { final Iterator> source = map.entrySet().iterator(); return new Iterator>() { public boolean hasNext() { return source.hasNext(); } @@ -853,20 +1041,20 @@ public class Defaults { }; } - public boolean add(Map.Entry e) { + @Override public boolean add(Map.Entry e) { return map.entrySet().add(e); } }; } - public V put(K key, V value) { + @Override public V put(K key, V value) { return map.put(key, value); } } /** * A simple mutable concurrent map implementation that provides only default - * implementations of all methods. ie. none of the ConcurrentMap interface + * implementations of all methods, i.e. none of the ConcurrentMap interface * default methods have overridden implementations. * * @param Type of keys @@ -875,14 +1063,26 @@ public class Defaults { public static class ImplementsConcurrentMap extends ExtendsAbstractMap, K, V> implements ConcurrentMap { public ImplementsConcurrentMap() { super(new ConcurrentHashMap()); } - // ConcurrentMap reabstracts these methods + // ConcurrentMap reabstracts these methods. + // + // Unlike ConcurrentHashMap, we have zero tolerance for null values. - public V replace(K k, V v) { return map.replace(k, v); }; + @Override public V replace(K k, V v) { + return map.replace(requireNonNull(k), requireNonNull(v)); + } - public boolean replace(K k, V v, V vv) { return map.replace(k, v, vv); }; + @Override public boolean replace(K k, V v, V vv) { + return map.replace(requireNonNull(k), + requireNonNull(v), + requireNonNull(vv)); + } - public boolean remove(Object k, Object v) { return map.remove(k, v); } + @Override public boolean remove(Object k, Object v) { + return map.remove(requireNonNull(k), requireNonNull(v)); + } - public V putIfAbsent(K k, V v) { return map.putIfAbsent(k, v); } + @Override public V putIfAbsent(K k, V v) { + return map.putIfAbsent(requireNonNull(k), requireNonNull(v)); + } } } diff --git a/jdk/test/java/util/UUID/UUIDTest.java b/jdk/test/java/util/UUID/UUIDTest.java index 06b240fa9fa..46e91e6df06 100644 --- a/jdk/test/java/util/UUID/UUIDTest.java +++ b/jdk/test/java/util/UUID/UUIDTest.java @@ -22,9 +22,11 @@ */ /* @test - * @bug 4173528 5068772 + * @bug 4173528 5068772 8148936 * @summary Unit tests for java.util.UUID * @key randomness + * @run main/othervm -XX:+CompactStrings UUIDTest + * @run main/othervm -XX:-CompactStrings UUIDTest */ import java.util.*; diff --git a/jdk/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java b/jdk/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java new file mode 100644 index 00000000000..9e140da9f72 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java @@ -0,0 +1,635 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.AbstractExecutorService; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AbstractExecutorServiceTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AbstractExecutorServiceTest.class); + } + + /** + * A no-frills implementation of AbstractExecutorService, designed + * to test the submit methods only. + */ + static class DirectExecutorService extends AbstractExecutorService { + public void execute(Runnable r) { r.run(); } + public void shutdown() { shutdown = true; } + public List shutdownNow() { + shutdown = true; + return Collections.EMPTY_LIST; + } + public boolean isShutdown() { return shutdown; } + public boolean isTerminated() { return isShutdown(); } + public boolean awaitTermination(long timeout, TimeUnit unit) { + return isShutdown(); + } + private volatile boolean shutdown = false; + } + + /** + * execute(runnable) runs it to completion + */ + public void testExecuteRunnable() throws Exception { + ExecutorService e = new DirectExecutorService(); + final AtomicBoolean done = new AtomicBoolean(false); + Future future = e.submit(new CheckedRunnable() { + public void realRun() { + done.set(true); + }}); + assertNull(future.get()); + assertNull(future.get(0, MILLISECONDS)); + assertTrue(done.get()); + assertTrue(future.isDone()); + assertFalse(future.isCancelled()); + } + + /** + * Completed submit(callable) returns result + */ + public void testSubmitCallable() throws Exception { + ExecutorService e = new DirectExecutorService(); + Future future = e.submit(new StringTask()); + String result = future.get(); + assertSame(TEST_STRING, result); + } + + /** + * Completed submit(runnable) returns successfully + */ + public void testSubmitRunnable() throws Exception { + ExecutorService e = new DirectExecutorService(); + Future future = e.submit(new NoOpRunnable()); + future.get(); + assertTrue(future.isDone()); + } + + /** + * Completed submit(runnable, result) returns result + */ + public void testSubmitRunnable2() throws Exception { + ExecutorService e = new DirectExecutorService(); + Future future = e.submit(new NoOpRunnable(), TEST_STRING); + String result = future.get(); + assertSame(TEST_STRING, result); + } + + /** + * A submitted privileged action runs to completion + */ + public void testSubmitPrivilegedAction() throws Exception { + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + ExecutorService e = new DirectExecutorService(); + Future future = e.submit(Executors.callable(new PrivilegedAction() { + public Object run() { + return TEST_STRING; + }})); + + assertSame(TEST_STRING, future.get()); + }}; + + runWithPermissions(r, + new RuntimePermission("getClassLoader"), + new RuntimePermission("setContextClassLoader"), + new RuntimePermission("modifyThread")); + } + + /** + * A submitted privileged exception action runs to completion + */ + public void testSubmitPrivilegedExceptionAction() throws Exception { + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + ExecutorService e = new DirectExecutorService(); + Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() { + public Object run() { + return TEST_STRING; + }})); + + assertSame(TEST_STRING, future.get()); + }}; + + runWithPermissions(r); + } + + /** + * A submitted failed privileged exception action reports exception + */ + public void testSubmitFailedPrivilegedExceptionAction() throws Exception { + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + ExecutorService e = new DirectExecutorService(); + Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() { + public Object run() throws Exception { + throw new IndexOutOfBoundsException(); + }})); + + try { + future.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof IndexOutOfBoundsException); + }}}; + + runWithPermissions(r); + } + + /** + * execute(null runnable) throws NPE + */ + public void testExecuteNullRunnable() { + ExecutorService e = new DirectExecutorService(); + try { + e.submit((Runnable) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * submit(null callable) throws NPE + */ + public void testSubmitNullCallable() { + ExecutorService e = new DirectExecutorService(); + try { + e.submit((Callable) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * submit(callable).get() throws InterruptedException if interrupted + */ + public void testInterruptedSubmit() throws InterruptedException { + final CountDownLatch submitted = new CountDownLatch(1); + final CountDownLatch quittingTime = new CountDownLatch(1); + final Callable awaiter = new CheckedCallable() { + public Void realCall() throws InterruptedException { + assertTrue(quittingTime.await(2*LONG_DELAY_MS, MILLISECONDS)); + return null; + }}; + final ExecutorService p + = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, quittingTime)) { + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws Exception { + Future future = p.submit(awaiter); + submitted.countDown(); + future.get(); + }}); + + await(submitted); + t.interrupt(); + awaitTermination(t); + } + } + + /** + * get of submit(callable) throws ExecutionException if callable + * throws exception + */ + public void testSubmitEE() throws InterruptedException { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + 60, TimeUnit.SECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + Callable c = new Callable() { + public Object call() { throw new ArithmeticException(); }}; + try { + p.submit(c).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof ArithmeticException); + } + } + } + + /** + * invokeAny(null) throws NPE + */ + public void testInvokeAny1() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAny(empty collection) throws IAE + */ + public void testInvokeAny2() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * invokeAny(c) throws NPE if c has null elements + */ + public void testInvokeAny3() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new Callable() { + public Long call() { throw new ArithmeticException(); }}); + l.add(null); + try { + e.invokeAny(l); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAny(c) throws ExecutionException if no task in c completes + */ + public void testInvokeAny4() throws InterruptedException { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAny(c) returns result of some task in c if at least one completes + */ + public void testInvokeAny5() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAll(null) throws NPE + */ + public void testInvokeAll1() throws InterruptedException { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAll(empty collection) returns empty collection + */ + public void testInvokeAll2() throws InterruptedException { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>()); + assertTrue(r.isEmpty()); + } + } + + /** + * invokeAll(c) throws NPE if c has null elements + */ + public void testInvokeAll3() throws InterruptedException { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of returned element of invokeAll(c) throws exception on failed task + */ + public void testInvokeAll4() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = e.invokeAll(l); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAll(c) returns results of all completed tasks in c + */ + public void testInvokeAll5() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = e.invokeAll(l); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAny(null) throws NPE + */ + public void testTimedInvokeAny1() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(null time unit) throws NPE + */ + public void testTimedInvokeAnyNullTimeUnit() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(empty collection) throws IAE + */ + public void testTimedInvokeAny2() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * timed invokeAny(c) throws NPE if c has null elements + */ + public void testTimedInvokeAny3() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new Callable() { + public Long call() { throw new ArithmeticException(); }}); + l.add(null); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(c) throws ExecutionException if no task completes + */ + public void testTimedInvokeAny4() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAny(c) returns result of some task in c + */ + public void testTimedInvokeAny5() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + assertSame(TEST_STRING, result); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAll(null) throws NPE + */ + public void testTimedInvokeAll1() throws InterruptedException { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(null time unit) throws NPE + */ + public void testTimedInvokeAllNullTimeUnit() throws InterruptedException { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(empty collection) returns empty collection + */ + public void testTimedInvokeAll2() throws InterruptedException { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>(), MEDIUM_DELAY_MS, MILLISECONDS); + assertTrue(r.isEmpty()); + } + } + + /** + * timed invokeAll(c) throws NPE if c has null elements + */ + public void testTimedInvokeAll3() throws InterruptedException { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of returned element of invokeAll(c) throws exception on failed task + */ + public void testTimedInvokeAll4() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = + e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * timed invokeAll(c) returns results of all completed tasks in c + */ + public void testTimedInvokeAll5() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = + e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAll cancels tasks not completed by timeout + */ + public void testTimedInvokeAll6() throws Exception { + final ExecutorService e = new DirectExecutorService(); + try (PoolCleaner cleaner = cleaner(e)) { + for (long timeout = timeoutMillis();;) { + List> tasks = new ArrayList<>(); + tasks.add(new StringTask("0")); + tasks.add(Executors.callable(possiblyInterruptedRunnable(timeout), + TEST_STRING)); + tasks.add(new StringTask("2")); + long startTime = System.nanoTime(); + List> futures = + e.invokeAll(tasks, timeout, MILLISECONDS); + assertEquals(tasks.size(), futures.size()); + assertTrue(millisElapsedSince(startTime) >= timeout); + for (Future future : futures) + assertTrue(future.isDone()); + try { + assertEquals("0", futures.get(0).get()); + assertEquals(TEST_STRING, futures.get(1).get()); + } catch (CancellationException retryWithLongerTimeout) { + // unusual delay before starting second task + timeout *= 2; + if (timeout >= LONG_DELAY_MS / 2) + fail("expected exactly one task to be cancelled"); + continue; + } + assertTrue(futures.get(2).isCancelled()); + break; + } + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AbstractQueueTest.java b/jdk/test/java/util/concurrent/tck/AbstractQueueTest.java new file mode 100644 index 00000000000..ddc769d3a45 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AbstractQueueTest.java @@ -0,0 +1,205 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.AbstractQueue; +import java.util.Arrays; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AbstractQueueTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AbstractQueueTest.class); + } + + static class Succeed extends AbstractQueue { + public boolean offer(Integer x) { + if (x == null) throw new NullPointerException(); + return true; + } + public Integer peek() { return one; } + public Integer poll() { return one; } + public int size() { return 0; } + public Iterator iterator() { return null; } // not needed + } + + static class Fail extends AbstractQueue { + public boolean offer(Integer x) { + if (x == null) throw new NullPointerException(); + return false; + } + public Integer peek() { return null; } + public Integer poll() { return null; } + public int size() { return 0; } + public Iterator iterator() { return null; } // not needed + } + + /** + * add returns true if offer succeeds + */ + public void testAddS() { + Succeed q = new Succeed(); + assertTrue(q.add(two)); + } + + /** + * add throws ISE true if offer fails + */ + public void testAddF() { + Fail q = new Fail(); + try { + q.add(one); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * add throws NPE if offer does + */ + public void testAddNPE() { + Succeed q = new Succeed(); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove returns normally if poll succeeds + */ + public void testRemoveS() { + Succeed q = new Succeed(); + q.remove(); + } + + /** + * remove throws NSEE if poll returns null + */ + public void testRemoveF() { + Fail q = new Fail(); + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * element returns normally if peek succeeds + */ + public void testElementS() { + Succeed q = new Succeed(); + q.element(); + } + + /** + * element throws NSEE if peek returns null + */ + public void testElementF() { + Fail q = new Fail(); + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + Succeed q = new Succeed(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll(this) throws IAE + */ + public void testAddAllSelf() { + Succeed q = new Succeed(); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testAddAll2() { + Succeed q = new Succeed(); + Integer[] ints = new Integer[SIZE]; + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + Succeed q = new Succeed(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll throws ISE if an add fails + */ + public void testAddAll4() { + Fail q = new Fail(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (IllegalStateException success) {} + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java b/jdk/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java new file mode 100644 index 00000000000..88bdd13b4dc --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java @@ -0,0 +1,1280 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; +import java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AbstractQueuedLongSynchronizerTest.class); + } + + /** + * A simple mutex class, adapted from the class javadoc. Exclusive + * acquire tests exercise this as a sample user extension. + */ + static class Mutex extends AbstractQueuedLongSynchronizer { + /** An eccentric value > 32 bits for locked synchronizer state. */ + static final long LOCKED = (1L << 63) | (1L << 15); + + static final long UNLOCKED = 0; + + public boolean isHeldExclusively() { + long state = getState(); + assertTrue(state == UNLOCKED || state == LOCKED); + return state == LOCKED; + } + + public boolean tryAcquire(long acquires) { + assertEquals(LOCKED, acquires); + return compareAndSetState(UNLOCKED, LOCKED); + } + + public boolean tryRelease(long releases) { + if (getState() != LOCKED) throw new IllegalMonitorStateException(); + setState(UNLOCKED); + return true; + } + + public boolean tryAcquireNanos(long nanos) throws InterruptedException { + return tryAcquireNanos(LOCKED, nanos); + } + + public boolean tryAcquire() { + return tryAcquire(LOCKED); + } + + public boolean tryRelease() { + return tryRelease(LOCKED); + } + + public void acquire() { + acquire(LOCKED); + } + + public void acquireInterruptibly() throws InterruptedException { + acquireInterruptibly(LOCKED); + } + + public void release() { + release(LOCKED); + } + + public ConditionObject newCondition() { + return new ConditionObject(); + } + } + + /** + * A simple latch class, to test shared mode. + */ + static class BooleanLatch extends AbstractQueuedLongSynchronizer { + public boolean isSignalled() { return getState() != 0; } + + public long tryAcquireShared(long ignore) { + return isSignalled() ? 1 : -1; + } + + public boolean tryReleaseShared(long ignore) { + setState(1L << 62); + return true; + } + } + + /** + * A runnable calling acquireInterruptibly that does not expect to + * be interrupted. + */ + class InterruptibleSyncRunnable extends CheckedRunnable { + final Mutex sync; + InterruptibleSyncRunnable(Mutex sync) { this.sync = sync; } + public void realRun() throws InterruptedException { + sync.acquireInterruptibly(); + } + } + + /** + * A runnable calling acquireInterruptibly that expects to be + * interrupted. + */ + class InterruptedSyncRunnable extends CheckedInterruptedRunnable { + final Mutex sync; + InterruptedSyncRunnable(Mutex sync) { this.sync = sync; } + public void realRun() throws InterruptedException { + sync.acquireInterruptibly(); + } + } + + /** A constant to clarify calls to checking methods below. */ + static final Thread[] NO_THREADS = new Thread[0]; + + /** + * Spin-waits until sync.isQueued(t) becomes true. + */ + void waitForQueuedThread(AbstractQueuedLongSynchronizer sync, + Thread t) { + long startTime = System.nanoTime(); + while (!sync.isQueued(t)) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + throw new AssertionFailedError("timed out"); + Thread.yield(); + } + assertTrue(t.isAlive()); + } + + /** + * Checks that sync has exactly the given queued threads. + */ + void assertHasQueuedThreads(AbstractQueuedLongSynchronizer sync, + Thread... expected) { + Collection actual = sync.getQueuedThreads(); + assertEquals(expected.length > 0, sync.hasQueuedThreads()); + assertEquals(expected.length, sync.getQueueLength()); + assertEquals(expected.length, actual.size()); + assertEquals(expected.length == 0, actual.isEmpty()); + assertEquals(new HashSet(actual), + new HashSet(Arrays.asList(expected))); + } + + /** + * Checks that sync has exactly the given (exclusive) queued threads. + */ + void assertHasExclusiveQueuedThreads(AbstractQueuedLongSynchronizer sync, + Thread... expected) { + assertHasQueuedThreads(sync, expected); + assertEquals(new HashSet(sync.getExclusiveQueuedThreads()), + new HashSet(sync.getQueuedThreads())); + assertEquals(0, sync.getSharedQueuedThreads().size()); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + } + + /** + * Checks that sync has exactly the given (shared) queued threads. + */ + void assertHasSharedQueuedThreads(AbstractQueuedLongSynchronizer sync, + Thread... expected) { + assertHasQueuedThreads(sync, expected); + assertEquals(new HashSet(sync.getSharedQueuedThreads()), + new HashSet(sync.getQueuedThreads())); + assertEquals(0, sync.getExclusiveQueuedThreads().size()); + assertTrue(sync.getExclusiveQueuedThreads().isEmpty()); + } + + /** + * Checks that condition c has exactly the given waiter threads, + * after acquiring mutex. + */ + void assertHasWaitersUnlocked(Mutex sync, ConditionObject c, + Thread... threads) { + sync.acquire(); + assertHasWaitersLocked(sync, c, threads); + sync.release(); + } + + /** + * Checks that condition c has exactly the given waiter threads. + */ + void assertHasWaitersLocked(Mutex sync, ConditionObject c, + Thread... threads) { + assertEquals(threads.length > 0, sync.hasWaiters(c)); + assertEquals(threads.length, sync.getWaitQueueLength(c)); + assertEquals(threads.length == 0, sync.getWaitingThreads(c).isEmpty()); + assertEquals(threads.length, sync.getWaitingThreads(c).size()); + assertEquals(new HashSet(sync.getWaitingThreads(c)), + new HashSet(Arrays.asList(threads))); + } + + enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil } + + /** + * Awaits condition using the specified AwaitMethod. + */ + void await(ConditionObject c, AwaitMethod awaitMethod) + throws InterruptedException { + long timeoutMillis = 2 * LONG_DELAY_MS; + switch (awaitMethod) { + case await: + c.await(); + break; + case awaitTimed: + assertTrue(c.await(timeoutMillis, MILLISECONDS)); + break; + case awaitNanos: + long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis); + long nanosRemaining = c.awaitNanos(nanosTimeout); + assertTrue(nanosRemaining > 0); + break; + case awaitUntil: + assertTrue(c.awaitUntil(delayedDate(timeoutMillis))); + break; + default: + throw new AssertionError(); + } + } + + /** + * Checks that awaiting the given condition times out (using the + * default timeout duration). + */ + void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) { + long timeoutMillis = timeoutMillis(); + long startTime; + try { + switch (awaitMethod) { + case awaitTimed: + startTime = System.nanoTime(); + assertFalse(c.await(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + break; + case awaitNanos: + startTime = System.nanoTime(); + long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis); + long nanosRemaining = c.awaitNanos(nanosTimeout); + assertTrue(nanosRemaining <= 0); + assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + break; + case awaitUntil: + // We shouldn't assume that nanoTime and currentTimeMillis + // use the same time source, so don't use nanoTime here. + java.util.Date delayedDate = delayedDate(timeoutMillis()); + assertFalse(c.awaitUntil(delayedDate(timeoutMillis))); + assertTrue(new java.util.Date().getTime() >= delayedDate.getTime()); + break; + default: + throw new UnsupportedOperationException(); + } + } catch (InterruptedException ie) { threadUnexpectedException(ie); } + } + + /** + * isHeldExclusively is false upon construction + */ + public void testIsHeldExclusively() { + Mutex sync = new Mutex(); + assertFalse(sync.isHeldExclusively()); + } + + /** + * acquiring released sync succeeds + */ + public void testAcquire() { + Mutex sync = new Mutex(); + sync.acquire(); + assertTrue(sync.isHeldExclusively()); + sync.release(); + assertFalse(sync.isHeldExclusively()); + } + + /** + * tryAcquire on a released sync succeeds + */ + public void testTryAcquire() { + Mutex sync = new Mutex(); + assertTrue(sync.tryAcquire()); + assertTrue(sync.isHeldExclusively()); + sync.release(); + assertFalse(sync.isHeldExclusively()); + } + + /** + * hasQueuedThreads reports whether there are waiting threads + */ + public void testHasQueuedThreads() { + final Mutex sync = new Mutex(); + assertFalse(sync.hasQueuedThreads()); + sync.acquire(); + Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t1); + assertTrue(sync.hasQueuedThreads()); + Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync)); + waitForQueuedThread(sync, t2); + assertTrue(sync.hasQueuedThreads()); + t1.interrupt(); + awaitTermination(t1); + assertTrue(sync.hasQueuedThreads()); + sync.release(); + awaitTermination(t2); + assertFalse(sync.hasQueuedThreads()); + } + + /** + * isQueued(null) throws NullPointerException + */ + public void testIsQueuedNPE() { + final Mutex sync = new Mutex(); + try { + sync.isQueued(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * isQueued reports whether a thread is queued + */ + public void testIsQueued() { + final Mutex sync = new Mutex(); + Thread t1 = new Thread(new InterruptedSyncRunnable(sync)); + Thread t2 = new Thread(new InterruptibleSyncRunnable(sync)); + assertFalse(sync.isQueued(t1)); + assertFalse(sync.isQueued(t2)); + sync.acquire(); + t1.start(); + waitForQueuedThread(sync, t1); + assertTrue(sync.isQueued(t1)); + assertFalse(sync.isQueued(t2)); + t2.start(); + waitForQueuedThread(sync, t2); + assertTrue(sync.isQueued(t1)); + assertTrue(sync.isQueued(t2)); + t1.interrupt(); + awaitTermination(t1); + assertFalse(sync.isQueued(t1)); + assertTrue(sync.isQueued(t2)); + sync.release(); + awaitTermination(t2); + assertFalse(sync.isQueued(t1)); + assertFalse(sync.isQueued(t2)); + } + + /** + * getFirstQueuedThread returns first waiting thread or null if none + */ + public void testGetFirstQueuedThread() { + final Mutex sync = new Mutex(); + assertNull(sync.getFirstQueuedThread()); + sync.acquire(); + Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t1); + assertEquals(t1, sync.getFirstQueuedThread()); + Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync)); + waitForQueuedThread(sync, t2); + assertEquals(t1, sync.getFirstQueuedThread()); + t1.interrupt(); + awaitTermination(t1); + assertEquals(t2, sync.getFirstQueuedThread()); + sync.release(); + awaitTermination(t2); + assertNull(sync.getFirstQueuedThread()); + } + + /** + * hasContended reports false if no thread has ever blocked, else true + */ + public void testHasContended() { + final Mutex sync = new Mutex(); + assertFalse(sync.hasContended()); + sync.acquire(); + assertFalse(sync.hasContended()); + Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t1); + assertTrue(sync.hasContended()); + Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync)); + waitForQueuedThread(sync, t2); + assertTrue(sync.hasContended()); + t1.interrupt(); + awaitTermination(t1); + assertTrue(sync.hasContended()); + sync.release(); + awaitTermination(t2); + assertTrue(sync.hasContended()); + } + + /** + * getQueuedThreads returns all waiting threads + */ + public void testGetQueuedThreads() { + final Mutex sync = new Mutex(); + Thread t1 = new Thread(new InterruptedSyncRunnable(sync)); + Thread t2 = new Thread(new InterruptibleSyncRunnable(sync)); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + sync.acquire(); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + t1.start(); + waitForQueuedThread(sync, t1); + assertHasExclusiveQueuedThreads(sync, t1); + assertTrue(sync.getQueuedThreads().contains(t1)); + assertFalse(sync.getQueuedThreads().contains(t2)); + t2.start(); + waitForQueuedThread(sync, t2); + assertHasExclusiveQueuedThreads(sync, t1, t2); + assertTrue(sync.getQueuedThreads().contains(t1)); + assertTrue(sync.getQueuedThreads().contains(t2)); + t1.interrupt(); + awaitTermination(t1); + assertHasExclusiveQueuedThreads(sync, t2); + sync.release(); + awaitTermination(t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + } + + /** + * getExclusiveQueuedThreads returns all exclusive waiting threads + */ + public void testGetExclusiveQueuedThreads() { + final Mutex sync = new Mutex(); + Thread t1 = new Thread(new InterruptedSyncRunnable(sync)); + Thread t2 = new Thread(new InterruptibleSyncRunnable(sync)); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + sync.acquire(); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + t1.start(); + waitForQueuedThread(sync, t1); + assertHasExclusiveQueuedThreads(sync, t1); + assertTrue(sync.getExclusiveQueuedThreads().contains(t1)); + assertFalse(sync.getExclusiveQueuedThreads().contains(t2)); + t2.start(); + waitForQueuedThread(sync, t2); + assertHasExclusiveQueuedThreads(sync, t1, t2); + assertTrue(sync.getExclusiveQueuedThreads().contains(t1)); + assertTrue(sync.getExclusiveQueuedThreads().contains(t2)); + t1.interrupt(); + awaitTermination(t1); + assertHasExclusiveQueuedThreads(sync, t2); + sync.release(); + awaitTermination(t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + } + + /** + * getSharedQueuedThreads does not include exclusively waiting threads + */ + public void testGetSharedQueuedThreads_Exclusive() { + final Mutex sync = new Mutex(); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + sync.acquire(); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t1); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync)); + waitForQueuedThread(sync, t2); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + t1.interrupt(); + awaitTermination(t1); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + sync.release(); + awaitTermination(t2); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + } + + /** + * getSharedQueuedThreads returns all shared waiting threads + */ + public void testGetSharedQueuedThreads_Shared() { + final BooleanLatch l = new BooleanLatch(); + assertHasSharedQueuedThreads(l, NO_THREADS); + Thread t1 = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + l.acquireSharedInterruptibly(0); + }}); + waitForQueuedThread(l, t1); + assertHasSharedQueuedThreads(l, t1); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + l.acquireSharedInterruptibly(0); + }}); + waitForQueuedThread(l, t2); + assertHasSharedQueuedThreads(l, t1, t2); + t1.interrupt(); + awaitTermination(t1); + assertHasSharedQueuedThreads(l, t2); + assertTrue(l.releaseShared(0)); + awaitTermination(t2); + assertHasSharedQueuedThreads(l, NO_THREADS); + } + + /** + * tryAcquireNanos is interruptible + */ + public void testTryAcquireNanos_Interruptible() { + final Mutex sync = new Mutex(); + sync.acquire(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + sync.tryAcquireNanos(MILLISECONDS.toNanos(2 * LONG_DELAY_MS)); + }}); + + waitForQueuedThread(sync, t); + t.interrupt(); + awaitTermination(t); + } + + /** + * tryAcquire on exclusively held sync fails + */ + public void testTryAcquireWhenSynced() { + final Mutex sync = new Mutex(); + sync.acquire(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertFalse(sync.tryAcquire()); + }}); + + awaitTermination(t); + sync.release(); + } + + /** + * tryAcquireNanos on an exclusively held sync times out + */ + public void testAcquireNanos_Timeout() { + final Mutex sync = new Mutex(); + sync.acquire(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + long nanos = MILLISECONDS.toNanos(timeoutMillis()); + assertFalse(sync.tryAcquireNanos(nanos)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}); + + awaitTermination(t); + sync.release(); + } + + /** + * getState is true when acquired and false when not + */ + public void testGetState() { + final Mutex sync = new Mutex(); + sync.acquire(); + assertTrue(sync.isHeldExclusively()); + sync.release(); + assertFalse(sync.isHeldExclusively()); + + final BooleanLatch acquired = new BooleanLatch(); + final BooleanLatch done = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertTrue(acquired.releaseShared(0)); + done.acquireShared(0); + sync.release(); + }}); + + acquired.acquireShared(0); + assertTrue(sync.isHeldExclusively()); + assertTrue(done.releaseShared(0)); + awaitTermination(t); + assertFalse(sync.isHeldExclusively()); + } + + /** + * acquireInterruptibly succeeds when released, else is interruptible + */ + public void testAcquireInterruptibly() throws InterruptedException { + final Mutex sync = new Mutex(); + final BooleanLatch threadStarted = new BooleanLatch(); + sync.acquireInterruptibly(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + assertTrue(threadStarted.releaseShared(0)); + sync.acquireInterruptibly(); + }}); + + threadStarted.acquireShared(0); + waitForQueuedThread(sync, t); + t.interrupt(); + awaitTermination(t); + assertTrue(sync.isHeldExclusively()); + } + + /** + * owns is true for a condition created by sync else false + */ + public void testOwns() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final Mutex sync2 = new Mutex(); + assertTrue(sync.owns(c)); + assertFalse(sync2.owns(c)); + } + + /** + * Calling await without holding sync throws IllegalMonitorStateException + */ + public void testAwait_IMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + for (AwaitMethod awaitMethod : AwaitMethod.values()) { + long startTime = System.nanoTime(); + try { + await(c, awaitMethod); + shouldThrow(); + } catch (IllegalMonitorStateException success) { + } catch (InterruptedException e) { threadUnexpectedException(e); } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * Calling signal without holding sync throws IllegalMonitorStateException + */ + public void testSignal_IMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + c.signal(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * Calling signalAll without holding sync throws IllegalMonitorStateException + */ + public void testSignalAll_IMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + c.signalAll(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * await/awaitNanos/awaitUntil without a signal times out + */ + public void testAwaitTimed_Timeout() { testAwait_Timeout(AwaitMethod.awaitTimed); } + public void testAwaitNanos_Timeout() { testAwait_Timeout(AwaitMethod.awaitNanos); } + public void testAwaitUntil_Timeout() { testAwait_Timeout(AwaitMethod.awaitUntil); } + public void testAwait_Timeout(AwaitMethod awaitMethod) { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + sync.acquire(); + assertAwaitTimesOut(c, awaitMethod); + sync.release(); + } + + /** + * await/awaitNanos/awaitUntil returns when signalled + */ + public void testSignal_await() { testSignal(AwaitMethod.await); } + public void testSignal_awaitTimed() { testSignal(AwaitMethod.awaitTimed); } + public void testSignal_awaitNanos() { testSignal(AwaitMethod.awaitNanos); } + public void testSignal_awaitUntil() { testSignal(AwaitMethod.awaitUntil); } + public void testSignal(final AwaitMethod awaitMethod) { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertTrue(acquired.releaseShared(0)); + await(c, awaitMethod); + sync.release(); + }}); + + acquired.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + c.signal(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t); + sync.release(); + awaitTermination(t); + } + + /** + * hasWaiters(null) throws NullPointerException + */ + public void testHasWaitersNPE() { + final Mutex sync = new Mutex(); + try { + sync.hasWaiters(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getWaitQueueLength(null) throws NullPointerException + */ + public void testGetWaitQueueLengthNPE() { + final Mutex sync = new Mutex(); + try { + sync.getWaitQueueLength(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getWaitingThreads throws NPE if null + */ + public void testGetWaitingThreadsNPE() { + final Mutex sync = new Mutex(); + try { + sync.getWaitingThreads(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * hasWaiters throws IllegalArgumentException if not owned + */ + public void testHasWaitersIAE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final Mutex sync2 = new Mutex(); + try { + sync2.hasWaiters(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * hasWaiters throws IllegalMonitorStateException if not synced + */ + public void testHasWaitersIMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + sync.hasWaiters(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitQueueLength throws IllegalArgumentException if not owned + */ + public void testGetWaitQueueLengthIAE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final Mutex sync2 = new Mutex(); + try { + sync2.getWaitQueueLength(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitQueueLength throws IllegalMonitorStateException if not synced + */ + public void testGetWaitQueueLengthIMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + sync.getWaitQueueLength(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitingThreads throws IllegalArgumentException if not owned + */ + public void testGetWaitingThreadsIAE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final Mutex sync2 = new Mutex(); + try { + sync2.getWaitingThreads(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitingThreads throws IllegalMonitorStateException if not synced + */ + public void testGetWaitingThreadsIMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + sync.getWaitingThreads(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * hasWaiters returns true when a thread is waiting, else false + */ + public void testHasWaiters() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertFalse(sync.hasWaiters(c)); + assertTrue(acquired.releaseShared(0)); + c.await(); + sync.release(); + }}); + + acquired.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + assertTrue(sync.hasWaiters(c)); + c.signal(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t); + assertFalse(sync.hasWaiters(c)); + sync.release(); + + awaitTermination(t); + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitQueueLength returns number of waiting threads + */ + public void testGetWaitQueueLength() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired1 = new BooleanLatch(); + final BooleanLatch acquired2 = new BooleanLatch(); + final Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertEquals(0, sync.getWaitQueueLength(c)); + assertTrue(acquired1.releaseShared(0)); + c.await(); + sync.release(); + }}); + acquired1.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1); + assertEquals(1, sync.getWaitQueueLength(c)); + sync.release(); + + final Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, t1); + assertEquals(1, sync.getWaitQueueLength(c)); + assertTrue(acquired2.releaseShared(0)); + c.await(); + sync.release(); + }}); + acquired2.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1, t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + assertEquals(2, sync.getWaitQueueLength(c)); + c.signalAll(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t1, t2); + assertEquals(0, sync.getWaitQueueLength(c)); + sync.release(); + + awaitTermination(t1); + awaitTermination(t2); + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitingThreads returns only and all waiting threads + */ + public void testGetWaitingThreads() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired1 = new BooleanLatch(); + final BooleanLatch acquired2 = new BooleanLatch(); + final Thread t1 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertTrue(sync.getWaitingThreads(c).isEmpty()); + assertTrue(acquired1.releaseShared(0)); + c.await(); + sync.release(); + }}); + + final Thread t2 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, t1); + assertTrue(sync.getWaitingThreads(c).contains(t1)); + assertFalse(sync.getWaitingThreads(c).isEmpty()); + assertEquals(1, sync.getWaitingThreads(c).size()); + assertTrue(acquired2.releaseShared(0)); + c.await(); + sync.release(); + }}); + + sync.acquire(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertFalse(sync.getWaitingThreads(c).contains(t1)); + assertFalse(sync.getWaitingThreads(c).contains(t2)); + assertTrue(sync.getWaitingThreads(c).isEmpty()); + assertEquals(0, sync.getWaitingThreads(c).size()); + sync.release(); + + t1.start(); + acquired1.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1); + assertTrue(sync.getWaitingThreads(c).contains(t1)); + assertFalse(sync.getWaitingThreads(c).contains(t2)); + assertFalse(sync.getWaitingThreads(c).isEmpty()); + assertEquals(1, sync.getWaitingThreads(c).size()); + sync.release(); + + t2.start(); + acquired2.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1, t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + assertTrue(sync.getWaitingThreads(c).contains(t1)); + assertTrue(sync.getWaitingThreads(c).contains(t2)); + assertFalse(sync.getWaitingThreads(c).isEmpty()); + assertEquals(2, sync.getWaitingThreads(c).size()); + c.signalAll(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t1, t2); + assertFalse(sync.getWaitingThreads(c).contains(t1)); + assertFalse(sync.getWaitingThreads(c).contains(t2)); + assertTrue(sync.getWaitingThreads(c).isEmpty()); + assertEquals(0, sync.getWaitingThreads(c).size()); + sync.release(); + + awaitTermination(t1); + awaitTermination(t2); + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * awaitUninterruptibly is uninterruptible + */ + public void testAwaitUninterruptibly() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch pleaseInterrupt = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + sync.acquire(); + assertTrue(pleaseInterrupt.releaseShared(0)); + c.awaitUninterruptibly(); + assertTrue(Thread.interrupted()); + assertHasWaitersLocked(sync, c, NO_THREADS); + sync.release(); + }}); + + pleaseInterrupt.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t); + sync.release(); + t.interrupt(); + assertHasWaitersUnlocked(sync, c, t); + assertThreadStaysAlive(t); + sync.acquire(); + assertHasWaitersLocked(sync, c, t); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + c.signal(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t); + sync.release(); + awaitTermination(t); + } + + /** + * await/awaitNanos/awaitUntil is interruptible + */ + public void testInterruptible_await() { testInterruptible(AwaitMethod.await); } + public void testInterruptible_awaitTimed() { testInterruptible(AwaitMethod.awaitTimed); } + public void testInterruptible_awaitNanos() { testInterruptible(AwaitMethod.awaitNanos); } + public void testInterruptible_awaitUntil() { testInterruptible(AwaitMethod.awaitUntil); } + public void testInterruptible(final AwaitMethod awaitMethod) { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch pleaseInterrupt = new BooleanLatch(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertTrue(pleaseInterrupt.releaseShared(0)); + await(c, awaitMethod); + }}); + + pleaseInterrupt.acquireShared(0); + t.interrupt(); + awaitTermination(t); + } + + /** + * signalAll wakes up all threads + */ + public void testSignalAll_await() { testSignalAll(AwaitMethod.await); } + public void testSignalAll_awaitTimed() { testSignalAll(AwaitMethod.awaitTimed); } + public void testSignalAll_awaitNanos() { testSignalAll(AwaitMethod.awaitNanos); } + public void testSignalAll_awaitUntil() { testSignalAll(AwaitMethod.awaitUntil); } + public void testSignalAll(final AwaitMethod awaitMethod) { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired1 = new BooleanLatch(); + final BooleanLatch acquired2 = new BooleanLatch(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + acquired1.releaseShared(0); + await(c, awaitMethod); + sync.release(); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + acquired2.releaseShared(0); + await(c, awaitMethod); + sync.release(); + }}); + + acquired1.acquireShared(0); + acquired2.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1, t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + c.signalAll(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t1, t2); + sync.release(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * toString indicates current state + */ + public void testToString() { + Mutex sync = new Mutex(); + assertTrue(sync.toString().contains("State = " + Mutex.UNLOCKED)); + sync.acquire(); + assertTrue(sync.toString().contains("State = " + Mutex.LOCKED)); + } + + /** + * A serialized AQS deserializes with current state, but no queued threads + */ + public void testSerialization() { + Mutex sync = new Mutex(); + assertFalse(serialClone(sync).isHeldExclusively()); + sync.acquire(); + Thread t = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t); + assertTrue(sync.isHeldExclusively()); + + Mutex clone = serialClone(sync); + assertTrue(clone.isHeldExclusively()); + assertHasExclusiveQueuedThreads(sync, t); + assertHasExclusiveQueuedThreads(clone, NO_THREADS); + t.interrupt(); + awaitTermination(t); + sync.release(); + assertFalse(sync.isHeldExclusively()); + assertTrue(clone.isHeldExclusively()); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + assertHasExclusiveQueuedThreads(clone, NO_THREADS); + } + + /** + * tryReleaseShared setting state changes getState + */ + public void testGetStateWithReleaseShared() { + final BooleanLatch l = new BooleanLatch(); + assertFalse(l.isSignalled()); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + } + + /** + * releaseShared has no effect when already signalled + */ + public void testReleaseShared() { + final BooleanLatch l = new BooleanLatch(); + assertFalse(l.isSignalled()); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + } + + /** + * acquireSharedInterruptibly returns after release, but not before + */ + public void testAcquireSharedInterruptibly() { + final BooleanLatch l = new BooleanLatch(); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + l.acquireSharedInterruptibly(0); + assertTrue(l.isSignalled()); + l.acquireSharedInterruptibly(0); + assertTrue(l.isSignalled()); + }}); + + waitForQueuedThread(l, t); + assertFalse(l.isSignalled()); + assertThreadStaysAlive(t); + assertHasSharedQueuedThreads(l, t); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + awaitTermination(t); + } + + /** + * tryAcquireSharedNanos returns after release, but not before + */ + public void testTryAcquireSharedNanos() { + final BooleanLatch l = new BooleanLatch(); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS); + assertTrue(l.tryAcquireSharedNanos(0, nanos)); + assertTrue(l.isSignalled()); + assertTrue(l.tryAcquireSharedNanos(0, nanos)); + assertTrue(l.isSignalled()); + }}); + + waitForQueuedThread(l, t); + assertFalse(l.isSignalled()); + assertThreadStaysAlive(t); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + awaitTermination(t); + } + + /** + * acquireSharedInterruptibly is interruptible + */ + public void testAcquireSharedInterruptibly_Interruptible() { + final BooleanLatch l = new BooleanLatch(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + l.acquireSharedInterruptibly(0); + }}); + + waitForQueuedThread(l, t); + assertFalse(l.isSignalled()); + t.interrupt(); + awaitTermination(t); + assertFalse(l.isSignalled()); + } + + /** + * tryAcquireSharedNanos is interruptible + */ + public void testTryAcquireSharedNanos_Interruptible() { + final BooleanLatch l = new BooleanLatch(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS); + l.tryAcquireSharedNanos(0, nanos); + }}); + + waitForQueuedThread(l, t); + assertFalse(l.isSignalled()); + t.interrupt(); + awaitTermination(t); + assertFalse(l.isSignalled()); + } + + /** + * tryAcquireSharedNanos times out if not released before timeout + */ + public void testTryAcquireSharedNanos_Timeout() { + final BooleanLatch l = new BooleanLatch(); + final BooleanLatch observedQueued = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + for (long millis = timeoutMillis(); + !observedQueued.isSignalled(); + millis *= 2) { + long nanos = MILLISECONDS.toNanos(millis); + long startTime = System.nanoTime(); + assertFalse(l.tryAcquireSharedNanos(0, nanos)); + assertTrue(millisElapsedSince(startTime) >= millis); + } + assertFalse(l.isSignalled()); + }}); + + waitForQueuedThread(l, t); + observedQueued.releaseShared(0); + assertFalse(l.isSignalled()); + awaitTermination(t); + assertFalse(l.isSignalled()); + } + + /** + * awaitNanos/timed await with 0 wait times out immediately + */ + public void testAwait_Zero() throws InterruptedException { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + sync.acquire(); + assertTrue(c.awaitNanos(0L) <= 0); + assertFalse(c.await(0L, NANOSECONDS)); + sync.release(); + } + + /** + * awaitNanos/timed await with maximum negative wait times does not underflow + */ + public void testAwait_NegativeInfinity() throws InterruptedException { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + sync.acquire(); + assertTrue(c.awaitNanos(Long.MIN_VALUE) <= 0); + assertFalse(c.await(Long.MIN_VALUE, NANOSECONDS)); + sync.release(); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java b/jdk/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java new file mode 100644 index 00000000000..8341a7e296c --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java @@ -0,0 +1,1283 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AbstractQueuedSynchronizerTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AbstractQueuedSynchronizerTest.class); + } + + /** + * A simple mutex class, adapted from the class javadoc. Exclusive + * acquire tests exercise this as a sample user extension. Other + * methods/features of AbstractQueuedSynchronizer are tested via + * other test classes, including those for ReentrantLock, + * ReentrantReadWriteLock, and Semaphore. + */ + static class Mutex extends AbstractQueuedSynchronizer { + /** An eccentric value for locked synchronizer state. */ + static final int LOCKED = (1 << 31) | (1 << 15); + + static final int UNLOCKED = 0; + + @Override public boolean isHeldExclusively() { + int state = getState(); + assertTrue(state == UNLOCKED || state == LOCKED); + return state == LOCKED; + } + + @Override public boolean tryAcquire(int acquires) { + assertEquals(LOCKED, acquires); + return compareAndSetState(UNLOCKED, LOCKED); + } + + @Override public boolean tryRelease(int releases) { + if (getState() != LOCKED) throw new IllegalMonitorStateException(); + assertEquals(LOCKED, releases); + setState(UNLOCKED); + return true; + } + + public boolean tryAcquireNanos(long nanos) throws InterruptedException { + return tryAcquireNanos(LOCKED, nanos); + } + + public boolean tryAcquire() { + return tryAcquire(LOCKED); + } + + public boolean tryRelease() { + return tryRelease(LOCKED); + } + + public void acquire() { + acquire(LOCKED); + } + + public void acquireInterruptibly() throws InterruptedException { + acquireInterruptibly(LOCKED); + } + + public void release() { + release(LOCKED); + } + + public ConditionObject newCondition() { + return new ConditionObject(); + } + } + + /** + * A simple latch class, to test shared mode. + */ + static class BooleanLatch extends AbstractQueuedSynchronizer { + public boolean isSignalled() { return getState() != 0; } + + public int tryAcquireShared(int ignore) { + return isSignalled() ? 1 : -1; + } + + public boolean tryReleaseShared(int ignore) { + setState(1); + return true; + } + } + + /** + * A runnable calling acquireInterruptibly that does not expect to + * be interrupted. + */ + class InterruptibleSyncRunnable extends CheckedRunnable { + final Mutex sync; + InterruptibleSyncRunnable(Mutex sync) { this.sync = sync; } + public void realRun() throws InterruptedException { + sync.acquireInterruptibly(); + } + } + + /** + * A runnable calling acquireInterruptibly that expects to be + * interrupted. + */ + class InterruptedSyncRunnable extends CheckedInterruptedRunnable { + final Mutex sync; + InterruptedSyncRunnable(Mutex sync) { this.sync = sync; } + public void realRun() throws InterruptedException { + sync.acquireInterruptibly(); + } + } + + /** A constant to clarify calls to checking methods below. */ + static final Thread[] NO_THREADS = new Thread[0]; + + /** + * Spin-waits until sync.isQueued(t) becomes true. + */ + void waitForQueuedThread(AbstractQueuedSynchronizer sync, Thread t) { + long startTime = System.nanoTime(); + while (!sync.isQueued(t)) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + throw new AssertionFailedError("timed out"); + Thread.yield(); + } + assertTrue(t.isAlive()); + } + + /** + * Checks that sync has exactly the given queued threads. + */ + void assertHasQueuedThreads(AbstractQueuedSynchronizer sync, + Thread... expected) { + Collection actual = sync.getQueuedThreads(); + assertEquals(expected.length > 0, sync.hasQueuedThreads()); + assertEquals(expected.length, sync.getQueueLength()); + assertEquals(expected.length, actual.size()); + assertEquals(expected.length == 0, actual.isEmpty()); + assertEquals(new HashSet(actual), + new HashSet(Arrays.asList(expected))); + } + + /** + * Checks that sync has exactly the given (exclusive) queued threads. + */ + void assertHasExclusiveQueuedThreads(AbstractQueuedSynchronizer sync, + Thread... expected) { + assertHasQueuedThreads(sync, expected); + assertEquals(new HashSet(sync.getExclusiveQueuedThreads()), + new HashSet(sync.getQueuedThreads())); + assertEquals(0, sync.getSharedQueuedThreads().size()); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + } + + /** + * Checks that sync has exactly the given (shared) queued threads. + */ + void assertHasSharedQueuedThreads(AbstractQueuedSynchronizer sync, + Thread... expected) { + assertHasQueuedThreads(sync, expected); + assertEquals(new HashSet(sync.getSharedQueuedThreads()), + new HashSet(sync.getQueuedThreads())); + assertEquals(0, sync.getExclusiveQueuedThreads().size()); + assertTrue(sync.getExclusiveQueuedThreads().isEmpty()); + } + + /** + * Checks that condition c has exactly the given waiter threads, + * after acquiring mutex. + */ + void assertHasWaitersUnlocked(Mutex sync, ConditionObject c, + Thread... threads) { + sync.acquire(); + assertHasWaitersLocked(sync, c, threads); + sync.release(); + } + + /** + * Checks that condition c has exactly the given waiter threads. + */ + void assertHasWaitersLocked(Mutex sync, ConditionObject c, + Thread... threads) { + assertEquals(threads.length > 0, sync.hasWaiters(c)); + assertEquals(threads.length, sync.getWaitQueueLength(c)); + assertEquals(threads.length == 0, sync.getWaitingThreads(c).isEmpty()); + assertEquals(threads.length, sync.getWaitingThreads(c).size()); + assertEquals(new HashSet(sync.getWaitingThreads(c)), + new HashSet(Arrays.asList(threads))); + } + + enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil } + + /** + * Awaits condition using the specified AwaitMethod. + */ + void await(ConditionObject c, AwaitMethod awaitMethod) + throws InterruptedException { + long timeoutMillis = 2 * LONG_DELAY_MS; + switch (awaitMethod) { + case await: + c.await(); + break; + case awaitTimed: + assertTrue(c.await(timeoutMillis, MILLISECONDS)); + break; + case awaitNanos: + long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis); + long nanosRemaining = c.awaitNanos(nanosTimeout); + assertTrue(nanosRemaining > 0); + break; + case awaitUntil: + assertTrue(c.awaitUntil(delayedDate(timeoutMillis))); + break; + default: + throw new AssertionError(); + } + } + + /** + * Checks that awaiting the given condition times out (using the + * default timeout duration). + */ + void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) { + long timeoutMillis = timeoutMillis(); + long startTime; + try { + switch (awaitMethod) { + case awaitTimed: + startTime = System.nanoTime(); + assertFalse(c.await(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + break; + case awaitNanos: + startTime = System.nanoTime(); + long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis); + long nanosRemaining = c.awaitNanos(nanosTimeout); + assertTrue(nanosRemaining <= 0); + assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + break; + case awaitUntil: + // We shouldn't assume that nanoTime and currentTimeMillis + // use the same time source, so don't use nanoTime here. + java.util.Date delayedDate = delayedDate(timeoutMillis()); + assertFalse(c.awaitUntil(delayedDate(timeoutMillis))); + assertTrue(new java.util.Date().getTime() >= delayedDate.getTime()); + break; + default: + throw new UnsupportedOperationException(); + } + } catch (InterruptedException ie) { threadUnexpectedException(ie); } + } + + /** + * isHeldExclusively is false upon construction + */ + public void testIsHeldExclusively() { + Mutex sync = new Mutex(); + assertFalse(sync.isHeldExclusively()); + } + + /** + * acquiring released sync succeeds + */ + public void testAcquire() { + Mutex sync = new Mutex(); + sync.acquire(); + assertTrue(sync.isHeldExclusively()); + sync.release(); + assertFalse(sync.isHeldExclusively()); + } + + /** + * tryAcquire on a released sync succeeds + */ + public void testTryAcquire() { + Mutex sync = new Mutex(); + assertTrue(sync.tryAcquire()); + assertTrue(sync.isHeldExclusively()); + sync.release(); + assertFalse(sync.isHeldExclusively()); + } + + /** + * hasQueuedThreads reports whether there are waiting threads + */ + public void testHasQueuedThreads() { + final Mutex sync = new Mutex(); + assertFalse(sync.hasQueuedThreads()); + sync.acquire(); + Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t1); + assertTrue(sync.hasQueuedThreads()); + Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync)); + waitForQueuedThread(sync, t2); + assertTrue(sync.hasQueuedThreads()); + t1.interrupt(); + awaitTermination(t1); + assertTrue(sync.hasQueuedThreads()); + sync.release(); + awaitTermination(t2); + assertFalse(sync.hasQueuedThreads()); + } + + /** + * isQueued(null) throws NullPointerException + */ + public void testIsQueuedNPE() { + final Mutex sync = new Mutex(); + try { + sync.isQueued(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * isQueued reports whether a thread is queued + */ + public void testIsQueued() { + final Mutex sync = new Mutex(); + Thread t1 = new Thread(new InterruptedSyncRunnable(sync)); + Thread t2 = new Thread(new InterruptibleSyncRunnable(sync)); + assertFalse(sync.isQueued(t1)); + assertFalse(sync.isQueued(t2)); + sync.acquire(); + t1.start(); + waitForQueuedThread(sync, t1); + assertTrue(sync.isQueued(t1)); + assertFalse(sync.isQueued(t2)); + t2.start(); + waitForQueuedThread(sync, t2); + assertTrue(sync.isQueued(t1)); + assertTrue(sync.isQueued(t2)); + t1.interrupt(); + awaitTermination(t1); + assertFalse(sync.isQueued(t1)); + assertTrue(sync.isQueued(t2)); + sync.release(); + awaitTermination(t2); + assertFalse(sync.isQueued(t1)); + assertFalse(sync.isQueued(t2)); + } + + /** + * getFirstQueuedThread returns first waiting thread or null if none + */ + public void testGetFirstQueuedThread() { + final Mutex sync = new Mutex(); + assertNull(sync.getFirstQueuedThread()); + sync.acquire(); + Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t1); + assertEquals(t1, sync.getFirstQueuedThread()); + Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync)); + waitForQueuedThread(sync, t2); + assertEquals(t1, sync.getFirstQueuedThread()); + t1.interrupt(); + awaitTermination(t1); + assertEquals(t2, sync.getFirstQueuedThread()); + sync.release(); + awaitTermination(t2); + assertNull(sync.getFirstQueuedThread()); + } + + /** + * hasContended reports false if no thread has ever blocked, else true + */ + public void testHasContended() { + final Mutex sync = new Mutex(); + assertFalse(sync.hasContended()); + sync.acquire(); + assertFalse(sync.hasContended()); + Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t1); + assertTrue(sync.hasContended()); + Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync)); + waitForQueuedThread(sync, t2); + assertTrue(sync.hasContended()); + t1.interrupt(); + awaitTermination(t1); + assertTrue(sync.hasContended()); + sync.release(); + awaitTermination(t2); + assertTrue(sync.hasContended()); + } + + /** + * getQueuedThreads returns all waiting threads + */ + public void testGetQueuedThreads() { + final Mutex sync = new Mutex(); + Thread t1 = new Thread(new InterruptedSyncRunnable(sync)); + Thread t2 = new Thread(new InterruptibleSyncRunnable(sync)); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + sync.acquire(); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + t1.start(); + waitForQueuedThread(sync, t1); + assertHasExclusiveQueuedThreads(sync, t1); + assertTrue(sync.getQueuedThreads().contains(t1)); + assertFalse(sync.getQueuedThreads().contains(t2)); + t2.start(); + waitForQueuedThread(sync, t2); + assertHasExclusiveQueuedThreads(sync, t1, t2); + assertTrue(sync.getQueuedThreads().contains(t1)); + assertTrue(sync.getQueuedThreads().contains(t2)); + t1.interrupt(); + awaitTermination(t1); + assertHasExclusiveQueuedThreads(sync, t2); + sync.release(); + awaitTermination(t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + } + + /** + * getExclusiveQueuedThreads returns all exclusive waiting threads + */ + public void testGetExclusiveQueuedThreads() { + final Mutex sync = new Mutex(); + Thread t1 = new Thread(new InterruptedSyncRunnable(sync)); + Thread t2 = new Thread(new InterruptibleSyncRunnable(sync)); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + sync.acquire(); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + t1.start(); + waitForQueuedThread(sync, t1); + assertHasExclusiveQueuedThreads(sync, t1); + assertTrue(sync.getExclusiveQueuedThreads().contains(t1)); + assertFalse(sync.getExclusiveQueuedThreads().contains(t2)); + t2.start(); + waitForQueuedThread(sync, t2); + assertHasExclusiveQueuedThreads(sync, t1, t2); + assertTrue(sync.getExclusiveQueuedThreads().contains(t1)); + assertTrue(sync.getExclusiveQueuedThreads().contains(t2)); + t1.interrupt(); + awaitTermination(t1); + assertHasExclusiveQueuedThreads(sync, t2); + sync.release(); + awaitTermination(t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + } + + /** + * getSharedQueuedThreads does not include exclusively waiting threads + */ + public void testGetSharedQueuedThreads_Exclusive() { + final Mutex sync = new Mutex(); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + sync.acquire(); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + Thread t1 = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t1); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + Thread t2 = newStartedThread(new InterruptibleSyncRunnable(sync)); + waitForQueuedThread(sync, t2); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + t1.interrupt(); + awaitTermination(t1); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + sync.release(); + awaitTermination(t2); + assertTrue(sync.getSharedQueuedThreads().isEmpty()); + } + + /** + * getSharedQueuedThreads returns all shared waiting threads + */ + public void testGetSharedQueuedThreads_Shared() { + final BooleanLatch l = new BooleanLatch(); + assertHasSharedQueuedThreads(l, NO_THREADS); + Thread t1 = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + l.acquireSharedInterruptibly(0); + }}); + waitForQueuedThread(l, t1); + assertHasSharedQueuedThreads(l, t1); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + l.acquireSharedInterruptibly(0); + }}); + waitForQueuedThread(l, t2); + assertHasSharedQueuedThreads(l, t1, t2); + t1.interrupt(); + awaitTermination(t1); + assertHasSharedQueuedThreads(l, t2); + assertTrue(l.releaseShared(0)); + awaitTermination(t2); + assertHasSharedQueuedThreads(l, NO_THREADS); + } + + /** + * tryAcquireNanos is interruptible + */ + public void testTryAcquireNanos_Interruptible() { + final Mutex sync = new Mutex(); + sync.acquire(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + sync.tryAcquireNanos(MILLISECONDS.toNanos(2 * LONG_DELAY_MS)); + }}); + + waitForQueuedThread(sync, t); + t.interrupt(); + awaitTermination(t); + } + + /** + * tryAcquire on exclusively held sync fails + */ + public void testTryAcquireWhenSynced() { + final Mutex sync = new Mutex(); + sync.acquire(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertFalse(sync.tryAcquire()); + }}); + + awaitTermination(t); + sync.release(); + } + + /** + * tryAcquireNanos on an exclusively held sync times out + */ + public void testAcquireNanos_Timeout() { + final Mutex sync = new Mutex(); + sync.acquire(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + long nanos = MILLISECONDS.toNanos(timeoutMillis()); + assertFalse(sync.tryAcquireNanos(nanos)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}); + + awaitTermination(t); + sync.release(); + } + + /** + * getState is true when acquired and false when not + */ + public void testGetState() { + final Mutex sync = new Mutex(); + sync.acquire(); + assertTrue(sync.isHeldExclusively()); + sync.release(); + assertFalse(sync.isHeldExclusively()); + + final BooleanLatch acquired = new BooleanLatch(); + final BooleanLatch done = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertTrue(acquired.releaseShared(0)); + done.acquireShared(0); + sync.release(); + }}); + + acquired.acquireShared(0); + assertTrue(sync.isHeldExclusively()); + assertTrue(done.releaseShared(0)); + awaitTermination(t); + assertFalse(sync.isHeldExclusively()); + } + + /** + * acquireInterruptibly succeeds when released, else is interruptible + */ + public void testAcquireInterruptibly() throws InterruptedException { + final Mutex sync = new Mutex(); + final BooleanLatch threadStarted = new BooleanLatch(); + sync.acquireInterruptibly(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + assertTrue(threadStarted.releaseShared(0)); + sync.acquireInterruptibly(); + }}); + + threadStarted.acquireShared(0); + waitForQueuedThread(sync, t); + t.interrupt(); + awaitTermination(t); + assertTrue(sync.isHeldExclusively()); + } + + /** + * owns is true for a condition created by sync else false + */ + public void testOwns() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final Mutex sync2 = new Mutex(); + assertTrue(sync.owns(c)); + assertFalse(sync2.owns(c)); + } + + /** + * Calling await without holding sync throws IllegalMonitorStateException + */ + public void testAwait_IMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + for (AwaitMethod awaitMethod : AwaitMethod.values()) { + long startTime = System.nanoTime(); + try { + await(c, awaitMethod); + shouldThrow(); + } catch (IllegalMonitorStateException success) { + } catch (InterruptedException e) { threadUnexpectedException(e); } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * Calling signal without holding sync throws IllegalMonitorStateException + */ + public void testSignal_IMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + c.signal(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * Calling signalAll without holding sync throws IllegalMonitorStateException + */ + public void testSignalAll_IMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + c.signalAll(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * await/awaitNanos/awaitUntil without a signal times out + */ + public void testAwaitTimed_Timeout() { testAwait_Timeout(AwaitMethod.awaitTimed); } + public void testAwaitNanos_Timeout() { testAwait_Timeout(AwaitMethod.awaitNanos); } + public void testAwaitUntil_Timeout() { testAwait_Timeout(AwaitMethod.awaitUntil); } + public void testAwait_Timeout(AwaitMethod awaitMethod) { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + sync.acquire(); + assertAwaitTimesOut(c, awaitMethod); + sync.release(); + } + + /** + * await/awaitNanos/awaitUntil returns when signalled + */ + public void testSignal_await() { testSignal(AwaitMethod.await); } + public void testSignal_awaitTimed() { testSignal(AwaitMethod.awaitTimed); } + public void testSignal_awaitNanos() { testSignal(AwaitMethod.awaitNanos); } + public void testSignal_awaitUntil() { testSignal(AwaitMethod.awaitUntil); } + public void testSignal(final AwaitMethod awaitMethod) { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertTrue(acquired.releaseShared(0)); + await(c, awaitMethod); + sync.release(); + }}); + + acquired.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + c.signal(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t); + sync.release(); + awaitTermination(t); + } + + /** + * hasWaiters(null) throws NullPointerException + */ + public void testHasWaitersNPE() { + final Mutex sync = new Mutex(); + try { + sync.hasWaiters(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getWaitQueueLength(null) throws NullPointerException + */ + public void testGetWaitQueueLengthNPE() { + final Mutex sync = new Mutex(); + try { + sync.getWaitQueueLength(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getWaitingThreads(null) throws NullPointerException + */ + public void testGetWaitingThreadsNPE() { + final Mutex sync = new Mutex(); + try { + sync.getWaitingThreads(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * hasWaiters throws IllegalArgumentException if not owned + */ + public void testHasWaitersIAE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final Mutex sync2 = new Mutex(); + try { + sync2.hasWaiters(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * hasWaiters throws IllegalMonitorStateException if not synced + */ + public void testHasWaitersIMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + sync.hasWaiters(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitQueueLength throws IllegalArgumentException if not owned + */ + public void testGetWaitQueueLengthIAE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final Mutex sync2 = new Mutex(); + try { + sync2.getWaitQueueLength(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitQueueLength throws IllegalMonitorStateException if not synced + */ + public void testGetWaitQueueLengthIMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + sync.getWaitQueueLength(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitingThreads throws IllegalArgumentException if not owned + */ + public void testGetWaitingThreadsIAE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final Mutex sync2 = new Mutex(); + try { + sync2.getWaitingThreads(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitingThreads throws IllegalMonitorStateException if not synced + */ + public void testGetWaitingThreadsIMSE() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + try { + sync.getWaitingThreads(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * hasWaiters returns true when a thread is waiting, else false + */ + public void testHasWaiters() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertFalse(sync.hasWaiters(c)); + assertTrue(acquired.releaseShared(0)); + c.await(); + sync.release(); + }}); + + acquired.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + assertTrue(sync.hasWaiters(c)); + c.signal(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t); + assertFalse(sync.hasWaiters(c)); + sync.release(); + + awaitTermination(t); + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitQueueLength returns number of waiting threads + */ + public void testGetWaitQueueLength() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired1 = new BooleanLatch(); + final BooleanLatch acquired2 = new BooleanLatch(); + final Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertEquals(0, sync.getWaitQueueLength(c)); + assertTrue(acquired1.releaseShared(0)); + c.await(); + sync.release(); + }}); + acquired1.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1); + assertEquals(1, sync.getWaitQueueLength(c)); + sync.release(); + + final Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, t1); + assertEquals(1, sync.getWaitQueueLength(c)); + assertTrue(acquired2.releaseShared(0)); + c.await(); + sync.release(); + }}); + acquired2.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1, t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + assertEquals(2, sync.getWaitQueueLength(c)); + c.signalAll(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t1, t2); + assertEquals(0, sync.getWaitQueueLength(c)); + sync.release(); + + awaitTermination(t1); + awaitTermination(t2); + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * getWaitingThreads returns only and all waiting threads + */ + public void testGetWaitingThreads() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired1 = new BooleanLatch(); + final BooleanLatch acquired2 = new BooleanLatch(); + final Thread t1 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertTrue(sync.getWaitingThreads(c).isEmpty()); + assertTrue(acquired1.releaseShared(0)); + c.await(); + sync.release(); + }}); + + final Thread t2 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertHasWaitersLocked(sync, c, t1); + assertTrue(sync.getWaitingThreads(c).contains(t1)); + assertFalse(sync.getWaitingThreads(c).isEmpty()); + assertEquals(1, sync.getWaitingThreads(c).size()); + assertTrue(acquired2.releaseShared(0)); + c.await(); + sync.release(); + }}); + + sync.acquire(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertFalse(sync.getWaitingThreads(c).contains(t1)); + assertFalse(sync.getWaitingThreads(c).contains(t2)); + assertTrue(sync.getWaitingThreads(c).isEmpty()); + assertEquals(0, sync.getWaitingThreads(c).size()); + sync.release(); + + t1.start(); + acquired1.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1); + assertTrue(sync.getWaitingThreads(c).contains(t1)); + assertFalse(sync.getWaitingThreads(c).contains(t2)); + assertFalse(sync.getWaitingThreads(c).isEmpty()); + assertEquals(1, sync.getWaitingThreads(c).size()); + sync.release(); + + t2.start(); + acquired2.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1, t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + assertTrue(sync.getWaitingThreads(c).contains(t1)); + assertTrue(sync.getWaitingThreads(c).contains(t2)); + assertFalse(sync.getWaitingThreads(c).isEmpty()); + assertEquals(2, sync.getWaitingThreads(c).size()); + c.signalAll(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t1, t2); + assertFalse(sync.getWaitingThreads(c).contains(t1)); + assertFalse(sync.getWaitingThreads(c).contains(t2)); + assertTrue(sync.getWaitingThreads(c).isEmpty()); + assertEquals(0, sync.getWaitingThreads(c).size()); + sync.release(); + + awaitTermination(t1); + awaitTermination(t2); + assertHasWaitersUnlocked(sync, c, NO_THREADS); + } + + /** + * awaitUninterruptibly is uninterruptible + */ + public void testAwaitUninterruptibly() { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch pleaseInterrupt = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + sync.acquire(); + assertTrue(pleaseInterrupt.releaseShared(0)); + c.awaitUninterruptibly(); + assertTrue(Thread.interrupted()); + assertHasWaitersLocked(sync, c, NO_THREADS); + sync.release(); + }}); + + pleaseInterrupt.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t); + sync.release(); + t.interrupt(); + assertHasWaitersUnlocked(sync, c, t); + assertThreadStaysAlive(t); + sync.acquire(); + assertHasWaitersLocked(sync, c, t); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + c.signal(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t); + sync.release(); + awaitTermination(t); + } + + /** + * await/awaitNanos/awaitUntil is interruptible + */ + public void testInterruptible_await() { testInterruptible(AwaitMethod.await); } + public void testInterruptible_awaitTimed() { testInterruptible(AwaitMethod.awaitTimed); } + public void testInterruptible_awaitNanos() { testInterruptible(AwaitMethod.awaitNanos); } + public void testInterruptible_awaitUntil() { testInterruptible(AwaitMethod.awaitUntil); } + public void testInterruptible(final AwaitMethod awaitMethod) { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch pleaseInterrupt = new BooleanLatch(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + assertTrue(pleaseInterrupt.releaseShared(0)); + await(c, awaitMethod); + }}); + + pleaseInterrupt.acquireShared(0); + t.interrupt(); + awaitTermination(t); + } + + /** + * signalAll wakes up all threads + */ + public void testSignalAll_await() { testSignalAll(AwaitMethod.await); } + public void testSignalAll_awaitTimed() { testSignalAll(AwaitMethod.awaitTimed); } + public void testSignalAll_awaitNanos() { testSignalAll(AwaitMethod.awaitNanos); } + public void testSignalAll_awaitUntil() { testSignalAll(AwaitMethod.awaitUntil); } + public void testSignalAll(final AwaitMethod awaitMethod) { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + final BooleanLatch acquired1 = new BooleanLatch(); + final BooleanLatch acquired2 = new BooleanLatch(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + acquired1.releaseShared(0); + await(c, awaitMethod); + sync.release(); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + sync.acquire(); + acquired2.releaseShared(0); + await(c, awaitMethod); + sync.release(); + }}); + + acquired1.acquireShared(0); + acquired2.acquireShared(0); + sync.acquire(); + assertHasWaitersLocked(sync, c, t1, t2); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + c.signalAll(); + assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasExclusiveQueuedThreads(sync, t1, t2); + sync.release(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * toString indicates current state + */ + public void testToString() { + Mutex sync = new Mutex(); + assertTrue(sync.toString().contains("State = " + Mutex.UNLOCKED)); + sync.acquire(); + assertTrue(sync.toString().contains("State = " + Mutex.LOCKED)); + } + + /** + * A serialized AQS deserializes with current state, but no queued threads + */ + public void testSerialization() { + Mutex sync = new Mutex(); + assertFalse(serialClone(sync).isHeldExclusively()); + sync.acquire(); + Thread t = newStartedThread(new InterruptedSyncRunnable(sync)); + waitForQueuedThread(sync, t); + assertTrue(sync.isHeldExclusively()); + + Mutex clone = serialClone(sync); + assertTrue(clone.isHeldExclusively()); + assertHasExclusiveQueuedThreads(sync, t); + assertHasExclusiveQueuedThreads(clone, NO_THREADS); + t.interrupt(); + awaitTermination(t); + sync.release(); + assertFalse(sync.isHeldExclusively()); + assertTrue(clone.isHeldExclusively()); + assertHasExclusiveQueuedThreads(sync, NO_THREADS); + assertHasExclusiveQueuedThreads(clone, NO_THREADS); + } + + /** + * tryReleaseShared setting state changes getState + */ + public void testGetStateWithReleaseShared() { + final BooleanLatch l = new BooleanLatch(); + assertFalse(l.isSignalled()); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + } + + /** + * releaseShared has no effect when already signalled + */ + public void testReleaseShared() { + final BooleanLatch l = new BooleanLatch(); + assertFalse(l.isSignalled()); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + } + + /** + * acquireSharedInterruptibly returns after release, but not before + */ + public void testAcquireSharedInterruptibly() { + final BooleanLatch l = new BooleanLatch(); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + l.acquireSharedInterruptibly(0); + assertTrue(l.isSignalled()); + l.acquireSharedInterruptibly(0); + assertTrue(l.isSignalled()); + }}); + + waitForQueuedThread(l, t); + assertFalse(l.isSignalled()); + assertThreadStaysAlive(t); + assertHasSharedQueuedThreads(l, t); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + awaitTermination(t); + } + + /** + * tryAcquireSharedNanos returns after release, but not before + */ + public void testTryAcquireSharedNanos() { + final BooleanLatch l = new BooleanLatch(); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS); + assertTrue(l.tryAcquireSharedNanos(0, nanos)); + assertTrue(l.isSignalled()); + assertTrue(l.tryAcquireSharedNanos(0, nanos)); + assertTrue(l.isSignalled()); + }}); + + waitForQueuedThread(l, t); + assertFalse(l.isSignalled()); + assertThreadStaysAlive(t); + assertTrue(l.releaseShared(0)); + assertTrue(l.isSignalled()); + awaitTermination(t); + } + + /** + * acquireSharedInterruptibly is interruptible + */ + public void testAcquireSharedInterruptibly_Interruptible() { + final BooleanLatch l = new BooleanLatch(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + l.acquireSharedInterruptibly(0); + }}); + + waitForQueuedThread(l, t); + assertFalse(l.isSignalled()); + t.interrupt(); + awaitTermination(t); + assertFalse(l.isSignalled()); + } + + /** + * tryAcquireSharedNanos is interruptible + */ + public void testTryAcquireSharedNanos_Interruptible() { + final BooleanLatch l = new BooleanLatch(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + long nanos = MILLISECONDS.toNanos(2 * LONG_DELAY_MS); + l.tryAcquireSharedNanos(0, nanos); + }}); + + waitForQueuedThread(l, t); + assertFalse(l.isSignalled()); + t.interrupt(); + awaitTermination(t); + assertFalse(l.isSignalled()); + } + + /** + * tryAcquireSharedNanos times out if not released before timeout + */ + public void testTryAcquireSharedNanos_Timeout() { + final BooleanLatch l = new BooleanLatch(); + final BooleanLatch observedQueued = new BooleanLatch(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(l.isSignalled()); + for (long millis = timeoutMillis(); + !observedQueued.isSignalled(); + millis *= 2) { + long nanos = MILLISECONDS.toNanos(millis); + long startTime = System.nanoTime(); + assertFalse(l.tryAcquireSharedNanos(0, nanos)); + assertTrue(millisElapsedSince(startTime) >= millis); + } + assertFalse(l.isSignalled()); + }}); + + waitForQueuedThread(l, t); + observedQueued.releaseShared(0); + assertFalse(l.isSignalled()); + awaitTermination(t); + assertFalse(l.isSignalled()); + } + + /** + * awaitNanos/timed await with 0 wait times out immediately + */ + public void testAwait_Zero() throws InterruptedException { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + sync.acquire(); + assertTrue(c.awaitNanos(0L) <= 0); + assertFalse(c.await(0L, NANOSECONDS)); + sync.release(); + } + + /** + * awaitNanos/timed await with maximum negative wait times does not underflow + */ + public void testAwait_NegativeInfinity() throws InterruptedException { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + sync.acquire(); + assertTrue(c.awaitNanos(Long.MIN_VALUE) <= 0); + assertFalse(c.await(Long.MIN_VALUE, NANOSECONDS)); + sync.release(); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java new file mode 100644 index 00000000000..e7fa0316197 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java @@ -0,0 +1,955 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; + +import junit.framework.Test; + +public class ArrayBlockingQueueTest extends JSR166TestCase { + + public static class Fair extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new ArrayBlockingQueue(SIZE, true); + } + } + + public static class NonFair extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new ArrayBlockingQueue(SIZE, false); + } + } + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return newTestSuite(ArrayBlockingQueueTest.class, + new Fair().testSuite(), + new NonFair().testSuite()); + } + + /** + * Returns a new queue of given size containing consecutive + * Integers 0 ... n. + */ + private ArrayBlockingQueue populatedQueue(int n) { + ArrayBlockingQueue q = new ArrayBlockingQueue(n); + assertTrue(q.isEmpty()); + for (int i = 0; i < n; i++) + assertTrue(q.offer(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(0, q.remainingCapacity()); + assertEquals(n, q.size()); + return q; + } + + /** + * A new queue has the indicated capacity + */ + public void testConstructor1() { + assertEquals(SIZE, new ArrayBlockingQueue(SIZE).remainingCapacity()); + } + + /** + * Constructor throws IAE if capacity argument nonpositive + */ + public void testConstructor2() { + try { + new ArrayBlockingQueue(0); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new ArrayBlockingQueue(1, true, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NPE + */ + public void testConstructor4() { + Collection elements = Arrays.asList(new Integer[SIZE]); + try { + new ArrayBlockingQueue(SIZE, false, elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws NPE + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = i; + Collection elements = Arrays.asList(ints); + try { + new ArrayBlockingQueue(SIZE, false, elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from too large collection throws IAE + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = i; + Collection elements = Arrays.asList(ints); + try { + new ArrayBlockingQueue(SIZE - 1, false, elements); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Queue contains all elements of collection used to initialize + */ + public void testConstructor7() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = i; + Collection elements = Arrays.asList(ints); + ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE, true, elements); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * Queue transitions from empty to full when elements added + */ + public void testEmptyFull() { + ArrayBlockingQueue q = new ArrayBlockingQueue(2); + assertTrue(q.isEmpty()); + assertEquals(2, q.remainingCapacity()); + q.add(one); + assertFalse(q.isEmpty()); + q.add(two); + assertFalse(q.isEmpty()); + assertEquals(0, q.remainingCapacity()); + assertFalse(q.offer(three)); + } + + /** + * remainingCapacity decreases on add, increases on remove + */ + public void testRemainingCapacity() { + BlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remainingCapacity()); + assertEquals(SIZE, q.size() + q.remainingCapacity()); + assertEquals(i, q.remove()); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.remainingCapacity()); + assertEquals(SIZE, q.size() + q.remainingCapacity()); + assertTrue(q.add(i)); + } + } + + /** + * Offer succeeds if not full; fails if full + */ + public void testOffer() { + ArrayBlockingQueue q = new ArrayBlockingQueue(1); + assertTrue(q.offer(zero)); + assertFalse(q.offer(one)); + } + + /** + * add succeeds if not full; throws ISE if full + */ + public void testAdd() { + ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.add(new Integer(i))); + } + assertEquals(0, q.remainingCapacity()); + try { + q.add(new Integer(SIZE)); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * addAll(this) throws IAE + */ + public void testAddAllSelf() { + ArrayBlockingQueue q = populatedQueue(SIZE); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll throws ISE if not enough room + */ + public void testAddAll4() { + ArrayBlockingQueue q = new ArrayBlockingQueue(1); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * Queue contains all elements, in traversal order, of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * all elements successfully put are contained + */ + public void testPut() throws InterruptedException { + ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + Integer x = new Integer(i); + q.put(x); + assertTrue(q.contains(x)); + } + assertEquals(0, q.remainingCapacity()); + } + + /** + * put blocks interruptibly if full + */ + public void testBlockingPut() throws InterruptedException { + final ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) + q.put(i); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + + Thread.currentThread().interrupt(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + } + + /** + * put blocks interruptibly waiting for take when full + */ + public void testPutWithTake() throws InterruptedException { + final int capacity = 2; + final ArrayBlockingQueue q = new ArrayBlockingQueue(capacity); + final CountDownLatch pleaseTake = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < capacity; i++) + q.put(i); + pleaseTake.countDown(); + q.put(86); + + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseTake); + assertEquals(0, q.remainingCapacity()); + assertEquals(0, q.take()); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(0, q.remainingCapacity()); + } + + /** + * timed offer times out if full and elements not taken + */ + public void testTimedOffer() throws InterruptedException { + final ArrayBlockingQueue q = new ArrayBlockingQueue(2); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(new Object()); + q.put(new Object()); + long startTime = System.nanoTime(); + assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + pleaseInterrupt.countDown(); + try { + q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * take retrieves elements in FIFO order + */ + public void testTake() throws InterruptedException { + ArrayBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.take()); + } + } + + /** + * Take removes existing elements until empty, then blocks interruptibly + */ + public void testBlockingTake() throws InterruptedException { + final ArrayBlockingQueue q = populatedQueue(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.take()); + } + + Thread.currentThread().interrupt(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + ArrayBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll()); + } + assertNull(q.poll()); + } + + /** + * timed poll with zero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll0() throws InterruptedException { + ArrayBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll(0, MILLISECONDS)); + } + assertNull(q.poll(0, MILLISECONDS)); + checkEmpty(q); + } + + /** + * timed poll with nonzero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll() throws InterruptedException { + ArrayBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + long startTime = System.nanoTime(); + assertEquals(i, q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + long startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + checkEmpty(q); + } + + /** + * Interrupted timed poll throws InterruptedException instead of + * returning timeout status + */ + public void testInterruptedTimedPoll() throws InterruptedException { + final BlockingQueue q = populatedQueue(SIZE); + final CountDownLatch aboutToWait = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); + } + aboutToWait.countDown(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) { + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + }}); + + await(aboutToWait); + waitForThreadToEnterWaitState(t, LONG_DELAY_MS); + t.interrupt(); + awaitTermination(t); + checkEmpty(q); + } + + /** + * peek returns next element, or null if empty + */ + public void testPeek() { + ArrayBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peek()); + assertEquals(i, q.poll()); + assertTrue(q.peek() == null || + !q.peek().equals(i)); + } + assertNull(q.peek()); + } + + /** + * element returns next element, or throws NSEE if empty + */ + public void testElement() { + ArrayBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.element()); + assertEquals(i, q.poll()); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove removes next element, or throws NSEE if empty + */ + public void testRemove() { + ArrayBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + ArrayBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + assertEquals(i, q.poll()); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + ArrayBlockingQueue q = populatedQueue(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertEquals(SIZE, q.remainingCapacity()); + q.add(one); + assertFalse(q.isEmpty()); + assertTrue(q.contains(one)); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + ArrayBlockingQueue q = populatedQueue(SIZE); + ArrayBlockingQueue p = new ArrayBlockingQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + ArrayBlockingQueue q = populatedQueue(SIZE); + ArrayBlockingQueue p = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + ArrayBlockingQueue q = populatedQueue(SIZE); + ArrayBlockingQueue p = populatedQueue(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.remove()); + assertFalse(q.contains(x)); + } + } + } + + void checkToArray(ArrayBlockingQueue q) { + int size = q.size(); + Object[] o = q.toArray(); + assertEquals(size, o.length); + Iterator it = q.iterator(); + for (int i = 0; i < size; i++) { + Integer x = (Integer) it.next(); + assertEquals((Integer)o[0] + i, (int) x); + assertSame(o[i], x); + } + } + + /** + * toArray() contains all elements in FIFO order + */ + public void testToArray() { + ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE); + for (int i = 0; i < SIZE; i++) { + checkToArray(q); + q.add(i); + } + // Provoke wraparound + for (int i = 0; i < SIZE; i++) { + checkToArray(q); + assertEquals(i, q.poll()); + checkToArray(q); + q.add(SIZE + i); + } + for (int i = 0; i < SIZE; i++) { + checkToArray(q); + assertEquals(SIZE + i, q.poll()); + } + } + + void checkToArray2(ArrayBlockingQueue q) { + int size = q.size(); + Integer[] a1 = (size == 0) ? null : new Integer[size - 1]; + Integer[] a2 = new Integer[size]; + Integer[] a3 = new Integer[size + 2]; + if (size > 0) Arrays.fill(a1, 42); + Arrays.fill(a2, 42); + Arrays.fill(a3, 42); + Integer[] b1 = (size == 0) ? null : (Integer[]) q.toArray(a1); + Integer[] b2 = (Integer[]) q.toArray(a2); + Integer[] b3 = (Integer[]) q.toArray(a3); + assertSame(a2, b2); + assertSame(a3, b3); + Iterator it = q.iterator(); + for (int i = 0; i < size; i++) { + Integer x = (Integer) it.next(); + assertSame(b1[i], x); + assertEquals(b1[0] + i, (int) x); + assertSame(b2[i], x); + assertSame(b3[i], x); + } + assertNull(a3[size]); + assertEquals(42, (int) a3[size + 1]); + if (size > 0) { + assertNotSame(a1, b1); + assertEquals(size, b1.length); + for (int i = 0; i < a1.length; i++) { + assertEquals(42, (int) a1[i]); + } + } + } + + /** + * toArray(a) contains all elements in FIFO order + */ + public void testToArray2() { + ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE); + for (int i = 0; i < SIZE; i++) { + checkToArray2(q); + q.add(i); + } + // Provoke wraparound + for (int i = 0; i < SIZE; i++) { + checkToArray2(q); + assertEquals(i, q.poll()); + checkToArray2(q); + q.add(SIZE + i); + } + for (int i = 0; i < SIZE; i++) { + checkToArray2(q); + assertEquals(SIZE + i, q.poll()); + } + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + ArrayBlockingQueue q = populatedQueue(SIZE); + try { + q.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * iterator iterates through all elements + */ + public void testIterator() throws InterruptedException { + ArrayBlockingQueue q = populatedQueue(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + + it = q.iterator(); + for (i = 0; it.hasNext(); i++) + assertEquals(it.next(), q.take()); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new ArrayBlockingQueue(SIZE).iterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final ArrayBlockingQueue q = new ArrayBlockingQueue(3); + q.add(two); + q.add(one); + q.add(three); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertSame(it.next(), one); + assertSame(it.next(), three); + assertFalse(it.hasNext()); + } + + /** + * iterator ordering is FIFO + */ + public void testIteratorOrdering() { + final ArrayBlockingQueue q = new ArrayBlockingQueue(3); + q.add(one); + q.add(two); + q.add(three); + + assertEquals("queue should be full", 0, q.remainingCapacity()); + + int k = 0; + for (Iterator it = q.iterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + assertEquals(3, k); + } + + /** + * Modifications do not cause iterators to fail + */ + public void testWeaklyConsistentIteration() { + final ArrayBlockingQueue q = new ArrayBlockingQueue(3); + q.add(one); + q.add(two); + q.add(three); + for (Iterator it = q.iterator(); it.hasNext();) { + q.remove(); + it.next(); + } + assertEquals(0, q.size()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + ArrayBlockingQueue q = populatedQueue(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * offer transfers elements across Executor tasks + */ + public void testOfferInExecutor() { + final ArrayBlockingQueue q = new ArrayBlockingQueue(2); + q.add(one); + q.add(two); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(q.offer(three)); + threadsStarted.await(); + assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS)); + assertEquals(0, q.remainingCapacity()); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + assertEquals(0, q.remainingCapacity()); + assertSame(one, q.take()); + }}); + } + } + + /** + * timed poll retrieves elements across Executor threads + */ + public void testPollInExecutor() { + final ArrayBlockingQueue q = new ArrayBlockingQueue(2); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertNull(q.poll()); + threadsStarted.await(); + assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS)); + checkEmpty(q); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + q.put(one); + }}); + } + } + + /** + * A deserialized serialized queue has same elements in same order + */ + public void testSerialization() throws Exception { + Queue x = populatedQueue(SIZE); + Queue y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(), y.remove()); + } + assertTrue(y.isEmpty()); + } + + /** + * drainTo(c) empties queue into another collection c + */ + public void testDrainTo() { + ArrayBlockingQueue q = populatedQueue(SIZE); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(SIZE, l.size()); + for (int i = 0; i < SIZE; ++i) + assertEquals(l.get(i), new Integer(i)); + q.add(zero); + q.add(one); + assertFalse(q.isEmpty()); + assertTrue(q.contains(zero)); + assertTrue(q.contains(one)); + l.clear(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(2, l.size()); + for (int i = 0; i < 2; ++i) + assertEquals(l.get(i), new Integer(i)); + } + + /** + * drainTo empties full queue, unblocking a waiting put. + */ + public void testDrainToWithActivePut() throws InterruptedException { + final ArrayBlockingQueue q = populatedQueue(SIZE); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(new Integer(SIZE + 1)); + }}); + + t.start(); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertTrue(l.size() >= SIZE); + for (int i = 0; i < SIZE; ++i) + assertEquals(l.get(i), new Integer(i)); + t.join(); + assertTrue(q.size() + l.size() >= SIZE); + } + + /** + * drainTo(c, n) empties first min(n, size) elements of queue into c + */ + public void testDrainToN() { + ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE * 2); + for (int i = 0; i < SIZE + 2; ++i) { + for (int j = 0; j < SIZE; j++) + assertTrue(q.offer(new Integer(j))); + ArrayList l = new ArrayList(); + q.drainTo(l, i); + int k = (i < SIZE) ? i : SIZE; + assertEquals(k, l.size()); + assertEquals(SIZE - k, q.size()); + for (int j = 0; j < k; ++j) + assertEquals(l.get(j), new Integer(j)); + do {} while (q.poll() != null); + } + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Collection[] qs = { + new ArrayBlockingQueue(10), + populatedQueue(2), + }; + + for (Collection q : qs) { + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + } + } +} diff --git a/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java b/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java new file mode 100644 index 00000000000..4241f59ef3d --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java @@ -0,0 +1,945 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Collection; +import java.util.Deque; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Random; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ArrayDequeTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ArrayDequeTest.class); + } + + /** + * Returns a new deque of given size containing consecutive + * Integers 0 ... n. + */ + private ArrayDeque populatedDeque(int n) { + ArrayDeque q = new ArrayDeque(); + assertTrue(q.isEmpty()); + for (int i = 0; i < n; ++i) + assertTrue(q.offerLast(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(n, q.size()); + return q; + } + + /** + * new deque is empty + */ + public void testConstructor1() { + assertEquals(0, new ArrayDeque().size()); + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new ArrayDeque((Collection)null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NPE + */ + public void testConstructor4() { + try { + new ArrayDeque(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws NPE + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + new ArrayDeque(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Deque contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + ArrayDeque q = new ArrayDeque(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.pollFirst()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + ArrayDeque q = new ArrayDeque(); + assertTrue(q.isEmpty()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.add(new Integer(2)); + q.removeFirst(); + q.removeFirst(); + assertTrue(q.isEmpty()); + } + + /** + * size changes when elements added and removed + */ + public void testSize() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.removeFirst(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * push(null) throws NPE + */ + public void testPushNull() { + ArrayDeque q = new ArrayDeque(1); + try { + q.push(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * peekFirst() returns element inserted with push + */ + public void testPush() { + ArrayDeque q = populatedDeque(3); + q.pollLast(); + q.push(four); + assertSame(four, q.peekFirst()); + } + + /** + * pop() removes next element, or throws NSEE if empty + */ + public void testPop() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pop()); + } + try { + q.pop(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * offer(null) throws NPE + */ + public void testOfferNull() { + ArrayDeque q = new ArrayDeque(); + try { + q.offer(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * offerFirst(null) throws NPE + */ + public void testOfferFirstNull() { + ArrayDeque q = new ArrayDeque(); + try { + q.offerFirst(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * offerLast(null) throws NPE + */ + public void testOfferLastNull() { + ArrayDeque q = new ArrayDeque(); + try { + q.offerLast(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * offer(x) succeeds + */ + public void testOffer() { + ArrayDeque q = new ArrayDeque(); + assertTrue(q.offer(zero)); + assertTrue(q.offer(one)); + assertSame(zero, q.peekFirst()); + assertSame(one, q.peekLast()); + } + + /** + * offerFirst(x) succeeds + */ + public void testOfferFirst() { + ArrayDeque q = new ArrayDeque(); + assertTrue(q.offerFirst(zero)); + assertTrue(q.offerFirst(one)); + assertSame(one, q.peekFirst()); + assertSame(zero, q.peekLast()); + } + + /** + * offerLast(x) succeeds + */ + public void testOfferLast() { + ArrayDeque q = new ArrayDeque(); + assertTrue(q.offerLast(zero)); + assertTrue(q.offerLast(one)); + assertSame(zero, q.peekFirst()); + assertSame(one, q.peekLast()); + } + + /** + * add(null) throws NPE + */ + public void testAddNull() { + ArrayDeque q = new ArrayDeque(); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addFirst(null) throws NPE + */ + public void testAddFirstNull() { + ArrayDeque q = new ArrayDeque(); + try { + q.addFirst(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addLast(null) throws NPE + */ + public void testAddLastNull() { + ArrayDeque q = new ArrayDeque(); + try { + q.addLast(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * add(x) succeeds + */ + public void testAdd() { + ArrayDeque q = new ArrayDeque(); + assertTrue(q.add(zero)); + assertTrue(q.add(one)); + assertSame(zero, q.peekFirst()); + assertSame(one, q.peekLast()); + } + + /** + * addFirst(x) succeeds + */ + public void testAddFirst() { + ArrayDeque q = new ArrayDeque(); + q.addFirst(zero); + q.addFirst(one); + assertSame(one, q.peekFirst()); + assertSame(zero, q.peekLast()); + } + + /** + * addLast(x) succeeds + */ + public void testAddLast() { + ArrayDeque q = new ArrayDeque(); + q.addLast(zero); + q.addLast(one); + assertSame(zero, q.peekFirst()); + assertSame(one, q.peekLast()); + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + ArrayDeque q = new ArrayDeque(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testAddAll2() { + ArrayDeque q = new ArrayDeque(); + try { + q.addAll(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + ArrayDeque q = new ArrayDeque(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Deque contains all elements, in traversal order, of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + ArrayDeque q = new ArrayDeque(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.pollFirst()); + } + + /** + * pollFirst() succeeds unless empty + */ + public void testPollFirst() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst()); + } + assertNull(q.pollFirst()); + } + + /** + * pollLast() succeeds unless empty + */ + public void testPollLast() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.pollLast()); + } + assertNull(q.pollLast()); + } + + /** + * poll() succeeds unless empty + */ + public void testPoll() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll()); + } + assertNull(q.poll()); + } + + /** + * remove() removes next element, or throws NSEE if empty + */ + public void testRemove() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove(x) removes x and returns true if present + */ + public void testRemoveElement() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertTrue(q.contains(i - 1)); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertFalse(q.remove(i + 1)); + assertFalse(q.contains(i + 1)); + } + assertTrue(q.isEmpty()); + } + + /** + * peekFirst() returns next element, or null if empty + */ + public void testPeekFirst() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peekFirst()); + assertEquals(i, q.pollFirst()); + assertTrue(q.peekFirst() == null || + !q.peekFirst().equals(i)); + } + assertNull(q.peekFirst()); + } + + /** + * peek() returns next element, or null if empty + */ + public void testPeek() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peek()); + assertEquals(i, q.poll()); + assertTrue(q.peek() == null || + !q.peek().equals(i)); + } + assertNull(q.peek()); + } + + /** + * peekLast() returns next element, or null if empty + */ + public void testPeekLast() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.peekLast()); + assertEquals(i, q.pollLast()); + assertTrue(q.peekLast() == null || + !q.peekLast().equals(i)); + } + assertNull(q.peekLast()); + } + + /** + * element() returns first element, or throws NSEE if empty + */ + public void testElement() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.element()); + assertEquals(i, q.poll()); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * getFirst() returns first element, or throws NSEE if empty + */ + public void testFirstElement() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.getFirst()); + assertEquals(i, q.pollFirst()); + } + try { + q.getFirst(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * getLast() returns last element, or throws NSEE if empty + */ + public void testLastElement() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.getLast()); + assertEquals(i, q.pollLast()); + } + try { + q.getLast(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekLast()); + } + + /** + * removeFirst() removes first element, or throws NSEE if empty + */ + public void testRemoveFirst() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.removeFirst()); + } + try { + q.removeFirst(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekFirst()); + } + + /** + * removeLast() removes last element, or throws NSEE if empty + */ + public void testRemoveLast() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.removeLast()); + } + try { + q.removeLast(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekLast()); + } + + /** + * removeFirstOccurrence(x) removes x and returns true if present + */ + public void testRemoveFirstOccurrence() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.removeFirstOccurrence(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.removeFirstOccurrence(new Integer(i))); + assertFalse(q.removeFirstOccurrence(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + + /** + * removeLastOccurrence(x) removes x and returns true if present + */ + public void testRemoveLastOccurrence() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.removeLastOccurrence(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.removeLastOccurrence(new Integer(i))); + assertFalse(q.removeLastOccurrence(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + ArrayDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + assertEquals(i, q.pollFirst()); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + ArrayDeque q = populatedDeque(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertTrue(q.add(new Integer(1))); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + ArrayDeque q = populatedDeque(SIZE); + ArrayDeque p = new ArrayDeque(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + assertTrue(p.add(new Integer(i))); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + ArrayDeque q = populatedDeque(SIZE); + ArrayDeque p = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + assertEquals(changed, (i > 0)); + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.removeFirst(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + ArrayDeque q = populatedDeque(SIZE); + ArrayDeque p = populatedDeque(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + assertFalse(q.contains(p.removeFirst())); + } + } + } + + void checkToArray(ArrayDeque q) { + int size = q.size(); + Object[] o = q.toArray(); + assertEquals(size, o.length); + Iterator it = q.iterator(); + for (int i = 0; i < size; i++) { + Integer x = (Integer) it.next(); + assertEquals((Integer)o[0] + i, (int) x); + assertSame(o[i], x); + } + } + + /** + * toArray() contains all elements in FIFO order + */ + public void testToArray() { + ArrayDeque q = new ArrayDeque(); + for (int i = 0; i < SIZE; i++) { + checkToArray(q); + q.addLast(i); + } + // Provoke wraparound + for (int i = 0; i < SIZE; i++) { + checkToArray(q); + assertEquals(i, q.poll()); + q.addLast(SIZE + i); + } + for (int i = 0; i < SIZE; i++) { + checkToArray(q); + assertEquals(SIZE + i, q.poll()); + } + } + + void checkToArray2(ArrayDeque q) { + int size = q.size(); + Integer[] a1 = (size == 0) ? null : new Integer[size - 1]; + Integer[] a2 = new Integer[size]; + Integer[] a3 = new Integer[size + 2]; + if (size > 0) Arrays.fill(a1, 42); + Arrays.fill(a2, 42); + Arrays.fill(a3, 42); + Integer[] b1 = (size == 0) ? null : (Integer[]) q.toArray(a1); + Integer[] b2 = (Integer[]) q.toArray(a2); + Integer[] b3 = (Integer[]) q.toArray(a3); + assertSame(a2, b2); + assertSame(a3, b3); + Iterator it = q.iterator(); + for (int i = 0; i < size; i++) { + Integer x = (Integer) it.next(); + assertSame(b1[i], x); + assertEquals(b1[0] + i, (int) x); + assertSame(b2[i], x); + assertSame(b3[i], x); + } + assertNull(a3[size]); + assertEquals(42, (int) a3[size + 1]); + if (size > 0) { + assertNotSame(a1, b1); + assertEquals(size, b1.length); + for (int i = 0; i < a1.length; i++) { + assertEquals(42, (int) a1[i]); + } + } + } + + /** + * toArray(a) contains all elements in FIFO order + */ + public void testToArray2() { + ArrayDeque q = new ArrayDeque(); + for (int i = 0; i < SIZE; i++) { + checkToArray2(q); + q.addLast(i); + } + // Provoke wraparound + for (int i = 0; i < SIZE; i++) { + checkToArray2(q); + assertEquals(i, q.poll()); + q.addLast(SIZE + i); + } + for (int i = 0; i < SIZE; i++) { + checkToArray2(q); + assertEquals(SIZE + i, q.poll()); + } + } + + /** + * toArray(null) throws NullPointerException + */ + public void testToArray_NullArg() { + ArrayDeque l = new ArrayDeque(); + l.add(new Object()); + try { + l.toArray(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + ArrayDeque l = new ArrayDeque(); + l.add(new Integer(5)); + try { + l.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * Iterator iterates through all elements + */ + public void testIterator() { + ArrayDeque q = populatedDeque(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + Deque c = new ArrayDeque(); + assertIteratorExhausted(c.iterator()); + assertIteratorExhausted(c.descendingIterator()); + } + + /** + * Iterator ordering is FIFO + */ + public void testIteratorOrdering() { + final ArrayDeque q = new ArrayDeque(); + q.add(one); + q.add(two); + q.add(three); + int k = 0; + for (Iterator it = q.iterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + + assertEquals(3, k); + } + + /** + * iterator.remove() removes current element + */ + public void testIteratorRemove() { + final ArrayDeque q = new ArrayDeque(); + final Random rng = new Random(); + for (int iters = 0; iters < 100; ++iters) { + int max = rng.nextInt(5) + 2; + int split = rng.nextInt(max - 1) + 1; + for (int j = 1; j <= max; ++j) + q.add(new Integer(j)); + Iterator it = q.iterator(); + for (int j = 1; j <= split; ++j) + assertEquals(it.next(), new Integer(j)); + it.remove(); + assertEquals(it.next(), new Integer(split + 1)); + for (int j = 1; j <= split; ++j) + q.remove(new Integer(j)); + it = q.iterator(); + for (int j = split + 1; j <= max; ++j) { + assertEquals(it.next(), new Integer(j)); + it.remove(); + } + assertFalse(it.hasNext()); + assertTrue(q.isEmpty()); + } + } + + /** + * Descending iterator iterates through all elements + */ + public void testDescendingIterator() { + ArrayDeque q = populatedDeque(SIZE); + int i = 0; + Iterator it = q.descendingIterator(); + while (it.hasNext()) { + assertTrue(q.contains(it.next())); + ++i; + } + assertEquals(i, SIZE); + assertFalse(it.hasNext()); + try { + it.next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * Descending iterator ordering is reverse FIFO + */ + public void testDescendingIteratorOrdering() { + final ArrayDeque q = new ArrayDeque(); + for (int iters = 0; iters < 100; ++iters) { + q.add(new Integer(3)); + q.add(new Integer(2)); + q.add(new Integer(1)); + int k = 0; + for (Iterator it = q.descendingIterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + + assertEquals(3, k); + q.remove(); + q.remove(); + q.remove(); + } + } + + /** + * descendingIterator.remove() removes current element + */ + public void testDescendingIteratorRemove() { + final ArrayDeque q = new ArrayDeque(); + final Random rng = new Random(); + for (int iters = 0; iters < 100; ++iters) { + int max = rng.nextInt(5) + 2; + int split = rng.nextInt(max - 1) + 1; + for (int j = max; j >= 1; --j) + q.add(new Integer(j)); + Iterator it = q.descendingIterator(); + for (int j = 1; j <= split; ++j) + assertEquals(it.next(), new Integer(j)); + it.remove(); + assertEquals(it.next(), new Integer(split + 1)); + for (int j = 1; j <= split; ++j) + q.remove(new Integer(j)); + it = q.descendingIterator(); + for (int j = split + 1; j <= max; ++j) { + assertEquals(it.next(), new Integer(j)); + it.remove(); + } + assertFalse(it.hasNext()); + assertTrue(q.isEmpty()); + } + } + + /** + * toString() contains toStrings of elements + */ + public void testToString() { + ArrayDeque q = populatedDeque(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized deque has same elements in same order + */ + public void testSerialization() throws Exception { + Queue x = populatedDeque(SIZE); + Queue y = serialClone(x); + + assertNotSame(y, x); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(), y.remove()); + } + assertTrue(y.isEmpty()); + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Deque[] qs = { + new ArrayDeque(), + populatedDeque(2), + }; + + for (Deque q : qs) { + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + assertFalse(q.removeFirstOccurrence(null)); + assertFalse(q.removeLastOccurrence(null)); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/Atomic8Test.java b/jdk/test/java/util/concurrent/tck/Atomic8Test.java new file mode 100644 index 00000000000..1e49299c21a --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/Atomic8Test.java @@ -0,0 +1,596 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerArray; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicLongArray; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class Atomic8Test extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(Atomic8Test.class); + } + + /* + * Tests of atomic class methods accepting lambdas + * introduced in JDK8. + */ + + static long addLong17(long x) { return x + 17; } + static int addInt17(int x) { return x + 17; } + static Integer addInteger17(Integer x) { + return new Integer(x.intValue() + 17); + } + static Integer sumInteger(Integer x, Integer y) { + return new Integer(x.intValue() + y.intValue()); + } + + volatile long aLongField; + volatile int anIntField; + volatile Integer anIntegerField; + + AtomicLongFieldUpdater aLongFieldUpdater() { + return AtomicLongFieldUpdater.newUpdater + (Atomic8Test.class, "aLongField"); + } + + AtomicIntegerFieldUpdater anIntFieldUpdater() { + return AtomicIntegerFieldUpdater.newUpdater + (Atomic8Test.class, "anIntField"); + } + + AtomicReferenceFieldUpdater anIntegerFieldUpdater() { + return AtomicReferenceFieldUpdater.newUpdater + (Atomic8Test.class, Integer.class, "anIntegerField"); + } + + /** + * AtomicLong getAndUpdate returns previous value and updates + * result of supplied function + */ + public void testLongGetAndUpdate() { + AtomicLong a = new AtomicLong(1L); + assertEquals(1L, a.getAndUpdate(Atomic8Test::addLong17)); + assertEquals(18L, a.getAndUpdate(Atomic8Test::addLong17)); + assertEquals(35L, a.get()); + } + + /** + * AtomicLong updateAndGet updates with supplied function and + * returns result. + */ + public void testLongUpdateAndGet() { + AtomicLong a = new AtomicLong(1L); + assertEquals(18L, a.updateAndGet(Atomic8Test::addLong17)); + assertEquals(35L, a.updateAndGet(Atomic8Test::addLong17)); + } + + /** + * AtomicLong getAndAccumulate returns previous value and updates + * with supplied function. + */ + public void testLongGetAndAccumulate() { + AtomicLong a = new AtomicLong(1L); + assertEquals(1L, a.getAndAccumulate(2L, Long::sum)); + assertEquals(3L, a.getAndAccumulate(3L, Long::sum)); + assertEquals(6L, a.get()); + } + + /** + * AtomicLong accumulateAndGet updates with supplied function and + * returns result. + */ + public void testLongAccumulateAndGet() { + AtomicLong a = new AtomicLong(1L); + assertEquals(7L, a.accumulateAndGet(6L, Long::sum)); + assertEquals(10L, a.accumulateAndGet(3L, Long::sum)); + assertEquals(10L, a.get()); + } + + /** + * AtomicInteger getAndUpdate returns previous value and updates + * result of supplied function + */ + public void testIntGetAndUpdate() { + AtomicInteger a = new AtomicInteger(1); + assertEquals(1, a.getAndUpdate(Atomic8Test::addInt17)); + assertEquals(18, a.getAndUpdate(Atomic8Test::addInt17)); + assertEquals(35, a.get()); + } + + /** + * AtomicInteger updateAndGet updates with supplied function and + * returns result. + */ + public void testIntUpdateAndGet() { + AtomicInteger a = new AtomicInteger(1); + assertEquals(18, a.updateAndGet(Atomic8Test::addInt17)); + assertEquals(35, a.updateAndGet(Atomic8Test::addInt17)); + assertEquals(35, a.get()); + } + + /** + * AtomicInteger getAndAccumulate returns previous value and updates + * with supplied function. + */ + public void testIntGetAndAccumulate() { + AtomicInteger a = new AtomicInteger(1); + assertEquals(1, a.getAndAccumulate(2, Integer::sum)); + assertEquals(3, a.getAndAccumulate(3, Integer::sum)); + assertEquals(6, a.get()); + } + + /** + * AtomicInteger accumulateAndGet updates with supplied function and + * returns result. + */ + public void testIntAccumulateAndGet() { + AtomicInteger a = new AtomicInteger(1); + assertEquals(7, a.accumulateAndGet(6, Integer::sum)); + assertEquals(10, a.accumulateAndGet(3, Integer::sum)); + assertEquals(10, a.get()); + } + + /** + * AtomicReference getAndUpdate returns previous value and updates + * result of supplied function + */ + public void testReferenceGetAndUpdate() { + AtomicReference a = new AtomicReference(one); + assertEquals(new Integer(1), a.getAndUpdate(Atomic8Test::addInteger17)); + assertEquals(new Integer(18), a.getAndUpdate(Atomic8Test::addInteger17)); + assertEquals(new Integer(35), a.get()); + } + + /** + * AtomicReference updateAndGet updates with supplied function and + * returns result. + */ + public void testReferenceUpdateAndGet() { + AtomicReference a = new AtomicReference(one); + assertEquals(new Integer(18), a.updateAndGet(Atomic8Test::addInteger17)); + assertEquals(new Integer(35), a.updateAndGet(Atomic8Test::addInteger17)); + assertEquals(new Integer(35), a.get()); + } + + /** + * AtomicReference getAndAccumulate returns previous value and updates + * with supplied function. + */ + public void testReferenceGetAndAccumulate() { + AtomicReference a = new AtomicReference(one); + assertEquals(new Integer(1), a.getAndAccumulate(2, Atomic8Test::sumInteger)); + assertEquals(new Integer(3), a.getAndAccumulate(3, Atomic8Test::sumInteger)); + assertEquals(new Integer(6), a.get()); + } + + /** + * AtomicReference accumulateAndGet updates with supplied function and + * returns result. + */ + public void testReferenceAccumulateAndGet() { + AtomicReference a = new AtomicReference(one); + assertEquals(new Integer(7), a.accumulateAndGet(6, Atomic8Test::sumInteger)); + assertEquals(new Integer(10), a.accumulateAndGet(3, Atomic8Test::sumInteger)); + assertEquals(new Integer(10), a.get()); + } + + /** + * AtomicLongArray getAndUpdate returns previous value and updates + * result of supplied function + */ + public void testLongArrayGetAndUpdate() { + AtomicLongArray a = new AtomicLongArray(1); + a.set(0, 1); + assertEquals(1L, a.getAndUpdate(0, Atomic8Test::addLong17)); + assertEquals(18L, a.getAndUpdate(0, Atomic8Test::addLong17)); + assertEquals(35L, a.get(0)); + } + + /** + * AtomicLongArray updateAndGet updates with supplied function and + * returns result. + */ + public void testLongArrayUpdateAndGet() { + AtomicLongArray a = new AtomicLongArray(1); + a.set(0, 1); + assertEquals(18L, a.updateAndGet(0, Atomic8Test::addLong17)); + assertEquals(35L, a.updateAndGet(0, Atomic8Test::addLong17)); + assertEquals(35L, a.get(0)); + } + + /** + * AtomicLongArray getAndAccumulate returns previous value and updates + * with supplied function. + */ + public void testLongArrayGetAndAccumulate() { + AtomicLongArray a = new AtomicLongArray(1); + a.set(0, 1); + assertEquals(1L, a.getAndAccumulate(0, 2L, Long::sum)); + assertEquals(3L, a.getAndAccumulate(0, 3L, Long::sum)); + assertEquals(6L, a.get(0)); + } + + /** + * AtomicLongArray accumulateAndGet updates with supplied function and + * returns result. + */ + public void testLongArrayAccumulateAndGet() { + AtomicLongArray a = new AtomicLongArray(1); + a.set(0, 1); + assertEquals(7L, a.accumulateAndGet(0, 6L, Long::sum)); + assertEquals(10L, a.accumulateAndGet(0, 3L, Long::sum)); + assertEquals(10L, a.get(0)); + } + + /** + * AtomicIntegerArray getAndUpdate returns previous value and updates + * result of supplied function + */ + public void testIntArrayGetAndUpdate() { + AtomicIntegerArray a = new AtomicIntegerArray(1); + a.set(0, 1); + assertEquals(1, a.getAndUpdate(0, Atomic8Test::addInt17)); + assertEquals(18, a.getAndUpdate(0, Atomic8Test::addInt17)); + assertEquals(35, a.get(0)); + } + + /** + * AtomicIntegerArray updateAndGet updates with supplied function and + * returns result. + */ + public void testIntArrayUpdateAndGet() { + AtomicIntegerArray a = new AtomicIntegerArray(1); + a.set(0, 1); + assertEquals(18, a.updateAndGet(0, Atomic8Test::addInt17)); + assertEquals(35, a.updateAndGet(0, Atomic8Test::addInt17)); + assertEquals(35, a.get(0)); + } + + /** + * AtomicIntegerArray getAndAccumulate returns previous value and updates + * with supplied function. + */ + public void testIntArrayGetAndAccumulate() { + AtomicIntegerArray a = new AtomicIntegerArray(1); + a.set(0, 1); + assertEquals(1, a.getAndAccumulate(0, 2, Integer::sum)); + assertEquals(3, a.getAndAccumulate(0, 3, Integer::sum)); + assertEquals(6, a.get(0)); + } + + /** + * AtomicIntegerArray accumulateAndGet updates with supplied function and + * returns result. + */ + public void testIntArrayAccumulateAndGet() { + AtomicIntegerArray a = new AtomicIntegerArray(1); + a.set(0, 1); + assertEquals(7, a.accumulateAndGet(0, 6, Integer::sum)); + assertEquals(10, a.accumulateAndGet(0, 3, Integer::sum)); + } + + /** + * AtomicReferenceArray getAndUpdate returns previous value and updates + * result of supplied function + */ + public void testReferenceArrayGetAndUpdate() { + AtomicReferenceArray a = new AtomicReferenceArray(1); + a.set(0, one); + assertEquals(new Integer(1), a.getAndUpdate(0, Atomic8Test::addInteger17)); + assertEquals(new Integer(18), a.getAndUpdate(0, Atomic8Test::addInteger17)); + assertEquals(new Integer(35), a.get(0)); + } + + /** + * AtomicReferenceArray updateAndGet updates with supplied function and + * returns result. + */ + public void testReferenceArrayUpdateAndGet() { + AtomicReferenceArray a = new AtomicReferenceArray(1); + a.set(0, one); + assertEquals(new Integer(18), a.updateAndGet(0, Atomic8Test::addInteger17)); + assertEquals(new Integer(35), a.updateAndGet(0, Atomic8Test::addInteger17)); + } + + /** + * AtomicReferenceArray getAndAccumulate returns previous value and updates + * with supplied function. + */ + public void testReferenceArrayGetAndAccumulate() { + AtomicReferenceArray a = new AtomicReferenceArray(1); + a.set(0, one); + assertEquals(new Integer(1), a.getAndAccumulate(0, 2, Atomic8Test::sumInteger)); + assertEquals(new Integer(3), a.getAndAccumulate(0, 3, Atomic8Test::sumInteger)); + assertEquals(new Integer(6), a.get(0)); + } + + /** + * AtomicReferenceArray accumulateAndGet updates with supplied function and + * returns result. + */ + public void testReferenceArrayAccumulateAndGet() { + AtomicReferenceArray a = new AtomicReferenceArray(1); + a.set(0, one); + assertEquals(new Integer(7), a.accumulateAndGet(0, 6, Atomic8Test::sumInteger)); + assertEquals(new Integer(10), a.accumulateAndGet(0, 3, Atomic8Test::sumInteger)); + } + + /** + * AtomicLongFieldUpdater getAndUpdate returns previous value and updates + * result of supplied function + */ + public void testLongFieldUpdaterGetAndUpdate() { + AtomicLongFieldUpdater a = aLongFieldUpdater(); + a.set(this, 1); + assertEquals(1L, a.getAndUpdate(this, Atomic8Test::addLong17)); + assertEquals(18L, a.getAndUpdate(this, Atomic8Test::addLong17)); + assertEquals(35L, a.get(this)); + assertEquals(35L, aLongField); + } + + /** + * AtomicLongFieldUpdater updateAndGet updates with supplied function and + * returns result. + */ + public void testLongFieldUpdaterUpdateAndGet() { + AtomicLongFieldUpdater a = aLongFieldUpdater(); + a.set(this, 1); + assertEquals(18L, a.updateAndGet(this, Atomic8Test::addLong17)); + assertEquals(35L, a.updateAndGet(this, Atomic8Test::addLong17)); + assertEquals(35L, a.get(this)); + assertEquals(35L, aLongField); + } + + /** + * AtomicLongFieldUpdater getAndAccumulate returns previous value + * and updates with supplied function. + */ + public void testLongFieldUpdaterGetAndAccumulate() { + AtomicLongFieldUpdater a = aLongFieldUpdater(); + a.set(this, 1); + assertEquals(1L, a.getAndAccumulate(this, 2L, Long::sum)); + assertEquals(3L, a.getAndAccumulate(this, 3L, Long::sum)); + assertEquals(6L, a.get(this)); + assertEquals(6L, aLongField); + } + + /** + * AtomicLongFieldUpdater accumulateAndGet updates with supplied + * function and returns result. + */ + public void testLongFieldUpdaterAccumulateAndGet() { + AtomicLongFieldUpdater a = aLongFieldUpdater(); + a.set(this, 1); + assertEquals(7L, a.accumulateAndGet(this, 6L, Long::sum)); + assertEquals(10L, a.accumulateAndGet(this, 3L, Long::sum)); + assertEquals(10L, a.get(this)); + assertEquals(10L, aLongField); + } + + /** + * AtomicIntegerFieldUpdater getAndUpdate returns previous value and updates + * result of supplied function + */ + public void testIntegerFieldUpdaterGetAndUpdate() { + AtomicIntegerFieldUpdater a = anIntFieldUpdater(); + a.set(this, 1); + assertEquals(1, a.getAndUpdate(this, Atomic8Test::addInt17)); + assertEquals(18, a.getAndUpdate(this, Atomic8Test::addInt17)); + assertEquals(35, a.get(this)); + assertEquals(35, anIntField); + } + + /** + * AtomicIntegerFieldUpdater updateAndGet updates with supplied function and + * returns result. + */ + public void testIntegerFieldUpdaterUpdateAndGet() { + AtomicIntegerFieldUpdater a = anIntFieldUpdater(); + a.set(this, 1); + assertEquals(18, a.updateAndGet(this, Atomic8Test::addInt17)); + assertEquals(35, a.updateAndGet(this, Atomic8Test::addInt17)); + assertEquals(35, a.get(this)); + assertEquals(35, anIntField); + } + + /** + * AtomicIntegerFieldUpdater getAndAccumulate returns previous value + * and updates with supplied function. + */ + public void testIntegerFieldUpdaterGetAndAccumulate() { + AtomicIntegerFieldUpdater a = anIntFieldUpdater(); + a.set(this, 1); + assertEquals(1, a.getAndAccumulate(this, 2, Integer::sum)); + assertEquals(3, a.getAndAccumulate(this, 3, Integer::sum)); + assertEquals(6, a.get(this)); + assertEquals(6, anIntField); + } + + /** + * AtomicIntegerFieldUpdater accumulateAndGet updates with supplied + * function and returns result. + */ + public void testIntegerFieldUpdaterAccumulateAndGet() { + AtomicIntegerFieldUpdater a = anIntFieldUpdater(); + a.set(this, 1); + assertEquals(7, a.accumulateAndGet(this, 6, Integer::sum)); + assertEquals(10, a.accumulateAndGet(this, 3, Integer::sum)); + assertEquals(10, a.get(this)); + assertEquals(10, anIntField); + } + + /** + * AtomicReferenceFieldUpdater getAndUpdate returns previous value + * and updates result of supplied function + */ + public void testReferenceFieldUpdaterGetAndUpdate() { + AtomicReferenceFieldUpdater a = anIntegerFieldUpdater(); + a.set(this, one); + assertEquals(new Integer(1), a.getAndUpdate(this, Atomic8Test::addInteger17)); + assertEquals(new Integer(18), a.getAndUpdate(this, Atomic8Test::addInteger17)); + assertEquals(new Integer(35), a.get(this)); + assertEquals(new Integer(35), anIntegerField); + } + + /** + * AtomicReferenceFieldUpdater updateAndGet updates with supplied + * function and returns result. + */ + public void testReferenceFieldUpdaterUpdateAndGet() { + AtomicReferenceFieldUpdater a = anIntegerFieldUpdater(); + a.set(this, one); + assertEquals(new Integer(18), a.updateAndGet(this, Atomic8Test::addInteger17)); + assertEquals(new Integer(35), a.updateAndGet(this, Atomic8Test::addInteger17)); + assertEquals(new Integer(35), a.get(this)); + assertEquals(new Integer(35), anIntegerField); + } + + /** + * AtomicReferenceFieldUpdater returns previous value and updates + * with supplied function. + */ + public void testReferenceFieldUpdaterGetAndAccumulate() { + AtomicReferenceFieldUpdater a = anIntegerFieldUpdater(); + a.set(this, one); + assertEquals(new Integer(1), a.getAndAccumulate(this, 2, Atomic8Test::sumInteger)); + assertEquals(new Integer(3), a.getAndAccumulate(this, 3, Atomic8Test::sumInteger)); + assertEquals(new Integer(6), a.get(this)); + assertEquals(new Integer(6), anIntegerField); + } + + /** + * AtomicReferenceFieldUpdater accumulateAndGet updates with + * supplied function and returns result. + */ + public void testReferenceFieldUpdaterAccumulateAndGet() { + AtomicReferenceFieldUpdater a = anIntegerFieldUpdater(); + a.set(this, one); + assertEquals(new Integer(7), a.accumulateAndGet(this, 6, Atomic8Test::sumInteger)); + assertEquals(new Integer(10), a.accumulateAndGet(this, 3, Atomic8Test::sumInteger)); + assertEquals(new Integer(10), a.get(this)); + assertEquals(new Integer(10), anIntegerField); + } + + /** + * All Atomic getAndUpdate methods throw NullPointerException on + * null function argument + */ + public void testGetAndUpdateNPE() { + Runnable[] throwingActions = { + () -> new AtomicLong().getAndUpdate(null), + () -> new AtomicInteger().getAndUpdate(null), + () -> new AtomicReference().getAndUpdate(null), + () -> new AtomicLongArray(1).getAndUpdate(0, null), + () -> new AtomicIntegerArray(1).getAndUpdate(0, null), + () -> new AtomicReferenceArray(1).getAndUpdate(0, null), + () -> aLongFieldUpdater().getAndUpdate(this, null), + () -> anIntFieldUpdater().getAndUpdate(this, null), + () -> anIntegerFieldUpdater().getAndUpdate(this, null), + ////() -> aLongFieldUpdater().getAndUpdate(null, Atomic8Test::addLong17), + ////() -> anIntFieldUpdater().getAndUpdate(null, Atomic8Test::addInt17), + ////() -> anIntegerFieldUpdater().getAndUpdate(null, Atomic8Test::addInteger17), + }; + assertThrows(NullPointerException.class, throwingActions); + } + + /** + * All Atomic updateAndGet methods throw NullPointerException on null function argument + */ + public void testUpdateAndGetNPE() { + Runnable[] throwingActions = { + () -> new AtomicLong().updateAndGet(null), + () -> new AtomicInteger().updateAndGet(null), + () -> new AtomicReference().updateAndGet(null), + () -> new AtomicLongArray(1).updateAndGet(0, null), + () -> new AtomicIntegerArray(1).updateAndGet(0, null), + () -> new AtomicReferenceArray(1).updateAndGet(0, null), + () -> aLongFieldUpdater().updateAndGet(this, null), + () -> anIntFieldUpdater().updateAndGet(this, null), + () -> anIntegerFieldUpdater().updateAndGet(this, null), + }; + assertThrows(NullPointerException.class, throwingActions); + } + + /** + * All Atomic getAndAccumulate methods throw NullPointerException + * on null function argument + */ + public void testGetAndAccumulateNPE() { + Runnable[] throwingActions = { + () -> new AtomicLong().getAndAccumulate(1L, null), + () -> new AtomicInteger().getAndAccumulate(1, null), + () -> new AtomicReference().getAndAccumulate(one, null), + () -> new AtomicLongArray(1).getAndAccumulate(0, 1L, null), + () -> new AtomicIntegerArray(1).getAndAccumulate(0, 1, null), + () -> new AtomicReferenceArray(1).getAndAccumulate(0, one, null), + () -> aLongFieldUpdater().getAndAccumulate(this, 1L, null), + () -> anIntFieldUpdater().getAndAccumulate(this, 1, null), + () -> anIntegerFieldUpdater().getAndAccumulate(this, one, null), + }; + assertThrows(NullPointerException.class, throwingActions); + } + + /** + * All Atomic accumulateAndGet methods throw NullPointerException + * on null function argument + */ + public void testAccumulateAndGetNPE() { + Runnable[] throwingActions = { + () -> new AtomicLong().accumulateAndGet(1L, null), + () -> new AtomicInteger().accumulateAndGet(1, null), + () -> new AtomicReference().accumulateAndGet(one, null), + () -> new AtomicLongArray(1).accumulateAndGet(0, 1L, null), + () -> new AtomicIntegerArray(1).accumulateAndGet(0, 1, null), + () -> new AtomicReferenceArray(1).accumulateAndGet(0, one, null), + () -> aLongFieldUpdater().accumulateAndGet(this, 1L, null), + () -> anIntFieldUpdater().accumulateAndGet(this, 1, null), + () -> anIntegerFieldUpdater().accumulateAndGet(this, one, null), + }; + assertThrows(NullPointerException.class, throwingActions); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java b/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java new file mode 100644 index 00000000000..91b5cfa8c1f --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicBooleanTest.java @@ -0,0 +1,169 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.concurrent.atomic.AtomicBoolean; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicBooleanTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicBooleanTest.class); + } + + /** + * constructor initializes to given value + */ + public void testConstructor() { + assertTrue(new AtomicBoolean(true).get()); + assertFalse(new AtomicBoolean(false).get()); + } + + /** + * default constructed initializes to false + */ + public void testConstructor2() { + AtomicBoolean ai = new AtomicBoolean(); + assertFalse(ai.get()); + } + + /** + * get returns the last value set + */ + public void testGetSet() { + AtomicBoolean ai = new AtomicBoolean(true); + assertTrue(ai.get()); + ai.set(false); + assertFalse(ai.get()); + ai.set(true); + assertTrue(ai.get()); + } + + /** + * get returns the last value lazySet in same thread + */ + public void testGetLazySet() { + AtomicBoolean ai = new AtomicBoolean(true); + assertTrue(ai.get()); + ai.lazySet(false); + assertFalse(ai.get()); + ai.lazySet(true); + assertTrue(ai.get()); + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicBoolean ai = new AtomicBoolean(true); + assertTrue(ai.compareAndSet(true, false)); + assertFalse(ai.get()); + assertTrue(ai.compareAndSet(false, false)); + assertFalse(ai.get()); + assertFalse(ai.compareAndSet(true, false)); + assertFalse(ai.get()); + assertTrue(ai.compareAndSet(false, true)); + assertTrue(ai.get()); + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + final AtomicBoolean ai = new AtomicBoolean(true); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!ai.compareAndSet(false, true)) Thread.yield(); + }}); + + t.start(); + assertTrue(ai.compareAndSet(true, false)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicBoolean ai = new AtomicBoolean(true); + do {} while (!ai.weakCompareAndSet(true, false)); + assertFalse(ai.get()); + do {} while (!ai.weakCompareAndSet(false, false)); + assertFalse(ai.get()); + do {} while (!ai.weakCompareAndSet(false, true)); + assertTrue(ai.get()); + } + + /** + * getAndSet returns previous value and sets to given value + */ + public void testGetAndSet() { + AtomicBoolean ai = new AtomicBoolean(true); + assertEquals(true, ai.getAndSet(false)); + assertEquals(false, ai.getAndSet(false)); + assertEquals(false, ai.getAndSet(true)); + assertTrue(ai.get()); + } + + /** + * a deserialized serialized atomic holds same value + */ + public void testSerialization() throws Exception { + AtomicBoolean x = new AtomicBoolean(); + AtomicBoolean y = serialClone(x); + x.set(true); + AtomicBoolean z = serialClone(x); + assertTrue(x.get()); + assertFalse(y.get()); + assertTrue(z.get()); + } + + /** + * toString returns current value. + */ + public void testToString() { + AtomicBoolean ai = new AtomicBoolean(); + assertEquals(Boolean.toString(false), ai.toString()); + ai.set(true); + assertEquals(Boolean.toString(true), ai.toString()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java b/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java new file mode 100644 index 00000000000..d3d8f14f5c0 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerArrayTest.java @@ -0,0 +1,370 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicIntegerArray; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicIntegerArrayTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicIntegerArrayTest.class); + } + + /** + * constructor creates array of given size with all elements zero + */ + public void testConstructor() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) + assertEquals(0, aa.get(i)); + } + + /** + * constructor with null array throws NPE + */ + public void testConstructor2NPE() { + try { + int[] a = null; + new AtomicIntegerArray(a); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * constructor with array is of same size and has all elements + */ + public void testConstructor2() { + int[] a = { 17, 3, -42, 99, -7 }; + AtomicIntegerArray aa = new AtomicIntegerArray(a); + assertEquals(a.length, aa.length()); + for (int i = 0; i < a.length; i++) + assertEquals(a[i], aa.get(i)); + } + + /** + * get and set for out of bound indices throw IndexOutOfBoundsException + */ + public void testIndexing() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int index : new int[] { -1, SIZE }) { + try { + aa.get(index); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.set(index, 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.lazySet(index, 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.compareAndSet(index, 1, 2); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.weakCompareAndSet(index, 1, 2); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.getAndAdd(index, 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.addAndGet(index, 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * get returns the last value set at index + */ + public void testGetSet() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.get(i)); + aa.set(i, 2); + assertEquals(2, aa.get(i)); + aa.set(i, -3); + assertEquals(-3, aa.get(i)); + } + } + + /** + * get returns the last value lazySet at index by same thread + */ + public void testGetLazySet() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.lazySet(i, 1); + assertEquals(1, aa.get(i)); + aa.lazySet(i, 2); + assertEquals(2, aa.get(i)); + aa.lazySet(i, -3); + assertEquals(-3, aa.get(i)); + } + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertTrue(aa.compareAndSet(i, 1, 2)); + assertTrue(aa.compareAndSet(i, 2, -4)); + assertEquals(-4, aa.get(i)); + assertFalse(aa.compareAndSet(i, -5, 7)); + assertEquals(-4, aa.get(i)); + assertTrue(aa.compareAndSet(i, -4, 7)); + assertEquals(7, aa.get(i)); + } + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + final AtomicIntegerArray a = new AtomicIntegerArray(1); + a.set(0, 1); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!a.compareAndSet(0, 2, 3)) + Thread.yield(); + }}); + + t.start(); + assertTrue(a.compareAndSet(0, 1, 2)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertEquals(3, a.get(0)); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + do {} while (!aa.weakCompareAndSet(i, 1, 2)); + do {} while (!aa.weakCompareAndSet(i, 2, -4)); + assertEquals(-4, aa.get(i)); + do {} while (!aa.weakCompareAndSet(i, -4, 7)); + assertEquals(7, aa.get(i)); + } + } + + /** + * getAndSet returns previous value and sets to given value at given index + */ + public void testGetAndSet() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.getAndSet(i, 0)); + assertEquals(0, aa.getAndSet(i, -10)); + assertEquals(-10, aa.getAndSet(i, 1)); + } + } + + /** + * getAndAdd returns previous value and adds given value + */ + public void testGetAndAdd() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.getAndAdd(i, 2)); + assertEquals(3, aa.get(i)); + assertEquals(3, aa.getAndAdd(i, -4)); + assertEquals(-1, aa.get(i)); + } + } + + /** + * getAndDecrement returns previous value and decrements + */ + public void testGetAndDecrement() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.getAndDecrement(i)); + assertEquals(0, aa.getAndDecrement(i)); + assertEquals(-1, aa.getAndDecrement(i)); + } + } + + /** + * getAndIncrement returns previous value and increments + */ + public void testGetAndIncrement() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.getAndIncrement(i)); + assertEquals(2, aa.get(i)); + aa.set(i, -2); + assertEquals(-2, aa.getAndIncrement(i)); + assertEquals(-1, aa.getAndIncrement(i)); + assertEquals(0, aa.getAndIncrement(i)); + assertEquals(1, aa.get(i)); + } + } + + /** + * addAndGet adds given value to current, and returns current value + */ + public void testAddAndGet() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(3, aa.addAndGet(i, 2)); + assertEquals(3, aa.get(i)); + assertEquals(-1, aa.addAndGet(i, -4)); + assertEquals(-1, aa.get(i)); + } + } + + /** + * decrementAndGet decrements and returns current value + */ + public void testDecrementAndGet() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(0, aa.decrementAndGet(i)); + assertEquals(-1, aa.decrementAndGet(i)); + assertEquals(-2, aa.decrementAndGet(i)); + assertEquals(-2, aa.get(i)); + } + } + + /** + * incrementAndGet increments and returns current value + */ + public void testIncrementAndGet() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(2, aa.incrementAndGet(i)); + assertEquals(2, aa.get(i)); + aa.set(i, -2); + assertEquals(-1, aa.incrementAndGet(i)); + assertEquals(0, aa.incrementAndGet(i)); + assertEquals(1, aa.incrementAndGet(i)); + assertEquals(1, aa.get(i)); + } + } + + class Counter extends CheckedRunnable { + final AtomicIntegerArray aa; + volatile int counts; + Counter(AtomicIntegerArray a) { aa = a; } + public void realRun() { + for (;;) { + boolean done = true; + for (int i = 0; i < aa.length(); i++) { + int v = aa.get(i); + assertTrue(v >= 0); + if (v != 0) { + done = false; + if (aa.compareAndSet(i, v, v - 1)) + ++counts; + } + } + if (done) + break; + } + } + } + + /** + * Multiple threads using same array of counters successfully + * update a number of times equal to total count + */ + public void testCountingInMultipleThreads() throws InterruptedException { + final AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + int countdown = 10000; + for (int i = 0; i < SIZE; i++) + aa.set(i, countdown); + Counter c1 = new Counter(aa); + Counter c2 = new Counter(aa); + Thread t1 = new Thread(c1); + Thread t2 = new Thread(c2); + t1.start(); + t2.start(); + t1.join(); + t2.join(); + assertEquals(c1.counts+c2.counts, SIZE * countdown); + } + + /** + * a deserialized serialized array holds same values + */ + public void testSerialization() throws Exception { + AtomicIntegerArray x = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) + x.set(i, -i); + AtomicIntegerArray y = serialClone(x); + assertNotSame(x, y); + assertEquals(x.length(), y.length()); + for (int i = 0; i < SIZE; i++) { + assertEquals(x.get(i), y.get(i)); + } + } + + /** + * toString returns current value. + */ + public void testToString() { + int[] a = { 17, 3, -42, 99, -7 }; + AtomicIntegerArray aa = new AtomicIntegerArray(a); + assertEquals(Arrays.toString(a), aa.toString()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicIntegerFieldUpdaterTest.java b/jdk/test/java/util/concurrent/tck/AtomicIntegerFieldUpdaterTest.java new file mode 100644 index 00000000000..5f7612de975 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerFieldUpdaterTest.java @@ -0,0 +1,363 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase { + volatile int x = 0; + protected volatile int protectedField; + private volatile int privateField; + int w; + float z; + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicIntegerFieldUpdaterTest.class); + } + + // for testing subclass access + static class AtomicIntegerFieldUpdaterTestSubclass extends AtomicIntegerFieldUpdaterTest { + public void checkPrivateAccess() { + try { + AtomicIntegerFieldUpdater a = + AtomicIntegerFieldUpdater.newUpdater + (AtomicIntegerFieldUpdaterTest.class, "privateField"); + shouldThrow(); + } catch (RuntimeException success) { + assertNotNull(success.getCause()); + } + } + + public void checkCompareAndSetProtectedSub() { + AtomicIntegerFieldUpdater a = + AtomicIntegerFieldUpdater.newUpdater + (AtomicIntegerFieldUpdaterTest.class, "protectedField"); + this.protectedField = 1; + assertTrue(a.compareAndSet(this, 1, 2)); + assertTrue(a.compareAndSet(this, 2, -4)); + assertEquals(-4, a.get(this)); + assertFalse(a.compareAndSet(this, -5, 7)); + assertEquals(-4, a.get(this)); + assertTrue(a.compareAndSet(this, -4, 7)); + assertEquals(7, a.get(this)); + } + } + + static class UnrelatedClass { + public void checkPackageAccess(AtomicIntegerFieldUpdaterTest obj) { + obj.x = 72; + AtomicIntegerFieldUpdater a = + AtomicIntegerFieldUpdater.newUpdater + (AtomicIntegerFieldUpdaterTest.class, "x"); + assertEquals(72, a.get(obj)); + assertTrue(a.compareAndSet(obj, 72, 73)); + assertEquals(73, a.get(obj)); + } + + public void checkPrivateAccess(AtomicIntegerFieldUpdaterTest obj) { + try { + AtomicIntegerFieldUpdater a = + AtomicIntegerFieldUpdater.newUpdater + (AtomicIntegerFieldUpdaterTest.class, "privateField"); + throw new AssertionError("should throw"); + } catch (RuntimeException success) { + assertNotNull(success.getCause()); + } + } + } + + AtomicIntegerFieldUpdater updaterFor(String fieldName) { + return AtomicIntegerFieldUpdater.newUpdater + (AtomicIntegerFieldUpdaterTest.class, fieldName); + } + + /** + * Construction with non-existent field throws RuntimeException + */ + public void testConstructor() { + try { + updaterFor("y"); + shouldThrow(); + } catch (RuntimeException success) { + assertNotNull(success.getCause()); + } + } + + /** + * construction with field not of given type throws IllegalArgumentException + */ + public void testConstructor2() { + try { + updaterFor("z"); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * construction with non-volatile field throws IllegalArgumentException + */ + public void testConstructor3() { + try { + updaterFor("w"); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * construction using private field from subclass throws RuntimeException + */ + public void testPrivateFieldInSubclass() { + AtomicIntegerFieldUpdaterTestSubclass s = + new AtomicIntegerFieldUpdaterTestSubclass(); + s.checkPrivateAccess(); + } + + /** + * construction from unrelated class; package access is allowed, + * private access is not + */ + public void testUnrelatedClassAccess() { + new UnrelatedClass().checkPackageAccess(this); + new UnrelatedClass().checkPrivateAccess(this); + } + + /** + * get returns the last value set or assigned + */ + public void testGetSet() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.get(this)); + a.set(this, 2); + assertEquals(2, a.get(this)); + a.set(this, -3); + assertEquals(-3, a.get(this)); + } + + /** + * get returns the last value lazySet by same thread + */ + public void testGetLazySet() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.get(this)); + a.lazySet(this, 2); + assertEquals(2, a.get(this)); + a.lazySet(this, -3); + assertEquals(-3, a.get(this)); + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertTrue(a.compareAndSet(this, 1, 2)); + assertTrue(a.compareAndSet(this, 2, -4)); + assertEquals(-4, a.get(this)); + assertFalse(a.compareAndSet(this, -5, 7)); + assertEquals(-4, a.get(this)); + assertTrue(a.compareAndSet(this, -4, 7)); + assertEquals(7, a.get(this)); + } + + /** + * compareAndSet succeeds in changing protected field value if + * equal to expected else fails + */ + public void testCompareAndSetProtected() { + AtomicIntegerFieldUpdater a; + a = updaterFor("protectedField"); + protectedField = 1; + assertTrue(a.compareAndSet(this, 1, 2)); + assertTrue(a.compareAndSet(this, 2, -4)); + assertEquals(-4, a.get(this)); + assertFalse(a.compareAndSet(this, -5, 7)); + assertEquals(-4, a.get(this)); + assertTrue(a.compareAndSet(this, -4, 7)); + assertEquals(7, a.get(this)); + } + + /** + * compareAndSet succeeds in changing protected field value if + * equal to expected else fails + */ + public void testCompareAndSetProtectedInSubclass() { + AtomicIntegerFieldUpdaterTestSubclass s = + new AtomicIntegerFieldUpdaterTestSubclass(); + s.checkCompareAndSetProtectedSub(); + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + x = 1; + final AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!a.compareAndSet(AtomicIntegerFieldUpdaterTest.this, 2, 3)) + Thread.yield(); + }}); + + t.start(); + assertTrue(a.compareAndSet(this, 1, 2)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertEquals(3, a.get(this)); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + do {} while (!a.weakCompareAndSet(this, 1, 2)); + do {} while (!a.weakCompareAndSet(this, 2, -4)); + assertEquals(-4, a.get(this)); + do {} while (!a.weakCompareAndSet(this, -4, 7)); + assertEquals(7, a.get(this)); + } + + /** + * getAndSet returns previous value and sets to given value + */ + public void testGetAndSet() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.getAndSet(this, 0)); + assertEquals(0, a.getAndSet(this, -10)); + assertEquals(-10, a.getAndSet(this, 1)); + } + + /** + * getAndAdd returns previous value and adds given value + */ + public void testGetAndAdd() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.getAndAdd(this, 2)); + assertEquals(3, a.get(this)); + assertEquals(3, a.getAndAdd(this, -4)); + assertEquals(-1, a.get(this)); + } + + /** + * getAndDecrement returns previous value and decrements + */ + public void testGetAndDecrement() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.getAndDecrement(this)); + assertEquals(0, a.getAndDecrement(this)); + assertEquals(-1, a.getAndDecrement(this)); + } + + /** + * getAndIncrement returns previous value and increments + */ + public void testGetAndIncrement() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.getAndIncrement(this)); + assertEquals(2, a.get(this)); + a.set(this, -2); + assertEquals(-2, a.getAndIncrement(this)); + assertEquals(-1, a.getAndIncrement(this)); + assertEquals(0, a.getAndIncrement(this)); + assertEquals(1, a.get(this)); + } + + /** + * addAndGet adds given value to current, and returns current value + */ + public void testAddAndGet() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(3, a.addAndGet(this, 2)); + assertEquals(3, a.get(this)); + assertEquals(-1, a.addAndGet(this, -4)); + assertEquals(-1, a.get(this)); + } + + /** + * decrementAndGet decrements and returns current value + */ + public void testDecrementAndGet() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(0, a.decrementAndGet(this)); + assertEquals(-1, a.decrementAndGet(this)); + assertEquals(-2, a.decrementAndGet(this)); + assertEquals(-2, a.get(this)); + } + + /** + * incrementAndGet increments and returns current value + */ + public void testIncrementAndGet() { + AtomicIntegerFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(2, a.incrementAndGet(this)); + assertEquals(2, a.get(this)); + a.set(this, -2); + assertEquals(-1, a.incrementAndGet(this)); + assertEquals(0, a.incrementAndGet(this)); + assertEquals(1, a.incrementAndGet(this)); + assertEquals(1, a.get(this)); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicIntegerTest.java b/jdk/test/java/util/concurrent/tck/AtomicIntegerTest.java new file mode 100644 index 00000000000..d148788d792 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerTest.java @@ -0,0 +1,294 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.concurrent.atomic.AtomicInteger; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicIntegerTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicIntegerTest.class); + } + + final int[] VALUES = { + Integer.MIN_VALUE, -1, 0, 1, 42, Integer.MAX_VALUE, + }; + + /** + * constructor initializes to given value + */ + public void testConstructor() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(1, ai.get()); + } + + /** + * default constructed initializes to zero + */ + public void testConstructor2() { + AtomicInteger ai = new AtomicInteger(); + assertEquals(0, ai.get()); + } + + /** + * get returns the last value set + */ + public void testGetSet() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(1, ai.get()); + ai.set(2); + assertEquals(2, ai.get()); + ai.set(-3); + assertEquals(-3, ai.get()); + } + + /** + * get returns the last value lazySet in same thread + */ + public void testGetLazySet() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(1, ai.get()); + ai.lazySet(2); + assertEquals(2, ai.get()); + ai.lazySet(-3); + assertEquals(-3, ai.get()); + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicInteger ai = new AtomicInteger(1); + assertTrue(ai.compareAndSet(1, 2)); + assertTrue(ai.compareAndSet(2, -4)); + assertEquals(-4, ai.get()); + assertFalse(ai.compareAndSet(-5, 7)); + assertEquals(-4, ai.get()); + assertTrue(ai.compareAndSet(-4, 7)); + assertEquals(7, ai.get()); + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + final AtomicInteger ai = new AtomicInteger(1); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!ai.compareAndSet(2, 3)) + Thread.yield(); + }}); + + t.start(); + assertTrue(ai.compareAndSet(1, 2)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertEquals(3, ai.get()); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicInteger ai = new AtomicInteger(1); + do {} while (!ai.weakCompareAndSet(1, 2)); + do {} while (!ai.weakCompareAndSet(2, -4)); + assertEquals(-4, ai.get()); + do {} while (!ai.weakCompareAndSet(-4, 7)); + assertEquals(7, ai.get()); + } + + /** + * getAndSet returns previous value and sets to given value + */ + public void testGetAndSet() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(1, ai.getAndSet(0)); + assertEquals(0, ai.getAndSet(-10)); + assertEquals(-10, ai.getAndSet(1)); + } + + /** + * getAndAdd returns previous value and adds given value + */ + public void testGetAndAdd() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(1, ai.getAndAdd(2)); + assertEquals(3, ai.get()); + assertEquals(3, ai.getAndAdd(-4)); + assertEquals(-1, ai.get()); + } + + /** + * getAndDecrement returns previous value and decrements + */ + public void testGetAndDecrement() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(1, ai.getAndDecrement()); + assertEquals(0, ai.getAndDecrement()); + assertEquals(-1, ai.getAndDecrement()); + } + + /** + * getAndIncrement returns previous value and increments + */ + public void testGetAndIncrement() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(1, ai.getAndIncrement()); + assertEquals(2, ai.get()); + ai.set(-2); + assertEquals(-2, ai.getAndIncrement()); + assertEquals(-1, ai.getAndIncrement()); + assertEquals(0, ai.getAndIncrement()); + assertEquals(1, ai.get()); + } + + /** + * addAndGet adds given value to current, and returns current value + */ + public void testAddAndGet() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(3, ai.addAndGet(2)); + assertEquals(3, ai.get()); + assertEquals(-1, ai.addAndGet(-4)); + assertEquals(-1, ai.get()); + } + + /** + * decrementAndGet decrements and returns current value + */ + public void testDecrementAndGet() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(0, ai.decrementAndGet()); + assertEquals(-1, ai.decrementAndGet()); + assertEquals(-2, ai.decrementAndGet()); + assertEquals(-2, ai.get()); + } + + /** + * incrementAndGet increments and returns current value + */ + public void testIncrementAndGet() { + AtomicInteger ai = new AtomicInteger(1); + assertEquals(2, ai.incrementAndGet()); + assertEquals(2, ai.get()); + ai.set(-2); + assertEquals(-1, ai.incrementAndGet()); + assertEquals(0, ai.incrementAndGet()); + assertEquals(1, ai.incrementAndGet()); + assertEquals(1, ai.get()); + } + + /** + * a deserialized serialized atomic holds same value + */ + public void testSerialization() throws Exception { + AtomicInteger x = new AtomicInteger(); + AtomicInteger y = serialClone(x); + assertNotSame(x, y); + x.set(22); + AtomicInteger z = serialClone(x); + assertEquals(22, x.get()); + assertEquals(0, y.get()); + assertEquals(22, z.get()); + } + + /** + * toString returns current value. + */ + public void testToString() { + AtomicInteger ai = new AtomicInteger(); + assertEquals("0", ai.toString()); + for (int x : VALUES) { + ai.set(x); + assertEquals(Integer.toString(x), ai.toString()); + } + } + + /** + * intValue returns current value. + */ + public void testIntValue() { + AtomicInteger ai = new AtomicInteger(); + assertEquals(0, ai.intValue()); + for (int x : VALUES) { + ai.set(x); + assertEquals(x, ai.intValue()); + } + } + + /** + * longValue returns current value. + */ + public void testLongValue() { + AtomicInteger ai = new AtomicInteger(); + assertEquals(0L, ai.longValue()); + for (int x : VALUES) { + ai.set(x); + assertEquals((long)x, ai.longValue()); + } + } + + /** + * floatValue returns current value. + */ + public void testFloatValue() { + AtomicInteger ai = new AtomicInteger(); + assertEquals(0.0f, ai.floatValue()); + for (int x : VALUES) { + ai.set(x); + assertEquals((float)x, ai.floatValue()); + } + } + + /** + * doubleValue returns current value. + */ + public void testDoubleValue() { + AtomicInteger ai = new AtomicInteger(); + assertEquals(0.0d, ai.doubleValue()); + for (int x : VALUES) { + ai.set(x); + assertEquals((double)x, ai.doubleValue()); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java b/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java new file mode 100644 index 00000000000..bd74addbf7f --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicLongArrayTest.java @@ -0,0 +1,369 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicLongArray; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicLongArrayTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicLongArrayTest.class); + } + + /** + * constructor creates array of given size with all elements zero + */ + public void testConstructor() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) + assertEquals(0, aa.get(i)); + } + + /** + * constructor with null array throws NPE + */ + public void testConstructor2NPE() { + try { + long[] a = null; + new AtomicLongArray(a); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * constructor with array is of same size and has all elements + */ + public void testConstructor2() { + long[] a = { 17L, 3L, -42L, 99L, -7L }; + AtomicLongArray aa = new AtomicLongArray(a); + assertEquals(a.length, aa.length()); + for (int i = 0; i < a.length; i++) + assertEquals(a[i], aa.get(i)); + } + + /** + * get and set for out of bound indices throw IndexOutOfBoundsException + */ + public void testIndexing() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int index : new int[] { -1, SIZE }) { + try { + aa.get(index); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.set(index, 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.lazySet(index, 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.compareAndSet(index, 1, 2); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.weakCompareAndSet(index, 1, 2); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.getAndAdd(index, 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.addAndGet(index, 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * get returns the last value set at index + */ + public void testGetSet() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.get(i)); + aa.set(i, 2); + assertEquals(2, aa.get(i)); + aa.set(i, -3); + assertEquals(-3, aa.get(i)); + } + } + + /** + * get returns the last value lazySet at index by same thread + */ + public void testGetLazySet() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.lazySet(i, 1); + assertEquals(1, aa.get(i)); + aa.lazySet(i, 2); + assertEquals(2, aa.get(i)); + aa.lazySet(i, -3); + assertEquals(-3, aa.get(i)); + } + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertTrue(aa.compareAndSet(i, 1, 2)); + assertTrue(aa.compareAndSet(i, 2, -4)); + assertEquals(-4, aa.get(i)); + assertFalse(aa.compareAndSet(i, -5, 7)); + assertEquals(-4, aa.get(i)); + assertTrue(aa.compareAndSet(i, -4, 7)); + assertEquals(7, aa.get(i)); + } + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws InterruptedException { + final AtomicLongArray a = new AtomicLongArray(1); + a.set(0, 1); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!a.compareAndSet(0, 2, 3)) + Thread.yield(); + }}); + + t.start(); + assertTrue(a.compareAndSet(0, 1, 2)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertEquals(3, a.get(0)); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + do {} while (!aa.weakCompareAndSet(i, 1, 2)); + do {} while (!aa.weakCompareAndSet(i, 2, -4)); + assertEquals(-4, aa.get(i)); + do {} while (!aa.weakCompareAndSet(i, -4, 7)); + assertEquals(7, aa.get(i)); + } + } + + /** + * getAndSet returns previous value and sets to given value at given index + */ + public void testGetAndSet() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.getAndSet(i, 0)); + assertEquals(0, aa.getAndSet(i, -10)); + assertEquals(-10, aa.getAndSet(i, 1)); + } + } + + /** + * getAndAdd returns previous value and adds given value + */ + public void testGetAndAdd() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.getAndAdd(i, 2)); + assertEquals(3, aa.get(i)); + assertEquals(3, aa.getAndAdd(i, -4)); + assertEquals(-1, aa.get(i)); + } + } + + /** + * getAndDecrement returns previous value and decrements + */ + public void testGetAndDecrement() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.getAndDecrement(i)); + assertEquals(0, aa.getAndDecrement(i)); + assertEquals(-1, aa.getAndDecrement(i)); + } + } + + /** + * getAndIncrement returns previous value and increments + */ + public void testGetAndIncrement() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(1, aa.getAndIncrement(i)); + assertEquals(2, aa.get(i)); + aa.set(i, -2); + assertEquals(-2, aa.getAndIncrement(i)); + assertEquals(-1, aa.getAndIncrement(i)); + assertEquals(0, aa.getAndIncrement(i)); + assertEquals(1, aa.get(i)); + } + } + + /** + * addAndGet adds given value to current, and returns current value + */ + public void testAddAndGet() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(3, aa.addAndGet(i, 2)); + assertEquals(3, aa.get(i)); + assertEquals(-1, aa.addAndGet(i, -4)); + assertEquals(-1, aa.get(i)); + } + } + + /** + * decrementAndGet decrements and returns current value + */ + public void testDecrementAndGet() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(0, aa.decrementAndGet(i)); + assertEquals(-1, aa.decrementAndGet(i)); + assertEquals(-2, aa.decrementAndGet(i)); + assertEquals(-2, aa.get(i)); + } + } + + /** + * incrementAndGet increments and returns current value + */ + public void testIncrementAndGet() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + assertEquals(2, aa.incrementAndGet(i)); + assertEquals(2, aa.get(i)); + aa.set(i, -2); + assertEquals(-1, aa.incrementAndGet(i)); + assertEquals(0, aa.incrementAndGet(i)); + assertEquals(1, aa.incrementAndGet(i)); + assertEquals(1, aa.get(i)); + } + } + + class Counter extends CheckedRunnable { + final AtomicLongArray aa; + volatile long counts; + Counter(AtomicLongArray a) { aa = a; } + public void realRun() { + for (;;) { + boolean done = true; + for (int i = 0; i < aa.length(); i++) { + long v = aa.get(i); + assertTrue(v >= 0); + if (v != 0) { + done = false; + if (aa.compareAndSet(i, v, v - 1)) + ++counts; + } + } + if (done) + break; + } + } + } + + /** + * Multiple threads using same array of counters successfully + * update a number of times equal to total count + */ + public void testCountingInMultipleThreads() throws InterruptedException { + final AtomicLongArray aa = new AtomicLongArray(SIZE); + long countdown = 10000; + for (int i = 0; i < SIZE; i++) + aa.set(i, countdown); + Counter c1 = new Counter(aa); + Counter c2 = new Counter(aa); + Thread t1 = new Thread(c1); + Thread t2 = new Thread(c2); + t1.start(); + t2.start(); + t1.join(); + t2.join(); + assertEquals(c1.counts+c2.counts, SIZE * countdown); + } + + /** + * a deserialized serialized array holds same values + */ + public void testSerialization() throws Exception { + AtomicLongArray x = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) + x.set(i, -i); + AtomicLongArray y = serialClone(x); + assertNotSame(x, y); + assertEquals(x.length(), y.length()); + for (int i = 0; i < SIZE; i++) { + assertEquals(x.get(i), y.get(i)); + } + } + + /** + * toString returns current value. + */ + public void testToString() { + long[] a = { 17, 3, -42, 99, -7 }; + AtomicLongArray aa = new AtomicLongArray(a); + assertEquals(Arrays.toString(a), aa.toString()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicLongFieldUpdaterTest.java b/jdk/test/java/util/concurrent/tck/AtomicLongFieldUpdaterTest.java new file mode 100644 index 00000000000..b9dc1017017 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicLongFieldUpdaterTest.java @@ -0,0 +1,363 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.concurrent.atomic.AtomicLongFieldUpdater; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicLongFieldUpdaterTest extends JSR166TestCase { + volatile long x = 0; + protected volatile long protectedField; + private volatile long privateField; + long w; + float z; + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicLongFieldUpdaterTest.class); + } + + // for testing subclass access + static class AtomicLongFieldUpdaterTestSubclass extends AtomicLongFieldUpdaterTest { + public void checkPrivateAccess() { + try { + AtomicLongFieldUpdater a = + AtomicLongFieldUpdater.newUpdater + (AtomicLongFieldUpdaterTest.class, "privateField"); + shouldThrow(); + } catch (RuntimeException success) { + assertNotNull(success.getCause()); + } + } + + public void checkCompareAndSetProtectedSub() { + AtomicLongFieldUpdater a = + AtomicLongFieldUpdater.newUpdater + (AtomicLongFieldUpdaterTest.class, "protectedField"); + this.protectedField = 1; + assertTrue(a.compareAndSet(this, 1, 2)); + assertTrue(a.compareAndSet(this, 2, -4)); + assertEquals(-4, a.get(this)); + assertFalse(a.compareAndSet(this, -5, 7)); + assertEquals(-4, a.get(this)); + assertTrue(a.compareAndSet(this, -4, 7)); + assertEquals(7, a.get(this)); + } + } + + static class UnrelatedClass { + public void checkPackageAccess(AtomicLongFieldUpdaterTest obj) { + obj.x = 72L; + AtomicLongFieldUpdater a = + AtomicLongFieldUpdater.newUpdater + (AtomicLongFieldUpdaterTest.class, "x"); + assertEquals(72L, a.get(obj)); + assertTrue(a.compareAndSet(obj, 72L, 73L)); + assertEquals(73L, a.get(obj)); + } + + public void checkPrivateAccess(AtomicLongFieldUpdaterTest obj) { + try { + AtomicLongFieldUpdater a = + AtomicLongFieldUpdater.newUpdater + (AtomicLongFieldUpdaterTest.class, "privateField"); + throw new AssertionError("should throw"); + } catch (RuntimeException success) { + assertNotNull(success.getCause()); + } + } + } + + AtomicLongFieldUpdater updaterFor(String fieldName) { + return AtomicLongFieldUpdater.newUpdater + (AtomicLongFieldUpdaterTest.class, fieldName); + } + + /** + * Construction with non-existent field throws RuntimeException + */ + public void testConstructor() { + try { + updaterFor("y"); + shouldThrow(); + } catch (RuntimeException success) { + assertNotNull(success.getCause()); + } + } + + /** + * construction with field not of given type throws IllegalArgumentException + */ + public void testConstructor2() { + try { + updaterFor("z"); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * construction with non-volatile field throws IllegalArgumentException + */ + public void testConstructor3() { + try { + updaterFor("w"); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * construction using private field from subclass throws RuntimeException + */ + public void testPrivateFieldInSubclass() { + AtomicLongFieldUpdaterTestSubclass s = + new AtomicLongFieldUpdaterTestSubclass(); + s.checkPrivateAccess(); + } + + /** + * construction from unrelated class; package access is allowed, + * private access is not + */ + public void testUnrelatedClassAccess() { + new UnrelatedClass().checkPackageAccess(this); + new UnrelatedClass().checkPrivateAccess(this); + } + + /** + * get returns the last value set or assigned + */ + public void testGetSet() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.get(this)); + a.set(this, 2); + assertEquals(2, a.get(this)); + a.set(this, -3); + assertEquals(-3, a.get(this)); + } + + /** + * get returns the last value lazySet by same thread + */ + public void testGetLazySet() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.get(this)); + a.lazySet(this, 2); + assertEquals(2, a.get(this)); + a.lazySet(this, -3); + assertEquals(-3, a.get(this)); + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertTrue(a.compareAndSet(this, 1, 2)); + assertTrue(a.compareAndSet(this, 2, -4)); + assertEquals(-4, a.get(this)); + assertFalse(a.compareAndSet(this, -5, 7)); + assertEquals(-4, a.get(this)); + assertTrue(a.compareAndSet(this, -4, 7)); + assertEquals(7, a.get(this)); + } + + /** + * compareAndSet succeeds in changing protected field value if + * equal to expected else fails + */ + public void testCompareAndSetProtected() { + AtomicLongFieldUpdater a; + a = updaterFor("protectedField"); + protectedField = 1; + assertTrue(a.compareAndSet(this, 1, 2)); + assertTrue(a.compareAndSet(this, 2, -4)); + assertEquals(-4, a.get(this)); + assertFalse(a.compareAndSet(this, -5, 7)); + assertEquals(-4, a.get(this)); + assertTrue(a.compareAndSet(this, -4, 7)); + assertEquals(7, a.get(this)); + } + + /** + * compareAndSet succeeds in changing protected field value if + * equal to expected else fails + */ + public void testCompareAndSetProtectedInSubclass() { + AtomicLongFieldUpdaterTestSubclass s = + new AtomicLongFieldUpdaterTestSubclass(); + s.checkCompareAndSetProtectedSub(); + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + x = 1; + final AtomicLongFieldUpdater a; + a = updaterFor("x"); + + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!a.compareAndSet(AtomicLongFieldUpdaterTest.this, 2, 3)) + Thread.yield(); + }}); + + t.start(); + assertTrue(a.compareAndSet(this, 1, 2)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertEquals(3, a.get(this)); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + do {} while (!a.weakCompareAndSet(this, 1, 2)); + do {} while (!a.weakCompareAndSet(this, 2, -4)); + assertEquals(-4, a.get(this)); + do {} while (!a.weakCompareAndSet(this, -4, 7)); + assertEquals(7, a.get(this)); + } + + /** + * getAndSet returns previous value and sets to given value + */ + public void testGetAndSet() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.getAndSet(this, 0)); + assertEquals(0, a.getAndSet(this, -10)); + assertEquals(-10, a.getAndSet(this, 1)); + } + + /** + * getAndAdd returns previous value and adds given value + */ + public void testGetAndAdd() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.getAndAdd(this, 2)); + assertEquals(3, a.get(this)); + assertEquals(3, a.getAndAdd(this, -4)); + assertEquals(-1, a.get(this)); + } + + /** + * getAndDecrement returns previous value and decrements + */ + public void testGetAndDecrement() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.getAndDecrement(this)); + assertEquals(0, a.getAndDecrement(this)); + assertEquals(-1, a.getAndDecrement(this)); + } + + /** + * getAndIncrement returns previous value and increments + */ + public void testGetAndIncrement() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(1, a.getAndIncrement(this)); + assertEquals(2, a.get(this)); + a.set(this, -2); + assertEquals(-2, a.getAndIncrement(this)); + assertEquals(-1, a.getAndIncrement(this)); + assertEquals(0, a.getAndIncrement(this)); + assertEquals(1, a.get(this)); + } + + /** + * addAndGet adds given value to current, and returns current value + */ + public void testAddAndGet() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(3, a.addAndGet(this, 2)); + assertEquals(3, a.get(this)); + assertEquals(-1, a.addAndGet(this, -4)); + assertEquals(-1, a.get(this)); + } + + /** + * decrementAndGet decrements and returns current value + */ + public void testDecrementAndGet() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(0, a.decrementAndGet(this)); + assertEquals(-1, a.decrementAndGet(this)); + assertEquals(-2, a.decrementAndGet(this)); + assertEquals(-2, a.get(this)); + } + + /** + * incrementAndGet increments and returns current value + */ + public void testIncrementAndGet() { + AtomicLongFieldUpdater a; + a = updaterFor("x"); + x = 1; + assertEquals(2, a.incrementAndGet(this)); + assertEquals(2, a.get(this)); + a.set(this, -2); + assertEquals(-1, a.incrementAndGet(this)); + assertEquals(0, a.incrementAndGet(this)); + assertEquals(1, a.incrementAndGet(this)); + assertEquals(1, a.get(this)); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicLongTest.java b/jdk/test/java/util/concurrent/tck/AtomicLongTest.java new file mode 100644 index 00000000000..f5191af99e6 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicLongTest.java @@ -0,0 +1,297 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.concurrent.atomic.AtomicLong; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicLongTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicLongTest.class); + } + + final long[] VALUES = { + Long.MIN_VALUE, + Integer.MIN_VALUE, -1, 0, 1, 42, Integer.MAX_VALUE, + Long.MAX_VALUE, + }; + + /** + * constructor initializes to given value + */ + public void testConstructor() { + AtomicLong ai = new AtomicLong(1); + assertEquals(1, ai.get()); + } + + /** + * default constructed initializes to zero + */ + public void testConstructor2() { + AtomicLong ai = new AtomicLong(); + assertEquals(0, ai.get()); + } + + /** + * get returns the last value set + */ + public void testGetSet() { + AtomicLong ai = new AtomicLong(1); + assertEquals(1, ai.get()); + ai.set(2); + assertEquals(2, ai.get()); + ai.set(-3); + assertEquals(-3, ai.get()); + } + + /** + * get returns the last value lazySet in same thread + */ + public void testGetLazySet() { + AtomicLong ai = new AtomicLong(1); + assertEquals(1, ai.get()); + ai.lazySet(2); + assertEquals(2, ai.get()); + ai.lazySet(-3); + assertEquals(-3, ai.get()); + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicLong ai = new AtomicLong(1); + assertTrue(ai.compareAndSet(1, 2)); + assertTrue(ai.compareAndSet(2, -4)); + assertEquals(-4, ai.get()); + assertFalse(ai.compareAndSet(-5, 7)); + assertEquals(-4, ai.get()); + assertTrue(ai.compareAndSet(-4, 7)); + assertEquals(7, ai.get()); + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + final AtomicLong ai = new AtomicLong(1); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!ai.compareAndSet(2, 3)) + Thread.yield(); + }}); + + t.start(); + assertTrue(ai.compareAndSet(1, 2)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertEquals(3, ai.get()); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicLong ai = new AtomicLong(1); + do {} while (!ai.weakCompareAndSet(1, 2)); + do {} while (!ai.weakCompareAndSet(2, -4)); + assertEquals(-4, ai.get()); + do {} while (!ai.weakCompareAndSet(-4, 7)); + assertEquals(7, ai.get()); + } + + /** + * getAndSet returns previous value and sets to given value + */ + public void testGetAndSet() { + AtomicLong ai = new AtomicLong(1); + assertEquals(1, ai.getAndSet(0)); + assertEquals(0, ai.getAndSet(-10)); + assertEquals(-10, ai.getAndSet(1)); + } + + /** + * getAndAdd returns previous value and adds given value + */ + public void testGetAndAdd() { + AtomicLong ai = new AtomicLong(1); + assertEquals(1, ai.getAndAdd(2)); + assertEquals(3, ai.get()); + assertEquals(3, ai.getAndAdd(-4)); + assertEquals(-1, ai.get()); + } + + /** + * getAndDecrement returns previous value and decrements + */ + public void testGetAndDecrement() { + AtomicLong ai = new AtomicLong(1); + assertEquals(1, ai.getAndDecrement()); + assertEquals(0, ai.getAndDecrement()); + assertEquals(-1, ai.getAndDecrement()); + } + + /** + * getAndIncrement returns previous value and increments + */ + public void testGetAndIncrement() { + AtomicLong ai = new AtomicLong(1); + assertEquals(1, ai.getAndIncrement()); + assertEquals(2, ai.get()); + ai.set(-2); + assertEquals(-2, ai.getAndIncrement()); + assertEquals(-1, ai.getAndIncrement()); + assertEquals(0, ai.getAndIncrement()); + assertEquals(1, ai.get()); + } + + /** + * addAndGet adds given value to current, and returns current value + */ + public void testAddAndGet() { + AtomicLong ai = new AtomicLong(1); + assertEquals(3, ai.addAndGet(2)); + assertEquals(3, ai.get()); + assertEquals(-1, ai.addAndGet(-4)); + assertEquals(-1, ai.get()); + } + + /** + * decrementAndGet decrements and returns current value + */ + public void testDecrementAndGet() { + AtomicLong ai = new AtomicLong(1); + assertEquals(0, ai.decrementAndGet()); + assertEquals(-1, ai.decrementAndGet()); + assertEquals(-2, ai.decrementAndGet()); + assertEquals(-2, ai.get()); + } + + /** + * incrementAndGet increments and returns current value + */ + public void testIncrementAndGet() { + AtomicLong ai = new AtomicLong(1); + assertEquals(2, ai.incrementAndGet()); + assertEquals(2, ai.get()); + ai.set(-2); + assertEquals(-1, ai.incrementAndGet()); + assertEquals(0, ai.incrementAndGet()); + assertEquals(1, ai.incrementAndGet()); + assertEquals(1, ai.get()); + } + + /** + * a deserialized serialized atomic holds same value + */ + public void testSerialization() throws Exception { + AtomicLong x = new AtomicLong(); + AtomicLong y = serialClone(x); + assertNotSame(x, y); + x.set(-22); + AtomicLong z = serialClone(x); + assertNotSame(y, z); + assertEquals(-22, x.get()); + assertEquals(0, y.get()); + assertEquals(-22, z.get()); + } + + /** + * toString returns current value. + */ + public void testToString() { + AtomicLong ai = new AtomicLong(); + assertEquals("0", ai.toString()); + for (long x : VALUES) { + ai.set(x); + assertEquals(Long.toString(x), ai.toString()); + } + } + + /** + * intValue returns current value. + */ + public void testIntValue() { + AtomicLong ai = new AtomicLong(); + assertEquals(0, ai.intValue()); + for (long x : VALUES) { + ai.set(x); + assertEquals((int)x, ai.intValue()); + } + } + + /** + * longValue returns current value. + */ + public void testLongValue() { + AtomicLong ai = new AtomicLong(); + assertEquals(0L, ai.longValue()); + for (long x : VALUES) { + ai.set(x); + assertEquals(x, ai.longValue()); + } + } + + /** + * floatValue returns current value. + */ + public void testFloatValue() { + AtomicLong ai = new AtomicLong(); + assertEquals(0.0f, ai.floatValue()); + for (long x : VALUES) { + ai.set(x); + assertEquals((float)x, ai.floatValue()); + } + } + + /** + * doubleValue returns current value. + */ + public void testDoubleValue() { + AtomicLong ai = new AtomicLong(); + assertEquals(0.0d, ai.doubleValue()); + for (long x : VALUES) { + ai.set(x); + assertEquals((double)x, ai.doubleValue()); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicMarkableReferenceTest.java b/jdk/test/java/util/concurrent/tck/AtomicMarkableReferenceTest.java new file mode 100644 index 00000000000..b1c77c468d2 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicMarkableReferenceTest.java @@ -0,0 +1,180 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.concurrent.atomic.AtomicMarkableReference; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicMarkableReferenceTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicMarkableReferenceTest.class); + } + + /** + * constructor initializes to given reference and mark + */ + public void testConstructor() { + AtomicMarkableReference ai = new AtomicMarkableReference(one, false); + assertSame(one, ai.getReference()); + assertFalse(ai.isMarked()); + AtomicMarkableReference a2 = new AtomicMarkableReference(null, true); + assertNull(a2.getReference()); + assertTrue(a2.isMarked()); + } + + /** + * get returns the last values of reference and mark set + */ + public void testGetSet() { + boolean[] mark = new boolean[1]; + AtomicMarkableReference ai = new AtomicMarkableReference(one, false); + assertSame(one, ai.getReference()); + assertFalse(ai.isMarked()); + assertSame(one, ai.get(mark)); + assertFalse(mark[0]); + ai.set(two, false); + assertSame(two, ai.getReference()); + assertFalse(ai.isMarked()); + assertSame(two, ai.get(mark)); + assertFalse(mark[0]); + ai.set(one, true); + assertSame(one, ai.getReference()); + assertTrue(ai.isMarked()); + assertSame(one, ai.get(mark)); + assertTrue(mark[0]); + } + + /** + * attemptMark succeeds in single thread + */ + public void testAttemptMark() { + boolean[] mark = new boolean[1]; + AtomicMarkableReference ai = new AtomicMarkableReference(one, false); + assertFalse(ai.isMarked()); + assertTrue(ai.attemptMark(one, true)); + assertTrue(ai.isMarked()); + assertSame(one, ai.get(mark)); + assertTrue(mark[0]); + } + + /** + * compareAndSet succeeds in changing values if equal to expected reference + * and mark else fails + */ + public void testCompareAndSet() { + boolean[] mark = new boolean[1]; + AtomicMarkableReference ai = new AtomicMarkableReference(one, false); + assertSame(one, ai.get(mark)); + assertFalse(ai.isMarked()); + assertFalse(mark[0]); + + assertTrue(ai.compareAndSet(one, two, false, false)); + assertSame(two, ai.get(mark)); + assertFalse(mark[0]); + + assertTrue(ai.compareAndSet(two, m3, false, true)); + assertSame(m3, ai.get(mark)); + assertTrue(mark[0]); + + assertFalse(ai.compareAndSet(two, m3, true, true)); + assertSame(m3, ai.get(mark)); + assertTrue(mark[0]); + } + + /** + * compareAndSet in one thread enables another waiting for reference value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + final AtomicMarkableReference ai = new AtomicMarkableReference(one, false); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!ai.compareAndSet(two, three, false, false)) + Thread.yield(); + }}); + + t.start(); + assertTrue(ai.compareAndSet(one, two, false, false)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertSame(three, ai.getReference()); + assertFalse(ai.isMarked()); + } + + /** + * compareAndSet in one thread enables another waiting for mark value + * to succeed + */ + public void testCompareAndSetInMultipleThreads2() throws Exception { + final AtomicMarkableReference ai = new AtomicMarkableReference(one, false); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!ai.compareAndSet(one, one, true, false)) + Thread.yield(); + }}); + + t.start(); + assertTrue(ai.compareAndSet(one, one, false, true)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertSame(one, ai.getReference()); + assertFalse(ai.isMarked()); + } + + /** + * repeated weakCompareAndSet succeeds in changing values when equal + * to expected + */ + public void testWeakCompareAndSet() { + boolean[] mark = new boolean[1]; + AtomicMarkableReference ai = new AtomicMarkableReference(one, false); + assertSame(one, ai.get(mark)); + assertFalse(ai.isMarked()); + assertFalse(mark[0]); + + do {} while (!ai.weakCompareAndSet(one, two, false, false)); + assertSame(two, ai.get(mark)); + assertFalse(mark[0]); + + do {} while (!ai.weakCompareAndSet(two, m3, false, true)); + assertSame(m3, ai.get(mark)); + assertTrue(mark[0]); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java b/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java new file mode 100644 index 00000000000..2457d40b426 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java @@ -0,0 +1,246 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReferenceArray; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicReferenceArrayTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicReferenceArrayTest.class); + } + + /** + * constructor creates array of given size with all elements null + */ + public void testConstructor() { + AtomicReferenceArray aa = new AtomicReferenceArray(SIZE); + for (int i = 0; i < SIZE; i++) { + assertNull(aa.get(i)); + } + } + + /** + * constructor with null array throws NPE + */ + public void testConstructor2NPE() { + try { + Integer[] a = null; + new AtomicReferenceArray(a); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * constructor with array is of same size and has all elements + */ + public void testConstructor2() { + Integer[] a = { two, one, three, four, seven }; + AtomicReferenceArray aa = new AtomicReferenceArray(a); + assertEquals(a.length, aa.length()); + for (int i = 0; i < a.length; i++) + assertEquals(a[i], aa.get(i)); + } + + /** + * Initialize AtomicReferenceArray with SubClass[] + */ + public void testConstructorSubClassArray() { + Integer[] a = { two, one, three, four, seven }; + AtomicReferenceArray aa = new AtomicReferenceArray(a); + assertEquals(a.length, aa.length()); + for (int i = 0; i < a.length; i++) { + assertSame(a[i], aa.get(i)); + Long x = Long.valueOf(i); + aa.set(i, x); + assertSame(x, aa.get(i)); + } + } + + /** + * get and set for out of bound indices throw IndexOutOfBoundsException + */ + public void testIndexing() { + AtomicReferenceArray aa = new AtomicReferenceArray(SIZE); + for (int index : new int[] { -1, SIZE }) { + try { + aa.get(index); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.set(index, null); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.lazySet(index, null); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.compareAndSet(index, null, null); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + try { + aa.weakCompareAndSet(index, null, null); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * get returns the last value set at index + */ + public void testGetSet() { + AtomicReferenceArray aa = new AtomicReferenceArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, one); + assertSame(one, aa.get(i)); + aa.set(i, two); + assertSame(two, aa.get(i)); + aa.set(i, m3); + assertSame(m3, aa.get(i)); + } + } + + /** + * get returns the last value lazySet at index by same thread + */ + public void testGetLazySet() { + AtomicReferenceArray aa = new AtomicReferenceArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.lazySet(i, one); + assertSame(one, aa.get(i)); + aa.lazySet(i, two); + assertSame(two, aa.get(i)); + aa.lazySet(i, m3); + assertSame(m3, aa.get(i)); + } + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicReferenceArray aa = new AtomicReferenceArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, one); + assertTrue(aa.compareAndSet(i, one, two)); + assertTrue(aa.compareAndSet(i, two, m4)); + assertSame(m4, aa.get(i)); + assertFalse(aa.compareAndSet(i, m5, seven)); + assertSame(m4, aa.get(i)); + assertTrue(aa.compareAndSet(i, m4, seven)); + assertSame(seven, aa.get(i)); + } + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws InterruptedException { + final AtomicReferenceArray a = new AtomicReferenceArray(1); + a.set(0, one); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!a.compareAndSet(0, two, three)) + Thread.yield(); + }}); + + t.start(); + assertTrue(a.compareAndSet(0, one, two)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertSame(three, a.get(0)); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicReferenceArray aa = new AtomicReferenceArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, one); + do {} while (!aa.weakCompareAndSet(i, one, two)); + do {} while (!aa.weakCompareAndSet(i, two, m4)); + assertSame(m4, aa.get(i)); + do {} while (!aa.weakCompareAndSet(i, m4, seven)); + assertSame(seven, aa.get(i)); + } + } + + /** + * getAndSet returns previous value and sets to given value at given index + */ + public void testGetAndSet() { + AtomicReferenceArray aa = new AtomicReferenceArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, one); + assertSame(one, aa.getAndSet(i, zero)); + assertSame(zero, aa.getAndSet(i, m10)); + assertSame(m10, aa.getAndSet(i, one)); + } + } + + /** + * a deserialized serialized array holds same values + */ + public void testSerialization() throws Exception { + AtomicReferenceArray x = new AtomicReferenceArray(SIZE); + for (int i = 0; i < SIZE; i++) { + x.set(i, new Integer(-i)); + } + AtomicReferenceArray y = serialClone(x); + assertNotSame(x, y); + assertEquals(x.length(), y.length()); + for (int i = 0; i < SIZE; i++) { + assertEquals(x.get(i), y.get(i)); + } + } + + /** + * toString returns current value. + */ + public void testToString() { + Integer[] a = { two, one, three, four, seven }; + AtomicReferenceArray aa = new AtomicReferenceArray(a); + assertEquals(Arrays.toString(a), aa.toString()); + } +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicReferenceFieldUpdaterTest.java b/jdk/test/java/util/concurrent/tck/AtomicReferenceFieldUpdaterTest.java new file mode 100644 index 00000000000..fb50658ea91 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceFieldUpdaterTest.java @@ -0,0 +1,265 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase { + volatile Integer x = null; + protected volatile Integer protectedField; + private volatile Integer privateField; + Object z; + Integer w; + volatile int i; + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicReferenceFieldUpdaterTest.class); + } + + // for testing subclass access + static class AtomicReferenceFieldUpdaterTestSubclass extends AtomicReferenceFieldUpdaterTest { + public void checkPrivateAccess() { + try { + AtomicReferenceFieldUpdater a = + AtomicReferenceFieldUpdater.newUpdater + (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField"); + shouldThrow(); + } catch (RuntimeException success) { + assertNotNull(success.getCause()); + } + } + + public void checkCompareAndSetProtectedSub() { + AtomicReferenceFieldUpdater a = + AtomicReferenceFieldUpdater.newUpdater + (AtomicReferenceFieldUpdaterTest.class, Integer.class, "protectedField"); + this.protectedField = one; + assertTrue(a.compareAndSet(this, one, two)); + assertTrue(a.compareAndSet(this, two, m4)); + assertSame(m4, a.get(this)); + assertFalse(a.compareAndSet(this, m5, seven)); + assertFalse(seven == a.get(this)); + assertTrue(a.compareAndSet(this, m4, seven)); + assertSame(seven, a.get(this)); + } + } + + static class UnrelatedClass { + public void checkPackageAccess(AtomicReferenceFieldUpdaterTest obj) { + obj.x = one; + AtomicReferenceFieldUpdater a = + AtomicReferenceFieldUpdater.newUpdater + (AtomicReferenceFieldUpdaterTest.class, Integer.class, "x"); + assertSame(one, a.get(obj)); + assertTrue(a.compareAndSet(obj, one, two)); + assertSame(two, a.get(obj)); + } + + public void checkPrivateAccess(AtomicReferenceFieldUpdaterTest obj) { + try { + AtomicReferenceFieldUpdater a = + AtomicReferenceFieldUpdater.newUpdater + (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField"); + throw new AssertionError("should throw"); + } catch (RuntimeException success) { + assertNotNull(success.getCause()); + } + } + } + + static AtomicReferenceFieldUpdater updaterFor(String fieldName) { + return AtomicReferenceFieldUpdater.newUpdater + (AtomicReferenceFieldUpdaterTest.class, Integer.class, fieldName); + } + + /** + * Construction with non-existent field throws RuntimeException + */ + public void testConstructor() { + try { + updaterFor("y"); + shouldThrow(); + } catch (RuntimeException success) { + assertNotNull(success.getCause()); + } + } + + /** + * construction with field not of given type throws ClassCastException + */ + public void testConstructor2() { + try { + updaterFor("z"); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * Constructor with non-volatile field throws IllegalArgumentException + */ + public void testConstructor3() { + try { + updaterFor("w"); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor with non-reference field throws ClassCastException + */ + public void testConstructor4() { + try { + updaterFor("i"); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * construction using private field from subclass throws RuntimeException + */ + public void testPrivateFieldInSubclass() { + AtomicReferenceFieldUpdaterTestSubclass s = + new AtomicReferenceFieldUpdaterTestSubclass(); + s.checkPrivateAccess(); + } + + /** + * construction from unrelated class; package access is allowed, + * private access is not + */ + public void testUnrelatedClassAccess() { + new UnrelatedClass().checkPackageAccess(this); + new UnrelatedClass().checkPrivateAccess(this); + } + + /** + * get returns the last value set or assigned + */ + public void testGetSet() { + AtomicReferenceFieldUpdater a; + a = updaterFor("x"); + x = one; + assertSame(one, a.get(this)); + a.set(this, two); + assertSame(two, a.get(this)); + a.set(this, m3); + assertSame(m3, a.get(this)); + } + + /** + * get returns the last value lazySet by same thread + */ + public void testGetLazySet() { + AtomicReferenceFieldUpdater a; + a = updaterFor("x"); + x = one; + assertSame(one, a.get(this)); + a.lazySet(this, two); + assertSame(two, a.get(this)); + a.lazySet(this, m3); + assertSame(m3, a.get(this)); + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicReferenceFieldUpdater a; + a = updaterFor("x"); + x = one; + assertTrue(a.compareAndSet(this, one, two)); + assertTrue(a.compareAndSet(this, two, m4)); + assertSame(m4, a.get(this)); + assertFalse(a.compareAndSet(this, m5, seven)); + assertFalse(seven == a.get(this)); + assertTrue(a.compareAndSet(this, m4, seven)); + assertSame(seven, a.get(this)); + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + x = one; + final AtomicReferenceFieldUpdater a; + a = updaterFor("x"); + + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!a.compareAndSet(AtomicReferenceFieldUpdaterTest.this, two, three)) + Thread.yield(); + }}); + + t.start(); + assertTrue(a.compareAndSet(this, one, two)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertSame(three, a.get(this)); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicReferenceFieldUpdater a; + a = updaterFor("x"); + x = one; + do {} while (!a.weakCompareAndSet(this, one, two)); + do {} while (!a.weakCompareAndSet(this, two, m4)); + assertSame(m4, a.get(this)); + do {} while (!a.weakCompareAndSet(this, m4, seven)); + assertSame(seven, a.get(this)); + } + + /** + * getAndSet returns previous value and sets to given value + */ + public void testGetAndSet() { + AtomicReferenceFieldUpdater a; + a = updaterFor("x"); + x = one; + assertSame(one, a.getAndSet(this, zero)); + assertSame(zero, a.getAndSet(this, m10)); + assertSame(m10, a.getAndSet(this, 1)); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java b/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java new file mode 100644 index 00000000000..bae2a43906a --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java @@ -0,0 +1,170 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.concurrent.atomic.AtomicReference; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicReferenceTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicReferenceTest.class); + } + + /** + * constructor initializes to given value + */ + public void testConstructor() { + AtomicReference ai = new AtomicReference(one); + assertSame(one, ai.get()); + } + + /** + * default constructed initializes to null + */ + public void testConstructor2() { + AtomicReference ai = new AtomicReference(); + assertNull(ai.get()); + } + + /** + * get returns the last value set + */ + public void testGetSet() { + AtomicReference ai = new AtomicReference(one); + assertSame(one, ai.get()); + ai.set(two); + assertSame(two, ai.get()); + ai.set(m3); + assertSame(m3, ai.get()); + } + + /** + * get returns the last value lazySet in same thread + */ + public void testGetLazySet() { + AtomicReference ai = new AtomicReference(one); + assertSame(one, ai.get()); + ai.lazySet(two); + assertSame(two, ai.get()); + ai.lazySet(m3); + assertSame(m3, ai.get()); + } + + /** + * compareAndSet succeeds in changing value if equal to expected else fails + */ + public void testCompareAndSet() { + AtomicReference ai = new AtomicReference(one); + assertTrue(ai.compareAndSet(one, two)); + assertTrue(ai.compareAndSet(two, m4)); + assertSame(m4, ai.get()); + assertFalse(ai.compareAndSet(m5, seven)); + assertSame(m4, ai.get()); + assertTrue(ai.compareAndSet(m4, seven)); + assertSame(seven, ai.get()); + } + + /** + * compareAndSet in one thread enables another waiting for value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + final AtomicReference ai = new AtomicReference(one); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!ai.compareAndSet(two, three)) + Thread.yield(); + }}); + + t.start(); + assertTrue(ai.compareAndSet(one, two)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertSame(three, ai.get()); + } + + /** + * repeated weakCompareAndSet succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSet() { + AtomicReference ai = new AtomicReference(one); + do {} while (!ai.weakCompareAndSet(one, two)); + do {} while (!ai.weakCompareAndSet(two, m4)); + assertSame(m4, ai.get()); + do {} while (!ai.weakCompareAndSet(m4, seven)); + assertSame(seven, ai.get()); + } + + /** + * getAndSet returns previous value and sets to given value + */ + public void testGetAndSet() { + AtomicReference ai = new AtomicReference(one); + assertSame(one, ai.getAndSet(zero)); + assertSame(zero, ai.getAndSet(m10)); + assertSame(m10, ai.getAndSet(one)); + } + + /** + * a deserialized serialized atomic holds same value + */ + public void testSerialization() throws Exception { + AtomicReference x = new AtomicReference(); + AtomicReference y = serialClone(x); + assertNotSame(x, y); + x.set(one); + AtomicReference z = serialClone(x); + assertNotSame(y, z); + assertEquals(one, x.get()); + assertEquals(null, y.get()); + assertEquals(one, z.get()); + } + + /** + * toString returns current value. + */ + public void testToString() { + AtomicReference ai = new AtomicReference(one); + assertEquals(one.toString(), ai.toString()); + ai.set(two); + assertEquals(two.toString(), ai.toString()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/AtomicStampedReferenceTest.java b/jdk/test/java/util/concurrent/tck/AtomicStampedReferenceTest.java new file mode 100644 index 00000000000..1a352130d3e --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/AtomicStampedReferenceTest.java @@ -0,0 +1,180 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.concurrent.atomic.AtomicStampedReference; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class AtomicStampedReferenceTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(AtomicStampedReferenceTest.class); + } + + /** + * constructor initializes to given reference and stamp + */ + public void testConstructor() { + AtomicStampedReference ai = new AtomicStampedReference(one, 0); + assertSame(one, ai.getReference()); + assertEquals(0, ai.getStamp()); + AtomicStampedReference a2 = new AtomicStampedReference(null, 1); + assertNull(a2.getReference()); + assertEquals(1, a2.getStamp()); + } + + /** + * get returns the last values of reference and stamp set + */ + public void testGetSet() { + int[] mark = new int[1]; + AtomicStampedReference ai = new AtomicStampedReference(one, 0); + assertSame(one, ai.getReference()); + assertEquals(0, ai.getStamp()); + assertSame(one, ai.get(mark)); + assertEquals(0, mark[0]); + ai.set(two, 0); + assertSame(two, ai.getReference()); + assertEquals(0, ai.getStamp()); + assertSame(two, ai.get(mark)); + assertEquals(0, mark[0]); + ai.set(one, 1); + assertSame(one, ai.getReference()); + assertEquals(1, ai.getStamp()); + assertSame(one, ai.get(mark)); + assertEquals(1, mark[0]); + } + + /** + * attemptStamp succeeds in single thread + */ + public void testAttemptStamp() { + int[] mark = new int[1]; + AtomicStampedReference ai = new AtomicStampedReference(one, 0); + assertEquals(0, ai.getStamp()); + assertTrue(ai.attemptStamp(one, 1)); + assertEquals(1, ai.getStamp()); + assertSame(one, ai.get(mark)); + assertEquals(1, mark[0]); + } + + /** + * compareAndSet succeeds in changing values if equal to expected reference + * and stamp else fails + */ + public void testCompareAndSet() { + int[] mark = new int[1]; + AtomicStampedReference ai = new AtomicStampedReference(one, 0); + assertSame(one, ai.get(mark)); + assertEquals(0, ai.getStamp()); + assertEquals(0, mark[0]); + + assertTrue(ai.compareAndSet(one, two, 0, 0)); + assertSame(two, ai.get(mark)); + assertEquals(0, mark[0]); + + assertTrue(ai.compareAndSet(two, m3, 0, 1)); + assertSame(m3, ai.get(mark)); + assertEquals(1, mark[0]); + + assertFalse(ai.compareAndSet(two, m3, 1, 1)); + assertSame(m3, ai.get(mark)); + assertEquals(1, mark[0]); + } + + /** + * compareAndSet in one thread enables another waiting for reference value + * to succeed + */ + public void testCompareAndSetInMultipleThreads() throws Exception { + final AtomicStampedReference ai = new AtomicStampedReference(one, 0); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!ai.compareAndSet(two, three, 0, 0)) + Thread.yield(); + }}); + + t.start(); + assertTrue(ai.compareAndSet(one, two, 0, 0)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertSame(three, ai.getReference()); + assertEquals(0, ai.getStamp()); + } + + /** + * compareAndSet in one thread enables another waiting for stamp value + * to succeed + */ + public void testCompareAndSetInMultipleThreads2() throws Exception { + final AtomicStampedReference ai = new AtomicStampedReference(one, 0); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + while (!ai.compareAndSet(one, one, 1, 2)) + Thread.yield(); + }}); + + t.start(); + assertTrue(ai.compareAndSet(one, one, 0, 1)); + t.join(LONG_DELAY_MS); + assertFalse(t.isAlive()); + assertSame(one, ai.getReference()); + assertEquals(2, ai.getStamp()); + } + + /** + * repeated weakCompareAndSet succeeds in changing values when equal + * to expected + */ + public void testWeakCompareAndSet() { + int[] mark = new int[1]; + AtomicStampedReference ai = new AtomicStampedReference(one, 0); + assertSame(one, ai.get(mark)); + assertEquals(0, ai.getStamp()); + assertEquals(0, mark[0]); + + do {} while (!ai.weakCompareAndSet(one, two, 0, 0)); + assertSame(two, ai.get(mark)); + assertEquals(0, mark[0]); + + do {} while (!ai.weakCompareAndSet(two, m3, 0, 1)); + assertSame(m3, ai.get(mark)); + assertEquals(1, mark[0]); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/BlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/BlockingQueueTest.java new file mode 100644 index 00000000000..aa38b3bd735 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/BlockingQueueTest.java @@ -0,0 +1,403 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from members + * of JCP JSR-166 Expert Group and released to the public domain, as + * explained at http://creativecommons.org/publicdomain/zero/1.0/ + * + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Queue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Contains "contract" tests applicable to all BlockingQueue implementations. + */ +public abstract class BlockingQueueTest extends JSR166TestCase { + /* + * This is the start of an attempt to refactor the tests for the + * various related implementations of related interfaces without + * too much duplicated code. junit does not really support such + * testing. Here subclasses of TestCase not only contain tests, + * but also configuration information that describes the + * implementation class, most importantly how to instantiate + * instances. + */ + + /** Like suite(), but non-static */ + public Test testSuite() { + // TODO: filter the returned tests using the configuration + // information provided by the subclass via protected methods. + return new TestSuite(this.getClass()); + } + + //---------------------------------------------------------------- + // Configuration methods + //---------------------------------------------------------------- + + /** Returns an empty instance of the implementation class. */ + protected abstract BlockingQueue emptyCollection(); + + /** + * Returns an element suitable for insertion in the collection. + * Override for collections with unusual element types. + */ + protected Object makeElement(int i) { + return Integer.valueOf(i); + } + + //---------------------------------------------------------------- + // Tests + //---------------------------------------------------------------- + + /** + * offer(null) throws NullPointerException + */ + public void testOfferNull() { + final Queue q = emptyCollection(); + try { + q.offer(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * add(null) throws NullPointerException + */ + public void testAddNull() { + final Collection q = emptyCollection(); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * timed offer(null) throws NullPointerException + */ + public void testTimedOfferNull() throws InterruptedException { + final BlockingQueue q = emptyCollection(); + long startTime = System.nanoTime(); + try { + q.offer(null, LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + + /** + * put(null) throws NullPointerException + */ + public void testPutNull() throws InterruptedException { + final BlockingQueue q = emptyCollection(); + try { + q.put(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * put(null) throws NullPointerException + */ + public void testAddAllNull() throws InterruptedException { + final Collection q = emptyCollection(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with null elements throws NullPointerException + */ + public void testAddAllNullElements() { + final Collection q = emptyCollection(); + final Collection elements = Arrays.asList(new Integer[SIZE]); + try { + q.addAll(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * toArray(null) throws NullPointerException + */ + public void testToArray_NullArray() { + final Collection q = emptyCollection(); + try { + q.toArray(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * drainTo(null) throws NullPointerException + */ + public void testDrainToNull() { + final BlockingQueue q = emptyCollection(); + try { + q.drainTo(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * drainTo(this) throws IllegalArgumentException + */ + public void testDrainToSelf() { + final BlockingQueue q = emptyCollection(); + try { + q.drainTo(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * drainTo(null, n) throws NullPointerException + */ + public void testDrainToNullN() { + final BlockingQueue q = emptyCollection(); + try { + q.drainTo(null, 0); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * drainTo(this, n) throws IllegalArgumentException + */ + public void testDrainToSelfN() { + final BlockingQueue q = emptyCollection(); + try { + q.drainTo(q, 0); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * drainTo(c, n) returns 0 and does nothing when n <= 0 + */ + public void testDrainToNonPositiveMaxElements() { + final BlockingQueue q = emptyCollection(); + final int[] ns = { 0, -1, -42, Integer.MIN_VALUE }; + for (int n : ns) + assertEquals(0, q.drainTo(new ArrayList(), n)); + if (q.remainingCapacity() > 0) { + // Not SynchronousQueue, that is + Object one = makeElement(1); + q.add(one); + ArrayList c = new ArrayList(); + for (int n : ns) + assertEquals(0, q.drainTo(new ArrayList(), n)); + assertEquals(1, q.size()); + assertSame(one, q.poll()); + assertTrue(c.isEmpty()); + } + } + + /** + * timed poll before a delayed offer times out; after offer succeeds; + * on interruption throws + */ + public void testTimedPollWithOffer() throws InterruptedException { + final BlockingQueue q = emptyCollection(); + final CheckedBarrier barrier = new CheckedBarrier(2); + final Object zero = makeElement(0); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + + barrier.await(); + + assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS)); + + Thread.currentThread().interrupt(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + barrier.await(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + barrier.await(); + long startTime = System.nanoTime(); + assertTrue(q.offer(zero, LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + + barrier.await(); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * take() blocks interruptibly when empty + */ + public void testTakeFromEmptyBlocksInterruptibly() { + final BlockingQueue q = emptyCollection(); + final CountDownLatch threadStarted = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + threadStarted.countDown(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(threadStarted); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * take() throws InterruptedException immediately if interrupted + * before waiting + */ + public void testTakeFromEmptyAfterInterrupt() { + final BlockingQueue q = emptyCollection(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + Thread.currentThread().interrupt(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + awaitTermination(t); + } + + /** + * timed poll() blocks interruptibly when empty + */ + public void testTimedPollFromEmptyBlocksInterruptibly() { + final BlockingQueue q = emptyCollection(); + final CountDownLatch threadStarted = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + threadStarted.countDown(); + try { + q.poll(2 * LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(threadStarted); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * timed poll() throws InterruptedException immediately if + * interrupted before waiting + */ + public void testTimedPollFromEmptyAfterInterrupt() { + final BlockingQueue q = emptyCollection(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + Thread.currentThread().interrupt(); + try { + q.poll(2 * LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + awaitTermination(t); + } + + /** + * remove(x) removes x and returns true if present + * TODO: move to superclass CollectionTest.java + */ + public void testRemoveElement() { + final BlockingQueue q = emptyCollection(); + final int size = Math.min(q.remainingCapacity(), SIZE); + final Object[] elts = new Object[size]; + assertFalse(q.contains(makeElement(99))); + assertFalse(q.remove(makeElement(99))); + checkEmpty(q); + for (int i = 0; i < size; i++) + q.add(elts[i] = makeElement(i)); + for (int i = 1; i < size; i += 2) { + for (int pass = 0; pass < 2; pass++) { + assertEquals((pass == 0), q.contains(elts[i])); + assertEquals((pass == 0), q.remove(elts[i])); + assertFalse(q.contains(elts[i])); + assertTrue(q.contains(elts[i - 1])); + if (i < size - 1) + assertTrue(q.contains(elts[i + 1])); + } + } + if (size > 0) + assertTrue(q.contains(elts[0])); + for (int i = size - 2; i >= 0; i -= 2) { + assertTrue(q.contains(elts[i])); + assertFalse(q.contains(elts[i + 1])); + assertTrue(q.remove(elts[i])); + assertFalse(q.contains(elts[i])); + assertFalse(q.remove(elts[i + 1])); + assertFalse(q.contains(elts[i + 1])); + } + checkEmpty(q); + } + + /** For debugging. */ + public void XXXXtestFails() { + fail(emptyCollection().getClass().toString()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/Collection8Test.java b/jdk/test/java/util/concurrent/tck/Collection8Test.java new file mode 100644 index 00000000000..1a10b280228 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/Collection8Test.java @@ -0,0 +1,124 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; + +import junit.framework.Test; + +/** + * Contains tests applicable to all jdk8+ Collection implementations. + * An extension of CollectionTest. + */ +public class Collection8Test extends JSR166TestCase { + final CollectionImplementation impl; + + /** Tests are parameterized by a Collection implementation. */ + Collection8Test(CollectionImplementation impl, String methodName) { + super(methodName); + this.impl = impl; + } + + public static Test testSuite(CollectionImplementation impl) { + return parameterizedTestSuite(Collection8Test.class, + CollectionImplementation.class, + impl); + } + + /** + * stream().forEach returns elements in the collection + */ + public void testForEach() throws Throwable { + final Collection c = impl.emptyCollection(); + final AtomicLong count = new AtomicLong(0L); + final Object x = impl.makeElement(1); + final Object y = impl.makeElement(2); + final ArrayList found = new ArrayList(); + Consumer spy = (o) -> { found.add(o); }; + c.stream().forEach(spy); + assertTrue(found.isEmpty()); + + assertTrue(c.add(x)); + c.stream().forEach(spy); + assertEquals(Collections.singletonList(x), found); + found.clear(); + + assertTrue(c.add(y)); + c.stream().forEach(spy); + assertEquals(2, found.size()); + assertTrue(found.contains(x)); + assertTrue(found.contains(y)); + found.clear(); + + c.clear(); + c.stream().forEach(spy); + assertTrue(found.isEmpty()); + } + + public void testForEachConcurrentStressTest() throws Throwable { + if (!impl.isConcurrent()) return; + final Collection c = impl.emptyCollection(); + final long testDurationMillis = SHORT_DELAY_MS; + final AtomicBoolean done = new AtomicBoolean(false); + final Object elt = impl.makeElement(1); + ExecutorService pool = Executors.newCachedThreadPool(); + Runnable checkElt = () -> { + while (!done.get()) + c.stream().forEach((x) -> { assertSame(x, elt); }); }; + Runnable addRemove = () -> { + while (!done.get()) { + assertTrue(c.add(elt)); + assertTrue(c.remove(elt)); + }}; + Future f1 = pool.submit(checkElt); + Future f2 = pool.submit(addRemove); + Thread.sleep(testDurationMillis); + done.set(true); + pool.shutdown(); + assertTrue(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertNull(f1.get(LONG_DELAY_MS, MILLISECONDS)); + assertNull(f2.get(LONG_DELAY_MS, MILLISECONDS)); + } + + // public void testCollection8DebugFail() { fail(); } +} diff --git a/jdk/test/java/util/concurrent/tck/CollectionImplementation.java b/jdk/test/java/util/concurrent/tck/CollectionImplementation.java new file mode 100644 index 00000000000..54ffb7c0921 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/CollectionImplementation.java @@ -0,0 +1,46 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.Collection; + +/** Allows tests to work with different Collection implementations. */ +public interface CollectionImplementation { + /** Returns the Collection class. */ + public Class klazz(); + /** Returns an empty collection. */ + public Collection emptyCollection(); + public Object makeElement(int i); + public boolean isConcurrent(); + public boolean permitsNulls(); +} diff --git a/jdk/test/java/util/concurrent/tck/CollectionTest.java b/jdk/test/java/util/concurrent/tck/CollectionTest.java new file mode 100644 index 00000000000..7b532af8019 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/CollectionTest.java @@ -0,0 +1,68 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.Collection; + +import junit.framework.Test; + +/** + * Contains tests applicable to all Collection implementations. + */ +public class CollectionTest extends JSR166TestCase { + final CollectionImplementation impl; + + /** Tests are parameterized by a Collection implementation. */ + CollectionTest(CollectionImplementation impl, String methodName) { + super(methodName); + this.impl = impl; + } + + public static Test testSuite(CollectionImplementation impl) { + return newTestSuite + (parameterizedTestSuite(CollectionTest.class, + CollectionImplementation.class, + impl), + jdk8ParameterizedTestSuite(CollectionTest.class, + CollectionImplementation.class, + impl)); + } + + /** A test of the CollectionImplementation implementation ! */ + public void testEmptyMeansEmpty() { + assertTrue(impl.emptyCollection().isEmpty()); + assertEquals(0, impl.emptyCollection().size()); + } + + // public void testCollectionDebugFail() { fail(); } +} diff --git a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java new file mode 100644 index 00000000000..a74a0403f2f --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java @@ -0,0 +1,3980 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.CompletableFuture.completedFuture; +import static java.util.concurrent.CompletableFuture.failedFuture; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +public class CompletableFutureTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(CompletableFutureTest.class); + } + + static class CFException extends RuntimeException {} + + void checkIncomplete(CompletableFuture f) { + assertFalse(f.isDone()); + assertFalse(f.isCancelled()); + assertTrue(f.toString().contains("Not completed")); + try { + assertNull(f.getNow(null)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + f.get(0L, SECONDS); + shouldThrow(); + } + catch (TimeoutException success) {} + catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedNormally(CompletableFuture f, T value) { + checkTimedGet(f, value); + + try { + assertEquals(value, f.join()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertEquals(value, f.getNow(null)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertEquals(value, f.get()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + assertTrue(f.isDone()); + assertFalse(f.isCancelled()); + assertFalse(f.isCompletedExceptionally()); + assertTrue(f.toString().contains("[Completed normally]")); + } + + /** + * Returns the "raw" internal exceptional completion of f, + * without any additional wrapping with CompletionException. + */ + Throwable exceptionalCompletion(CompletableFuture f) { + // handle (and whenComplete) can distinguish between "direct" + // and "wrapped" exceptional completion + return f.handle((U u, Throwable t) -> t).join(); + } + + void checkCompletedExceptionally(CompletableFuture f, + boolean wrapped, + Consumer checker) { + Throwable cause = exceptionalCompletion(f); + if (wrapped) { + assertTrue(cause instanceof CompletionException); + cause = cause.getCause(); + } + checker.accept(cause); + + long startTime = System.nanoTime(); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(cause, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2); + + try { + f.join(); + shouldThrow(); + } catch (CompletionException success) { + assertSame(cause, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + f.getNow(null); + shouldThrow(); + } catch (CompletionException success) { + assertSame(cause, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(cause, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + assertFalse(f.isCancelled()); + assertTrue(f.isDone()); + assertTrue(f.isCompletedExceptionally()); + assertTrue(f.toString().contains("[Completed exceptionally]")); + } + + void checkCompletedWithWrappedCFException(CompletableFuture f) { + checkCompletedExceptionally(f, true, + (t) -> assertTrue(t instanceof CFException)); + } + + void checkCompletedWithWrappedCancellationException(CompletableFuture f) { + checkCompletedExceptionally(f, true, + (t) -> assertTrue(t instanceof CancellationException)); + } + + void checkCompletedWithTimeoutException(CompletableFuture f) { + checkCompletedExceptionally(f, false, + (t) -> assertTrue(t instanceof TimeoutException)); + } + + void checkCompletedWithWrappedException(CompletableFuture f, + Throwable ex) { + checkCompletedExceptionally(f, true, (t) -> assertSame(t, ex)); + } + + void checkCompletedExceptionally(CompletableFuture f, Throwable ex) { + checkCompletedExceptionally(f, false, (t) -> assertSame(t, ex)); + } + + void checkCancelled(CompletableFuture f) { + long startTime = System.nanoTime(); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2); + + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) {} + try { + f.getNow(null); + shouldThrow(); + } catch (CancellationException success) {} + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + assertTrue(exceptionalCompletion(f) instanceof CancellationException); + + assertTrue(f.isDone()); + assertTrue(f.isCompletedExceptionally()); + assertTrue(f.isCancelled()); + assertTrue(f.toString().contains("[Completed exceptionally]")); + } + + /** + * A newly constructed CompletableFuture is incomplete, as indicated + * by methods isDone, isCancelled, and getNow + */ + public void testConstructor() { + CompletableFuture f = new CompletableFuture<>(); + checkIncomplete(f); + } + + /** + * complete completes normally, as indicated by methods isDone, + * isCancelled, join, get, and getNow + */ + public void testComplete() { + for (Integer v1 : new Integer[] { 1, null }) + { + CompletableFuture f = new CompletableFuture<>(); + checkIncomplete(f); + assertTrue(f.complete(v1)); + assertFalse(f.complete(v1)); + checkCompletedNormally(f, v1); + }} + + /** + * completeExceptionally completes exceptionally, as indicated by + * methods isDone, isCancelled, join, get, and getNow + */ + public void testCompleteExceptionally() { + CompletableFuture f = new CompletableFuture<>(); + CFException ex = new CFException(); + checkIncomplete(f); + f.completeExceptionally(ex); + checkCompletedExceptionally(f, ex); + } + + /** + * cancel completes exceptionally and reports cancelled, as indicated by + * methods isDone, isCancelled, join, get, and getNow + */ + public void testCancel() { + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + { + CompletableFuture f = new CompletableFuture<>(); + checkIncomplete(f); + assertTrue(f.cancel(mayInterruptIfRunning)); + assertTrue(f.cancel(mayInterruptIfRunning)); + assertTrue(f.cancel(!mayInterruptIfRunning)); + checkCancelled(f); + }} + + /** + * obtrudeValue forces completion with given value + */ + public void testObtrudeValue() { + CompletableFuture f = new CompletableFuture<>(); + checkIncomplete(f); + assertTrue(f.complete(one)); + checkCompletedNormally(f, one); + f.obtrudeValue(three); + checkCompletedNormally(f, three); + f.obtrudeValue(two); + checkCompletedNormally(f, two); + f = new CompletableFuture<>(); + f.obtrudeValue(three); + checkCompletedNormally(f, three); + f.obtrudeValue(null); + checkCompletedNormally(f, null); + f = new CompletableFuture<>(); + f.completeExceptionally(new CFException()); + f.obtrudeValue(four); + checkCompletedNormally(f, four); + } + + /** + * obtrudeException forces completion with given exception + */ + public void testObtrudeException() { + for (Integer v1 : new Integer[] { 1, null }) + { + CFException ex; + CompletableFuture f; + + f = new CompletableFuture<>(); + assertTrue(f.complete(v1)); + for (int i = 0; i < 2; i++) { + f.obtrudeException(ex = new CFException()); + checkCompletedExceptionally(f, ex); + } + + f = new CompletableFuture<>(); + for (int i = 0; i < 2; i++) { + f.obtrudeException(ex = new CFException()); + checkCompletedExceptionally(f, ex); + } + + f = new CompletableFuture<>(); + f.completeExceptionally(ex = new CFException()); + f.obtrudeValue(v1); + checkCompletedNormally(f, v1); + f.obtrudeException(ex = new CFException()); + checkCompletedExceptionally(f, ex); + f.completeExceptionally(new CFException()); + checkCompletedExceptionally(f, ex); + assertFalse(f.complete(v1)); + checkCompletedExceptionally(f, ex); + }} + + /** + * getNumberOfDependents returns number of dependent tasks + */ + public void testGetNumberOfDependents() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + CompletableFuture f = new CompletableFuture<>(); + assertEquals(0, f.getNumberOfDependents()); + final CompletableFuture g = m.thenRun(f, new Noop(m)); + assertEquals(1, f.getNumberOfDependents()); + assertEquals(0, g.getNumberOfDependents()); + final CompletableFuture h = m.thenRun(f, new Noop(m)); + assertEquals(2, f.getNumberOfDependents()); + assertEquals(0, h.getNumberOfDependents()); + assertTrue(f.complete(v1)); + checkCompletedNormally(g, null); + checkCompletedNormally(h, null); + assertEquals(0, f.getNumberOfDependents()); + assertEquals(0, g.getNumberOfDependents()); + assertEquals(0, h.getNumberOfDependents()); + }} + + /** + * toString indicates current completion state + */ + public void testToString() { + CompletableFuture f; + + f = new CompletableFuture(); + assertTrue(f.toString().contains("[Not completed]")); + + assertTrue(f.complete("foo")); + assertTrue(f.toString().contains("[Completed normally]")); + + f = new CompletableFuture(); + assertTrue(f.completeExceptionally(new IndexOutOfBoundsException())); + assertTrue(f.toString().contains("[Completed exceptionally]")); + + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) { + f = new CompletableFuture(); + assertTrue(f.cancel(mayInterruptIfRunning)); + assertTrue(f.toString().contains("[Completed exceptionally]")); + } + } + + /** + * completedFuture returns a completed CompletableFuture with given value + */ + public void testCompletedFuture() { + CompletableFuture f = CompletableFuture.completedFuture("test"); + checkCompletedNormally(f, "test"); + } + + abstract class CheckedAction { + int invocationCount = 0; + final ExecutionMode m; + CheckedAction(ExecutionMode m) { this.m = m; } + void invoked() { + m.checkExecutionMode(); + assertEquals(0, invocationCount++); + } + void assertNotInvoked() { assertEquals(0, invocationCount); } + void assertInvoked() { assertEquals(1, invocationCount); } + } + + abstract class CheckedIntegerAction extends CheckedAction { + Integer value; + CheckedIntegerAction(ExecutionMode m) { super(m); } + void assertValue(Integer expected) { + assertInvoked(); + assertEquals(expected, value); + } + } + + class IntegerSupplier extends CheckedAction + implements Supplier + { + final Integer value; + IntegerSupplier(ExecutionMode m, Integer value) { + super(m); + this.value = value; + } + public Integer get() { + invoked(); + return value; + } + } + + // A function that handles and produces null values as well. + static Integer inc(Integer x) { + return (x == null) ? null : x + 1; + } + + class NoopConsumer extends CheckedIntegerAction + implements Consumer + { + NoopConsumer(ExecutionMode m) { super(m); } + public void accept(Integer x) { + invoked(); + value = x; + } + } + + class IncFunction extends CheckedIntegerAction + implements Function + { + IncFunction(ExecutionMode m) { super(m); } + public Integer apply(Integer x) { + invoked(); + return value = inc(x); + } + } + + // Choose non-commutative actions for better coverage + // A non-commutative function that handles and produces null values as well. + static Integer subtract(Integer x, Integer y) { + return (x == null && y == null) ? null : + ((x == null) ? 42 : x.intValue()) + - ((y == null) ? 99 : y.intValue()); + } + + class SubtractAction extends CheckedIntegerAction + implements BiConsumer + { + SubtractAction(ExecutionMode m) { super(m); } + public void accept(Integer x, Integer y) { + invoked(); + value = subtract(x, y); + } + } + + class SubtractFunction extends CheckedIntegerAction + implements BiFunction + { + SubtractFunction(ExecutionMode m) { super(m); } + public Integer apply(Integer x, Integer y) { + invoked(); + return value = subtract(x, y); + } + } + + class Noop extends CheckedAction implements Runnable { + Noop(ExecutionMode m) { super(m); } + public void run() { + invoked(); + } + } + + class FailingSupplier extends CheckedAction + implements Supplier + { + FailingSupplier(ExecutionMode m) { super(m); } + public Integer get() { + invoked(); + throw new CFException(); + } + } + + class FailingConsumer extends CheckedIntegerAction + implements Consumer + { + FailingConsumer(ExecutionMode m) { super(m); } + public void accept(Integer x) { + invoked(); + value = x; + throw new CFException(); + } + } + + class FailingBiConsumer extends CheckedIntegerAction + implements BiConsumer + { + FailingBiConsumer(ExecutionMode m) { super(m); } + public void accept(Integer x, Integer y) { + invoked(); + value = subtract(x, y); + throw new CFException(); + } + } + + class FailingFunction extends CheckedIntegerAction + implements Function + { + FailingFunction(ExecutionMode m) { super(m); } + public Integer apply(Integer x) { + invoked(); + value = x; + throw new CFException(); + } + } + + class FailingBiFunction extends CheckedIntegerAction + implements BiFunction + { + FailingBiFunction(ExecutionMode m) { super(m); } + public Integer apply(Integer x, Integer y) { + invoked(); + value = subtract(x, y); + throw new CFException(); + } + } + + class FailingRunnable extends CheckedAction implements Runnable { + FailingRunnable(ExecutionMode m) { super(m); } + public void run() { + invoked(); + throw new CFException(); + } + } + + class CompletableFutureInc extends CheckedIntegerAction + implements Function> + { + CompletableFutureInc(ExecutionMode m) { super(m); } + public CompletableFuture apply(Integer x) { + invoked(); + value = x; + CompletableFuture f = new CompletableFuture<>(); + assertTrue(f.complete(inc(x))); + return f; + } + } + + class FailingCompletableFutureFunction extends CheckedIntegerAction + implements Function> + { + FailingCompletableFutureFunction(ExecutionMode m) { super(m); } + public CompletableFuture apply(Integer x) { + invoked(); + value = x; + throw new CFException(); + } + } + + // Used for explicit executor tests + static final class ThreadExecutor implements Executor { + final AtomicInteger count = new AtomicInteger(0); + static final ThreadGroup tg = new ThreadGroup("ThreadExecutor"); + static boolean startedCurrentThread() { + return Thread.currentThread().getThreadGroup() == tg; + } + + public void execute(Runnable r) { + count.getAndIncrement(); + new Thread(tg, r).start(); + } + } + + static final boolean defaultExecutorIsCommonPool + = ForkJoinPool.getCommonPoolParallelism() > 1; + + /** + * Permits the testing of parallel code for the 3 different + * execution modes without copy/pasting all the test methods. + */ + enum ExecutionMode { + SYNC { + public void checkExecutionMode() { + assertFalse(ThreadExecutor.startedCurrentThread()); + assertNull(ForkJoinTask.getPool()); + } + public CompletableFuture runAsync(Runnable a) { + throw new UnsupportedOperationException(); + } + public CompletableFuture supplyAsync(Supplier a) { + throw new UnsupportedOperationException(); + } + public CompletableFuture thenRun + (CompletableFuture f, Runnable a) { + return f.thenRun(a); + } + public CompletableFuture thenAccept + (CompletableFuture f, Consumer a) { + return f.thenAccept(a); + } + public CompletableFuture thenApply + (CompletableFuture f, Function a) { + return f.thenApply(a); + } + public CompletableFuture thenCompose + (CompletableFuture f, + Function> a) { + return f.thenCompose(a); + } + public CompletableFuture handle + (CompletableFuture f, + BiFunction a) { + return f.handle(a); + } + public CompletableFuture whenComplete + (CompletableFuture f, + BiConsumer a) { + return f.whenComplete(a); + } + public CompletableFuture runAfterBoth + (CompletableFuture f, CompletableFuture g, Runnable a) { + return f.runAfterBoth(g, a); + } + public CompletableFuture thenAcceptBoth + (CompletableFuture f, + CompletionStage g, + BiConsumer a) { + return f.thenAcceptBoth(g, a); + } + public CompletableFuture thenCombine + (CompletableFuture f, + CompletionStage g, + BiFunction a) { + return f.thenCombine(g, a); + } + public CompletableFuture runAfterEither + (CompletableFuture f, + CompletionStage g, + java.lang.Runnable a) { + return f.runAfterEither(g, a); + } + public CompletableFuture acceptEither + (CompletableFuture f, + CompletionStage g, + Consumer a) { + return f.acceptEither(g, a); + } + public CompletableFuture applyToEither + (CompletableFuture f, + CompletionStage g, + Function a) { + return f.applyToEither(g, a); + } + }, + + ASYNC { + public void checkExecutionMode() { + assertEquals(defaultExecutorIsCommonPool, + (ForkJoinPool.commonPool() == ForkJoinTask.getPool())); + } + public CompletableFuture runAsync(Runnable a) { + return CompletableFuture.runAsync(a); + } + public CompletableFuture supplyAsync(Supplier a) { + return CompletableFuture.supplyAsync(a); + } + public CompletableFuture thenRun + (CompletableFuture f, Runnable a) { + return f.thenRunAsync(a); + } + public CompletableFuture thenAccept + (CompletableFuture f, Consumer a) { + return f.thenAcceptAsync(a); + } + public CompletableFuture thenApply + (CompletableFuture f, Function a) { + return f.thenApplyAsync(a); + } + public CompletableFuture thenCompose + (CompletableFuture f, + Function> a) { + return f.thenComposeAsync(a); + } + public CompletableFuture handle + (CompletableFuture f, + BiFunction a) { + return f.handleAsync(a); + } + public CompletableFuture whenComplete + (CompletableFuture f, + BiConsumer a) { + return f.whenCompleteAsync(a); + } + public CompletableFuture runAfterBoth + (CompletableFuture f, CompletableFuture g, Runnable a) { + return f.runAfterBothAsync(g, a); + } + public CompletableFuture thenAcceptBoth + (CompletableFuture f, + CompletionStage g, + BiConsumer a) { + return f.thenAcceptBothAsync(g, a); + } + public CompletableFuture thenCombine + (CompletableFuture f, + CompletionStage g, + BiFunction a) { + return f.thenCombineAsync(g, a); + } + public CompletableFuture runAfterEither + (CompletableFuture f, + CompletionStage g, + java.lang.Runnable a) { + return f.runAfterEitherAsync(g, a); + } + public CompletableFuture acceptEither + (CompletableFuture f, + CompletionStage g, + Consumer a) { + return f.acceptEitherAsync(g, a); + } + public CompletableFuture applyToEither + (CompletableFuture f, + CompletionStage g, + Function a) { + return f.applyToEitherAsync(g, a); + } + }, + + EXECUTOR { + public void checkExecutionMode() { + assertTrue(ThreadExecutor.startedCurrentThread()); + } + public CompletableFuture runAsync(Runnable a) { + return CompletableFuture.runAsync(a, new ThreadExecutor()); + } + public CompletableFuture supplyAsync(Supplier a) { + return CompletableFuture.supplyAsync(a, new ThreadExecutor()); + } + public CompletableFuture thenRun + (CompletableFuture f, Runnable a) { + return f.thenRunAsync(a, new ThreadExecutor()); + } + public CompletableFuture thenAccept + (CompletableFuture f, Consumer a) { + return f.thenAcceptAsync(a, new ThreadExecutor()); + } + public CompletableFuture thenApply + (CompletableFuture f, Function a) { + return f.thenApplyAsync(a, new ThreadExecutor()); + } + public CompletableFuture thenCompose + (CompletableFuture f, + Function> a) { + return f.thenComposeAsync(a, new ThreadExecutor()); + } + public CompletableFuture handle + (CompletableFuture f, + BiFunction a) { + return f.handleAsync(a, new ThreadExecutor()); + } + public CompletableFuture whenComplete + (CompletableFuture f, + BiConsumer a) { + return f.whenCompleteAsync(a, new ThreadExecutor()); + } + public CompletableFuture runAfterBoth + (CompletableFuture f, CompletableFuture g, Runnable a) { + return f.runAfterBothAsync(g, a, new ThreadExecutor()); + } + public CompletableFuture thenAcceptBoth + (CompletableFuture f, + CompletionStage g, + BiConsumer a) { + return f.thenAcceptBothAsync(g, a, new ThreadExecutor()); + } + public CompletableFuture thenCombine + (CompletableFuture f, + CompletionStage g, + BiFunction a) { + return f.thenCombineAsync(g, a, new ThreadExecutor()); + } + public CompletableFuture runAfterEither + (CompletableFuture f, + CompletionStage g, + java.lang.Runnable a) { + return f.runAfterEitherAsync(g, a, new ThreadExecutor()); + } + public CompletableFuture acceptEither + (CompletableFuture f, + CompletionStage g, + Consumer a) { + return f.acceptEitherAsync(g, a, new ThreadExecutor()); + } + public CompletableFuture applyToEither + (CompletableFuture f, + CompletionStage g, + Function a) { + return f.applyToEitherAsync(g, a, new ThreadExecutor()); + } + }; + + public abstract void checkExecutionMode(); + public abstract CompletableFuture runAsync(Runnable a); + public abstract CompletableFuture supplyAsync(Supplier a); + public abstract CompletableFuture thenRun + (CompletableFuture f, Runnable a); + public abstract CompletableFuture thenAccept + (CompletableFuture f, Consumer a); + public abstract CompletableFuture thenApply + (CompletableFuture f, Function a); + public abstract CompletableFuture thenCompose + (CompletableFuture f, + Function> a); + public abstract CompletableFuture handle + (CompletableFuture f, + BiFunction a); + public abstract CompletableFuture whenComplete + (CompletableFuture f, + BiConsumer a); + public abstract CompletableFuture runAfterBoth + (CompletableFuture f, CompletableFuture g, Runnable a); + public abstract CompletableFuture thenAcceptBoth + (CompletableFuture f, + CompletionStage g, + BiConsumer a); + public abstract CompletableFuture thenCombine + (CompletableFuture f, + CompletionStage g, + BiFunction a); + public abstract CompletableFuture runAfterEither + (CompletableFuture f, + CompletionStage g, + java.lang.Runnable a); + public abstract CompletableFuture acceptEither + (CompletableFuture f, + CompletionStage g, + Consumer a); + public abstract CompletableFuture applyToEither + (CompletableFuture f, + CompletionStage g, + Function a); + } + + /** + * exceptionally action is not invoked when source completes + * normally, and source result is propagated + */ + public void testExceptionally_normalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final AtomicInteger a = new AtomicInteger(0); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletableFuture g = f.exceptionally + ((Throwable t) -> { + a.getAndIncrement(); + threadFail("should not be called"); + return null; // unreached + }); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedNormally(g, v1); + checkCompletedNormally(f, v1); + assertEquals(0, a.get()); + }} + + /** + * exceptionally action completes with function value on source + * exception + */ + public void testExceptionally_exceptionalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final AtomicInteger a = new AtomicInteger(0); + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletableFuture g = f.exceptionally + ((Throwable t) -> { + ExecutionMode.SYNC.checkExecutionMode(); + threadAssertSame(t, ex); + a.getAndIncrement(); + return v1; + }); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedNormally(g, v1); + assertEquals(1, a.get()); + }} + + /** + * If an "exceptionally action" throws an exception, it completes + * exceptionally with that exception + */ + public void testExceptionally_exceptionalCompletionActionFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + { + final AtomicInteger a = new AtomicInteger(0); + final CFException ex1 = new CFException(); + final CFException ex2 = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) f.completeExceptionally(ex1); + final CompletableFuture g = f.exceptionally + ((Throwable t) -> { + ExecutionMode.SYNC.checkExecutionMode(); + threadAssertSame(t, ex1); + a.getAndIncrement(); + throw ex2; + }); + if (createIncomplete) f.completeExceptionally(ex1); + + checkCompletedWithWrappedException(g, ex2); + checkCompletedExceptionally(f, ex1); + assertEquals(1, a.get()); + }} + + /** + * whenComplete action executes on normal completion, propagating + * source result. + */ + public void testWhenComplete_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final AtomicInteger a = new AtomicInteger(0); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletableFuture g = m.whenComplete + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertSame(result, v1); + threadAssertNull(t); + a.getAndIncrement(); + }); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedNormally(g, v1); + checkCompletedNormally(f, v1); + assertEquals(1, a.get()); + }} + + /** + * whenComplete action executes on exceptional completion, propagating + * source result. + */ + public void testWhenComplete_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + { + final AtomicInteger a = new AtomicInteger(0); + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletableFuture g = m.whenComplete + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertNull(result); + threadAssertSame(t, ex); + a.getAndIncrement(); + }); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedWithWrappedException(g, ex); + checkCompletedExceptionally(f, ex); + assertEquals(1, a.get()); + }} + + /** + * whenComplete action executes on cancelled source, propagating + * CancellationException. + */ + public void testWhenComplete_sourceCancelled() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (boolean createIncomplete : new boolean[] { true, false }) + { + final AtomicInteger a = new AtomicInteger(0); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning)); + final CompletableFuture g = m.whenComplete + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertNull(result); + threadAssertTrue(t instanceof CancellationException); + a.getAndIncrement(); + }); + if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning)); + + checkCompletedWithWrappedCancellationException(g); + checkCancelled(f); + assertEquals(1, a.get()); + }} + + /** + * If a whenComplete action throws an exception when triggered by + * a normal completion, it completes exceptionally + */ + public void testWhenComplete_sourceCompletedNormallyActionFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final AtomicInteger a = new AtomicInteger(0); + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletableFuture g = m.whenComplete + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertSame(result, v1); + threadAssertNull(t); + a.getAndIncrement(); + throw ex; + }); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedWithWrappedException(g, ex); + checkCompletedNormally(f, v1); + assertEquals(1, a.get()); + }} + + /** + * If a whenComplete action throws an exception when triggered by + * a source completion that also throws an exception, the source + * exception takes precedence (unlike handle) + */ + public void testWhenComplete_sourceFailedActionFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (ExecutionMode m : ExecutionMode.values()) + { + final AtomicInteger a = new AtomicInteger(0); + final CFException ex1 = new CFException(); + final CFException ex2 = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + + if (!createIncomplete) f.completeExceptionally(ex1); + final CompletableFuture g = m.whenComplete + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertSame(t, ex1); + threadAssertNull(result); + a.getAndIncrement(); + throw ex2; + }); + if (createIncomplete) f.completeExceptionally(ex1); + + checkCompletedWithWrappedException(g, ex1); + checkCompletedExceptionally(f, ex1); + // oops... temporarily disabled +// if (testImplementationDetails) { +// assertEquals(1, ex1.getSuppressed().length); +// assertSame(ex2, ex1.getSuppressed()[0]); +// } + assertEquals(1, a.get()); + }} + + /** + * handle action completes normally with function value on normal + * completion of source + */ + public void testHandle_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final AtomicInteger a = new AtomicInteger(0); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletableFuture g = m.handle + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertSame(result, v1); + threadAssertNull(t); + a.getAndIncrement(); + return inc(v1); + }); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedNormally(g, inc(v1)); + checkCompletedNormally(f, v1); + assertEquals(1, a.get()); + }} + + /** + * handle action completes normally with function value on + * exceptional completion of source + */ + public void testHandle_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final AtomicInteger a = new AtomicInteger(0); + final CFException ex = new CFException(); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletableFuture g = m.handle + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertNull(result); + threadAssertSame(t, ex); + a.getAndIncrement(); + return v1; + }); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedNormally(g, v1); + checkCompletedExceptionally(f, ex); + assertEquals(1, a.get()); + }} + + /** + * handle action completes normally with function value on + * cancelled source + */ + public void testHandle_sourceCancelled() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final AtomicInteger a = new AtomicInteger(0); + if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning)); + final CompletableFuture g = m.handle + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertNull(result); + threadAssertTrue(t instanceof CancellationException); + a.getAndIncrement(); + return v1; + }); + if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning)); + + checkCompletedNormally(g, v1); + checkCancelled(f); + assertEquals(1, a.get()); + }} + + /** + * If a "handle action" throws an exception when triggered by + * a normal completion, it completes exceptionally + */ + public void testHandle_sourceCompletedNormallyActionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final AtomicInteger a = new AtomicInteger(0); + final CFException ex = new CFException(); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletableFuture g = m.handle + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertSame(result, v1); + threadAssertNull(t); + a.getAndIncrement(); + throw ex; + }); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedWithWrappedException(g, ex); + checkCompletedNormally(f, v1); + assertEquals(1, a.get()); + }} + + /** + * If a "handle action" throws an exception when triggered by + * a source completion that also throws an exception, the action + * exception takes precedence (unlike whenComplete) + */ + public void testHandle_sourceFailedActionFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (ExecutionMode m : ExecutionMode.values()) + { + final AtomicInteger a = new AtomicInteger(0); + final CFException ex1 = new CFException(); + final CFException ex2 = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + + if (!createIncomplete) f.completeExceptionally(ex1); + final CompletableFuture g = m.handle + (f, + (Integer result, Throwable t) -> { + m.checkExecutionMode(); + threadAssertNull(result); + threadAssertSame(ex1, t); + a.getAndIncrement(); + throw ex2; + }); + if (createIncomplete) f.completeExceptionally(ex1); + + checkCompletedWithWrappedException(g, ex2); + checkCompletedExceptionally(f, ex1); + assertEquals(1, a.get()); + }} + + /** + * runAsync completes after running Runnable + */ + public void testRunAsync_normalCompletion() { + ExecutionMode[] executionModes = { + ExecutionMode.ASYNC, + ExecutionMode.EXECUTOR, + }; + for (ExecutionMode m : executionModes) + { + final Noop r = new Noop(m); + final CompletableFuture f = m.runAsync(r); + assertNull(f.join()); + checkCompletedNormally(f, null); + r.assertInvoked(); + }} + + /** + * failing runAsync completes exceptionally after running Runnable + */ + public void testRunAsync_exceptionalCompletion() { + ExecutionMode[] executionModes = { + ExecutionMode.ASYNC, + ExecutionMode.EXECUTOR, + }; + for (ExecutionMode m : executionModes) + { + final FailingRunnable r = new FailingRunnable(m); + final CompletableFuture f = m.runAsync(r); + checkCompletedWithWrappedCFException(f); + r.assertInvoked(); + }} + + /** + * supplyAsync completes with result of supplier + */ + public void testSupplyAsync_normalCompletion() { + ExecutionMode[] executionModes = { + ExecutionMode.ASYNC, + ExecutionMode.EXECUTOR, + }; + for (ExecutionMode m : executionModes) + for (Integer v1 : new Integer[] { 1, null }) + { + final IntegerSupplier r = new IntegerSupplier(m, v1); + final CompletableFuture f = m.supplyAsync(r); + assertSame(v1, f.join()); + checkCompletedNormally(f, v1); + r.assertInvoked(); + }} + + /** + * Failing supplyAsync completes exceptionally + */ + public void testSupplyAsync_exceptionalCompletion() { + ExecutionMode[] executionModes = { + ExecutionMode.ASYNC, + ExecutionMode.EXECUTOR, + }; + for (ExecutionMode m : executionModes) + { + FailingSupplier r = new FailingSupplier(m); + CompletableFuture f = m.supplyAsync(r); + checkCompletedWithWrappedCFException(f); + r.assertInvoked(); + }} + + // seq completion methods + + /** + * thenRun result completes normally after normal completion of source + */ + public void testThenRun_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final Noop[] rs = new Noop[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m); + + final CompletableFuture h0 = m.thenRun(f, rs[0]); + final CompletableFuture h1 = m.runAfterBoth(f, f, rs[1]); + final CompletableFuture h2 = m.runAfterEither(f, f, rs[2]); + checkIncomplete(h0); + checkIncomplete(h1); + checkIncomplete(h2); + assertTrue(f.complete(v1)); + final CompletableFuture h3 = m.thenRun(f, rs[3]); + final CompletableFuture h4 = m.runAfterBoth(f, f, rs[4]); + final CompletableFuture h5 = m.runAfterEither(f, f, rs[5]); + + checkCompletedNormally(h0, null); + checkCompletedNormally(h1, null); + checkCompletedNormally(h2, null); + checkCompletedNormally(h3, null); + checkCompletedNormally(h4, null); + checkCompletedNormally(h5, null); + checkCompletedNormally(f, v1); + for (Noop r : rs) r.assertInvoked(); + }} + + /** + * thenRun result completes exceptionally after exceptional + * completion of source + */ + public void testThenRun_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + { + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final Noop[] rs = new Noop[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m); + + final CompletableFuture h0 = m.thenRun(f, rs[0]); + final CompletableFuture h1 = m.runAfterBoth(f, f, rs[1]); + final CompletableFuture h2 = m.runAfterEither(f, f, rs[2]); + checkIncomplete(h0); + checkIncomplete(h1); + checkIncomplete(h2); + assertTrue(f.completeExceptionally(ex)); + final CompletableFuture h3 = m.thenRun(f, rs[3]); + final CompletableFuture h4 = m.runAfterBoth(f, f, rs[4]); + final CompletableFuture h5 = m.runAfterEither(f, f, rs[5]); + + checkCompletedWithWrappedException(h0, ex); + checkCompletedWithWrappedException(h1, ex); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + checkCompletedWithWrappedException(h4, ex); + checkCompletedWithWrappedException(h5, ex); + checkCompletedExceptionally(f, ex); + for (Noop r : rs) r.assertNotInvoked(); + }} + + /** + * thenRun result completes exceptionally if source cancelled + */ + public void testThenRun_sourceCancelled() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + { + final CompletableFuture f = new CompletableFuture<>(); + final Noop[] rs = new Noop[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m); + + final CompletableFuture h0 = m.thenRun(f, rs[0]); + final CompletableFuture h1 = m.runAfterBoth(f, f, rs[1]); + final CompletableFuture h2 = m.runAfterEither(f, f, rs[2]); + checkIncomplete(h0); + checkIncomplete(h1); + checkIncomplete(h2); + assertTrue(f.cancel(mayInterruptIfRunning)); + final CompletableFuture h3 = m.thenRun(f, rs[3]); + final CompletableFuture h4 = m.runAfterBoth(f, f, rs[4]); + final CompletableFuture h5 = m.runAfterEither(f, f, rs[5]); + + checkCompletedWithWrappedCancellationException(h0); + checkCompletedWithWrappedCancellationException(h1); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + checkCompletedWithWrappedCancellationException(h4); + checkCompletedWithWrappedCancellationException(h5); + checkCancelled(f); + for (Noop r : rs) r.assertNotInvoked(); + }} + + /** + * thenRun result completes exceptionally if action does + */ + public void testThenRun_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final FailingRunnable[] rs = new FailingRunnable[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new FailingRunnable(m); + + final CompletableFuture h0 = m.thenRun(f, rs[0]); + final CompletableFuture h1 = m.runAfterBoth(f, f, rs[1]); + final CompletableFuture h2 = m.runAfterEither(f, f, rs[2]); + assertTrue(f.complete(v1)); + final CompletableFuture h3 = m.thenRun(f, rs[3]); + final CompletableFuture h4 = m.runAfterBoth(f, f, rs[4]); + final CompletableFuture h5 = m.runAfterEither(f, f, rs[5]); + + checkCompletedWithWrappedCFException(h0); + checkCompletedWithWrappedCFException(h1); + checkCompletedWithWrappedCFException(h2); + checkCompletedWithWrappedCFException(h3); + checkCompletedWithWrappedCFException(h4); + checkCompletedWithWrappedCFException(h5); + checkCompletedNormally(f, v1); + }} + + /** + * thenApply result completes normally after normal completion of source + */ + public void testThenApply_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final IncFunction[] rs = new IncFunction[4]; + for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m); + + final CompletableFuture h0 = m.thenApply(f, rs[0]); + final CompletableFuture h1 = m.applyToEither(f, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + assertTrue(f.complete(v1)); + final CompletableFuture h2 = m.thenApply(f, rs[2]); + final CompletableFuture h3 = m.applyToEither(f, f, rs[3]); + + checkCompletedNormally(h0, inc(v1)); + checkCompletedNormally(h1, inc(v1)); + checkCompletedNormally(h2, inc(v1)); + checkCompletedNormally(h3, inc(v1)); + checkCompletedNormally(f, v1); + for (IncFunction r : rs) r.assertValue(inc(v1)); + }} + + /** + * thenApply result completes exceptionally after exceptional + * completion of source + */ + public void testThenApply_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + { + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final IncFunction[] rs = new IncFunction[4]; + for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m); + + final CompletableFuture h0 = m.thenApply(f, rs[0]); + final CompletableFuture h1 = m.applyToEither(f, f, rs[1]); + assertTrue(f.completeExceptionally(ex)); + final CompletableFuture h2 = m.thenApply(f, rs[2]); + final CompletableFuture h3 = m.applyToEither(f, f, rs[3]); + + checkCompletedWithWrappedException(h0, ex); + checkCompletedWithWrappedException(h1, ex); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + checkCompletedExceptionally(f, ex); + for (IncFunction r : rs) r.assertNotInvoked(); + }} + + /** + * thenApply result completes exceptionally if source cancelled + */ + public void testThenApply_sourceCancelled() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + { + final CompletableFuture f = new CompletableFuture<>(); + final IncFunction[] rs = new IncFunction[4]; + for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m); + + final CompletableFuture h0 = m.thenApply(f, rs[0]); + final CompletableFuture h1 = m.applyToEither(f, f, rs[1]); + assertTrue(f.cancel(mayInterruptIfRunning)); + final CompletableFuture h2 = m.thenApply(f, rs[2]); + final CompletableFuture h3 = m.applyToEither(f, f, rs[3]); + + checkCompletedWithWrappedCancellationException(h0); + checkCompletedWithWrappedCancellationException(h1); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + checkCancelled(f); + for (IncFunction r : rs) r.assertNotInvoked(); + }} + + /** + * thenApply result completes exceptionally if action does + */ + public void testThenApply_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final FailingFunction[] rs = new FailingFunction[4]; + for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m); + + final CompletableFuture h0 = m.thenApply(f, rs[0]); + final CompletableFuture h1 = m.applyToEither(f, f, rs[1]); + assertTrue(f.complete(v1)); + final CompletableFuture h2 = m.thenApply(f, rs[2]); + final CompletableFuture h3 = m.applyToEither(f, f, rs[3]); + + checkCompletedWithWrappedCFException(h0); + checkCompletedWithWrappedCFException(h1); + checkCompletedWithWrappedCFException(h2); + checkCompletedWithWrappedCFException(h3); + checkCompletedNormally(f, v1); + }} + + /** + * thenAccept result completes normally after normal completion of source + */ + public void testThenAccept_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final NoopConsumer[] rs = new NoopConsumer[4]; + for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m); + + final CompletableFuture h0 = m.thenAccept(f, rs[0]); + final CompletableFuture h1 = m.acceptEither(f, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + assertTrue(f.complete(v1)); + final CompletableFuture h2 = m.thenAccept(f, rs[2]); + final CompletableFuture h3 = m.acceptEither(f, f, rs[3]); + + checkCompletedNormally(h0, null); + checkCompletedNormally(h1, null); + checkCompletedNormally(h2, null); + checkCompletedNormally(h3, null); + checkCompletedNormally(f, v1); + for (NoopConsumer r : rs) r.assertValue(v1); + }} + + /** + * thenAccept result completes exceptionally after exceptional + * completion of source + */ + public void testThenAccept_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + { + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final NoopConsumer[] rs = new NoopConsumer[4]; + for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m); + + final CompletableFuture h0 = m.thenAccept(f, rs[0]); + final CompletableFuture h1 = m.acceptEither(f, f, rs[1]); + assertTrue(f.completeExceptionally(ex)); + final CompletableFuture h2 = m.thenAccept(f, rs[2]); + final CompletableFuture h3 = m.acceptEither(f, f, rs[3]); + + checkCompletedWithWrappedException(h0, ex); + checkCompletedWithWrappedException(h1, ex); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + checkCompletedExceptionally(f, ex); + for (NoopConsumer r : rs) r.assertNotInvoked(); + }} + + /** + * thenAccept result completes exceptionally if source cancelled + */ + public void testThenAccept_sourceCancelled() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + { + final CompletableFuture f = new CompletableFuture<>(); + final NoopConsumer[] rs = new NoopConsumer[4]; + for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m); + + final CompletableFuture h0 = m.thenAccept(f, rs[0]); + final CompletableFuture h1 = m.acceptEither(f, f, rs[1]); + assertTrue(f.cancel(mayInterruptIfRunning)); + final CompletableFuture h2 = m.thenAccept(f, rs[2]); + final CompletableFuture h3 = m.acceptEither(f, f, rs[3]); + + checkCompletedWithWrappedCancellationException(h0); + checkCompletedWithWrappedCancellationException(h1); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + checkCancelled(f); + for (NoopConsumer r : rs) r.assertNotInvoked(); + }} + + /** + * thenAccept result completes exceptionally if action does + */ + public void testThenAccept_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final FailingConsumer[] rs = new FailingConsumer[4]; + for (int i = 0; i < rs.length; i++) rs[i] = new FailingConsumer(m); + + final CompletableFuture h0 = m.thenAccept(f, rs[0]); + final CompletableFuture h1 = m.acceptEither(f, f, rs[1]); + assertTrue(f.complete(v1)); + final CompletableFuture h2 = m.thenAccept(f, rs[2]); + final CompletableFuture h3 = m.acceptEither(f, f, rs[3]); + + checkCompletedWithWrappedCFException(h0); + checkCompletedWithWrappedCFException(h1); + checkCompletedWithWrappedCFException(h2); + checkCompletedWithWrappedCFException(h3); + checkCompletedNormally(f, v1); + }} + + /** + * thenCombine result completes normally after normal completion + * of sources + */ + public void testThenCombine_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction[] rs = new SubtractFunction[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new SubtractFunction(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Integer w1 = fFirst ? v1 : v2; + final Integer w2 = !fFirst ? v1 : v2; + + final CompletableFuture h0 = m.thenCombine(f, g, rs[0]); + final CompletableFuture h1 = m.thenCombine(fst, fst, rs[1]); + assertTrue(fst.complete(w1)); + final CompletableFuture h2 = m.thenCombine(f, g, rs[2]); + final CompletableFuture h3 = m.thenCombine(fst, fst, rs[3]); + checkIncomplete(h0); rs[0].assertNotInvoked(); + checkIncomplete(h2); rs[2].assertNotInvoked(); + checkCompletedNormally(h1, subtract(w1, w1)); + checkCompletedNormally(h3, subtract(w1, w1)); + rs[1].assertValue(subtract(w1, w1)); + rs[3].assertValue(subtract(w1, w1)); + assertTrue(snd.complete(w2)); + final CompletableFuture h4 = m.thenCombine(f, g, rs[4]); + + checkCompletedNormally(h0, subtract(v1, v2)); + checkCompletedNormally(h2, subtract(v1, v2)); + checkCompletedNormally(h4, subtract(v1, v2)); + rs[0].assertValue(subtract(v1, v2)); + rs[2].assertValue(subtract(v1, v2)); + rs[4].assertValue(subtract(v1, v2)); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + }} + + /** + * thenCombine result completes exceptionally after exceptional + * completion of either source + */ + public void testThenCombine_exceptionalCompletion() throws Throwable { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (boolean failFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CFException ex = new CFException(); + final SubtractFunction r1 = new SubtractFunction(m); + final SubtractFunction r2 = new SubtractFunction(m); + final SubtractFunction r3 = new SubtractFunction(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Callable complete1 = failFirst ? + () -> fst.completeExceptionally(ex) : + () -> fst.complete(v1); + final Callable complete2 = failFirst ? + () -> snd.complete(v1) : + () -> snd.completeExceptionally(ex); + + final CompletableFuture h1 = m.thenCombine(f, g, r1); + assertTrue(complete1.call()); + final CompletableFuture h2 = m.thenCombine(f, g, r2); + checkIncomplete(h1); + checkIncomplete(h2); + assertTrue(complete2.call()); + final CompletableFuture h3 = m.thenCombine(f, g, r3); + + checkCompletedWithWrappedException(h1, ex); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + r1.assertNotInvoked(); + r2.assertNotInvoked(); + r3.assertNotInvoked(); + checkCompletedNormally(failFirst ? snd : fst, v1); + checkCompletedExceptionally(failFirst ? fst : snd, ex); + }} + + /** + * thenCombine result completes exceptionally if either source cancelled + */ + public void testThenCombine_sourceCancelled() throws Throwable { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (boolean fFirst : new boolean[] { true, false }) + for (boolean failFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction r1 = new SubtractFunction(m); + final SubtractFunction r2 = new SubtractFunction(m); + final SubtractFunction r3 = new SubtractFunction(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Callable complete1 = failFirst ? + () -> fst.cancel(mayInterruptIfRunning) : + () -> fst.complete(v1); + final Callable complete2 = failFirst ? + () -> snd.complete(v1) : + () -> snd.cancel(mayInterruptIfRunning); + + final CompletableFuture h1 = m.thenCombine(f, g, r1); + assertTrue(complete1.call()); + final CompletableFuture h2 = m.thenCombine(f, g, r2); + checkIncomplete(h1); + checkIncomplete(h2); + assertTrue(complete2.call()); + final CompletableFuture h3 = m.thenCombine(f, g, r3); + + checkCompletedWithWrappedCancellationException(h1); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + r1.assertNotInvoked(); + r2.assertNotInvoked(); + r3.assertNotInvoked(); + checkCompletedNormally(failFirst ? snd : fst, v1); + checkCancelled(failFirst ? fst : snd); + }} + + /** + * thenCombine result completes exceptionally if action does + */ + public void testThenCombine_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingBiFunction r1 = new FailingBiFunction(m); + final FailingBiFunction r2 = new FailingBiFunction(m); + final FailingBiFunction r3 = new FailingBiFunction(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Integer w1 = fFirst ? v1 : v2; + final Integer w2 = !fFirst ? v1 : v2; + + final CompletableFuture h1 = m.thenCombine(f, g, r1); + assertTrue(fst.complete(w1)); + final CompletableFuture h2 = m.thenCombine(f, g, r2); + assertTrue(snd.complete(w2)); + final CompletableFuture h3 = m.thenCombine(f, g, r3); + + checkCompletedWithWrappedCFException(h1); + checkCompletedWithWrappedCFException(h2); + checkCompletedWithWrappedCFException(h3); + r1.assertInvoked(); + r2.assertInvoked(); + r3.assertInvoked(); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + }} + + /** + * thenAcceptBoth result completes normally after normal + * completion of sources + */ + public void testThenAcceptBoth_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r1 = new SubtractAction(m); + final SubtractAction r2 = new SubtractAction(m); + final SubtractAction r3 = new SubtractAction(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Integer w1 = fFirst ? v1 : v2; + final Integer w2 = !fFirst ? v1 : v2; + + final CompletableFuture h1 = m.thenAcceptBoth(f, g, r1); + assertTrue(fst.complete(w1)); + final CompletableFuture h2 = m.thenAcceptBoth(f, g, r2); + checkIncomplete(h1); + checkIncomplete(h2); + r1.assertNotInvoked(); + r2.assertNotInvoked(); + assertTrue(snd.complete(w2)); + final CompletableFuture h3 = m.thenAcceptBoth(f, g, r3); + + checkCompletedNormally(h1, null); + checkCompletedNormally(h2, null); + checkCompletedNormally(h3, null); + r1.assertValue(subtract(v1, v2)); + r2.assertValue(subtract(v1, v2)); + r3.assertValue(subtract(v1, v2)); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + }} + + /** + * thenAcceptBoth result completes exceptionally after exceptional + * completion of either source + */ + public void testThenAcceptBoth_exceptionalCompletion() throws Throwable { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (boolean failFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CFException ex = new CFException(); + final SubtractAction r1 = new SubtractAction(m); + final SubtractAction r2 = new SubtractAction(m); + final SubtractAction r3 = new SubtractAction(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Callable complete1 = failFirst ? + () -> fst.completeExceptionally(ex) : + () -> fst.complete(v1); + final Callable complete2 = failFirst ? + () -> snd.complete(v1) : + () -> snd.completeExceptionally(ex); + + final CompletableFuture h1 = m.thenAcceptBoth(f, g, r1); + assertTrue(complete1.call()); + final CompletableFuture h2 = m.thenAcceptBoth(f, g, r2); + checkIncomplete(h1); + checkIncomplete(h2); + assertTrue(complete2.call()); + final CompletableFuture h3 = m.thenAcceptBoth(f, g, r3); + + checkCompletedWithWrappedException(h1, ex); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + r1.assertNotInvoked(); + r2.assertNotInvoked(); + r3.assertNotInvoked(); + checkCompletedNormally(failFirst ? snd : fst, v1); + checkCompletedExceptionally(failFirst ? fst : snd, ex); + }} + + /** + * thenAcceptBoth result completes exceptionally if either source cancelled + */ + public void testThenAcceptBoth_sourceCancelled() throws Throwable { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (boolean fFirst : new boolean[] { true, false }) + for (boolean failFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r1 = new SubtractAction(m); + final SubtractAction r2 = new SubtractAction(m); + final SubtractAction r3 = new SubtractAction(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Callable complete1 = failFirst ? + () -> fst.cancel(mayInterruptIfRunning) : + () -> fst.complete(v1); + final Callable complete2 = failFirst ? + () -> snd.complete(v1) : + () -> snd.cancel(mayInterruptIfRunning); + + final CompletableFuture h1 = m.thenAcceptBoth(f, g, r1); + assertTrue(complete1.call()); + final CompletableFuture h2 = m.thenAcceptBoth(f, g, r2); + checkIncomplete(h1); + checkIncomplete(h2); + assertTrue(complete2.call()); + final CompletableFuture h3 = m.thenAcceptBoth(f, g, r3); + + checkCompletedWithWrappedCancellationException(h1); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + r1.assertNotInvoked(); + r2.assertNotInvoked(); + r3.assertNotInvoked(); + checkCompletedNormally(failFirst ? snd : fst, v1); + checkCancelled(failFirst ? fst : snd); + }} + + /** + * thenAcceptBoth result completes exceptionally if action does + */ + public void testThenAcceptBoth_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingBiConsumer r1 = new FailingBiConsumer(m); + final FailingBiConsumer r2 = new FailingBiConsumer(m); + final FailingBiConsumer r3 = new FailingBiConsumer(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Integer w1 = fFirst ? v1 : v2; + final Integer w2 = !fFirst ? v1 : v2; + + final CompletableFuture h1 = m.thenAcceptBoth(f, g, r1); + assertTrue(fst.complete(w1)); + final CompletableFuture h2 = m.thenAcceptBoth(f, g, r2); + assertTrue(snd.complete(w2)); + final CompletableFuture h3 = m.thenAcceptBoth(f, g, r3); + + checkCompletedWithWrappedCFException(h1); + checkCompletedWithWrappedCFException(h2); + checkCompletedWithWrappedCFException(h3); + r1.assertInvoked(); + r2.assertInvoked(); + r3.assertInvoked(); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + }} + + /** + * runAfterBoth result completes normally after normal + * completion of sources + */ + public void testRunAfterBoth_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r1 = new Noop(m); + final Noop r2 = new Noop(m); + final Noop r3 = new Noop(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Integer w1 = fFirst ? v1 : v2; + final Integer w2 = !fFirst ? v1 : v2; + + final CompletableFuture h1 = m.runAfterBoth(f, g, r1); + assertTrue(fst.complete(w1)); + final CompletableFuture h2 = m.runAfterBoth(f, g, r2); + checkIncomplete(h1); + checkIncomplete(h2); + r1.assertNotInvoked(); + r2.assertNotInvoked(); + assertTrue(snd.complete(w2)); + final CompletableFuture h3 = m.runAfterBoth(f, g, r3); + + checkCompletedNormally(h1, null); + checkCompletedNormally(h2, null); + checkCompletedNormally(h3, null); + r1.assertInvoked(); + r2.assertInvoked(); + r3.assertInvoked(); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + }} + + /** + * runAfterBoth result completes exceptionally after exceptional + * completion of either source + */ + public void testRunAfterBoth_exceptionalCompletion() throws Throwable { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (boolean failFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CFException ex = new CFException(); + final Noop r1 = new Noop(m); + final Noop r2 = new Noop(m); + final Noop r3 = new Noop(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Callable complete1 = failFirst ? + () -> fst.completeExceptionally(ex) : + () -> fst.complete(v1); + final Callable complete2 = failFirst ? + () -> snd.complete(v1) : + () -> snd.completeExceptionally(ex); + + final CompletableFuture h1 = m.runAfterBoth(f, g, r1); + assertTrue(complete1.call()); + final CompletableFuture h2 = m.runAfterBoth(f, g, r2); + checkIncomplete(h1); + checkIncomplete(h2); + assertTrue(complete2.call()); + final CompletableFuture h3 = m.runAfterBoth(f, g, r3); + + checkCompletedWithWrappedException(h1, ex); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + r1.assertNotInvoked(); + r2.assertNotInvoked(); + r3.assertNotInvoked(); + checkCompletedNormally(failFirst ? snd : fst, v1); + checkCompletedExceptionally(failFirst ? fst : snd, ex); + }} + + /** + * runAfterBoth result completes exceptionally if either source cancelled + */ + public void testRunAfterBoth_sourceCancelled() throws Throwable { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (boolean fFirst : new boolean[] { true, false }) + for (boolean failFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r1 = new Noop(m); + final Noop r2 = new Noop(m); + final Noop r3 = new Noop(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Callable complete1 = failFirst ? + () -> fst.cancel(mayInterruptIfRunning) : + () -> fst.complete(v1); + final Callable complete2 = failFirst ? + () -> snd.complete(v1) : + () -> snd.cancel(mayInterruptIfRunning); + + final CompletableFuture h1 = m.runAfterBoth(f, g, r1); + assertTrue(complete1.call()); + final CompletableFuture h2 = m.runAfterBoth(f, g, r2); + checkIncomplete(h1); + checkIncomplete(h2); + assertTrue(complete2.call()); + final CompletableFuture h3 = m.runAfterBoth(f, g, r3); + + checkCompletedWithWrappedCancellationException(h1); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + r1.assertNotInvoked(); + r2.assertNotInvoked(); + r3.assertNotInvoked(); + checkCompletedNormally(failFirst ? snd : fst, v1); + checkCancelled(failFirst ? fst : snd); + }} + + /** + * runAfterBoth result completes exceptionally if action does + */ + public void testRunAfterBoth_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingRunnable r1 = new FailingRunnable(m); + final FailingRunnable r2 = new FailingRunnable(m); + final FailingRunnable r3 = new FailingRunnable(m); + + final CompletableFuture fst = fFirst ? f : g; + final CompletableFuture snd = !fFirst ? f : g; + final Integer w1 = fFirst ? v1 : v2; + final Integer w2 = !fFirst ? v1 : v2; + + final CompletableFuture h1 = m.runAfterBoth(f, g, r1); + assertTrue(fst.complete(w1)); + final CompletableFuture h2 = m.runAfterBoth(f, g, r2); + assertTrue(snd.complete(w2)); + final CompletableFuture h3 = m.runAfterBoth(f, g, r3); + + checkCompletedWithWrappedCFException(h1); + checkCompletedWithWrappedCFException(h2); + checkCompletedWithWrappedCFException(h3); + r1.assertInvoked(); + r2.assertInvoked(); + r3.assertInvoked(); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + }} + + /** + * applyToEither result completes normally after normal completion + * of either source + */ + public void testApplyToEither_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncFunction[] rs = new IncFunction[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m); + + final CompletableFuture h0 = m.applyToEither(f, g, rs[0]); + final CompletableFuture h1 = m.applyToEither(g, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + rs[0].assertNotInvoked(); + rs[1].assertNotInvoked(); + f.complete(v1); + checkCompletedNormally(h0, inc(v1)); + checkCompletedNormally(h1, inc(v1)); + final CompletableFuture h2 = m.applyToEither(f, g, rs[2]); + final CompletableFuture h3 = m.applyToEither(g, f, rs[3]); + checkCompletedNormally(h2, inc(v1)); + checkCompletedNormally(h3, inc(v1)); + g.complete(v2); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.applyToEither(f, g, rs[4]); + final CompletableFuture h5 = m.applyToEither(g, f, rs[5]); + rs[4].assertValue(h4.join()); + rs[5].assertValue(h5.join()); + assertTrue(Objects.equals(inc(v1), h4.join()) || + Objects.equals(inc(v2), h4.join())); + assertTrue(Objects.equals(inc(v1), h5.join()) || + Objects.equals(inc(v2), h5.join())); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + checkCompletedNormally(h0, inc(v1)); + checkCompletedNormally(h1, inc(v1)); + checkCompletedNormally(h2, inc(v1)); + checkCompletedNormally(h3, inc(v1)); + for (int i = 0; i < 4; i++) rs[i].assertValue(inc(v1)); + }} + + /** + * applyToEither result completes exceptionally after exceptional + * completion of either source + */ + public void testApplyToEither_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CFException ex = new CFException(); + final IncFunction[] rs = new IncFunction[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m); + + final CompletableFuture h0 = m.applyToEither(f, g, rs[0]); + final CompletableFuture h1 = m.applyToEither(g, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + rs[0].assertNotInvoked(); + rs[1].assertNotInvoked(); + f.completeExceptionally(ex); + checkCompletedWithWrappedException(h0, ex); + checkCompletedWithWrappedException(h1, ex); + final CompletableFuture h2 = m.applyToEither(f, g, rs[2]); + final CompletableFuture h3 = m.applyToEither(g, f, rs[3]); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + g.complete(v1); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.applyToEither(f, g, rs[4]); + final CompletableFuture h5 = m.applyToEither(g, f, rs[5]); + try { + assertEquals(inc(v1), h4.join()); + rs[4].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h4, ex); + rs[4].assertNotInvoked(); + } + try { + assertEquals(inc(v1), h5.join()); + rs[5].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h5, ex); + rs[5].assertNotInvoked(); + } + + checkCompletedExceptionally(f, ex); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedException(h0, ex); + checkCompletedWithWrappedException(h1, ex); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + checkCompletedWithWrappedException(h4, ex); + for (int i = 0; i < 4; i++) rs[i].assertNotInvoked(); + }} + + public void testApplyToEither_exceptionalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CFException ex = new CFException(); + final IncFunction[] rs = new IncFunction[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m); + + final CompletableFuture h0 = m.applyToEither(f, g, rs[0]); + final CompletableFuture h1 = m.applyToEither(g, f, rs[1]); + assertTrue(fFirst ? f.complete(v1) : g.completeExceptionally(ex)); + assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex)); + final CompletableFuture h2 = m.applyToEither(f, g, rs[2]); + final CompletableFuture h3 = m.applyToEither(g, f, rs[3]); + + // unspecified behavior - both source completions available + try { + assertEquals(inc(v1), h0.join()); + rs[0].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h0, ex); + rs[0].assertNotInvoked(); + } + try { + assertEquals(inc(v1), h1.join()); + rs[1].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h1, ex); + rs[1].assertNotInvoked(); + } + try { + assertEquals(inc(v1), h2.join()); + rs[2].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h2, ex); + rs[2].assertNotInvoked(); + } + try { + assertEquals(inc(v1), h3.join()); + rs[3].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h3, ex); + rs[3].assertNotInvoked(); + } + + checkCompletedNormally(f, v1); + checkCompletedExceptionally(g, ex); + }} + + /** + * applyToEither result completes exceptionally if either source cancelled + */ + public void testApplyToEither_sourceCancelled() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncFunction[] rs = new IncFunction[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m); + + final CompletableFuture h0 = m.applyToEither(f, g, rs[0]); + final CompletableFuture h1 = m.applyToEither(g, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + rs[0].assertNotInvoked(); + rs[1].assertNotInvoked(); + f.cancel(mayInterruptIfRunning); + checkCompletedWithWrappedCancellationException(h0); + checkCompletedWithWrappedCancellationException(h1); + final CompletableFuture h2 = m.applyToEither(f, g, rs[2]); + final CompletableFuture h3 = m.applyToEither(g, f, rs[3]); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + g.complete(v1); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.applyToEither(f, g, rs[4]); + final CompletableFuture h5 = m.applyToEither(g, f, rs[5]); + try { + assertEquals(inc(v1), h4.join()); + rs[4].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h4); + rs[4].assertNotInvoked(); + } + try { + assertEquals(inc(v1), h5.join()); + rs[5].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h5); + rs[5].assertNotInvoked(); + } + + checkCancelled(f); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedCancellationException(h0); + checkCompletedWithWrappedCancellationException(h1); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + for (int i = 0; i < 4; i++) rs[i].assertNotInvoked(); + }} + + public void testApplyToEither_sourceCancelled2() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncFunction[] rs = new IncFunction[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m); + + final CompletableFuture h0 = m.applyToEither(f, g, rs[0]); + final CompletableFuture h1 = m.applyToEither(g, f, rs[1]); + assertTrue(fFirst ? f.complete(v1) : g.cancel(mayInterruptIfRunning)); + assertTrue(!fFirst ? f.complete(v1) : g.cancel(mayInterruptIfRunning)); + final CompletableFuture h2 = m.applyToEither(f, g, rs[2]); + final CompletableFuture h3 = m.applyToEither(g, f, rs[3]); + + // unspecified behavior - both source completions available + try { + assertEquals(inc(v1), h0.join()); + rs[0].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h0); + rs[0].assertNotInvoked(); + } + try { + assertEquals(inc(v1), h1.join()); + rs[1].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h1); + rs[1].assertNotInvoked(); + } + try { + assertEquals(inc(v1), h2.join()); + rs[2].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h2); + rs[2].assertNotInvoked(); + } + try { + assertEquals(inc(v1), h3.join()); + rs[3].assertValue(inc(v1)); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h3); + rs[3].assertNotInvoked(); + } + + checkCompletedNormally(f, v1); + checkCancelled(g); + }} + + /** + * applyToEither result completes exceptionally if action does + */ + public void testApplyToEither_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingFunction[] rs = new FailingFunction[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m); + + final CompletableFuture h0 = m.applyToEither(f, g, rs[0]); + final CompletableFuture h1 = m.applyToEither(g, f, rs[1]); + f.complete(v1); + final CompletableFuture h2 = m.applyToEither(f, g, rs[2]); + final CompletableFuture h3 = m.applyToEither(g, f, rs[3]); + checkCompletedWithWrappedCFException(h0); + checkCompletedWithWrappedCFException(h1); + checkCompletedWithWrappedCFException(h2); + checkCompletedWithWrappedCFException(h3); + for (int i = 0; i < 4; i++) rs[i].assertValue(v1); + + g.complete(v2); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.applyToEither(f, g, rs[4]); + final CompletableFuture h5 = m.applyToEither(g, f, rs[5]); + + checkCompletedWithWrappedCFException(h4); + assertTrue(Objects.equals(v1, rs[4].value) || + Objects.equals(v2, rs[4].value)); + checkCompletedWithWrappedCFException(h5); + assertTrue(Objects.equals(v1, rs[5].value) || + Objects.equals(v2, rs[5].value)); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + }} + + /** + * acceptEither result completes normally after normal completion + * of either source + */ + public void testAcceptEither_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final NoopConsumer[] rs = new NoopConsumer[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m); + + final CompletableFuture h0 = m.acceptEither(f, g, rs[0]); + final CompletableFuture h1 = m.acceptEither(g, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + rs[0].assertNotInvoked(); + rs[1].assertNotInvoked(); + f.complete(v1); + checkCompletedNormally(h0, null); + checkCompletedNormally(h1, null); + rs[0].assertValue(v1); + rs[1].assertValue(v1); + final CompletableFuture h2 = m.acceptEither(f, g, rs[2]); + final CompletableFuture h3 = m.acceptEither(g, f, rs[3]); + checkCompletedNormally(h2, null); + checkCompletedNormally(h3, null); + rs[2].assertValue(v1); + rs[3].assertValue(v1); + g.complete(v2); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.acceptEither(f, g, rs[4]); + final CompletableFuture h5 = m.acceptEither(g, f, rs[5]); + checkCompletedNormally(h4, null); + checkCompletedNormally(h5, null); + assertTrue(Objects.equals(v1, rs[4].value) || + Objects.equals(v2, rs[4].value)); + assertTrue(Objects.equals(v1, rs[5].value) || + Objects.equals(v2, rs[5].value)); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + checkCompletedNormally(h0, null); + checkCompletedNormally(h1, null); + checkCompletedNormally(h2, null); + checkCompletedNormally(h3, null); + for (int i = 0; i < 4; i++) rs[i].assertValue(v1); + }} + + /** + * acceptEither result completes exceptionally after exceptional + * completion of either source + */ + public void testAcceptEither_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CFException ex = new CFException(); + final NoopConsumer[] rs = new NoopConsumer[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m); + + final CompletableFuture h0 = m.acceptEither(f, g, rs[0]); + final CompletableFuture h1 = m.acceptEither(g, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + rs[0].assertNotInvoked(); + rs[1].assertNotInvoked(); + f.completeExceptionally(ex); + checkCompletedWithWrappedException(h0, ex); + checkCompletedWithWrappedException(h1, ex); + final CompletableFuture h2 = m.acceptEither(f, g, rs[2]); + final CompletableFuture h3 = m.acceptEither(g, f, rs[3]); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + + g.complete(v1); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.acceptEither(f, g, rs[4]); + final CompletableFuture h5 = m.acceptEither(g, f, rs[5]); + try { + assertNull(h4.join()); + rs[4].assertValue(v1); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h4, ex); + rs[4].assertNotInvoked(); + } + try { + assertNull(h5.join()); + rs[5].assertValue(v1); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h5, ex); + rs[5].assertNotInvoked(); + } + + checkCompletedExceptionally(f, ex); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedException(h0, ex); + checkCompletedWithWrappedException(h1, ex); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + checkCompletedWithWrappedException(h4, ex); + for (int i = 0; i < 4; i++) rs[i].assertNotInvoked(); + }} + + public void testAcceptEither_exceptionalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CFException ex = new CFException(); + final NoopConsumer[] rs = new NoopConsumer[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m); + + final CompletableFuture h0 = m.acceptEither(f, g, rs[0]); + final CompletableFuture h1 = m.acceptEither(g, f, rs[1]); + assertTrue(fFirst ? f.complete(v1) : g.completeExceptionally(ex)); + assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex)); + final CompletableFuture h2 = m.acceptEither(f, g, rs[2]); + final CompletableFuture h3 = m.acceptEither(g, f, rs[3]); + + // unspecified behavior - both source completions available + try { + assertEquals(null, h0.join()); + rs[0].assertValue(v1); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h0, ex); + rs[0].assertNotInvoked(); + } + try { + assertEquals(null, h1.join()); + rs[1].assertValue(v1); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h1, ex); + rs[1].assertNotInvoked(); + } + try { + assertEquals(null, h2.join()); + rs[2].assertValue(v1); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h2, ex); + rs[2].assertNotInvoked(); + } + try { + assertEquals(null, h3.join()); + rs[3].assertValue(v1); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h3, ex); + rs[3].assertNotInvoked(); + } + + checkCompletedNormally(f, v1); + checkCompletedExceptionally(g, ex); + }} + + /** + * acceptEither result completes exceptionally if either source cancelled + */ + public void testAcceptEither_sourceCancelled() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final NoopConsumer[] rs = new NoopConsumer[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m); + + final CompletableFuture h0 = m.acceptEither(f, g, rs[0]); + final CompletableFuture h1 = m.acceptEither(g, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + rs[0].assertNotInvoked(); + rs[1].assertNotInvoked(); + f.cancel(mayInterruptIfRunning); + checkCompletedWithWrappedCancellationException(h0); + checkCompletedWithWrappedCancellationException(h1); + final CompletableFuture h2 = m.acceptEither(f, g, rs[2]); + final CompletableFuture h3 = m.acceptEither(g, f, rs[3]); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + + g.complete(v1); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.acceptEither(f, g, rs[4]); + final CompletableFuture h5 = m.acceptEither(g, f, rs[5]); + try { + assertNull(h4.join()); + rs[4].assertValue(v1); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h4); + rs[4].assertNotInvoked(); + } + try { + assertNull(h5.join()); + rs[5].assertValue(v1); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h5); + rs[5].assertNotInvoked(); + } + + checkCancelled(f); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedCancellationException(h0); + checkCompletedWithWrappedCancellationException(h1); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + for (int i = 0; i < 4; i++) rs[i].assertNotInvoked(); + }} + + /** + * acceptEither result completes exceptionally if action does + */ + public void testAcceptEither_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingConsumer[] rs = new FailingConsumer[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new FailingConsumer(m); + + final CompletableFuture h0 = m.acceptEither(f, g, rs[0]); + final CompletableFuture h1 = m.acceptEither(g, f, rs[1]); + f.complete(v1); + final CompletableFuture h2 = m.acceptEither(f, g, rs[2]); + final CompletableFuture h3 = m.acceptEither(g, f, rs[3]); + checkCompletedWithWrappedCFException(h0); + checkCompletedWithWrappedCFException(h1); + checkCompletedWithWrappedCFException(h2); + checkCompletedWithWrappedCFException(h3); + for (int i = 0; i < 4; i++) rs[i].assertValue(v1); + + g.complete(v2); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.acceptEither(f, g, rs[4]); + final CompletableFuture h5 = m.acceptEither(g, f, rs[5]); + + checkCompletedWithWrappedCFException(h4); + assertTrue(Objects.equals(v1, rs[4].value) || + Objects.equals(v2, rs[4].value)); + checkCompletedWithWrappedCFException(h5); + assertTrue(Objects.equals(v1, rs[5].value) || + Objects.equals(v2, rs[5].value)); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + }} + + /** + * runAfterEither result completes normally after normal completion + * of either source + */ + public void testRunAfterEither_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop[] rs = new Noop[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m); + + final CompletableFuture h0 = m.runAfterEither(f, g, rs[0]); + final CompletableFuture h1 = m.runAfterEither(g, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + rs[0].assertNotInvoked(); + rs[1].assertNotInvoked(); + f.complete(v1); + checkCompletedNormally(h0, null); + checkCompletedNormally(h1, null); + rs[0].assertInvoked(); + rs[1].assertInvoked(); + final CompletableFuture h2 = m.runAfterEither(f, g, rs[2]); + final CompletableFuture h3 = m.runAfterEither(g, f, rs[3]); + checkCompletedNormally(h2, null); + checkCompletedNormally(h3, null); + rs[2].assertInvoked(); + rs[3].assertInvoked(); + + g.complete(v2); + + final CompletableFuture h4 = m.runAfterEither(f, g, rs[4]); + final CompletableFuture h5 = m.runAfterEither(g, f, rs[5]); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + checkCompletedNormally(h0, null); + checkCompletedNormally(h1, null); + checkCompletedNormally(h2, null); + checkCompletedNormally(h3, null); + checkCompletedNormally(h4, null); + checkCompletedNormally(h5, null); + for (int i = 0; i < 6; i++) rs[i].assertInvoked(); + }} + + /** + * runAfterEither result completes exceptionally after exceptional + * completion of either source + */ + public void testRunAfterEither_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CFException ex = new CFException(); + final Noop[] rs = new Noop[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m); + + final CompletableFuture h0 = m.runAfterEither(f, g, rs[0]); + final CompletableFuture h1 = m.runAfterEither(g, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + rs[0].assertNotInvoked(); + rs[1].assertNotInvoked(); + assertTrue(f.completeExceptionally(ex)); + checkCompletedWithWrappedException(h0, ex); + checkCompletedWithWrappedException(h1, ex); + final CompletableFuture h2 = m.runAfterEither(f, g, rs[2]); + final CompletableFuture h3 = m.runAfterEither(g, f, rs[3]); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + + assertTrue(g.complete(v1)); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.runAfterEither(f, g, rs[4]); + final CompletableFuture h5 = m.runAfterEither(g, f, rs[5]); + try { + assertNull(h4.join()); + rs[4].assertInvoked(); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h4, ex); + rs[4].assertNotInvoked(); + } + try { + assertNull(h5.join()); + rs[5].assertInvoked(); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h5, ex); + rs[5].assertNotInvoked(); + } + + checkCompletedExceptionally(f, ex); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedException(h0, ex); + checkCompletedWithWrappedException(h1, ex); + checkCompletedWithWrappedException(h2, ex); + checkCompletedWithWrappedException(h3, ex); + checkCompletedWithWrappedException(h4, ex); + for (int i = 0; i < 4; i++) rs[i].assertNotInvoked(); + }} + + public void testRunAfterEither_exceptionalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean fFirst : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CFException ex = new CFException(); + final Noop[] rs = new Noop[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m); + + final CompletableFuture h0 = m.runAfterEither(f, g, rs[0]); + final CompletableFuture h1 = m.runAfterEither(g, f, rs[1]); + assertTrue( fFirst ? f.complete(v1) : g.completeExceptionally(ex)); + assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex)); + final CompletableFuture h2 = m.runAfterEither(f, g, rs[2]); + final CompletableFuture h3 = m.runAfterEither(g, f, rs[3]); + + // unspecified behavior - both source completions available + try { + assertEquals(null, h0.join()); + rs[0].assertInvoked(); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h0, ex); + rs[0].assertNotInvoked(); + } + try { + assertEquals(null, h1.join()); + rs[1].assertInvoked(); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h1, ex); + rs[1].assertNotInvoked(); + } + try { + assertEquals(null, h2.join()); + rs[2].assertInvoked(); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h2, ex); + rs[2].assertNotInvoked(); + } + try { + assertEquals(null, h3.join()); + rs[3].assertInvoked(); + } catch (CompletionException ok) { + checkCompletedWithWrappedException(h3, ex); + rs[3].assertNotInvoked(); + } + + checkCompletedNormally(f, v1); + checkCompletedExceptionally(g, ex); + }} + + /** + * runAfterEither result completes exceptionally if either source cancelled + */ + public void testRunAfterEither_sourceCancelled() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop[] rs = new Noop[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m); + + final CompletableFuture h0 = m.runAfterEither(f, g, rs[0]); + final CompletableFuture h1 = m.runAfterEither(g, f, rs[1]); + checkIncomplete(h0); + checkIncomplete(h1); + rs[0].assertNotInvoked(); + rs[1].assertNotInvoked(); + f.cancel(mayInterruptIfRunning); + checkCompletedWithWrappedCancellationException(h0); + checkCompletedWithWrappedCancellationException(h1); + final CompletableFuture h2 = m.runAfterEither(f, g, rs[2]); + final CompletableFuture h3 = m.runAfterEither(g, f, rs[3]); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + + assertTrue(g.complete(v1)); + + // unspecified behavior - both source completions available + final CompletableFuture h4 = m.runAfterEither(f, g, rs[4]); + final CompletableFuture h5 = m.runAfterEither(g, f, rs[5]); + try { + assertNull(h4.join()); + rs[4].assertInvoked(); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h4); + rs[4].assertNotInvoked(); + } + try { + assertNull(h5.join()); + rs[5].assertInvoked(); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h5); + rs[5].assertNotInvoked(); + } + + checkCancelled(f); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedCancellationException(h0); + checkCompletedWithWrappedCancellationException(h1); + checkCompletedWithWrappedCancellationException(h2); + checkCompletedWithWrappedCancellationException(h3); + for (int i = 0; i < 4; i++) rs[i].assertNotInvoked(); + }} + + /** + * runAfterEither result completes exceptionally if action does + */ + public void testRunAfterEither_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingRunnable[] rs = new FailingRunnable[6]; + for (int i = 0; i < rs.length; i++) rs[i] = new FailingRunnable(m); + + final CompletableFuture h0 = m.runAfterEither(f, g, rs[0]); + final CompletableFuture h1 = m.runAfterEither(g, f, rs[1]); + assertTrue(f.complete(v1)); + final CompletableFuture h2 = m.runAfterEither(f, g, rs[2]); + final CompletableFuture h3 = m.runAfterEither(g, f, rs[3]); + checkCompletedWithWrappedCFException(h0); + checkCompletedWithWrappedCFException(h1); + checkCompletedWithWrappedCFException(h2); + checkCompletedWithWrappedCFException(h3); + for (int i = 0; i < 4; i++) rs[i].assertInvoked(); + assertTrue(g.complete(v2)); + final CompletableFuture h4 = m.runAfterEither(f, g, rs[4]); + final CompletableFuture h5 = m.runAfterEither(g, f, rs[5]); + checkCompletedWithWrappedCFException(h4); + checkCompletedWithWrappedCFException(h5); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + for (int i = 0; i < 6; i++) rs[i].assertInvoked(); + }} + + /** + * thenCompose result completes normally after normal completion of source + */ + public void testThenCompose_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFutureInc r = new CompletableFutureInc(m); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletableFuture g = m.thenCompose(f, r); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedNormally(g, inc(v1)); + checkCompletedNormally(f, v1); + r.assertValue(v1); + }} + + /** + * thenCompose result completes exceptionally after exceptional + * completion of source + */ + public void testThenCompose_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + { + final CFException ex = new CFException(); + final CompletableFutureInc r = new CompletableFutureInc(m); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletableFuture g = m.thenCompose(f, r); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedWithWrappedException(g, ex); + checkCompletedExceptionally(f, ex); + r.assertNotInvoked(); + }} + + /** + * thenCompose result completes exceptionally if action does + */ + public void testThenCompose_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final FailingCompletableFutureFunction r + = new FailingCompletableFutureFunction(m); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletableFuture g = m.thenCompose(f, r); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedWithWrappedCFException(g); + checkCompletedNormally(f, v1); + }} + + /** + * thenCompose result completes exceptionally if source cancelled + */ + public void testThenCompose_sourceCancelled() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + { + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFutureInc r = new CompletableFutureInc(m); + if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning)); + final CompletableFuture g = m.thenCompose(f, r); + if (createIncomplete) { + checkIncomplete(g); + assertTrue(f.cancel(mayInterruptIfRunning)); + } + + checkCompletedWithWrappedCancellationException(g); + checkCancelled(f); + }} + + /** + * thenCompose result completes exceptionally if the result of the action does + */ + public void testThenCompose_actionReturnsFailingFuture() { + for (ExecutionMode m : ExecutionMode.values()) + for (int order = 0; order < 6; order++) + for (Integer v1 : new Integer[] { 1, null }) + { + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CompletableFuture h; + // Test all permutations of orders + switch (order) { + case 0: + assertTrue(f.complete(v1)); + assertTrue(g.completeExceptionally(ex)); + h = m.thenCompose(f, (x -> g)); + break; + case 1: + assertTrue(f.complete(v1)); + h = m.thenCompose(f, (x -> g)); + assertTrue(g.completeExceptionally(ex)); + break; + case 2: + assertTrue(g.completeExceptionally(ex)); + assertTrue(f.complete(v1)); + h = m.thenCompose(f, (x -> g)); + break; + case 3: + assertTrue(g.completeExceptionally(ex)); + h = m.thenCompose(f, (x -> g)); + assertTrue(f.complete(v1)); + break; + case 4: + h = m.thenCompose(f, (x -> g)); + assertTrue(f.complete(v1)); + assertTrue(g.completeExceptionally(ex)); + break; + case 5: + h = m.thenCompose(f, (x -> g)); + assertTrue(f.complete(v1)); + assertTrue(g.completeExceptionally(ex)); + break; + default: throw new AssertionError(); + } + + checkCompletedExceptionally(g, ex); + checkCompletedWithWrappedException(h, ex); + checkCompletedNormally(f, v1); + }} + + // other static methods + + /** + * allOf(no component futures) returns a future completed normally + * with the value null + */ + public void testAllOf_empty() throws Exception { + CompletableFuture f = CompletableFuture.allOf(); + checkCompletedNormally(f, null); + } + + /** + * allOf returns a future completed normally with the value null + * when all components complete normally + */ + public void testAllOf_normal() throws Exception { + for (int k = 1; k < 10; k++) { + CompletableFuture[] fs + = (CompletableFuture[]) new CompletableFuture[k]; + for (int i = 0; i < k; i++) + fs[i] = new CompletableFuture<>(); + CompletableFuture f = CompletableFuture.allOf(fs); + for (int i = 0; i < k; i++) { + checkIncomplete(f); + checkIncomplete(CompletableFuture.allOf(fs)); + fs[i].complete(one); + } + checkCompletedNormally(f, null); + checkCompletedNormally(CompletableFuture.allOf(fs), null); + } + } + + public void testAllOf_backwards() throws Exception { + for (int k = 1; k < 10; k++) { + CompletableFuture[] fs + = (CompletableFuture[]) new CompletableFuture[k]; + for (int i = 0; i < k; i++) + fs[i] = new CompletableFuture<>(); + CompletableFuture f = CompletableFuture.allOf(fs); + for (int i = k - 1; i >= 0; i--) { + checkIncomplete(f); + checkIncomplete(CompletableFuture.allOf(fs)); + fs[i].complete(one); + } + checkCompletedNormally(f, null); + checkCompletedNormally(CompletableFuture.allOf(fs), null); + } + } + + public void testAllOf_exceptional() throws Exception { + for (int k = 1; k < 10; k++) { + CompletableFuture[] fs + = (CompletableFuture[]) new CompletableFuture[k]; + CFException ex = new CFException(); + for (int i = 0; i < k; i++) + fs[i] = new CompletableFuture<>(); + CompletableFuture f = CompletableFuture.allOf(fs); + for (int i = 0; i < k; i++) { + checkIncomplete(f); + checkIncomplete(CompletableFuture.allOf(fs)); + if (i != k / 2) { + fs[i].complete(i); + checkCompletedNormally(fs[i], i); + } else { + fs[i].completeExceptionally(ex); + checkCompletedExceptionally(fs[i], ex); + } + } + checkCompletedWithWrappedException(f, ex); + checkCompletedWithWrappedException(CompletableFuture.allOf(fs), ex); + } + } + + /** + * anyOf(no component futures) returns an incomplete future + */ + public void testAnyOf_empty() throws Exception { + for (Integer v1 : new Integer[] { 1, null }) + { + CompletableFuture f = CompletableFuture.anyOf(); + checkIncomplete(f); + + f.complete(v1); + checkCompletedNormally(f, v1); + }} + + /** + * anyOf returns a future completed normally with a value when + * a component future does + */ + public void testAnyOf_normal() throws Exception { + for (int k = 0; k < 10; k++) { + CompletableFuture[] fs = new CompletableFuture[k]; + for (int i = 0; i < k; i++) + fs[i] = new CompletableFuture<>(); + CompletableFuture f = CompletableFuture.anyOf(fs); + checkIncomplete(f); + for (int i = 0; i < k; i++) { + fs[i].complete(i); + checkCompletedNormally(f, 0); + int x = (int) CompletableFuture.anyOf(fs).join(); + assertTrue(0 <= x && x <= i); + } + } + } + public void testAnyOf_normal_backwards() throws Exception { + for (int k = 0; k < 10; k++) { + CompletableFuture[] fs = new CompletableFuture[k]; + for (int i = 0; i < k; i++) + fs[i] = new CompletableFuture<>(); + CompletableFuture f = CompletableFuture.anyOf(fs); + checkIncomplete(f); + for (int i = k - 1; i >= 0; i--) { + fs[i].complete(i); + checkCompletedNormally(f, k - 1); + int x = (int) CompletableFuture.anyOf(fs).join(); + assertTrue(i <= x && x <= k - 1); + } + } + } + + /** + * anyOf result completes exceptionally when any component does. + */ + public void testAnyOf_exceptional() throws Exception { + for (int k = 0; k < 10; k++) { + CompletableFuture[] fs = new CompletableFuture[k]; + CFException[] exs = new CFException[k]; + for (int i = 0; i < k; i++) { + fs[i] = new CompletableFuture<>(); + exs[i] = new CFException(); + } + CompletableFuture f = CompletableFuture.anyOf(fs); + checkIncomplete(f); + for (int i = 0; i < k; i++) { + fs[i].completeExceptionally(exs[i]); + checkCompletedWithWrappedException(f, exs[0]); + checkCompletedWithWrappedCFException(CompletableFuture.anyOf(fs)); + } + } + } + + public void testAnyOf_exceptional_backwards() throws Exception { + for (int k = 0; k < 10; k++) { + CompletableFuture[] fs = new CompletableFuture[k]; + CFException[] exs = new CFException[k]; + for (int i = 0; i < k; i++) { + fs[i] = new CompletableFuture<>(); + exs[i] = new CFException(); + } + CompletableFuture f = CompletableFuture.anyOf(fs); + checkIncomplete(f); + for (int i = k - 1; i >= 0; i--) { + fs[i].completeExceptionally(exs[i]); + checkCompletedWithWrappedException(f, exs[k - 1]); + checkCompletedWithWrappedCFException(CompletableFuture.anyOf(fs)); + } + } + } + + /** + * Completion methods throw NullPointerException with null arguments + */ + public void testNPE() { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture g = new CompletableFuture<>(); + CompletableFuture nullFuture = (CompletableFuture)null; + ThreadExecutor exec = new ThreadExecutor(); + + Runnable[] throwingActions = { + () -> CompletableFuture.supplyAsync(null), + () -> CompletableFuture.supplyAsync(null, exec), + () -> CompletableFuture.supplyAsync(new IntegerSupplier(ExecutionMode.SYNC, 42), null), + + () -> CompletableFuture.runAsync(null), + () -> CompletableFuture.runAsync(null, exec), + () -> CompletableFuture.runAsync(() -> {}, null), + + () -> f.completeExceptionally(null), + + () -> f.thenApply(null), + () -> f.thenApplyAsync(null), + () -> f.thenApplyAsync((x) -> x, null), + () -> f.thenApplyAsync(null, exec), + + () -> f.thenAccept(null), + () -> f.thenAcceptAsync(null), + () -> f.thenAcceptAsync((x) -> {} , null), + () -> f.thenAcceptAsync(null, exec), + + () -> f.thenRun(null), + () -> f.thenRunAsync(null), + () -> f.thenRunAsync(() -> {} , null), + () -> f.thenRunAsync(null, exec), + + () -> f.thenCombine(g, null), + () -> f.thenCombineAsync(g, null), + () -> f.thenCombineAsync(g, null, exec), + () -> f.thenCombine(nullFuture, (x, y) -> x), + () -> f.thenCombineAsync(nullFuture, (x, y) -> x), + () -> f.thenCombineAsync(nullFuture, (x, y) -> x, exec), + () -> f.thenCombineAsync(g, (x, y) -> x, null), + + () -> f.thenAcceptBoth(g, null), + () -> f.thenAcceptBothAsync(g, null), + () -> f.thenAcceptBothAsync(g, null, exec), + () -> f.thenAcceptBoth(nullFuture, (x, y) -> {}), + () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}), + () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}, exec), + () -> f.thenAcceptBothAsync(g, (x, y) -> {}, null), + + () -> f.runAfterBoth(g, null), + () -> f.runAfterBothAsync(g, null), + () -> f.runAfterBothAsync(g, null, exec), + () -> f.runAfterBoth(nullFuture, () -> {}), + () -> f.runAfterBothAsync(nullFuture, () -> {}), + () -> f.runAfterBothAsync(nullFuture, () -> {}, exec), + () -> f.runAfterBothAsync(g, () -> {}, null), + + () -> f.applyToEither(g, null), + () -> f.applyToEitherAsync(g, null), + () -> f.applyToEitherAsync(g, null, exec), + () -> f.applyToEither(nullFuture, (x) -> x), + () -> f.applyToEitherAsync(nullFuture, (x) -> x), + () -> f.applyToEitherAsync(nullFuture, (x) -> x, exec), + () -> f.applyToEitherAsync(g, (x) -> x, null), + + () -> f.acceptEither(g, null), + () -> f.acceptEitherAsync(g, null), + () -> f.acceptEitherAsync(g, null, exec), + () -> f.acceptEither(nullFuture, (x) -> {}), + () -> f.acceptEitherAsync(nullFuture, (x) -> {}), + () -> f.acceptEitherAsync(nullFuture, (x) -> {}, exec), + () -> f.acceptEitherAsync(g, (x) -> {}, null), + + () -> f.runAfterEither(g, null), + () -> f.runAfterEitherAsync(g, null), + () -> f.runAfterEitherAsync(g, null, exec), + () -> f.runAfterEither(nullFuture, () -> {}), + () -> f.runAfterEitherAsync(nullFuture, () -> {}), + () -> f.runAfterEitherAsync(nullFuture, () -> {}, exec), + () -> f.runAfterEitherAsync(g, () -> {}, null), + + () -> f.thenCompose(null), + () -> f.thenComposeAsync(null), + () -> f.thenComposeAsync(new CompletableFutureInc(ExecutionMode.EXECUTOR), null), + () -> f.thenComposeAsync(null, exec), + + () -> f.exceptionally(null), + + () -> f.handle(null), + + () -> CompletableFuture.allOf((CompletableFuture)null), + () -> CompletableFuture.allOf((CompletableFuture[])null), + () -> CompletableFuture.allOf(f, null), + () -> CompletableFuture.allOf(null, f), + + () -> CompletableFuture.anyOf((CompletableFuture)null), + () -> CompletableFuture.anyOf((CompletableFuture[])null), + () -> CompletableFuture.anyOf(f, null), + () -> CompletableFuture.anyOf(null, f), + + () -> f.obtrudeException(null), + + () -> CompletableFuture.delayedExecutor(1L, SECONDS, null), + () -> CompletableFuture.delayedExecutor(1L, null, new ThreadExecutor()), + () -> CompletableFuture.delayedExecutor(1L, null), + + () -> f.orTimeout(1L, null), + () -> f.completeOnTimeout(42, 1L, null), + + () -> CompletableFuture.failedFuture(null), + () -> CompletableFuture.failedStage(null), + }; + + assertThrows(NullPointerException.class, throwingActions); + assertEquals(0, exec.count.get()); + } + + /** + * toCompletableFuture returns this CompletableFuture. + */ + public void testToCompletableFuture() { + CompletableFuture f = new CompletableFuture<>(); + assertSame(f, f.toCompletableFuture()); + } + + // jdk9 + + /** + * newIncompleteFuture returns an incomplete CompletableFuture + */ + public void testNewIncompleteFuture() { + for (Integer v1 : new Integer[] { 1, null }) + { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture g = f.newIncompleteFuture(); + checkIncomplete(f); + checkIncomplete(g); + f.complete(v1); + checkCompletedNormally(f, v1); + checkIncomplete(g); + g.complete(v1); + checkCompletedNormally(g, v1); + assertSame(g.getClass(), CompletableFuture.class); + }} + + /** + * completedStage returns a completed CompletionStage + */ + public void testCompletedStage() { + AtomicInteger x = new AtomicInteger(0); + AtomicReference r = new AtomicReference(); + CompletionStage f = CompletableFuture.completedStage(1); + f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);}); + assertEquals(x.get(), 1); + assertNull(r.get()); + } + + /** + * defaultExecutor by default returns the commonPool if + * it supports more than one thread. + */ + public void testDefaultExecutor() { + CompletableFuture f = new CompletableFuture<>(); + Executor e = f.defaultExecutor(); + Executor c = ForkJoinPool.commonPool(); + if (ForkJoinPool.getCommonPoolParallelism() > 1) + assertSame(e, c); + else + assertNotSame(e, c); + } + + /** + * failedFuture returns a CompletableFuture completed + * exceptionally with the given Exception + */ + public void testFailedFuture() { + CFException ex = new CFException(); + CompletableFuture f = CompletableFuture.failedFuture(ex); + checkCompletedExceptionally(f, ex); + } + + /** + * failedFuture(null) throws NPE + */ + public void testFailedFuture_null() { + try { + CompletableFuture f = CompletableFuture.failedFuture(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * copy returns a CompletableFuture that is completed normally, + * with the same value, when source is. + */ + public void testCopy() { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture g = f.copy(); + checkIncomplete(f); + checkIncomplete(g); + f.complete(1); + checkCompletedNormally(f, 1); + checkCompletedNormally(g, 1); + } + + /** + * copy returns a CompletableFuture that is completed exceptionally + * when source is. + */ + public void testCopy2() { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture g = f.copy(); + checkIncomplete(f); + checkIncomplete(g); + CFException ex = new CFException(); + f.completeExceptionally(ex); + checkCompletedExceptionally(f, ex); + checkCompletedWithWrappedException(g, ex); + } + + /** + * minimalCompletionStage returns a CompletableFuture that is + * completed normally, with the same value, when source is. + */ + public void testMinimalCompletionStage() { + CompletableFuture f = new CompletableFuture<>(); + CompletionStage g = f.minimalCompletionStage(); + AtomicInteger x = new AtomicInteger(0); + AtomicReference r = new AtomicReference(); + checkIncomplete(f); + g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);}); + f.complete(1); + checkCompletedNormally(f, 1); + assertEquals(x.get(), 1); + assertNull(r.get()); + } + + /** + * minimalCompletionStage returns a CompletableFuture that is + * completed exceptionally when source is. + */ + public void testMinimalCompletionStage2() { + CompletableFuture f = new CompletableFuture<>(); + CompletionStage g = f.minimalCompletionStage(); + AtomicInteger x = new AtomicInteger(0); + AtomicReference r = new AtomicReference(); + g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);}); + checkIncomplete(f); + CFException ex = new CFException(); + f.completeExceptionally(ex); + checkCompletedExceptionally(f, ex); + assertEquals(x.get(), 0); + assertEquals(r.get().getCause(), ex); + } + + /** + * failedStage returns a CompletionStage completed + * exceptionally with the given Exception + */ + public void testFailedStage() { + CFException ex = new CFException(); + CompletionStage f = CompletableFuture.failedStage(ex); + AtomicInteger x = new AtomicInteger(0); + AtomicReference r = new AtomicReference(); + f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);}); + assertEquals(x.get(), 0); + assertEquals(r.get(), ex); + } + + /** + * completeAsync completes with value of given supplier + */ + public void testCompleteAsync() { + for (Integer v1 : new Integer[] { 1, null }) + { + CompletableFuture f = new CompletableFuture<>(); + f.completeAsync(() -> v1); + f.join(); + checkCompletedNormally(f, v1); + }} + + /** + * completeAsync completes exceptionally if given supplier throws + */ + public void testCompleteAsync2() { + CompletableFuture f = new CompletableFuture<>(); + CFException ex = new CFException(); + f.completeAsync(() -> {if (true) throw ex; return 1;}); + try { + f.join(); + shouldThrow(); + } catch (CompletionException success) {} + checkCompletedWithWrappedException(f, ex); + } + + /** + * completeAsync with given executor completes with value of given supplier + */ + public void testCompleteAsync3() { + for (Integer v1 : new Integer[] { 1, null }) + { + CompletableFuture f = new CompletableFuture<>(); + ThreadExecutor executor = new ThreadExecutor(); + f.completeAsync(() -> v1, executor); + assertSame(v1, f.join()); + checkCompletedNormally(f, v1); + assertEquals(1, executor.count.get()); + }} + + /** + * completeAsync with given executor completes exceptionally if + * given supplier throws + */ + public void testCompleteAsync4() { + CompletableFuture f = new CompletableFuture<>(); + CFException ex = new CFException(); + ThreadExecutor executor = new ThreadExecutor(); + f.completeAsync(() -> {if (true) throw ex; return 1;}, executor); + try { + f.join(); + shouldThrow(); + } catch (CompletionException success) {} + checkCompletedWithWrappedException(f, ex); + assertEquals(1, executor.count.get()); + } + + /** + * orTimeout completes with TimeoutException if not complete + */ + public void testOrTimeout_timesOut() { + long timeoutMillis = timeoutMillis(); + CompletableFuture f = new CompletableFuture<>(); + long startTime = System.nanoTime(); + f.orTimeout(timeoutMillis, MILLISECONDS); + checkCompletedWithTimeoutException(f); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + } + + /** + * orTimeout completes normally if completed before timeout + */ + public void testOrTimeout_completed() { + for (Integer v1 : new Integer[] { 1, null }) + { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture g = new CompletableFuture<>(); + long startTime = System.nanoTime(); + f.complete(v1); + f.orTimeout(LONG_DELAY_MS, MILLISECONDS); + g.orTimeout(LONG_DELAY_MS, MILLISECONDS); + g.complete(v1); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v1); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2); + }} + + /** + * completeOnTimeout completes with given value if not complete + */ + public void testCompleteOnTimeout_timesOut() { + testInParallel(() -> testCompleteOnTimeout_timesOut(42), + () -> testCompleteOnTimeout_timesOut(null)); + } + + public void testCompleteOnTimeout_timesOut(Integer v) { + long timeoutMillis = timeoutMillis(); + CompletableFuture f = new CompletableFuture<>(); + long startTime = System.nanoTime(); + f.completeOnTimeout(v, timeoutMillis, MILLISECONDS); + assertSame(v, f.join()); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + f.complete(99); // should have no effect + checkCompletedNormally(f, v); + } + + /** + * completeOnTimeout has no effect if completed within timeout + */ + public void testCompleteOnTimeout_completed() { + for (Integer v1 : new Integer[] { 1, null }) + { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture g = new CompletableFuture<>(); + long startTime = System.nanoTime(); + f.complete(v1); + f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS); + g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS); + g.complete(v1); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v1); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2); + }} + + /** + * delayedExecutor returns an executor that delays submission + */ + public void testDelayedExecutor() { + testInParallel(() -> testDelayedExecutor(null, null), + () -> testDelayedExecutor(null, 1), + () -> testDelayedExecutor(new ThreadExecutor(), 1), + () -> testDelayedExecutor(new ThreadExecutor(), 1)); + } + + public void testDelayedExecutor(Executor executor, Integer v) throws Exception { + long timeoutMillis = timeoutMillis(); + // Use an "unreasonably long" long timeout to catch lingering threads + long longTimeoutMillis = 1000 * 60 * 60 * 24; + final Executor delayer, longDelayer; + if (executor == null) { + delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS); + longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS); + } else { + delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS, executor); + longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS, executor); + } + long startTime = System.nanoTime(); + CompletableFuture f = + CompletableFuture.supplyAsync(() -> v, delayer); + CompletableFuture g = + CompletableFuture.supplyAsync(() -> v, longDelayer); + + assertNull(g.getNow(null)); + + assertSame(v, f.get(LONG_DELAY_MS, MILLISECONDS)); + long millisElapsed = millisElapsedSince(startTime); + assertTrue(millisElapsed >= timeoutMillis); + assertTrue(millisElapsed < LONG_DELAY_MS / 2); + + checkCompletedNormally(f, v); + + checkIncomplete(g); + assertTrue(g.cancel(true)); + } + + //--- tests of implementation details; not part of official tck --- + + Object resultOf(CompletableFuture f) { + try { + java.lang.reflect.Field resultField + = CompletableFuture.class.getDeclaredField("result"); + resultField.setAccessible(true); + return resultField.get(f); + } catch (Throwable t) { throw new AssertionError(t); } + } + + public void testExceptionPropagationReusesResultObject() { + if (!testImplementationDetails) return; + for (ExecutionMode m : ExecutionMode.values()) + { + final CFException ex = new CFException(); + final CompletableFuture v42 = CompletableFuture.completedFuture(42); + final CompletableFuture incomplete = new CompletableFuture<>(); + + List, CompletableFuture>> funs + = new ArrayList<>(); + + funs.add((y) -> m.thenRun(y, new Noop(m))); + funs.add((y) -> m.thenAccept(y, new NoopConsumer(m))); + funs.add((y) -> m.thenApply(y, new IncFunction(m))); + + funs.add((y) -> m.runAfterEither(y, incomplete, new Noop(m))); + funs.add((y) -> m.acceptEither(y, incomplete, new NoopConsumer(m))); + funs.add((y) -> m.applyToEither(y, incomplete, new IncFunction(m))); + + funs.add((y) -> m.runAfterBoth(y, v42, new Noop(m))); + funs.add((y) -> m.thenAcceptBoth(y, v42, new SubtractAction(m))); + funs.add((y) -> m.thenCombine(y, v42, new SubtractFunction(m))); + + funs.add((y) -> m.whenComplete(y, (Integer r, Throwable t) -> {})); + + funs.add((y) -> m.thenCompose(y, new CompletableFutureInc(m))); + + funs.add((y) -> CompletableFuture.allOf(new CompletableFuture[] {y, v42})); + funs.add((y) -> CompletableFuture.anyOf(new CompletableFuture[] {y, incomplete})); + + for (Function, CompletableFuture> + fun : funs) { + CompletableFuture f = new CompletableFuture<>(); + f.completeExceptionally(ex); + CompletableFuture src = m.thenApply(f, new IncFunction(m)); + checkCompletedWithWrappedException(src, ex); + CompletableFuture dep = fun.apply(src); + checkCompletedWithWrappedException(dep, ex); + assertSame(resultOf(src), resultOf(dep)); + } + + for (Function, CompletableFuture> + fun : funs) { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture src = m.thenApply(f, new IncFunction(m)); + CompletableFuture dep = fun.apply(src); + f.completeExceptionally(ex); + checkCompletedWithWrappedException(src, ex); + checkCompletedWithWrappedException(dep, ex); + assertSame(resultOf(src), resultOf(dep)); + } + + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (Function, CompletableFuture> + fun : funs) { + CompletableFuture f = new CompletableFuture<>(); + f.cancel(mayInterruptIfRunning); + checkCancelled(f); + CompletableFuture src = m.thenApply(f, new IncFunction(m)); + checkCompletedWithWrappedCancellationException(src); + CompletableFuture dep = fun.apply(src); + checkCompletedWithWrappedCancellationException(dep); + assertSame(resultOf(src), resultOf(dep)); + } + + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (Function, CompletableFuture> + fun : funs) { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture src = m.thenApply(f, new IncFunction(m)); + CompletableFuture dep = fun.apply(src); + f.cancel(mayInterruptIfRunning); + checkCancelled(f); + checkCompletedWithWrappedCancellationException(src); + checkCompletedWithWrappedCancellationException(dep); + assertSame(resultOf(src), resultOf(dep)); + } + }} + + /** + * Minimal completion stages throw UOE for all non-CompletionStage methods + */ + public void testMinimalCompletionStage_minimality() { + if (!testImplementationDetails) return; + Function toSignature = + (method) -> method.getName() + Arrays.toString(method.getParameterTypes()); + Predicate isNotStatic = + (method) -> (method.getModifiers() & Modifier.STATIC) == 0; + List minimalMethods = + Stream.of(Object.class, CompletionStage.class) + .flatMap((klazz) -> Stream.of(klazz.getMethods())) + .filter(isNotStatic) + .collect(Collectors.toList()); + // Methods from CompletableFuture permitted NOT to throw UOE + String[] signatureWhitelist = { + "newIncompleteFuture[]", + "defaultExecutor[]", + "minimalCompletionStage[]", + "copy[]", + }; + Set permittedMethodSignatures = + Stream.concat(minimalMethods.stream().map(toSignature), + Stream.of(signatureWhitelist)) + .collect(Collectors.toSet()); + List allMethods = Stream.of(CompletableFuture.class.getMethods()) + .filter(isNotStatic) + .filter((method) -> !permittedMethodSignatures.contains(toSignature.apply(method))) + .collect(Collectors.toList()); + + CompletionStage minimalStage = + new CompletableFuture().minimalCompletionStage(); + + List bugs = new ArrayList<>(); + for (Method method : allMethods) { + Class[] parameterTypes = method.getParameterTypes(); + Object[] args = new Object[parameterTypes.length]; + // Manufacture boxed primitives for primitive params + for (int i = 0; i < args.length; i++) { + Class type = parameterTypes[i]; + if (parameterTypes[i] == boolean.class) + args[i] = false; + else if (parameterTypes[i] == int.class) + args[i] = 0; + else if (parameterTypes[i] == long.class) + args[i] = 0L; + } + try { + method.invoke(minimalStage, args); + bugs.add(method); + } + catch (java.lang.reflect.InvocationTargetException expected) { + if (! (expected.getCause() instanceof UnsupportedOperationException)) { + bugs.add(method); + // expected.getCause().printStackTrace(); + } + } + catch (ReflectiveOperationException bad) { throw new Error(bad); } + } + if (!bugs.isEmpty()) + throw new Error("Methods did not throw UOE: " + bugs.toString()); + } + + static class Monad { + static class ZeroException extends RuntimeException { + public ZeroException() { super("monadic zero"); } + } + // "return", "unit" + static CompletableFuture unit(T value) { + return completedFuture(value); + } + // monadic zero ? + static CompletableFuture zero() { + return failedFuture(new ZeroException()); + } + // >=> + static Function> compose + (Function> f, + Function> g) { + return (x) -> f.apply(x).thenCompose(g); + } + + static void assertZero(CompletableFuture f) { + try { + f.getNow(null); + throw new AssertionFailedError("should throw"); + } catch (CompletionException success) { + assertTrue(success.getCause() instanceof ZeroException); + } + } + + static void assertFutureEquals(CompletableFuture f, + CompletableFuture g) { + T fval = null, gval = null; + Throwable fex = null, gex = null; + + try { fval = f.get(); } + catch (ExecutionException ex) { fex = ex.getCause(); } + catch (Throwable ex) { fex = ex; } + + try { gval = g.get(); } + catch (ExecutionException ex) { gex = ex.getCause(); } + catch (Throwable ex) { gex = ex; } + + if (fex != null || gex != null) + assertSame(fex.getClass(), gex.getClass()); + else + assertEquals(fval, gval); + } + + static class PlusFuture extends CompletableFuture { + AtomicReference firstFailure = new AtomicReference<>(null); + } + + /** Implements "monadic plus". */ + static CompletableFuture plus(CompletableFuture f, + CompletableFuture g) { + PlusFuture plus = new PlusFuture(); + BiConsumer action = (T result, Throwable ex) -> { + try { + if (ex == null) { + if (plus.complete(result)) + if (plus.firstFailure.get() != null) + plus.firstFailure.set(null); + } + else if (plus.firstFailure.compareAndSet(null, ex)) { + if (plus.isDone()) + plus.firstFailure.set(null); + } + else { + // first failure has precedence + Throwable first = plus.firstFailure.getAndSet(null); + + // may fail with "Self-suppression not permitted" + try { first.addSuppressed(ex); } + catch (Exception ignored) {} + + plus.completeExceptionally(first); + } + } catch (Throwable unexpected) { + plus.completeExceptionally(unexpected); + } + }; + f.whenComplete(action); + g.whenComplete(action); + return plus; + } + } + + /** + * CompletableFuture is an additive monad - sort of. + * https://en.wikipedia.org/wiki/Monad_(functional_programming)#Additive_monads + */ + public void testAdditiveMonad() throws Throwable { + Function> unit = Monad::unit; + CompletableFuture zero = Monad.zero(); + + // Some mutually non-commutative functions + Function> triple + = (x) -> Monad.unit(3 * x); + Function> inc + = (x) -> Monad.unit(x + 1); + + // unit is a right identity: m >>= unit === m + Monad.assertFutureEquals(inc.apply(5L).thenCompose(unit), + inc.apply(5L)); + // unit is a left identity: (unit x) >>= f === f x + Monad.assertFutureEquals(unit.apply(5L).thenCompose(inc), + inc.apply(5L)); + + // associativity: (m >>= f) >>= g === m >>= ( \x -> (f x >>= g) ) + Monad.assertFutureEquals( + unit.apply(5L).thenCompose(inc).thenCompose(triple), + unit.apply(5L).thenCompose((x) -> inc.apply(x).thenCompose(triple))); + + // The case for CompletableFuture as an additive monad is weaker... + + // zero is a monadic zero + Monad.assertZero(zero); + + // left zero: zero >>= f === zero + Monad.assertZero(zero.thenCompose(inc)); + // right zero: f >>= (\x -> zero) === zero + Monad.assertZero(inc.apply(5L).thenCompose((x) -> zero)); + + // f plus zero === f + Monad.assertFutureEquals(Monad.unit(5L), + Monad.plus(Monad.unit(5L), zero)); + // zero plus f === f + Monad.assertFutureEquals(Monad.unit(5L), + Monad.plus(zero, Monad.unit(5L))); + // zero plus zero === zero + Monad.assertZero(Monad.plus(zero, zero)); + { + CompletableFuture f = Monad.plus(Monad.unit(5L), + Monad.unit(8L)); + // non-determinism + assertTrue(f.get() == 5L || f.get() == 8L); + } + + CompletableFuture godot = new CompletableFuture<>(); + // f plus godot === f (doesn't wait for godot) + Monad.assertFutureEquals(Monad.unit(5L), + Monad.plus(Monad.unit(5L), godot)); + // godot plus f === f (doesn't wait for godot) + Monad.assertFutureEquals(Monad.unit(5L), + Monad.plus(godot, Monad.unit(5L))); + } + +// static U join(CompletionStage stage) { +// CompletableFuture f = new CompletableFuture<>(); +// stage.whenComplete((v, ex) -> { +// if (ex != null) f.completeExceptionally(ex); else f.complete(v); +// }); +// return f.join(); +// } + +// static boolean isDone(CompletionStage stage) { +// CompletableFuture f = new CompletableFuture<>(); +// stage.whenComplete((v, ex) -> { +// if (ex != null) f.completeExceptionally(ex); else f.complete(v); +// }); +// return f.isDone(); +// } + +// static U join2(CompletionStage stage) { +// return stage.toCompletableFuture().copy().join(); +// } + +// static boolean isDone2(CompletionStage stage) { +// return stage.toCompletableFuture().copy().isDone(); +// } + +} diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java new file mode 100644 index 00000000000..518fab33170 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java @@ -0,0 +1,1118 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.Spliterator.CONCURRENT; +import static java.util.Spliterator.DISTINCT; +import static java.util.Spliterator.NONNULL; + +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.Spliterator; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.LongAdder; +import java.util.function.BiFunction; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ConcurrentHashMap8Test extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ConcurrentHashMap8Test.class); + } + + /** + * Returns a new map from Integers 1-5 to Strings "A"-"E". + */ + private static ConcurrentHashMap map5() { + ConcurrentHashMap map = new ConcurrentHashMap(5); + assertTrue(map.isEmpty()); + map.put(one, "A"); + map.put(two, "B"); + map.put(three, "C"); + map.put(four, "D"); + map.put(five, "E"); + assertFalse(map.isEmpty()); + assertEquals(5, map.size()); + return map; + } + + /** + * getOrDefault returns value if present, else default + */ + public void testGetOrDefault() { + ConcurrentHashMap map = map5(); + assertEquals(map.getOrDefault(one, "Z"), "A"); + assertEquals(map.getOrDefault(six, "Z"), "Z"); + } + + /** + * computeIfAbsent adds when the given key is not present + */ + public void testComputeIfAbsent() { + ConcurrentHashMap map = map5(); + map.computeIfAbsent(six, (x) -> "Z"); + assertTrue(map.containsKey(six)); + } + + /** + * computeIfAbsent does not replace if the key is already present + */ + public void testComputeIfAbsent2() { + ConcurrentHashMap map = map5(); + assertEquals("A", map.computeIfAbsent(one, (x) -> "Z")); + } + + /** + * computeIfAbsent does not add if function returns null + */ + public void testComputeIfAbsent3() { + ConcurrentHashMap map = map5(); + map.computeIfAbsent(six, (x) -> null); + assertFalse(map.containsKey(six)); + } + + /** + * computeIfPresent does not replace if the key is already present + */ + public void testComputeIfPresent() { + ConcurrentHashMap map = map5(); + map.computeIfPresent(six, (x, y) -> "Z"); + assertFalse(map.containsKey(six)); + } + + /** + * computeIfPresent adds when the given key is not present + */ + public void testComputeIfPresent2() { + ConcurrentHashMap map = map5(); + assertEquals("Z", map.computeIfPresent(one, (x, y) -> "Z")); + } + + /** + * compute does not replace if the function returns null + */ + public void testCompute() { + ConcurrentHashMap map = map5(); + map.compute(six, (x, y) -> null); + assertFalse(map.containsKey(six)); + } + + /** + * compute adds when the given key is not present + */ + public void testCompute2() { + ConcurrentHashMap map = map5(); + assertEquals("Z", map.compute(six, (x, y) -> "Z")); + } + + /** + * compute replaces when the given key is present + */ + public void testCompute3() { + ConcurrentHashMap map = map5(); + assertEquals("Z", map.compute(one, (x, y) -> "Z")); + } + + /** + * compute removes when the given key is present and function returns null + */ + public void testCompute4() { + ConcurrentHashMap map = map5(); + map.compute(one, (x, y) -> null); + assertFalse(map.containsKey(one)); + } + + /** + * merge adds when the given key is not present + */ + public void testMerge1() { + ConcurrentHashMap map = map5(); + assertEquals("Y", map.merge(six, "Y", (x, y) -> "Z")); + } + + /** + * merge replaces when the given key is present + */ + public void testMerge2() { + ConcurrentHashMap map = map5(); + assertEquals("Z", map.merge(one, "Y", (x, y) -> "Z")); + } + + /** + * merge removes when the given key is present and function returns null + */ + public void testMerge3() { + ConcurrentHashMap map = map5(); + map.merge(one, "Y", (x, y) -> null); + assertFalse(map.containsKey(one)); + } + + static Set populatedSet(int n) { + Set a = ConcurrentHashMap.newKeySet(); + assertTrue(a.isEmpty()); + for (int i = 0; i < n; i++) + assertTrue(a.add(i)); + assertEquals(n == 0, a.isEmpty()); + assertEquals(n, a.size()); + return a; + } + + static Set populatedSet(Integer[] elements) { + Set a = ConcurrentHashMap.newKeySet(); + assertTrue(a.isEmpty()); + for (int i = 0; i < elements.length; i++) + assertTrue(a.add(elements[i])); + assertFalse(a.isEmpty()); + assertEquals(elements.length, a.size()); + return a; + } + + /** + * replaceAll replaces all matching values. + */ + public void testReplaceAll() { + ConcurrentHashMap map = map5(); + map.replaceAll((x, y) -> { return x > 3 ? "Z" : y; }); + assertEquals("A", map.get(one)); + assertEquals("B", map.get(two)); + assertEquals("C", map.get(three)); + assertEquals("Z", map.get(four)); + assertEquals("Z", map.get(five)); + } + + /** + * Default-constructed set is empty + */ + public void testNewKeySet() { + Set a = ConcurrentHashMap.newKeySet(); + assertTrue(a.isEmpty()); + } + + /** + * keySet.add adds the key with the established value to the map; + * remove removes it. + */ + public void testKeySetAddRemove() { + ConcurrentHashMap map = map5(); + Set set1 = map.keySet(); + Set set2 = map.keySet(true); + set2.add(six); + assertTrue(((ConcurrentHashMap.KeySetView)set2).getMap() == map); + assertTrue(((ConcurrentHashMap.KeySetView)set1).getMap() == map); + assertEquals(set2.size(), map.size()); + assertEquals(set1.size(), map.size()); + assertTrue((Boolean)map.get(six)); + assertTrue(set1.contains(six)); + assertTrue(set2.contains(six)); + set2.remove(six); + assertNull(map.get(six)); + assertFalse(set1.contains(six)); + assertFalse(set2.contains(six)); + } + + /** + * keySet.addAll adds each element from the given collection + */ + public void testAddAll() { + Set full = populatedSet(3); + assertTrue(full.addAll(Arrays.asList(three, four, five))); + assertEquals(6, full.size()); + assertFalse(full.addAll(Arrays.asList(three, four, five))); + assertEquals(6, full.size()); + } + + /** + * keySet.addAll adds each element from the given collection that did not + * already exist in the set + */ + public void testAddAll2() { + Set full = populatedSet(3); + // "one" is duplicate and will not be added + assertTrue(full.addAll(Arrays.asList(three, four, one))); + assertEquals(5, full.size()); + assertFalse(full.addAll(Arrays.asList(three, four, one))); + assertEquals(5, full.size()); + } + + /** + * keySet.add will not add the element if it already exists in the set + */ + public void testAdd2() { + Set full = populatedSet(3); + assertFalse(full.add(one)); + assertEquals(3, full.size()); + } + + /** + * keySet.add adds the element when it does not exist in the set + */ + public void testAdd3() { + Set full = populatedSet(3); + assertTrue(full.add(three)); + assertTrue(full.contains(three)); + assertFalse(full.add(three)); + assertTrue(full.contains(three)); + } + + /** + * keySet.add throws UnsupportedOperationException if no default + * mapped value + */ + public void testAdd4() { + Set full = map5().keySet(); + try { + full.add(three); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + } + + /** + * keySet.add throws NullPointerException if the specified key is + * null + */ + public void testAdd5() { + Set full = populatedSet(3); + try { + full.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * KeySetView.getMappedValue returns the map's mapped value + */ + public void testGetMappedValue() { + ConcurrentHashMap map = map5(); + assertNull(map.keySet().getMappedValue()); + try { + map.keySet(null); + shouldThrow(); + } catch (NullPointerException success) {} + ConcurrentHashMap.KeySetView set = map.keySet(one); + assertFalse(set.add(one)); + assertTrue(set.add(six)); + assertTrue(set.add(seven)); + assertTrue(set.getMappedValue() == one); + assertTrue(map.get(one) != one); + assertTrue(map.get(six) == one); + assertTrue(map.get(seven) == one); + } + + void checkSpliteratorCharacteristics(Spliterator sp, + int requiredCharacteristics) { + assertEquals(requiredCharacteristics, + requiredCharacteristics & sp.characteristics()); + } + + /** + * KeySetView.spliterator returns spliterator over the elements in this set + */ + public void testKeySetSpliterator() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap map = map5(); + Set set = map.keySet(); + Spliterator sp = set.spliterator(); + checkSpliteratorCharacteristics(sp, CONCURRENT | DISTINCT | NONNULL); + assertEquals(sp.estimateSize(), map.size()); + Spliterator sp2 = sp.trySplit(); + sp.forEachRemaining((Integer x) -> adder.add(x.longValue())); + long v = adder.sumThenReset(); + sp2.forEachRemaining((Integer x) -> adder.add(x.longValue())); + long v2 = adder.sum(); + assertEquals(v + v2, 15); + } + + /** + * keyset.clear removes all elements from the set + */ + public void testClear() { + Set full = populatedSet(3); + full.clear(); + assertEquals(0, full.size()); + } + + /** + * keyset.contains returns true for added elements + */ + public void testContains() { + Set full = populatedSet(3); + assertTrue(full.contains(one)); + assertFalse(full.contains(five)); + } + + /** + * KeySets with equal elements are equal + */ + public void testEquals() { + Set a = populatedSet(3); + Set b = populatedSet(3); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + assertEquals(a.hashCode(), b.hashCode()); + a.add(m1); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + b.add(m1); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + assertEquals(a.hashCode(), b.hashCode()); + } + + /** + * KeySet.containsAll returns true for collections with subset of elements + */ + public void testContainsAll() { + Collection full = populatedSet(3); + assertTrue(full.containsAll(Arrays.asList())); + assertTrue(full.containsAll(Arrays.asList(one))); + assertTrue(full.containsAll(Arrays.asList(one, two))); + assertFalse(full.containsAll(Arrays.asList(one, two, six))); + assertFalse(full.containsAll(Arrays.asList(six))); + } + + /** + * KeySet.isEmpty is true when empty, else false + */ + public void testIsEmpty() { + assertTrue(populatedSet(0).isEmpty()); + assertFalse(populatedSet(3).isEmpty()); + } + + /** + * KeySet.iterator() returns an iterator containing the elements of the + * set + */ + public void testIterator() { + Collection empty = ConcurrentHashMap.newKeySet(); + int size = 20; + assertFalse(empty.iterator().hasNext()); + try { + empty.iterator().next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + + Integer[] elements = new Integer[size]; + for (int i = 0; i < size; i++) + elements[i] = i; + Collections.shuffle(Arrays.asList(elements)); + Collection full = populatedSet(elements); + + Iterator it = full.iterator(); + for (int j = 0; j < size; j++) { + assertTrue(it.hasNext()); + it.next(); + } + assertIteratorExhausted(it); + } + + /** + * iterator of empty collections has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(ConcurrentHashMap.newKeySet().iterator()); + assertIteratorExhausted(new ConcurrentHashMap().entrySet().iterator()); + assertIteratorExhausted(new ConcurrentHashMap().values().iterator()); + assertIteratorExhausted(new ConcurrentHashMap().keySet().iterator()); + } + + /** + * KeySet.iterator.remove removes current element + */ + public void testIteratorRemove() { + Set q = populatedSet(3); + Iterator it = q.iterator(); + Object removed = it.next(); + it.remove(); + + it = q.iterator(); + assertFalse(it.next().equals(removed)); + assertFalse(it.next().equals(removed)); + assertFalse(it.hasNext()); + } + + /** + * KeySet.toString holds toString of elements + */ + public void testToString() { + assertEquals("[]", ConcurrentHashMap.newKeySet().toString()); + Set full = populatedSet(3); + String s = full.toString(); + for (int i = 0; i < 3; ++i) + assertTrue(s.contains(String.valueOf(i))); + } + + /** + * KeySet.removeAll removes all elements from the given collection + */ + public void testRemoveAll() { + Set full = populatedSet(3); + assertTrue(full.removeAll(Arrays.asList(one, two))); + assertEquals(1, full.size()); + assertFalse(full.removeAll(Arrays.asList(one, two))); + assertEquals(1, full.size()); + } + + /** + * KeySet.remove removes an element + */ + public void testRemove() { + Set full = populatedSet(3); + full.remove(one); + assertFalse(full.contains(one)); + assertEquals(2, full.size()); + } + + /** + * keySet.size returns the number of elements + */ + public void testSize() { + Set empty = ConcurrentHashMap.newKeySet(); + Set full = populatedSet(3); + assertEquals(3, full.size()); + assertEquals(0, empty.size()); + } + + /** + * KeySet.toArray() returns an Object array containing all elements from + * the set + */ + public void testToArray() { + Object[] a = ConcurrentHashMap.newKeySet().toArray(); + assertTrue(Arrays.equals(new Object[0], a)); + assertSame(Object[].class, a.getClass()); + int size = 20; + Integer[] elements = new Integer[size]; + for (int i = 0; i < size; i++) + elements[i] = i; + Collections.shuffle(Arrays.asList(elements)); + Collection full = populatedSet(elements); + + assertTrue(Arrays.asList(elements).containsAll(Arrays.asList(full.toArray()))); + assertTrue(full.containsAll(Arrays.asList(full.toArray()))); + assertSame(Object[].class, full.toArray().getClass()); + } + + /** + * toArray(Integer array) returns an Integer array containing all + * elements from the set + */ + public void testToArray2() { + Collection empty = ConcurrentHashMap.newKeySet(); + Integer[] a; + int size = 20; + + a = new Integer[0]; + assertSame(a, empty.toArray(a)); + + a = new Integer[size / 2]; + Arrays.fill(a, 42); + assertSame(a, empty.toArray(a)); + assertNull(a[0]); + for (int i = 1; i < a.length; i++) + assertEquals(42, (int) a[i]); + + Integer[] elements = new Integer[size]; + for (int i = 0; i < size; i++) + elements[i] = i; + Collections.shuffle(Arrays.asList(elements)); + Collection full = populatedSet(elements); + + Arrays.fill(a, 42); + assertTrue(Arrays.asList(elements).containsAll(Arrays.asList(full.toArray(a)))); + for (int i = 0; i < a.length; i++) + assertEquals(42, (int) a[i]); + assertSame(Integer[].class, full.toArray(a).getClass()); + + a = new Integer[size]; + Arrays.fill(a, 42); + assertSame(a, full.toArray(a)); + assertTrue(Arrays.asList(elements).containsAll(Arrays.asList(full.toArray(a)))); + } + + /** + * A deserialized serialized set is equal + */ + public void testSerialization() throws Exception { + int size = 20; + Set x = populatedSet(size); + Set y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x, y); + assertEquals(y, x); + } + + static final int SIZE = 10000; + static ConcurrentHashMap longMap; + + static ConcurrentHashMap longMap() { + if (longMap == null) { + longMap = new ConcurrentHashMap(SIZE); + for (int i = 0; i < SIZE; ++i) + longMap.put(Long.valueOf(i), Long.valueOf(2 *i)); + } + return longMap; + } + + // explicit function class to avoid type inference problems + static class AddKeys implements BiFunction, Map.Entry, Map.Entry> { + public Map.Entry apply(Map.Entry x, Map.Entry y) { + return new AbstractMap.SimpleEntry + (Long.valueOf(x.getKey().longValue() + y.getKey().longValue()), + Long.valueOf(1L)); + } + } + + /** + * forEachKeySequentially traverses all keys + */ + public void testForEachKeySequentially() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachKey(Long.MAX_VALUE, (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), SIZE * (SIZE - 1) / 2); + } + + /** + * forEachValueSequentially traverses all values + */ + public void testForEachValueSequentially() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachValue(Long.MAX_VALUE, (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), SIZE * (SIZE - 1)); + } + + /** + * forEachSequentially traverses all mappings + */ + public void testForEachSequentially() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEach(Long.MAX_VALUE, (Long x, Long y) -> adder.add(x.longValue() + y.longValue())); + assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); + } + + /** + * forEachEntrySequentially traverses all entries + */ + public void testForEachEntrySequentially() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachEntry(Long.MAX_VALUE, (Map.Entry e) -> adder.add(e.getKey().longValue() + e.getValue().longValue())); + assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); + } + + /** + * forEachKeyInParallel traverses all keys + */ + public void testForEachKeyInParallel() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachKey(1L, (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), SIZE * (SIZE - 1) / 2); + } + + /** + * forEachValueInParallel traverses all values + */ + public void testForEachValueInParallel() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachValue(1L, (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), SIZE * (SIZE - 1)); + } + + /** + * forEachInParallel traverses all mappings + */ + public void testForEachInParallel() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEach(1L, (Long x, Long y) -> adder.add(x.longValue() + y.longValue())); + assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); + } + + /** + * forEachEntryInParallel traverses all entries + */ + public void testForEachEntryInParallel() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachEntry(1L, (Map.Entry e) -> adder.add(e.getKey().longValue() + e.getValue().longValue())); + assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped forEachKeySequentially traverses the given + * transformations of all keys + */ + public void testMappedForEachKeySequentially() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachKey(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()), + (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped forEachValueSequentially traverses the given + * transformations of all values + */ + public void testMappedForEachValueSequentially() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachValue(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()), + (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1)); + } + + /** + * Mapped forEachSequentially traverses the given + * transformations of all mappings + */ + public void testMappedForEachSequentially() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEach(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()), + (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped forEachEntrySequentially traverses the given + * transformations of all entries + */ + public void testMappedForEachEntrySequentially() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachEntry(Long.MAX_VALUE, (Map.Entry e) -> Long.valueOf(e.getKey().longValue() + e.getValue().longValue()), + (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped forEachKeyInParallel traverses the given + * transformations of all keys + */ + public void testMappedForEachKeyInParallel() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachKey(1L, (Long x) -> Long.valueOf(4 * x.longValue()), + (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped forEachValueInParallel traverses the given + * transformations of all values + */ + public void testMappedForEachValueInParallel() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachValue(1L, (Long x) -> Long.valueOf(4 * x.longValue()), + (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), 4 * SIZE * (SIZE - 1)); + } + + /** + * Mapped forEachInParallel traverses the given + * transformations of all mappings + */ + public void testMappedForEachInParallel() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEach(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()), + (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped forEachEntryInParallel traverses the given + * transformations of all entries + */ + public void testMappedForEachEntryInParallel() { + LongAdder adder = new LongAdder(); + ConcurrentHashMap m = longMap(); + m.forEachEntry(1L, (Map.Entry e) -> Long.valueOf(e.getKey().longValue() + e.getValue().longValue()), + (Long x) -> adder.add(x.longValue())); + assertEquals(adder.sum(), 3 * SIZE * (SIZE - 1) / 2); + } + + /** + * reduceKeysSequentially accumulates across all keys, + */ + public void testReduceKeysSequentially() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.reduceKeys(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + assertEquals((long)r, (long)SIZE * (SIZE - 1) / 2); + } + + /** + * reduceValuesSequentially accumulates across all values + */ + public void testReduceValuesSequentially() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.reduceKeys(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + assertEquals((long)r, (long)SIZE * (SIZE - 1) / 2); + } + + /** + * reduceEntriesSequentially accumulates across all entries + */ + public void testReduceEntriesSequentially() { + ConcurrentHashMap m = longMap(); + Map.Entry r; + r = m.reduceEntries(Long.MAX_VALUE, new AddKeys()); + assertEquals(r.getKey().longValue(), (long)SIZE * (SIZE - 1) / 2); + } + + /** + * reduceKeysInParallel accumulates across all keys + */ + public void testReduceKeysInParallel() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.reduceKeys(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + assertEquals((long)r, (long)SIZE * (SIZE - 1) / 2); + } + + /** + * reduceValuesInParallel accumulates across all values + */ + public void testReduceValuesInParallel() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.reduceValues(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + assertEquals((long)r, (long)SIZE * (SIZE - 1)); + } + + /** + * reduceEntriesInParallel accumulate across all entries + */ + public void testReduceEntriesInParallel() { + ConcurrentHashMap m = longMap(); + Map.Entry r; + r = m.reduceEntries(1L, new AddKeys()); + assertEquals(r.getKey().longValue(), (long)SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped reduceKeysSequentially accumulates mapped keys + */ + public void testMapReduceKeysSequentially() { + ConcurrentHashMap m = longMap(); + Long r = m.reduceKeys(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()), + (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + assertEquals((long)r, (long)4 * SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped reduceValuesSequentially accumulates mapped values + */ + public void testMapReduceValuesSequentially() { + ConcurrentHashMap m = longMap(); + Long r = m.reduceValues(Long.MAX_VALUE, (Long x) -> Long.valueOf(4 * x.longValue()), + (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + assertEquals((long)r, (long)4 * SIZE * (SIZE - 1)); + } + + /** + * reduceSequentially accumulates across all transformed mappings + */ + public void testMappedReduceSequentially() { + ConcurrentHashMap m = longMap(); + Long r = m.reduce(Long.MAX_VALUE, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()), + (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + + assertEquals((long)r, (long)3 * SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped reduceKeysInParallel, accumulates mapped keys + */ + public void testMapReduceKeysInParallel() { + ConcurrentHashMap m = longMap(); + Long r = m.reduceKeys(1L, (Long x) -> Long.valueOf(4 * x.longValue()), + (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + assertEquals((long)r, (long)4 * SIZE * (SIZE - 1) / 2); + } + + /** + * Mapped reduceValuesInParallel accumulates mapped values + */ + public void testMapReduceValuesInParallel() { + ConcurrentHashMap m = longMap(); + Long r = m.reduceValues(1L, (Long x) -> Long.valueOf(4 * x.longValue()), + (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + assertEquals((long)r, (long)4 * SIZE * (SIZE - 1)); + } + + /** + * reduceInParallel accumulate across all transformed mappings + */ + public void testMappedReduceInParallel() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.reduce(1L, (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue()), + (Long x, Long y) -> Long.valueOf(x.longValue() + y.longValue())); + assertEquals((long)r, (long)3 * SIZE * (SIZE - 1) / 2); + } + + /** + * reduceKeysToLongSequentially accumulates mapped keys + */ + public void testReduceKeysToLongSequentially() { + ConcurrentHashMap m = longMap(); + long lr = m.reduceKeysToLong(Long.MAX_VALUE, (Long x) -> x.longValue(), 0L, Long::sum); + assertEquals(lr, (long)SIZE * (SIZE - 1) / 2); + } + + /** + * reduceKeysToIntSequentially accumulates mapped keys + */ + public void testReduceKeysToIntSequentially() { + ConcurrentHashMap m = longMap(); + int ir = m.reduceKeysToInt(Long.MAX_VALUE, (Long x) -> x.intValue(), 0, Integer::sum); + assertEquals(ir, SIZE * (SIZE - 1) / 2); + } + + /** + * reduceKeysToDoubleSequentially accumulates mapped keys + */ + public void testReduceKeysToDoubleSequentially() { + ConcurrentHashMap m = longMap(); + double dr = m.reduceKeysToDouble(Long.MAX_VALUE, (Long x) -> x.doubleValue(), 0.0, Double::sum); + assertEquals(dr, (double)SIZE * (SIZE - 1) / 2); + } + + /** + * reduceValuesToLongSequentially accumulates mapped values + */ + public void testReduceValuesToLongSequentially() { + ConcurrentHashMap m = longMap(); + long lr = m.reduceValuesToLong(Long.MAX_VALUE, (Long x) -> x.longValue(), 0L, Long::sum); + assertEquals(lr, (long)SIZE * (SIZE - 1)); + } + + /** + * reduceValuesToIntSequentially accumulates mapped values + */ + public void testReduceValuesToIntSequentially() { + ConcurrentHashMap m = longMap(); + int ir = m.reduceValuesToInt(Long.MAX_VALUE, (Long x) -> x.intValue(), 0, Integer::sum); + assertEquals(ir, SIZE * (SIZE - 1)); + } + + /** + * reduceValuesToDoubleSequentially accumulates mapped values + */ + public void testReduceValuesToDoubleSequentially() { + ConcurrentHashMap m = longMap(); + double dr = m.reduceValuesToDouble(Long.MAX_VALUE, (Long x) -> x.doubleValue(), 0.0, Double::sum); + assertEquals(dr, (double)SIZE * (SIZE - 1)); + } + + /** + * reduceKeysToLongInParallel accumulates mapped keys + */ + public void testReduceKeysToLongInParallel() { + ConcurrentHashMap m = longMap(); + long lr = m.reduceKeysToLong(1L, (Long x) -> x.longValue(), 0L, Long::sum); + assertEquals(lr, (long)SIZE * (SIZE - 1) / 2); + } + + /** + * reduceKeysToIntInParallel accumulates mapped keys + */ + public void testReduceKeysToIntInParallel() { + ConcurrentHashMap m = longMap(); + int ir = m.reduceKeysToInt(1L, (Long x) -> x.intValue(), 0, Integer::sum); + assertEquals(ir, SIZE * (SIZE - 1) / 2); + } + + /** + * reduceKeysToDoubleInParallel accumulates mapped values + */ + public void testReduceKeysToDoubleInParallel() { + ConcurrentHashMap m = longMap(); + double dr = m.reduceKeysToDouble(1L, (Long x) -> x.doubleValue(), 0.0, Double::sum); + assertEquals(dr, (double)SIZE * (SIZE - 1) / 2); + } + + /** + * reduceValuesToLongInParallel accumulates mapped values + */ + public void testReduceValuesToLongInParallel() { + ConcurrentHashMap m = longMap(); + long lr = m.reduceValuesToLong(1L, (Long x) -> x.longValue(), 0L, Long::sum); + assertEquals(lr, (long)SIZE * (SIZE - 1)); + } + + /** + * reduceValuesToIntInParallel accumulates mapped values + */ + public void testReduceValuesToIntInParallel() { + ConcurrentHashMap m = longMap(); + int ir = m.reduceValuesToInt(1L, (Long x) -> x.intValue(), 0, Integer::sum); + assertEquals(ir, SIZE * (SIZE - 1)); + } + + /** + * reduceValuesToDoubleInParallel accumulates mapped values + */ + public void testReduceValuesToDoubleInParallel() { + ConcurrentHashMap m = longMap(); + double dr = m.reduceValuesToDouble(1L, (Long x) -> x.doubleValue(), 0.0, Double::sum); + assertEquals(dr, (double)SIZE * (SIZE - 1)); + } + + /** + * searchKeysSequentially returns a non-null result of search + * function, or null if none + */ + public void testSearchKeysSequentially() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.searchKeys(Long.MAX_VALUE, (Long x) -> x.longValue() == (long)(SIZE/2) ? x : null); + assertEquals((long)r, (long)(SIZE/2)); + r = m.searchKeys(Long.MAX_VALUE, (Long x) -> x.longValue() < 0L ? x : null); + assertNull(r); + } + + /** + * searchValuesSequentially returns a non-null result of search + * function, or null if none + */ + public void testSearchValuesSequentially() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.searchValues(Long.MAX_VALUE, + (Long x) -> (x.longValue() == (long)(SIZE/2)) ? x : null); + assertEquals((long)r, (long)(SIZE/2)); + r = m.searchValues(Long.MAX_VALUE, + (Long x) -> (x.longValue() < 0L) ? x : null); + assertNull(r); + } + + /** + * searchSequentially returns a non-null result of search + * function, or null if none + */ + public void testSearchSequentially() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.search(Long.MAX_VALUE, (Long x, Long y) -> x.longValue() == (long)(SIZE/2) ? x : null); + assertEquals((long)r, (long)(SIZE/2)); + r = m.search(Long.MAX_VALUE, (Long x, Long y) -> x.longValue() < 0L ? x : null); + assertNull(r); + } + + /** + * searchEntriesSequentially returns a non-null result of search + * function, or null if none + */ + public void testSearchEntriesSequentially() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.searchEntries(Long.MAX_VALUE, (Map.Entry e) -> e.getKey().longValue() == (long)(SIZE/2) ? e.getKey() : null); + assertEquals((long)r, (long)(SIZE/2)); + r = m.searchEntries(Long.MAX_VALUE, (Map.Entry e) -> e.getKey().longValue() < 0L ? e.getKey() : null); + assertNull(r); + } + + /** + * searchKeysInParallel returns a non-null result of search + * function, or null if none + */ + public void testSearchKeysInParallel() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.searchKeys(1L, (Long x) -> x.longValue() == (long)(SIZE/2) ? x : null); + assertEquals((long)r, (long)(SIZE/2)); + r = m.searchKeys(1L, (Long x) -> x.longValue() < 0L ? x : null); + assertNull(r); + } + + /** + * searchValuesInParallel returns a non-null result of search + * function, or null if none + */ + public void testSearchValuesInParallel() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.searchValues(1L, (Long x) -> x.longValue() == (long)(SIZE/2) ? x : null); + assertEquals((long)r, (long)(SIZE/2)); + r = m.searchValues(1L, (Long x) -> x.longValue() < 0L ? x : null); + assertNull(r); + } + + /** + * searchInParallel returns a non-null result of search function, + * or null if none + */ + public void testSearchInParallel() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.search(1L, (Long x, Long y) -> x.longValue() == (long)(SIZE/2) ? x : null); + assertEquals((long)r, (long)(SIZE/2)); + r = m.search(1L, (Long x, Long y) -> x.longValue() < 0L ? x : null); + assertNull(r); + } + + /** + * searchEntriesInParallel returns a non-null result of search + * function, or null if none + */ + public void testSearchEntriesInParallel() { + ConcurrentHashMap m = longMap(); + Long r; + r = m.searchEntries(1L, (Map.Entry e) -> e.getKey().longValue() == (long)(SIZE/2) ? e.getKey() : null); + assertEquals((long)r, (long)(SIZE/2)); + r = m.searchEntries(1L, (Map.Entry e) -> e.getKey().longValue() < 0L ? e.getKey() : null); + assertNull(r); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java new file mode 100644 index 00000000000..766511902af --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java @@ -0,0 +1,833 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ConcurrentHashMapTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ConcurrentHashMapTest.class); + } + + /** + * Returns a new map from Integers 1-5 to Strings "A"-"E". + */ + private static ConcurrentHashMap map5() { + ConcurrentHashMap map = new ConcurrentHashMap(5); + assertTrue(map.isEmpty()); + map.put(one, "A"); + map.put(two, "B"); + map.put(three, "C"); + map.put(four, "D"); + map.put(five, "E"); + assertFalse(map.isEmpty()); + assertEquals(5, map.size()); + return map; + } + + /** Re-implement Integer.compare for old java versions */ + static int compare(int x, int y) { + return (x < y) ? -1 : (x > y) ? 1 : 0; + } + + // classes for testing Comparable fallbacks + static class BI implements Comparable { + private final int value; + BI(int value) { this.value = value; } + public int compareTo(BI other) { + return compare(value, other.value); + } + public boolean equals(Object x) { + return (x instanceof BI) && ((BI)x).value == value; + } + public int hashCode() { return 42; } + } + static class CI extends BI { CI(int value) { super(value); } } + static class DI extends BI { DI(int value) { super(value); } } + + static class BS implements Comparable { + private final String value; + BS(String value) { this.value = value; } + public int compareTo(BS other) { + return value.compareTo(other.value); + } + public boolean equals(Object x) { + return (x instanceof BS) && value.equals(((BS)x).value); + } + public int hashCode() { return 42; } + } + + static class LexicographicList> extends ArrayList + implements Comparable> { + LexicographicList(Collection c) { super(c); } + LexicographicList(E e) { super(Collections.singleton(e)); } + public int compareTo(LexicographicList other) { + int common = Math.min(size(), other.size()); + int r = 0; + for (int i = 0; i < common; i++) { + if ((r = get(i).compareTo(other.get(i))) != 0) + break; + } + if (r == 0) + r = compare(size(), other.size()); + return r; + } + private static final long serialVersionUID = 0; + } + + static class CollidingObject { + final String value; + CollidingObject(final String value) { this.value = value; } + public int hashCode() { return this.value.hashCode() & 1; } + public boolean equals(final Object obj) { + return (obj instanceof CollidingObject) && ((CollidingObject)obj).value.equals(value); + } + } + + static class ComparableCollidingObject extends CollidingObject implements Comparable { + ComparableCollidingObject(final String value) { super(value); } + public int compareTo(final ComparableCollidingObject o) { + return value.compareTo(o.value); + } + } + + /** + * Inserted elements that are subclasses of the same Comparable + * class are found. + */ + public void testComparableFamily() { + int size = 500; // makes measured test run time -> 60ms + ConcurrentHashMap m = + new ConcurrentHashMap(); + for (int i = 0; i < size; i++) { + assertTrue(m.put(new CI(i), true) == null); + } + for (int i = 0; i < size; i++) { + assertTrue(m.containsKey(new CI(i))); + assertTrue(m.containsKey(new DI(i))); + } + } + + /** + * Elements of classes with erased generic type parameters based + * on Comparable can be inserted and found. + */ + public void testGenericComparable() { + int size = 120; // makes measured test run time -> 60ms + ConcurrentHashMap m = + new ConcurrentHashMap(); + for (int i = 0; i < size; i++) { + BI bi = new BI(i); + BS bs = new BS(String.valueOf(i)); + LexicographicList bis = new LexicographicList(bi); + LexicographicList bss = new LexicographicList(bs); + assertTrue(m.putIfAbsent(bis, true) == null); + assertTrue(m.containsKey(bis)); + if (m.putIfAbsent(bss, true) == null) + assertTrue(m.containsKey(bss)); + assertTrue(m.containsKey(bis)); + } + for (int i = 0; i < size; i++) { + assertTrue(m.containsKey(Collections.singletonList(new BI(i)))); + } + } + + /** + * Elements of non-comparable classes equal to those of classes + * with erased generic type parameters based on Comparable can be + * inserted and found. + */ + public void testGenericComparable2() { + int size = 500; // makes measured test run time -> 60ms + ConcurrentHashMap m = + new ConcurrentHashMap(); + for (int i = 0; i < size; i++) { + m.put(Collections.singletonList(new BI(i)), true); + } + + for (int i = 0; i < size; i++) { + LexicographicList bis = new LexicographicList(new BI(i)); + assertTrue(m.containsKey(bis)); + } + } + + /** + * Mixtures of instances of comparable and non-comparable classes + * can be inserted and found. + */ + public void testMixedComparable() { + int size = 1200; // makes measured test run time -> 35ms + ConcurrentHashMap map = + new ConcurrentHashMap(); + Random rng = new Random(); + for (int i = 0; i < size; i++) { + Object x; + switch (rng.nextInt(4)) { + case 0: + x = new Object(); + break; + case 1: + x = new CollidingObject(Integer.toString(i)); + break; + default: + x = new ComparableCollidingObject(Integer.toString(i)); + } + assertNull(map.put(x, x)); + } + int count = 0; + for (Object k : map.keySet()) { + assertEquals(map.get(k), k); + ++count; + } + assertEquals(count, size); + assertEquals(map.size(), size); + for (Object k : map.keySet()) { + assertEquals(map.put(k, k), k); + } + } + + /** + * clear removes all pairs + */ + public void testClear() { + ConcurrentHashMap map = map5(); + map.clear(); + assertEquals(0, map.size()); + } + + /** + * Maps with same contents are equal + */ + public void testEquals() { + ConcurrentHashMap map1 = map5(); + ConcurrentHashMap map2 = map5(); + assertEquals(map1, map2); + assertEquals(map2, map1); + map1.clear(); + assertFalse(map1.equals(map2)); + assertFalse(map2.equals(map1)); + } + + /** + * hashCode() equals sum of each key.hashCode ^ value.hashCode + */ + public void testHashCode() { + ConcurrentHashMap map = map5(); + int sum = 0; + for (Map.Entry e : map.entrySet()) + sum += e.getKey().hashCode() ^ e.getValue().hashCode(); + assertEquals(sum, map.hashCode()); + } + + /** + * contains returns true for contained value + */ + public void testContains() { + ConcurrentHashMap map = map5(); + assertTrue(map.contains("A")); + assertFalse(map.contains("Z")); + } + + /** + * containsKey returns true for contained key + */ + public void testContainsKey() { + ConcurrentHashMap map = map5(); + assertTrue(map.containsKey(one)); + assertFalse(map.containsKey(zero)); + } + + /** + * containsValue returns true for held values + */ + public void testContainsValue() { + ConcurrentHashMap map = map5(); + assertTrue(map.containsValue("A")); + assertFalse(map.containsValue("Z")); + } + + /** + * enumeration returns an enumeration containing the correct + * elements + */ + public void testEnumeration() { + ConcurrentHashMap map = map5(); + Enumeration e = map.elements(); + int count = 0; + while (e.hasMoreElements()) { + count++; + e.nextElement(); + } + assertEquals(5, count); + } + + /** + * get returns the correct element at the given key, + * or null if not present + */ + public void testGet() { + ConcurrentHashMap map = map5(); + assertEquals("A", (String)map.get(one)); + ConcurrentHashMap empty = new ConcurrentHashMap(); + assertNull(map.get("anything")); + assertNull(empty.get("anything")); + } + + /** + * isEmpty is true of empty map and false for non-empty + */ + public void testIsEmpty() { + ConcurrentHashMap empty = new ConcurrentHashMap(); + ConcurrentHashMap map = map5(); + assertTrue(empty.isEmpty()); + assertFalse(map.isEmpty()); + } + + /** + * keys returns an enumeration containing all the keys from the map + */ + public void testKeys() { + ConcurrentHashMap map = map5(); + Enumeration e = map.keys(); + int count = 0; + while (e.hasMoreElements()) { + count++; + e.nextElement(); + } + assertEquals(5, count); + } + + /** + * keySet returns a Set containing all the keys + */ + public void testKeySet() { + ConcurrentHashMap map = map5(); + Set s = map.keySet(); + assertEquals(5, s.size()); + assertTrue(s.contains(one)); + assertTrue(s.contains(two)); + assertTrue(s.contains(three)); + assertTrue(s.contains(four)); + assertTrue(s.contains(five)); + } + + /** + * keySet.toArray returns contains all keys + */ + public void testKeySetToArray() { + ConcurrentHashMap map = map5(); + Set s = map.keySet(); + Object[] ar = s.toArray(); + assertTrue(s.containsAll(Arrays.asList(ar))); + assertEquals(5, ar.length); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * Values.toArray contains all values + */ + public void testValuesToArray() { + ConcurrentHashMap map = map5(); + Collection v = map.values(); + Object[] ar = v.toArray(); + ArrayList s = new ArrayList(Arrays.asList(ar)); + assertEquals(5, ar.length); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * entrySet.toArray contains all entries + */ + public void testEntrySetToArray() { + ConcurrentHashMap map = map5(); + Set s = map.entrySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + for (int i = 0; i < 5; ++i) { + assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey())); + assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue())); + } + } + + /** + * values collection contains all values + */ + public void testValues() { + ConcurrentHashMap map = map5(); + Collection s = map.values(); + assertEquals(5, s.size()); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * entrySet contains all pairs + */ + public void testEntrySet() { + ConcurrentHashMap map = map5(); + Set s = map.entrySet(); + assertEquals(5, s.size()); + Iterator it = s.iterator(); + while (it.hasNext()) { + Map.Entry e = (Map.Entry) it.next(); + assertTrue( + (e.getKey().equals(one) && e.getValue().equals("A")) || + (e.getKey().equals(two) && e.getValue().equals("B")) || + (e.getKey().equals(three) && e.getValue().equals("C")) || + (e.getKey().equals(four) && e.getValue().equals("D")) || + (e.getKey().equals(five) && e.getValue().equals("E"))); + } + } + + /** + * putAll adds all key-value pairs from the given map + */ + public void testPutAll() { + ConcurrentHashMap empty = new ConcurrentHashMap(); + ConcurrentHashMap map = map5(); + empty.putAll(map); + assertEquals(5, empty.size()); + assertTrue(empty.containsKey(one)); + assertTrue(empty.containsKey(two)); + assertTrue(empty.containsKey(three)); + assertTrue(empty.containsKey(four)); + assertTrue(empty.containsKey(five)); + } + + /** + * putIfAbsent works when the given key is not present + */ + public void testPutIfAbsent() { + ConcurrentHashMap map = map5(); + map.putIfAbsent(six, "Z"); + assertTrue(map.containsKey(six)); + } + + /** + * putIfAbsent does not add the pair if the key is already present + */ + public void testPutIfAbsent2() { + ConcurrentHashMap map = map5(); + assertEquals("A", map.putIfAbsent(one, "Z")); + } + + /** + * replace fails when the given key is not present + */ + public void testReplace() { + ConcurrentHashMap map = map5(); + assertNull(map.replace(six, "Z")); + assertFalse(map.containsKey(six)); + } + + /** + * replace succeeds if the key is already present + */ + public void testReplace2() { + ConcurrentHashMap map = map5(); + assertNotNull(map.replace(one, "Z")); + assertEquals("Z", map.get(one)); + } + + /** + * replace value fails when the given key not mapped to expected value + */ + public void testReplaceValue() { + ConcurrentHashMap map = map5(); + assertEquals("A", map.get(one)); + assertFalse(map.replace(one, "Z", "Z")); + assertEquals("A", map.get(one)); + } + + /** + * replace value succeeds when the given key mapped to expected value + */ + public void testReplaceValue2() { + ConcurrentHashMap map = map5(); + assertEquals("A", map.get(one)); + assertTrue(map.replace(one, "A", "Z")); + assertEquals("Z", map.get(one)); + } + + /** + * remove removes the correct key-value pair from the map + */ + public void testRemove() { + ConcurrentHashMap map = map5(); + map.remove(five); + assertEquals(4, map.size()); + assertFalse(map.containsKey(five)); + } + + /** + * remove(key,value) removes only if pair present + */ + public void testRemove2() { + ConcurrentHashMap map = map5(); + map.remove(five, "E"); + assertEquals(4, map.size()); + assertFalse(map.containsKey(five)); + map.remove(four, "A"); + assertEquals(4, map.size()); + assertTrue(map.containsKey(four)); + } + + /** + * size returns the correct values + */ + public void testSize() { + ConcurrentHashMap map = map5(); + ConcurrentHashMap empty = new ConcurrentHashMap(); + assertEquals(0, empty.size()); + assertEquals(5, map.size()); + } + + /** + * toString contains toString of elements + */ + public void testToString() { + ConcurrentHashMap map = map5(); + String s = map.toString(); + for (int i = 1; i <= 5; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + // Exception tests + + /** + * Cannot create with only negative capacity + */ + public void testConstructor1() { + try { + new ConcurrentHashMap(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor (initialCapacity, loadFactor) throws + * IllegalArgumentException if either argument is negative + */ + public void testConstructor2() { + try { + new ConcurrentHashMap(-1, .75f); + shouldThrow(); + } catch (IllegalArgumentException success) {} + + try { + new ConcurrentHashMap(16, -1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor (initialCapacity, loadFactor, concurrencyLevel) + * throws IllegalArgumentException if any argument is negative + */ + public void testConstructor3() { + try { + new ConcurrentHashMap(-1, .75f, 1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + + try { + new ConcurrentHashMap(16, -1, 1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + + try { + new ConcurrentHashMap(16, .75f, -1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * ConcurrentHashMap(map) throws NullPointerException if the given + * map is null + */ + public void testConstructor4() { + try { + new ConcurrentHashMap(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * ConcurrentHashMap(map) creates a new map with the same mappings + * as the given map + */ + public void testConstructor5() { + ConcurrentHashMap map1 = map5(); + ConcurrentHashMap map2 = new ConcurrentHashMap(map5()); + assertTrue(map2.equals(map1)); + map2.put(one, "F"); + assertFalse(map2.equals(map1)); + } + + /** + * get(null) throws NPE + */ + public void testGet_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.get(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsKey(null) throws NPE + */ + public void testContainsKey_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.containsKey(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsValue(null) throws NPE + */ + public void testContainsValue_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.containsValue(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * contains(null) throws NPE + */ + public void testContains_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.contains(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * put(null,x) throws NPE + */ + public void testPut1_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.put(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * put(x, null) throws NPE + */ + public void testPut2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.put("whatever", null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * putIfAbsent(null, x) throws NPE + */ + public void testPutIfAbsent1_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.putIfAbsent(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(null, x) throws NPE + */ + public void testReplace_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.replace(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(null, x, y) throws NPE + */ + public void testReplaceValue_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.replace(null, one, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * putIfAbsent(x, null) throws NPE + */ + public void testPutIfAbsent2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.putIfAbsent("whatever", null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(x, null) throws NPE + */ + public void testReplace2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.replace("whatever", null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(x, null, y) throws NPE + */ + public void testReplaceValue2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.replace("whatever", null, "A"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(x, y, null) throws NPE + */ + public void testReplaceValue3_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + try { + c.replace("whatever", one, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null) throws NPE + */ + public void testRemove1_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + c.put("sadsdf", "asdads"); + try { + c.remove(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null, x) throws NPE + */ + public void testRemove2_NullPointerException() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + c.put("sadsdf", "asdads"); + try { + c.remove(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(x, null) returns false + */ + public void testRemove3() { + ConcurrentHashMap c = new ConcurrentHashMap(5); + c.put("sadsdf", "asdads"); + assertFalse(c.remove("sadsdf", null)); + } + + /** + * A deserialized map equals original + */ + public void testSerialization() throws Exception { + Map x = map5(); + Map y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x, y); + assertEquals(y, x); + } + + /** + * SetValue of an EntrySet entry sets value in the map. + */ + public void testSetValueWriteThrough() { + // Adapted from a bug report by Eric Zoerner + ConcurrentHashMap map = new ConcurrentHashMap(2, 5.0f, 1); + assertTrue(map.isEmpty()); + for (int i = 0; i < 20; i++) + map.put(new Integer(i), new Integer(i)); + assertFalse(map.isEmpty()); + Map.Entry entry1 = (Map.Entry)map.entrySet().iterator().next(); + // Unless it happens to be first (in which case remainder of + // test is skipped), remove a possibly-colliding key from map + // which, under some implementations, may cause entry1 to be + // cloned in map + if (!entry1.getKey().equals(new Integer(16))) { + map.remove(new Integer(16)); + entry1.setValue("XYZ"); + assertTrue(map.containsValue("XYZ")); // fails if write-through broken + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java new file mode 100644 index 00000000000..daab5381529 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java @@ -0,0 +1,926 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.Arrays; +import java.util.Collection; +import java.util.Deque; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Random; +import java.util.concurrent.ConcurrentLinkedDeque; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ConcurrentLinkedDequeTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ConcurrentLinkedDequeTest.class); + } + + /** + * Returns a new deque of given size containing consecutive + * Integers 0 ... n. + */ + private ConcurrentLinkedDeque populatedDeque(int n) { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + assertTrue(q.isEmpty()); + for (int i = 0; i < n; ++i) + assertTrue(q.offer(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(n, q.size()); + return q; + } + + /** + * new deque is empty + */ + public void testConstructor1() { + assertTrue(new ConcurrentLinkedDeque().isEmpty()); + assertEquals(0, new ConcurrentLinkedDeque().size()); + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new ConcurrentLinkedDeque((Collection)null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NPE + */ + public void testConstructor4() { + try { + new ConcurrentLinkedDeque(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws NPE + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + new ConcurrentLinkedDeque(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Deque contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + assertTrue(q.isEmpty()); + q.add(one); + assertFalse(q.isEmpty()); + q.add(two); + q.remove(); + q.remove(); + assertTrue(q.isEmpty()); + } + + /** + * size() changes when elements added and removed + */ + public void testSize() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.remove(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * push(null) throws NPE + */ + public void testPushNull() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + try { + q.push(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * peekFirst() returns element inserted with push + */ + public void testPush() { + ConcurrentLinkedDeque q = populatedDeque(3); + q.pollLast(); + q.push(four); + assertSame(four, q.peekFirst()); + } + + /** + * pop() removes first element, or throws NSEE if empty + */ + public void testPop() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pop()); + } + try { + q.pop(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * offer(null) throws NPE + */ + public void testOfferNull() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + try { + q.offer(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * offerFirst(null) throws NPE + */ + public void testOfferFirstNull() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + try { + q.offerFirst(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * offerLast(null) throws NPE + */ + public void testOfferLastNull() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + try { + q.offerLast(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * offer(x) succeeds + */ + public void testOffer() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + assertTrue(q.offer(zero)); + assertTrue(q.offer(one)); + assertSame(zero, q.peekFirst()); + assertSame(one, q.peekLast()); + } + + /** + * offerFirst(x) succeeds + */ + public void testOfferFirst() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + assertTrue(q.offerFirst(zero)); + assertTrue(q.offerFirst(one)); + assertSame(one, q.peekFirst()); + assertSame(zero, q.peekLast()); + } + + /** + * offerLast(x) succeeds + */ + public void testOfferLast() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + assertTrue(q.offerLast(zero)); + assertTrue(q.offerLast(one)); + assertSame(zero, q.peekFirst()); + assertSame(one, q.peekLast()); + } + + /** + * add(null) throws NPE + */ + public void testAddNull() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addFirst(null) throws NPE + */ + public void testAddFirstNull() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + try { + q.addFirst(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addLast(null) throws NPE + */ + public void testAddLastNull() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + try { + q.addLast(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * add(x) succeeds + */ + public void testAdd() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + assertTrue(q.add(zero)); + assertTrue(q.add(one)); + assertSame(zero, q.peekFirst()); + assertSame(one, q.peekLast()); + } + + /** + * addFirst(x) succeeds + */ + public void testAddFirst() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + q.addFirst(zero); + q.addFirst(one); + assertSame(one, q.peekFirst()); + assertSame(zero, q.peekLast()); + } + + /** + * addLast(x) succeeds + */ + public void testAddLast() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + q.addLast(zero); + q.addLast(one); + assertSame(zero, q.peekFirst()); + assertSame(one, q.peekLast()); + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll(this) throws IAE + */ + public void testAddAllSelf() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testAddAll2() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + try { + q.addAll(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Deque contains all elements, in traversal order, of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * pollFirst() succeeds unless empty + */ + public void testPollFirst() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst()); + } + assertNull(q.pollFirst()); + } + + /** + * pollLast() succeeds unless empty + */ + public void testPollLast() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.pollLast()); + } + assertNull(q.pollLast()); + } + + /** + * poll() succeeds unless empty + */ + public void testPoll() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll()); + } + assertNull(q.poll()); + } + + /** + * peek() returns next element, or null if empty + */ + public void testPeek() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peek()); + assertEquals(i, q.poll()); + assertTrue(q.peek() == null || + !q.peek().equals(i)); + } + assertNull(q.peek()); + } + + /** + * element() returns first element, or throws NSEE if empty + */ + public void testElement() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.element()); + assertEquals(i, q.poll()); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove() removes next element, or throws NSEE if empty + */ + public void testRemove() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove(x) removes x and returns true if present + */ + public void testRemoveElement() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertTrue(q.contains(i - 1)); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertFalse(q.remove(i + 1)); + assertFalse(q.contains(i + 1)); + } + assertTrue(q.isEmpty()); + } + + /** + * peekFirst() returns next element, or null if empty + */ + public void testPeekFirst() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peekFirst()); + assertEquals(i, q.pollFirst()); + assertTrue(q.peekFirst() == null || + !q.peekFirst().equals(i)); + } + assertNull(q.peekFirst()); + } + + /** + * peekLast() returns next element, or null if empty + */ + public void testPeekLast() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.peekLast()); + assertEquals(i, q.pollLast()); + assertTrue(q.peekLast() == null || + !q.peekLast().equals(i)); + } + assertNull(q.peekLast()); + } + + /** + * getFirst() returns first element, or throws NSEE if empty + */ + public void testFirstElement() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.getFirst()); + assertEquals(i, q.pollFirst()); + } + try { + q.getFirst(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * getLast() returns last element, or throws NSEE if empty + */ + public void testLastElement() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.getLast()); + assertEquals(i, q.pollLast()); + } + try { + q.getLast(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekLast()); + } + + /** + * removeFirst() removes first element, or throws NSEE if empty + */ + public void testRemoveFirst() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.removeFirst()); + } + try { + q.removeFirst(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekFirst()); + } + + /** + * removeLast() removes last element, or throws NSEE if empty + */ + public void testRemoveLast() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.removeLast()); + } + try { + q.removeLast(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekLast()); + } + + /** + * removeFirstOccurrence(x) removes x and returns true if present + */ + public void testRemoveFirstOccurrence() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.removeFirstOccurrence(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.removeFirstOccurrence(new Integer(i))); + assertFalse(q.removeFirstOccurrence(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + + /** + * removeLastOccurrence(x) removes x and returns true if present + */ + public void testRemoveLastOccurrence() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.removeLastOccurrence(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.removeLastOccurrence(new Integer(i))); + assertFalse(q.removeLastOccurrence(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.poll(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear() removes all elements + */ + public void testClear() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + q.add(one); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + ConcurrentLinkedDeque p = new ConcurrentLinkedDeque(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if change + */ + public void testRetainAll() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + ConcurrentLinkedDeque p = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + ConcurrentLinkedDeque p = populatedDeque(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.remove()); + assertFalse(q.contains(x)); + } + } + } + + /** + * toArray() contains all elements in FIFO order + */ + public void testToArray() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.poll()); + } + + /** + * toArray(a) contains all elements in FIFO order + */ + public void testToArray2() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.poll()); + } + + /** + * toArray(null) throws NullPointerException + */ + public void testToArray_NullArg() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + try { + q.toArray(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + try { + q.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * Iterator iterates through all elements + */ + public void testIterator() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + Deque c = new ConcurrentLinkedDeque(); + assertIteratorExhausted(c.iterator()); + assertIteratorExhausted(c.descendingIterator()); + } + + /** + * Iterator ordering is FIFO + */ + public void testIteratorOrdering() { + final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + q.add(one); + q.add(two); + q.add(three); + + int k = 0; + for (Iterator it = q.iterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + + assertEquals(3, k); + } + + /** + * Modifications do not cause iterators to fail + */ + public void testWeaklyConsistentIteration() { + final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + q.add(one); + q.add(two); + q.add(three); + + for (Iterator it = q.iterator(); it.hasNext();) { + q.remove(); + it.next(); + } + + assertEquals("deque should be empty again", 0, q.size()); + } + + /** + * iterator.remove() removes current element + */ + public void testIteratorRemove() { + final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + final Random rng = new Random(); + for (int iters = 0; iters < 100; ++iters) { + int max = rng.nextInt(5) + 2; + int split = rng.nextInt(max - 1) + 1; + for (int j = 1; j <= max; ++j) + q.add(new Integer(j)); + Iterator it = q.iterator(); + for (int j = 1; j <= split; ++j) + assertEquals(it.next(), new Integer(j)); + it.remove(); + assertEquals(it.next(), new Integer(split + 1)); + for (int j = 1; j <= split; ++j) + q.remove(new Integer(j)); + it = q.iterator(); + for (int j = split + 1; j <= max; ++j) { + assertEquals(it.next(), new Integer(j)); + it.remove(); + } + assertFalse(it.hasNext()); + assertTrue(q.isEmpty()); + } + } + + /** + * Descending iterator iterates through all elements + */ + public void testDescendingIterator() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + int i = 0; + Iterator it = q.descendingIterator(); + while (it.hasNext()) { + assertTrue(q.contains(it.next())); + ++i; + } + assertEquals(i, SIZE); + assertFalse(it.hasNext()); + try { + it.next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * Descending iterator ordering is reverse FIFO + */ + public void testDescendingIteratorOrdering() { + final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + for (int iters = 0; iters < 100; ++iters) { + q.add(new Integer(3)); + q.add(new Integer(2)); + q.add(new Integer(1)); + int k = 0; + for (Iterator it = q.descendingIterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + + assertEquals(3, k); + q.remove(); + q.remove(); + q.remove(); + } + } + + /** + * descendingIterator.remove() removes current element + */ + public void testDescendingIteratorRemove() { + final ConcurrentLinkedDeque q = new ConcurrentLinkedDeque(); + final Random rng = new Random(); + for (int iters = 0; iters < 100; ++iters) { + int max = rng.nextInt(5) + 2; + int split = rng.nextInt(max - 1) + 1; + for (int j = max; j >= 1; --j) + q.add(new Integer(j)); + Iterator it = q.descendingIterator(); + for (int j = 1; j <= split; ++j) + assertEquals(it.next(), new Integer(j)); + it.remove(); + assertEquals(it.next(), new Integer(split + 1)); + for (int j = 1; j <= split; ++j) + q.remove(new Integer(j)); + it = q.descendingIterator(); + for (int j = split + 1; j <= max; ++j) { + assertEquals(it.next(), new Integer(j)); + it.remove(); + } + assertFalse(it.hasNext()); + assertTrue(q.isEmpty()); + } + } + + /** + * toString() contains toStrings of elements + */ + public void testToString() { + ConcurrentLinkedDeque q = populatedDeque(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized deque has same elements in same order + */ + public void testSerialization() throws Exception { + Queue x = populatedDeque(SIZE); + Queue y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(), y.remove()); + } + assertTrue(y.isEmpty()); + } + + /** + * contains(null) always return false. + * remove(null) always throws NullPointerException. + */ + public void testNeverContainsNull() { + Deque[] qs = { + new ConcurrentLinkedDeque(), + populatedDeque(2), + }; + + for (Deque q : qs) { + assertFalse(q.contains(null)); + try { + assertFalse(q.remove(null)); + shouldThrow(); + } catch (NullPointerException success) {} + try { + assertFalse(q.removeFirstOccurrence(null)); + shouldThrow(); + } catch (NullPointerException success) {} + try { + assertFalse(q.removeLastOccurrence(null)); + shouldThrow(); + } catch (NullPointerException success) {} + } + } +} diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java new file mode 100644 index 00000000000..bafaa6581f0 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java @@ -0,0 +1,564 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ConcurrentLinkedQueueTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ConcurrentLinkedQueueTest.class); + } + + /** + * Returns a new queue of given size containing consecutive + * Integers 0 ... n. + */ + private ConcurrentLinkedQueue populatedQueue(int n) { + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + assertTrue(q.isEmpty()); + for (int i = 0; i < n; ++i) + assertTrue(q.offer(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(n, q.size()); + return q; + } + + /** + * new queue is empty + */ + public void testConstructor1() { + assertEquals(0, new ConcurrentLinkedQueue().size()); + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new ConcurrentLinkedQueue((Collection)null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NPE + */ + public void testConstructor4() { + try { + new ConcurrentLinkedQueue(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws NPE + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + new ConcurrentLinkedQueue(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + assertTrue(q.isEmpty()); + q.add(one); + assertFalse(q.isEmpty()); + q.add(two); + q.remove(); + q.remove(); + assertTrue(q.isEmpty()); + } + + /** + * size changes when elements added and removed + */ + public void testSize() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.remove(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * offer(null) throws NPE + */ + public void testOfferNull() { + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + try { + q.offer(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * add(null) throws NPE + */ + public void testAddNull() { + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Offer returns true + */ + public void testOffer() { + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + assertTrue(q.offer(zero)); + assertTrue(q.offer(one)); + } + + /** + * add returns true + */ + public void testAdd() { + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + assertTrue(q.add(new Integer(i))); + } + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll(this) throws IAE + */ + public void testAddAllSelf() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testAddAll2() { + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + try { + q.addAll(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements, in traversal order, of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll()); + } + assertNull(q.poll()); + } + + /** + * peek returns next element, or null if empty + */ + public void testPeek() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peek()); + assertEquals(i, q.poll()); + assertTrue(q.peek() == null || + !q.peek().equals(i)); + } + assertNull(q.peek()); + } + + /** + * element returns next element, or throws NSEE if empty + */ + public void testElement() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.element()); + assertEquals(i, q.poll()); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove removes next element, or throws NSEE if empty + */ + public void testRemove() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove(x) removes x and returns true if present + */ + public void testRemoveElement() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertTrue(q.contains(i - 1)); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertFalse(q.remove(i + 1)); + assertFalse(q.contains(i + 1)); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.poll(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + q.add(one); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + ConcurrentLinkedQueue p = new ConcurrentLinkedQueue(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if change + */ + public void testRetainAll() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + ConcurrentLinkedQueue p = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + ConcurrentLinkedQueue p = populatedQueue(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.remove()); + assertFalse(q.contains(x)); + } + } + } + + /** + * toArray contains all elements in FIFO order + */ + public void testToArray() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.poll()); + } + + /** + * toArray(a) contains all elements in FIFO order + */ + public void testToArray2() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.poll()); + } + + /** + * toArray(null) throws NullPointerException + */ + public void testToArray_NullArg() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + try { + q.toArray(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + try { + q.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * iterator iterates through all elements + */ + public void testIterator() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new ConcurrentLinkedQueue().iterator()); + } + + /** + * iterator ordering is FIFO + */ + public void testIteratorOrdering() { + final ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + q.add(one); + q.add(two); + q.add(three); + + int k = 0; + for (Iterator it = q.iterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + + assertEquals(3, k); + } + + /** + * Modifications do not cause iterators to fail + */ + public void testWeaklyConsistentIteration() { + final ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + q.add(one); + q.add(two); + q.add(three); + + for (Iterator it = q.iterator(); it.hasNext();) { + q.remove(); + it.next(); + } + + assertEquals("queue should be empty again", 0, q.size()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(); + q.add(one); + q.add(two); + q.add(three); + Iterator it = q.iterator(); + it.next(); + it.remove(); + it = q.iterator(); + assertSame(it.next(), two); + assertSame(it.next(), three); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + ConcurrentLinkedQueue q = populatedQueue(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized queue has same elements in same order + */ + public void testSerialization() throws Exception { + Queue x = populatedQueue(SIZE); + Queue y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(), y.remove()); + } + assertTrue(y.isEmpty()); + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Collection[] qs = { + new ConcurrentLinkedQueue(), + populatedQueue(2), + }; + + for (Collection q : qs) { + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + } + } +} diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java new file mode 100644 index 00000000000..515303e3e64 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListMapTest.java @@ -0,0 +1,1306 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.ConcurrentSkipListMap; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ConcurrentSkipListMapTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ConcurrentSkipListMapTest.class); + } + + /** + * Returns a new map from Integers 1-5 to Strings "A"-"E". + */ + private static ConcurrentSkipListMap map5() { + ConcurrentSkipListMap map = new ConcurrentSkipListMap(); + assertTrue(map.isEmpty()); + map.put(one, "A"); + map.put(five, "E"); + map.put(three, "C"); + map.put(two, "B"); + map.put(four, "D"); + assertFalse(map.isEmpty()); + assertEquals(5, map.size()); + return map; + } + + /** + * clear removes all pairs + */ + public void testClear() { + ConcurrentSkipListMap map = map5(); + map.clear(); + assertEquals(0, map.size()); + } + + /** + * copy constructor creates map equal to source map + */ + public void testConstructFromSorted() { + ConcurrentSkipListMap map = map5(); + ConcurrentSkipListMap map2 = new ConcurrentSkipListMap(map); + assertEquals(map, map2); + } + + /** + * Maps with same contents are equal + */ + public void testEquals() { + ConcurrentSkipListMap map1 = map5(); + ConcurrentSkipListMap map2 = map5(); + assertEquals(map1, map2); + assertEquals(map2, map1); + map1.clear(); + assertFalse(map1.equals(map2)); + assertFalse(map2.equals(map1)); + } + + /** + * containsKey returns true for contained key + */ + public void testContainsKey() { + ConcurrentSkipListMap map = map5(); + assertTrue(map.containsKey(one)); + assertFalse(map.containsKey(zero)); + } + + /** + * containsValue returns true for held values + */ + public void testContainsValue() { + ConcurrentSkipListMap map = map5(); + assertTrue(map.containsValue("A")); + assertFalse(map.containsValue("Z")); + } + + /** + * get returns the correct element at the given key, + * or null if not present + */ + public void testGet() { + ConcurrentSkipListMap map = map5(); + assertEquals("A", (String)map.get(one)); + ConcurrentSkipListMap empty = new ConcurrentSkipListMap(); + assertNull(empty.get(one)); + } + + /** + * isEmpty is true of empty map and false for non-empty + */ + public void testIsEmpty() { + ConcurrentSkipListMap empty = new ConcurrentSkipListMap(); + ConcurrentSkipListMap map = map5(); + assertTrue(empty.isEmpty()); + assertFalse(map.isEmpty()); + } + + /** + * firstKey returns first key + */ + public void testFirstKey() { + ConcurrentSkipListMap map = map5(); + assertEquals(one, map.firstKey()); + } + + /** + * lastKey returns last key + */ + public void testLastKey() { + ConcurrentSkipListMap map = map5(); + assertEquals(five, map.lastKey()); + } + + /** + * keySet.toArray returns contains all keys + */ + public void testKeySetToArray() { + ConcurrentSkipListMap map = map5(); + Set s = map.keySet(); + Object[] ar = s.toArray(); + assertTrue(s.containsAll(Arrays.asList(ar))); + assertEquals(5, ar.length); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * descendingkeySet.toArray returns contains all keys + */ + public void testDescendingKeySetToArray() { + ConcurrentSkipListMap map = map5(); + Set s = map.descendingKeySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + assertTrue(s.containsAll(Arrays.asList(ar))); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * keySet returns a Set containing all the keys + */ + public void testKeySet() { + ConcurrentSkipListMap map = map5(); + Set s = map.keySet(); + assertEquals(5, s.size()); + assertTrue(s.contains(one)); + assertTrue(s.contains(two)); + assertTrue(s.contains(three)); + assertTrue(s.contains(four)); + assertTrue(s.contains(five)); + } + + /** + * keySet is ordered + */ + public void testKeySetOrder() { + ConcurrentSkipListMap map = map5(); + Set s = map.keySet(); + Iterator i = s.iterator(); + Integer last = (Integer)i.next(); + assertEquals(last, one); + int count = 1; + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) < 0); + last = k; + ++count; + } + assertEquals(5, count); + } + + /** + * descending iterator of key set is inverse ordered + */ + public void testKeySetDescendingIteratorOrder() { + ConcurrentSkipListMap map = map5(); + NavigableSet s = map.navigableKeySet(); + Iterator i = s.descendingIterator(); + Integer last = (Integer)i.next(); + assertEquals(last, five); + int count = 1; + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) > 0); + last = k; + ++count; + } + assertEquals(5, count); + } + + /** + * descendingKeySet is ordered + */ + public void testDescendingKeySetOrder() { + ConcurrentSkipListMap map = map5(); + Set s = map.descendingKeySet(); + Iterator i = s.iterator(); + Integer last = (Integer)i.next(); + assertEquals(last, five); + int count = 1; + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) > 0); + last = k; + ++count; + } + assertEquals(5, count); + } + + /** + * descending iterator of descendingKeySet is ordered + */ + public void testDescendingKeySetDescendingIteratorOrder() { + ConcurrentSkipListMap map = map5(); + NavigableSet s = map.descendingKeySet(); + Iterator i = s.descendingIterator(); + Integer last = (Integer)i.next(); + assertEquals(last, one); + int count = 1; + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) < 0); + last = k; + ++count; + } + assertEquals(5, count); + } + + /** + * Values.toArray contains all values + */ + public void testValuesToArray() { + ConcurrentSkipListMap map = map5(); + Collection v = map.values(); + Object[] ar = v.toArray(); + ArrayList s = new ArrayList(Arrays.asList(ar)); + assertEquals(5, ar.length); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * values collection contains all values + */ + public void testValues() { + ConcurrentSkipListMap map = map5(); + Collection s = map.values(); + assertEquals(5, s.size()); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * entrySet contains all pairs + */ + public void testEntrySet() { + ConcurrentSkipListMap map = map5(); + Set s = map.entrySet(); + assertEquals(5, s.size()); + Iterator it = s.iterator(); + while (it.hasNext()) { + Map.Entry e = (Map.Entry) it.next(); + assertTrue( + (e.getKey().equals(one) && e.getValue().equals("A")) || + (e.getKey().equals(two) && e.getValue().equals("B")) || + (e.getKey().equals(three) && e.getValue().equals("C")) || + (e.getKey().equals(four) && e.getValue().equals("D")) || + (e.getKey().equals(five) && e.getValue().equals("E"))); + } + } + + /** + * descendingEntrySet contains all pairs + */ + public void testDescendingEntrySet() { + ConcurrentSkipListMap map = map5(); + Set s = map.descendingMap().entrySet(); + assertEquals(5, s.size()); + Iterator it = s.iterator(); + while (it.hasNext()) { + Map.Entry e = (Map.Entry) it.next(); + assertTrue( + (e.getKey().equals(one) && e.getValue().equals("A")) || + (e.getKey().equals(two) && e.getValue().equals("B")) || + (e.getKey().equals(three) && e.getValue().equals("C")) || + (e.getKey().equals(four) && e.getValue().equals("D")) || + (e.getKey().equals(five) && e.getValue().equals("E"))); + } + } + + /** + * entrySet.toArray contains all entries + */ + public void testEntrySetToArray() { + ConcurrentSkipListMap map = map5(); + Set s = map.entrySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + for (int i = 0; i < 5; ++i) { + assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey())); + assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue())); + } + } + + /** + * descendingEntrySet.toArray contains all entries + */ + public void testDescendingEntrySetToArray() { + ConcurrentSkipListMap map = map5(); + Set s = map.descendingMap().entrySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + for (int i = 0; i < 5; ++i) { + assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey())); + assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue())); + } + } + + /** + * putAll adds all key-value pairs from the given map + */ + public void testPutAll() { + ConcurrentSkipListMap empty = new ConcurrentSkipListMap(); + ConcurrentSkipListMap map = map5(); + empty.putAll(map); + assertEquals(5, empty.size()); + assertTrue(empty.containsKey(one)); + assertTrue(empty.containsKey(two)); + assertTrue(empty.containsKey(three)); + assertTrue(empty.containsKey(four)); + assertTrue(empty.containsKey(five)); + } + + /** + * putIfAbsent works when the given key is not present + */ + public void testPutIfAbsent() { + ConcurrentSkipListMap map = map5(); + map.putIfAbsent(six, "Z"); + assertTrue(map.containsKey(six)); + } + + /** + * putIfAbsent does not add the pair if the key is already present + */ + public void testPutIfAbsent2() { + ConcurrentSkipListMap map = map5(); + assertEquals("A", map.putIfAbsent(one, "Z")); + } + + /** + * replace fails when the given key is not present + */ + public void testReplace() { + ConcurrentSkipListMap map = map5(); + assertNull(map.replace(six, "Z")); + assertFalse(map.containsKey(six)); + } + + /** + * replace succeeds if the key is already present + */ + public void testReplace2() { + ConcurrentSkipListMap map = map5(); + assertNotNull(map.replace(one, "Z")); + assertEquals("Z", map.get(one)); + } + + /** + * replace value fails when the given key not mapped to expected value + */ + public void testReplaceValue() { + ConcurrentSkipListMap map = map5(); + assertEquals("A", map.get(one)); + assertFalse(map.replace(one, "Z", "Z")); + assertEquals("A", map.get(one)); + } + + /** + * replace value succeeds when the given key mapped to expected value + */ + public void testReplaceValue2() { + ConcurrentSkipListMap map = map5(); + assertEquals("A", map.get(one)); + assertTrue(map.replace(one, "A", "Z")); + assertEquals("Z", map.get(one)); + } + + /** + * remove removes the correct key-value pair from the map + */ + public void testRemove() { + ConcurrentSkipListMap map = map5(); + map.remove(five); + assertEquals(4, map.size()); + assertFalse(map.containsKey(five)); + } + + /** + * remove(key,value) removes only if pair present + */ + public void testRemove2() { + ConcurrentSkipListMap map = map5(); + assertTrue(map.containsKey(five)); + assertEquals("E", map.get(five)); + map.remove(five, "E"); + assertEquals(4, map.size()); + assertFalse(map.containsKey(five)); + map.remove(four, "A"); + assertEquals(4, map.size()); + assertTrue(map.containsKey(four)); + } + + /** + * lowerEntry returns preceding entry. + */ + public void testLowerEntry() { + ConcurrentSkipListMap map = map5(); + Map.Entry e1 = map.lowerEntry(three); + assertEquals(two, e1.getKey()); + + Map.Entry e2 = map.lowerEntry(six); + assertEquals(five, e2.getKey()); + + Map.Entry e3 = map.lowerEntry(one); + assertNull(e3); + + Map.Entry e4 = map.lowerEntry(zero); + assertNull(e4); + } + + /** + * higherEntry returns next entry. + */ + public void testHigherEntry() { + ConcurrentSkipListMap map = map5(); + Map.Entry e1 = map.higherEntry(three); + assertEquals(four, e1.getKey()); + + Map.Entry e2 = map.higherEntry(zero); + assertEquals(one, e2.getKey()); + + Map.Entry e3 = map.higherEntry(five); + assertNull(e3); + + Map.Entry e4 = map.higherEntry(six); + assertNull(e4); + } + + /** + * floorEntry returns preceding entry. + */ + public void testFloorEntry() { + ConcurrentSkipListMap map = map5(); + Map.Entry e1 = map.floorEntry(three); + assertEquals(three, e1.getKey()); + + Map.Entry e2 = map.floorEntry(six); + assertEquals(five, e2.getKey()); + + Map.Entry e3 = map.floorEntry(one); + assertEquals(one, e3.getKey()); + + Map.Entry e4 = map.floorEntry(zero); + assertNull(e4); + } + + /** + * ceilingEntry returns next entry. + */ + public void testCeilingEntry() { + ConcurrentSkipListMap map = map5(); + Map.Entry e1 = map.ceilingEntry(three); + assertEquals(three, e1.getKey()); + + Map.Entry e2 = map.ceilingEntry(zero); + assertEquals(one, e2.getKey()); + + Map.Entry e3 = map.ceilingEntry(five); + assertEquals(five, e3.getKey()); + + Map.Entry e4 = map.ceilingEntry(six); + assertNull(e4); + } + + /** + * lowerEntry, higherEntry, ceilingEntry, and floorEntry return + * immutable entries + */ + public void testEntryImmutability() { + ConcurrentSkipListMap map = map5(); + Map.Entry e = map.lowerEntry(three); + assertEquals(two, e.getKey()); + try { + e.setValue("X"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.higherEntry(zero); + assertEquals(one, e.getKey()); + try { + e.setValue("X"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.floorEntry(one); + assertEquals(one, e.getKey()); + try { + e.setValue("X"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.ceilingEntry(five); + assertEquals(five, e.getKey()); + try { + e.setValue("X"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + } + + /** + * lowerKey returns preceding element + */ + public void testLowerKey() { + ConcurrentSkipListMap q = map5(); + Object e1 = q.lowerKey(three); + assertEquals(two, e1); + + Object e2 = q.lowerKey(six); + assertEquals(five, e2); + + Object e3 = q.lowerKey(one); + assertNull(e3); + + Object e4 = q.lowerKey(zero); + assertNull(e4); + } + + /** + * higherKey returns next element + */ + public void testHigherKey() { + ConcurrentSkipListMap q = map5(); + Object e1 = q.higherKey(three); + assertEquals(four, e1); + + Object e2 = q.higherKey(zero); + assertEquals(one, e2); + + Object e3 = q.higherKey(five); + assertNull(e3); + + Object e4 = q.higherKey(six); + assertNull(e4); + } + + /** + * floorKey returns preceding element + */ + public void testFloorKey() { + ConcurrentSkipListMap q = map5(); + Object e1 = q.floorKey(three); + assertEquals(three, e1); + + Object e2 = q.floorKey(six); + assertEquals(five, e2); + + Object e3 = q.floorKey(one); + assertEquals(one, e3); + + Object e4 = q.floorKey(zero); + assertNull(e4); + } + + /** + * ceilingKey returns next element + */ + public void testCeilingKey() { + ConcurrentSkipListMap q = map5(); + Object e1 = q.ceilingKey(three); + assertEquals(three, e1); + + Object e2 = q.ceilingKey(zero); + assertEquals(one, e2); + + Object e3 = q.ceilingKey(five); + assertEquals(five, e3); + + Object e4 = q.ceilingKey(six); + assertNull(e4); + } + + /** + * pollFirstEntry returns entries in order + */ + public void testPollFirstEntry() { + ConcurrentSkipListMap map = map5(); + Map.Entry e = map.pollFirstEntry(); + assertEquals(one, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(two, e.getKey()); + map.put(one, "A"); + e = map.pollFirstEntry(); + assertEquals(one, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(three, e.getKey()); + map.remove(four); + e = map.pollFirstEntry(); + assertEquals(five, e.getKey()); + try { + e.setValue("A"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollFirstEntry(); + assertNull(e); + } + + /** + * pollLastEntry returns entries in order + */ + public void testPollLastEntry() { + ConcurrentSkipListMap map = map5(); + Map.Entry e = map.pollLastEntry(); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(four, e.getKey()); + map.put(five, "E"); + e = map.pollLastEntry(); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(three, e.getKey()); + map.remove(two); + e = map.pollLastEntry(); + assertEquals(one, e.getKey()); + try { + e.setValue("E"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollLastEntry(); + assertNull(e); + } + + /** + * size returns the correct values + */ + public void testSize() { + ConcurrentSkipListMap map = map5(); + ConcurrentSkipListMap empty = new ConcurrentSkipListMap(); + assertEquals(0, empty.size()); + assertEquals(5, map.size()); + } + + /** + * toString contains toString of elements + */ + public void testToString() { + ConcurrentSkipListMap map = map5(); + String s = map.toString(); + for (int i = 1; i <= 5; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + // Exception tests + + /** + * get(null) of nonempty map throws NPE + */ + public void testGet_NullPointerException() { + ConcurrentSkipListMap c = map5(); + try { + c.get(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsKey(null) of nonempty map throws NPE + */ + public void testContainsKey_NullPointerException() { + ConcurrentSkipListMap c = map5(); + try { + c.containsKey(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsValue(null) throws NPE + */ + public void testContainsValue_NullPointerException() { + ConcurrentSkipListMap c = new ConcurrentSkipListMap(); + try { + c.containsValue(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * put(null,x) throws NPE + */ + public void testPut1_NullPointerException() { + ConcurrentSkipListMap c = map5(); + try { + c.put(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * putIfAbsent(null, x) throws NPE + */ + public void testPutIfAbsent1_NullPointerException() { + ConcurrentSkipListMap c = map5(); + try { + c.putIfAbsent(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(null, x) throws NPE + */ + public void testReplace_NullPointerException() { + ConcurrentSkipListMap c = map5(); + try { + c.replace(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(null, x, y) throws NPE + */ + public void testReplaceValue_NullPointerException() { + ConcurrentSkipListMap c = map5(); + try { + c.replace(null, one, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null) throws NPE + */ + public void testRemove1_NullPointerException() { + ConcurrentSkipListMap c = new ConcurrentSkipListMap(); + c.put("sadsdf", "asdads"); + try { + c.remove(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null, x) throws NPE + */ + public void testRemove2_NullPointerException() { + ConcurrentSkipListMap c = new ConcurrentSkipListMap(); + c.put("sadsdf", "asdads"); + try { + c.remove(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(x, null) returns false + */ + public void testRemove3() { + ConcurrentSkipListMap c = new ConcurrentSkipListMap(); + c.put("sadsdf", "asdads"); + assertFalse(c.remove("sadsdf", null)); + } + + /** + * A deserialized map equals original + */ + public void testSerialization() throws Exception { + NavigableMap x = map5(); + NavigableMap y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertEquals(x, y); + assertEquals(y, x); + } + + /** + * subMap returns map with keys in requested range + */ + public void testSubMapContents() { + ConcurrentSkipListMap map = map5(); + NavigableMap sm = map.subMap(two, true, four, false); + assertEquals(two, sm.firstKey()); + assertEquals(three, sm.lastKey()); + assertEquals(2, sm.size()); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + Iterator r = sm.descendingKeySet().iterator(); + k = (Integer)(r.next()); + assertEquals(three, k); + k = (Integer)(r.next()); + assertEquals(two, k); + assertFalse(r.hasNext()); + + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(two)); + assertEquals(4, map.size()); + assertEquals(1, sm.size()); + assertEquals(three, sm.firstKey()); + assertEquals(three, sm.lastKey()); + assertEquals("C", sm.remove(three)); + assertTrue(sm.isEmpty()); + assertEquals(3, map.size()); + } + + public void testSubMapContents2() { + ConcurrentSkipListMap map = map5(); + NavigableMap sm = map.subMap(two, true, three, false); + assertEquals(1, sm.size()); + assertEquals(two, sm.firstKey()); + assertEquals(two, sm.lastKey()); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertFalse(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + assertFalse(i.hasNext()); + Iterator r = sm.descendingKeySet().iterator(); + k = (Integer)(r.next()); + assertEquals(two, k); + assertFalse(r.hasNext()); + + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(two)); + assertEquals(4, map.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertSame(sm.remove(three), null); + assertEquals(4, map.size()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testHeadMapContents() { + ConcurrentSkipListMap map = map5(); + NavigableMap sm = map.headMap(four, false); + assertTrue(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(one, k); + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, map.size()); + assertEquals(four, map.firstKey()); + } + + /** + * tailMap returns map with keys in requested range + */ + public void testTailMapContents() { + ConcurrentSkipListMap map = map5(); + NavigableMap sm = map.tailMap(two, true); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertTrue(sm.containsKey(four)); + assertTrue(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + k = (Integer)(i.next()); + assertEquals(four, k); + k = (Integer)(i.next()); + assertEquals(five, k); + assertFalse(i.hasNext()); + Iterator r = sm.descendingKeySet().iterator(); + k = (Integer)(r.next()); + assertEquals(five, k); + k = (Integer)(r.next()); + assertEquals(four, k); + k = (Integer)(r.next()); + assertEquals(three, k); + k = (Integer)(r.next()); + assertEquals(two, k); + assertFalse(r.hasNext()); + + Iterator ei = sm.entrySet().iterator(); + Map.Entry e; + e = (Map.Entry)(ei.next()); + assertEquals(two, e.getKey()); + assertEquals("B", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(three, e.getKey()); + assertEquals("C", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(four, e.getKey()); + assertEquals("D", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + assertFalse(i.hasNext()); + + NavigableMap ssm = sm.tailMap(four, true); + assertEquals(four, ssm.firstKey()); + assertEquals(five, ssm.lastKey()); + assertEquals("D", ssm.remove(four)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, map.size()); + } + + Random rnd = new Random(666); + BitSet bs; + + /** + * Submaps of submaps subdivide correctly + */ + public void testRecursiveSubMaps() throws Exception { + int mapSize = expensiveTests ? 1000 : 100; + Class cl = ConcurrentSkipListMap.class; + NavigableMap map = newMap(cl); + bs = new BitSet(mapSize); + + populate(map, mapSize); + check(map, 0, mapSize - 1, true); + check(map.descendingMap(), 0, mapSize - 1, false); + + mutateMap(map, 0, mapSize - 1); + check(map, 0, mapSize - 1, true); + check(map.descendingMap(), 0, mapSize - 1, false); + + bashSubMap(map.subMap(0, true, mapSize, false), + 0, mapSize - 1, true); + } + + static NavigableMap newMap(Class cl) throws Exception { + NavigableMap result = + (NavigableMap) cl.newInstance(); + assertEquals(0, result.size()); + assertFalse(result.keySet().iterator().hasNext()); + return result; + } + + void populate(NavigableMap map, int limit) { + for (int i = 0, n = 2 * limit / 3; i < n; i++) { + int key = rnd.nextInt(limit); + put(map, key); + } + } + + void mutateMap(NavigableMap map, int min, int max) { + int size = map.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(map, min - 5 + rnd.nextInt(rangeSize + 10)); + } + + // Remove a bunch of entries with iterator + for (Iterator it = map.keySet().iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next()); + it.remove(); + } + } + + // Add entries till we're back to original size + while (map.size() < size) { + int key = min + rnd.nextInt(rangeSize); + assertTrue(key >= min && key <= max); + put(map, key); + } + } + + void mutateSubMap(NavigableMap map, int min, int max) { + int size = map.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(map, min - 5 + rnd.nextInt(rangeSize + 10)); + } + + // Remove a bunch of entries with iterator + for (Iterator it = map.keySet().iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next()); + it.remove(); + } + } + + // Add entries till we're back to original size + while (map.size() < size) { + int key = min - 5 + rnd.nextInt(rangeSize + 10); + if (key >= min && key <= max) { + put(map, key); + } else { + try { + map.put(key, 2 * key); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + } + + void put(NavigableMap map, int key) { + if (map.put(key, 2 * key) == null) + bs.set(key); + } + + void remove(NavigableMap map, int key) { + if (map.remove(key) != null) + bs.clear(key); + } + + void bashSubMap(NavigableMap map, + int min, int max, boolean ascending) { + check(map, min, max, ascending); + check(map.descendingMap(), min, max, !ascending); + + mutateSubMap(map, min, max); + check(map, min, max, ascending); + check(map.descendingMap(), min, max, !ascending); + + // Recurse + if (max - min < 2) + return; + int midPoint = (min + max) / 2; + + // headMap - pick direction and endpoint inclusion randomly + boolean incl = rnd.nextBoolean(); + NavigableMap hm = map.headMap(midPoint, incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubMap(hm, min, midPoint - (incl ? 0 : 1), true); + else + bashSubMap(hm.descendingMap(), min, midPoint - (incl ? 0 : 1), + false); + } else { + if (rnd.nextBoolean()) + bashSubMap(hm, midPoint + (incl ? 0 : 1), max, false); + else + bashSubMap(hm.descendingMap(), midPoint + (incl ? 0 : 1), max, + true); + } + + // tailMap - pick direction and endpoint inclusion randomly + incl = rnd.nextBoolean(); + NavigableMap tm = map.tailMap(midPoint,incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubMap(tm, midPoint + (incl ? 0 : 1), max, true); + else + bashSubMap(tm.descendingMap(), midPoint + (incl ? 0 : 1), max, + false); + } else { + if (rnd.nextBoolean()) { + bashSubMap(tm, min, midPoint - (incl ? 0 : 1), false); + } else { + bashSubMap(tm.descendingMap(), min, midPoint - (incl ? 0 : 1), + true); + } + } + + // subMap - pick direction and endpoint inclusion randomly + int rangeSize = max - min + 1; + int[] endpoints = new int[2]; + endpoints[0] = min + rnd.nextInt(rangeSize); + endpoints[1] = min + rnd.nextInt(rangeSize); + Arrays.sort(endpoints); + boolean lowIncl = rnd.nextBoolean(); + boolean highIncl = rnd.nextBoolean(); + if (ascending) { + NavigableMap sm = map.subMap( + endpoints[0], lowIncl, endpoints[1], highIncl); + if (rnd.nextBoolean()) + bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true); + else + bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false); + } else { + NavigableMap sm = map.subMap( + endpoints[1], highIncl, endpoints[0], lowIncl); + if (rnd.nextBoolean()) + bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false); + else + bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true); + } + } + + /** + * min and max are both inclusive. If max < min, interval is empty. + */ + void check(NavigableMap map, + final int min, final int max, final boolean ascending) { + class ReferenceSet { + int lower(int key) { + return ascending ? lowerAscending(key) : higherAscending(key); + } + int floor(int key) { + return ascending ? floorAscending(key) : ceilingAscending(key); + } + int ceiling(int key) { + return ascending ? ceilingAscending(key) : floorAscending(key); + } + int higher(int key) { + return ascending ? higherAscending(key) : lowerAscending(key); + } + int first() { + return ascending ? firstAscending() : lastAscending(); + } + int last() { + return ascending ? lastAscending() : firstAscending(); + } + int lowerAscending(int key) { + return floorAscending(key - 1); + } + int floorAscending(int key) { + if (key < min) + return -1; + else if (key > max) + key = max; + + // BitSet should support this! Test would run much faster + while (key >= min) { + if (bs.get(key)) + return key; + key--; + } + return -1; + } + int ceilingAscending(int key) { + if (key < min) + key = min; + else if (key > max) + return -1; + int result = bs.nextSetBit(key); + return result > max ? -1 : result; + } + int higherAscending(int key) { + return ceilingAscending(key + 1); + } + private int firstAscending() { + int result = ceilingAscending(min); + return result > max ? -1 : result; + } + private int lastAscending() { + int result = floorAscending(max); + return result < min ? -1 : result; + } + } + ReferenceSet rs = new ReferenceSet(); + + // Test contents using containsKey + int size = 0; + for (int i = min; i <= max; i++) { + boolean bsContainsI = bs.get(i); + assertEquals(bsContainsI, map.containsKey(i)); + if (bsContainsI) + size++; + } + assertEquals(size, map.size()); + + // Test contents using contains keySet iterator + int size2 = 0; + int previousKey = -1; + for (int key : map.keySet()) { + assertTrue(bs.get(key)); + size2++; + assertTrue(previousKey < 0 || + (ascending ? key - previousKey > 0 : key - previousKey < 0)); + previousKey = key; + } + assertEquals(size2, size); + + // Test navigation ops + for (int key = min - 1; key <= max + 1; key++) { + assertEq(map.lowerKey(key), rs.lower(key)); + assertEq(map.floorKey(key), rs.floor(key)); + assertEq(map.higherKey(key), rs.higher(key)); + assertEq(map.ceilingKey(key), rs.ceiling(key)); + } + + // Test extrema + if (map.size() != 0) { + assertEq(map.firstKey(), rs.first()); + assertEq(map.lastKey(), rs.last()); + } else { + assertEq(rs.first(), -1); + assertEq(rs.last(), -1); + try { + map.firstKey(); + shouldThrow(); + } catch (NoSuchElementException success) {} + try { + map.lastKey(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + } + + static void assertEq(Integer i, int j) { + if (i == null) + assertEquals(j, -1); + else + assertEquals((int) i, j); + } + + static boolean eq(Integer i, int j) { + return (i == null) ? j == -1 : i == j; + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java new file mode 100644 index 00000000000..9012417716c --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java @@ -0,0 +1,1007 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.Set; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentSkipListSet; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ConcurrentSkipListSetTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ConcurrentSkipListSetTest.class); + } + + static class MyReverseComparator implements Comparator { + public int compare(Object x, Object y) { + return ((Comparable)y).compareTo(x); + } + } + + /** + * Returns a new set of given size containing consecutive + * Integers 0 ... n. + */ + private ConcurrentSkipListSet populatedSet(int n) { + ConcurrentSkipListSet q = + new ConcurrentSkipListSet(); + assertTrue(q.isEmpty()); + for (int i = n - 1; i >= 0; i -= 2) + assertTrue(q.add(new Integer(i))); + for (int i = (n & 1); i < n; i += 2) + assertTrue(q.add(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(n, q.size()); + return q; + } + + /** + * Returns a new set of first 5 ints. + */ + private ConcurrentSkipListSet set5() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + assertTrue(q.isEmpty()); + q.add(one); + q.add(two); + q.add(three); + q.add(four); + q.add(five); + assertEquals(5, q.size()); + return q; + } + + /** + * A new set has unbounded capacity + */ + public void testConstructor1() { + assertEquals(0, new ConcurrentSkipListSet().size()); + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new ConcurrentSkipListSet((Collection)null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NPE + */ + public void testConstructor4() { + try { + new ConcurrentSkipListSet(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws NPE + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + new ConcurrentSkipListSet(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Set contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + ConcurrentSkipListSet q = new ConcurrentSkipListSet(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.pollFirst()); + } + + /** + * The comparator used in constructor is used + */ + public void testConstructor7() { + MyReverseComparator cmp = new MyReverseComparator(); + ConcurrentSkipListSet q = new ConcurrentSkipListSet(cmp); + assertEquals(cmp, q.comparator()); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + q.addAll(Arrays.asList(ints)); + for (int i = SIZE - 1; i >= 0; --i) + assertEquals(ints[i], q.pollFirst()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + assertTrue(q.isEmpty()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.add(new Integer(2)); + q.pollFirst(); + q.pollFirst(); + assertTrue(q.isEmpty()); + } + + /** + * size changes when elements added and removed + */ + public void testSize() { + ConcurrentSkipListSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.pollFirst(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * add(null) throws NPE + */ + public void testAddNull() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Add of comparable element succeeds + */ + public void testAdd() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + assertTrue(q.add(zero)); + assertTrue(q.add(one)); + } + + /** + * Add of duplicate element fails + */ + public void testAddDup() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + assertTrue(q.add(zero)); + assertFalse(q.add(zero)); + } + + /** + * Add of non-Comparable throws CCE + */ + public void testAddNonComparable() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + try { + q.add(new Object()); + q.add(new Object()); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testAddAll2() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + Integer[] ints = new Integer[SIZE]; + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Set contains all elements of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(SIZE - 1 - i); + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(i, q.pollFirst()); + } + + /** + * pollFirst succeeds unless empty + */ + public void testPollFirst() { + ConcurrentSkipListSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst()); + } + assertNull(q.pollFirst()); + } + + /** + * pollLast succeeds unless empty + */ + public void testPollLast() { + ConcurrentSkipListSet q = populatedSet(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.pollLast()); + } + assertNull(q.pollFirst()); + } + + /** + * remove(x) removes x and returns true if present + */ + public void testRemoveElement() { + ConcurrentSkipListSet q = populatedSet(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertTrue(q.contains(i - 1)); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertFalse(q.remove(i + 1)); + assertFalse(q.contains(i + 1)); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + ConcurrentSkipListSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.pollFirst(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + ConcurrentSkipListSet q = populatedSet(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + ConcurrentSkipListSet q = populatedSet(SIZE); + ConcurrentSkipListSet p = new ConcurrentSkipListSet(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + ConcurrentSkipListSet q = populatedSet(SIZE); + ConcurrentSkipListSet p = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.pollFirst(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + ConcurrentSkipListSet q = populatedSet(SIZE); + ConcurrentSkipListSet p = populatedSet(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.pollFirst()); + assertFalse(q.contains(x)); + } + } + } + + /** + * lower returns preceding element + */ + public void testLower() { + ConcurrentSkipListSet q = set5(); + Object e1 = q.lower(three); + assertEquals(two, e1); + + Object e2 = q.lower(six); + assertEquals(five, e2); + + Object e3 = q.lower(one); + assertNull(e3); + + Object e4 = q.lower(zero); + assertNull(e4); + } + + /** + * higher returns next element + */ + public void testHigher() { + ConcurrentSkipListSet q = set5(); + Object e1 = q.higher(three); + assertEquals(four, e1); + + Object e2 = q.higher(zero); + assertEquals(one, e2); + + Object e3 = q.higher(five); + assertNull(e3); + + Object e4 = q.higher(six); + assertNull(e4); + } + + /** + * floor returns preceding element + */ + public void testFloor() { + ConcurrentSkipListSet q = set5(); + Object e1 = q.floor(three); + assertEquals(three, e1); + + Object e2 = q.floor(six); + assertEquals(five, e2); + + Object e3 = q.floor(one); + assertEquals(one, e3); + + Object e4 = q.floor(zero); + assertNull(e4); + } + + /** + * ceiling returns next element + */ + public void testCeiling() { + ConcurrentSkipListSet q = set5(); + Object e1 = q.ceiling(three); + assertEquals(three, e1); + + Object e2 = q.ceiling(zero); + assertEquals(one, e2); + + Object e3 = q.ceiling(five); + assertEquals(five, e3); + + Object e4 = q.ceiling(six); + assertNull(e4); + } + + /** + * toArray contains all elements in sorted order + */ + public void testToArray() { + ConcurrentSkipListSet q = populatedSet(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.pollFirst()); + } + + /** + * toArray(a) contains all elements in sorted order + */ + public void testToArray2() { + ConcurrentSkipListSet q = populatedSet(SIZE); + Integer[] ints = new Integer[SIZE]; + assertSame(ints, q.toArray(ints)); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.pollFirst()); + } + + /** + * iterator iterates through all elements + */ + public void testIterator() { + ConcurrentSkipListSet q = populatedSet(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty set has no elements + */ + public void testEmptyIterator() { + NavigableSet s = new ConcurrentSkipListSet(); + assertIteratorExhausted(s.iterator()); + assertIteratorExhausted(s.descendingSet().iterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + q.add(new Integer(2)); + q.add(new Integer(1)); + q.add(new Integer(3)); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertEquals(it.next(), new Integer(2)); + assertEquals(it.next(), new Integer(3)); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + ConcurrentSkipListSet q = populatedSet(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized set has same elements + */ + public void testSerialization() throws Exception { + NavigableSet x = populatedSet(SIZE); + NavigableSet y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x, y); + assertEquals(y, x); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.pollFirst(), y.pollFirst()); + } + assertTrue(y.isEmpty()); + } + + /** + * subSet returns set with keys in requested range + */ + public void testSubSetContents() { + ConcurrentSkipListSet set = set5(); + SortedSet sm = set.subSet(two, four); + assertEquals(two, sm.first()); + assertEquals(three, sm.last()); + assertEquals(2, sm.size()); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(two)); + assertEquals(4, set.size()); + assertEquals(1, sm.size()); + assertEquals(three, sm.first()); + assertEquals(three, sm.last()); + assertTrue(sm.remove(three)); + assertTrue(sm.isEmpty()); + assertEquals(3, set.size()); + } + + public void testSubSetContents2() { + ConcurrentSkipListSet set = set5(); + SortedSet sm = set.subSet(two, three); + assertEquals(1, sm.size()); + assertEquals(two, sm.first()); + assertEquals(two, sm.last()); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertFalse(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(two)); + assertEquals(4, set.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertFalse(sm.remove(three)); + assertEquals(4, set.size()); + } + + /** + * headSet returns set with keys in requested range + */ + public void testHeadSetContents() { + ConcurrentSkipListSet set = set5(); + SortedSet sm = set.headSet(four); + assertTrue(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(one, k); + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, set.size()); + assertEquals(four, set.first()); + } + + /** + * tailSet returns set with keys in requested range + */ + public void testTailSetContents() { + ConcurrentSkipListSet set = set5(); + SortedSet sm = set.tailSet(two); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertTrue(sm.contains(four)); + assertTrue(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + k = (Integer)(i.next()); + assertEquals(four, k); + k = (Integer)(i.next()); + assertEquals(five, k); + assertFalse(i.hasNext()); + + SortedSet ssm = sm.tailSet(four); + assertEquals(four, ssm.first()); + assertEquals(five, ssm.last()); + assertTrue(ssm.remove(four)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, set.size()); + } + + Random rnd = new Random(666); + + /** + * Subsets of subsets subdivide correctly + */ + public void testRecursiveSubSets() throws Exception { + int setSize = expensiveTests ? 1000 : 100; + Class cl = ConcurrentSkipListSet.class; + + NavigableSet set = newSet(cl); + BitSet bs = new BitSet(setSize); + + populate(set, setSize, bs); + check(set, 0, setSize - 1, true, bs); + check(set.descendingSet(), 0, setSize - 1, false, bs); + + mutateSet(set, 0, setSize - 1, bs); + check(set, 0, setSize - 1, true, bs); + check(set.descendingSet(), 0, setSize - 1, false, bs); + + bashSubSet(set.subSet(0, true, setSize, false), + 0, setSize - 1, true, bs); + } + + /** + * addAll is idempotent + */ + public void testAddAll_idempotent() throws Exception { + Set x = populatedSet(SIZE); + Set y = new ConcurrentSkipListSet(x); + y.addAll(x); + assertEquals(x, y); + assertEquals(y, x); + } + + static NavigableSet newSet(Class cl) throws Exception { + NavigableSet result = (NavigableSet) cl.newInstance(); + assertEquals(0, result.size()); + assertFalse(result.iterator().hasNext()); + return result; + } + + void populate(NavigableSet set, int limit, BitSet bs) { + for (int i = 0, n = 2 * limit / 3; i < n; i++) { + int element = rnd.nextInt(limit); + put(set, element, bs); + } + } + + void mutateSet(NavigableSet set, int min, int max, BitSet bs) { + int size = set.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(set, min - 5 + rnd.nextInt(rangeSize + 10), bs); + } + + // Remove a bunch of entries with iterator + for (Iterator it = set.iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next()); + it.remove(); + } + } + + // Add entries till we're back to original size + while (set.size() < size) { + int element = min + rnd.nextInt(rangeSize); + assertTrue(element >= min && element <= max); + put(set, element, bs); + } + } + + void mutateSubSet(NavigableSet set, int min, int max, + BitSet bs) { + int size = set.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(set, min - 5 + rnd.nextInt(rangeSize + 10), bs); + } + + // Remove a bunch of entries with iterator + for (Iterator it = set.iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next()); + it.remove(); + } + } + + // Add entries till we're back to original size + while (set.size() < size) { + int element = min - 5 + rnd.nextInt(rangeSize + 10); + if (element >= min && element <= max) { + put(set, element, bs); + } else { + try { + set.add(element); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + } + + void put(NavigableSet set, int element, BitSet bs) { + if (set.add(element)) + bs.set(element); + } + + void remove(NavigableSet set, int element, BitSet bs) { + if (set.remove(element)) + bs.clear(element); + } + + void bashSubSet(NavigableSet set, + int min, int max, boolean ascending, + BitSet bs) { + check(set, min, max, ascending, bs); + check(set.descendingSet(), min, max, !ascending, bs); + + mutateSubSet(set, min, max, bs); + check(set, min, max, ascending, bs); + check(set.descendingSet(), min, max, !ascending, bs); + + // Recurse + if (max - min < 2) + return; + int midPoint = (min + max) / 2; + + // headSet - pick direction and endpoint inclusion randomly + boolean incl = rnd.nextBoolean(); + NavigableSet hm = set.headSet(midPoint, incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubSet(hm, min, midPoint - (incl ? 0 : 1), true, bs); + else + bashSubSet(hm.descendingSet(), min, midPoint - (incl ? 0 : 1), + false, bs); + } else { + if (rnd.nextBoolean()) + bashSubSet(hm, midPoint + (incl ? 0 : 1), max, false, bs); + else + bashSubSet(hm.descendingSet(), midPoint + (incl ? 0 : 1), max, + true, bs); + } + + // tailSet - pick direction and endpoint inclusion randomly + incl = rnd.nextBoolean(); + NavigableSet tm = set.tailSet(midPoint,incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubSet(tm, midPoint + (incl ? 0 : 1), max, true, bs); + else + bashSubSet(tm.descendingSet(), midPoint + (incl ? 0 : 1), max, + false, bs); + } else { + if (rnd.nextBoolean()) { + bashSubSet(tm, min, midPoint - (incl ? 0 : 1), false, bs); + } else { + bashSubSet(tm.descendingSet(), min, midPoint - (incl ? 0 : 1), + true, bs); + } + } + + // subSet - pick direction and endpoint inclusion randomly + int rangeSize = max - min + 1; + int[] endpoints = new int[2]; + endpoints[0] = min + rnd.nextInt(rangeSize); + endpoints[1] = min + rnd.nextInt(rangeSize); + Arrays.sort(endpoints); + boolean lowIncl = rnd.nextBoolean(); + boolean highIncl = rnd.nextBoolean(); + if (ascending) { + NavigableSet sm = set.subSet( + endpoints[0], lowIncl, endpoints[1], highIncl); + if (rnd.nextBoolean()) + bashSubSet(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true, bs); + else + bashSubSet(sm.descendingSet(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false, bs); + } else { + NavigableSet sm = set.subSet( + endpoints[1], highIncl, endpoints[0], lowIncl); + if (rnd.nextBoolean()) + bashSubSet(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false, bs); + else + bashSubSet(sm.descendingSet(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true, bs); + } + } + + /** + * min and max are both inclusive. If max < min, interval is empty. + */ + void check(NavigableSet set, + final int min, final int max, final boolean ascending, + final BitSet bs) { + class ReferenceSet { + int lower(int element) { + return ascending ? + lowerAscending(element) : higherAscending(element); + } + int floor(int element) { + return ascending ? + floorAscending(element) : ceilingAscending(element); + } + int ceiling(int element) { + return ascending ? + ceilingAscending(element) : floorAscending(element); + } + int higher(int element) { + return ascending ? + higherAscending(element) : lowerAscending(element); + } + int first() { + return ascending ? firstAscending() : lastAscending(); + } + int last() { + return ascending ? lastAscending() : firstAscending(); + } + int lowerAscending(int element) { + return floorAscending(element - 1); + } + int floorAscending(int element) { + if (element < min) + return -1; + else if (element > max) + element = max; + + // BitSet should support this! Test would run much faster + while (element >= min) { + if (bs.get(element)) + return element; + element--; + } + return -1; + } + int ceilingAscending(int element) { + if (element < min) + element = min; + else if (element > max) + return -1; + int result = bs.nextSetBit(element); + return result > max ? -1 : result; + } + int higherAscending(int element) { + return ceilingAscending(element + 1); + } + private int firstAscending() { + int result = ceilingAscending(min); + return result > max ? -1 : result; + } + private int lastAscending() { + int result = floorAscending(max); + return result < min ? -1 : result; + } + } + ReferenceSet rs = new ReferenceSet(); + + // Test contents using containsElement + int size = 0; + for (int i = min; i <= max; i++) { + boolean bsContainsI = bs.get(i); + assertEquals(bsContainsI, set.contains(i)); + if (bsContainsI) + size++; + } + assertEquals(size, set.size()); + + // Test contents using contains elementSet iterator + int size2 = 0; + int previousElement = -1; + for (int element : set) { + assertTrue(bs.get(element)); + size2++; + assertTrue(previousElement < 0 || (ascending ? + element - previousElement > 0 : element - previousElement < 0)); + previousElement = element; + } + assertEquals(size2, size); + + // Test navigation ops + for (int element = min - 1; element <= max + 1; element++) { + assertEq(set.lower(element), rs.lower(element)); + assertEq(set.floor(element), rs.floor(element)); + assertEq(set.higher(element), rs.higher(element)); + assertEq(set.ceiling(element), rs.ceiling(element)); + } + + // Test extrema + if (set.size() != 0) { + assertEq(set.first(), rs.first()); + assertEq(set.last(), rs.last()); + } else { + assertEq(rs.first(), -1); + assertEq(rs.last(), -1); + try { + set.first(); + shouldThrow(); + } catch (NoSuchElementException success) {} + try { + set.last(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + } + + static void assertEq(Integer i, int j) { + if (i == null) + assertEquals(j, -1); + else + assertEquals((int) i, j); + } + + static boolean eq(Integer i, int j) { + return (i == null) ? j == -1 : i == j; + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubMapTest.java new file mode 100644 index 00000000000..ddc82f78a56 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubMapTest.java @@ -0,0 +1,1450 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.Set; +import java.util.SortedMap; +import java.util.concurrent.ConcurrentNavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ConcurrentSkipListSubMapTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ConcurrentSkipListSubMapTest.class); + } + + /** + * Returns a new map from Integers 1-5 to Strings "A"-"E". + */ + private static ConcurrentNavigableMap map5() { + ConcurrentSkipListMap map = new ConcurrentSkipListMap(); + assertTrue(map.isEmpty()); + map.put(zero, "Z"); + map.put(one, "A"); + map.put(five, "E"); + map.put(three, "C"); + map.put(two, "B"); + map.put(four, "D"); + map.put(seven, "F"); + assertFalse(map.isEmpty()); + assertEquals(7, map.size()); + return map.subMap(one, true, seven, false); + } + + /** + * Returns a new map from Integers -5 to -1 to Strings "A"-"E". + */ + private static ConcurrentNavigableMap dmap5() { + ConcurrentSkipListMap map = new ConcurrentSkipListMap(); + assertTrue(map.isEmpty()); + map.put(m1, "A"); + map.put(m5, "E"); + map.put(m3, "C"); + map.put(m2, "B"); + map.put(m4, "D"); + assertFalse(map.isEmpty()); + assertEquals(5, map.size()); + return map.descendingMap(); + } + + private static ConcurrentNavigableMap map0() { + ConcurrentSkipListMap map = new ConcurrentSkipListMap(); + assertTrue(map.isEmpty()); + return map.tailMap(one, true); + } + + private static ConcurrentNavigableMap dmap0() { + ConcurrentSkipListMap map = new ConcurrentSkipListMap(); + assertTrue(map.isEmpty()); + return map; + } + + /** + * clear removes all pairs + */ + public void testClear() { + ConcurrentNavigableMap map = map5(); + map.clear(); + assertEquals(0, map.size()); + } + + /** + * Maps with same contents are equal + */ + public void testEquals() { + ConcurrentNavigableMap map1 = map5(); + ConcurrentNavigableMap map2 = map5(); + assertEquals(map1, map2); + assertEquals(map2, map1); + map1.clear(); + assertFalse(map1.equals(map2)); + assertFalse(map2.equals(map1)); + } + + /** + * containsKey returns true for contained key + */ + public void testContainsKey() { + ConcurrentNavigableMap map = map5(); + assertTrue(map.containsKey(one)); + assertFalse(map.containsKey(zero)); + } + + /** + * containsValue returns true for held values + */ + public void testContainsValue() { + ConcurrentNavigableMap map = map5(); + assertTrue(map.containsValue("A")); + assertFalse(map.containsValue("Z")); + } + + /** + * get returns the correct element at the given key, + * or null if not present + */ + public void testGet() { + ConcurrentNavigableMap map = map5(); + assertEquals("A", (String)map.get(one)); + ConcurrentNavigableMap empty = map0(); + assertNull(empty.get(one)); + } + + /** + * isEmpty is true of empty map and false for non-empty + */ + public void testIsEmpty() { + ConcurrentNavigableMap empty = map0(); + ConcurrentNavigableMap map = map5(); + assertTrue(empty.isEmpty()); + assertFalse(map.isEmpty()); + } + + /** + * firstKey returns first key + */ + public void testFirstKey() { + ConcurrentNavigableMap map = map5(); + assertEquals(one, map.firstKey()); + } + + /** + * lastKey returns last key + */ + public void testLastKey() { + ConcurrentNavigableMap map = map5(); + assertEquals(five, map.lastKey()); + } + + /** + * keySet returns a Set containing all the keys + */ + public void testKeySet() { + ConcurrentNavigableMap map = map5(); + Set s = map.keySet(); + assertEquals(5, s.size()); + assertTrue(s.contains(one)); + assertTrue(s.contains(two)); + assertTrue(s.contains(three)); + assertTrue(s.contains(four)); + assertTrue(s.contains(five)); + } + + /** + * keySet is ordered + */ + public void testKeySetOrder() { + ConcurrentNavigableMap map = map5(); + Set s = map.keySet(); + Iterator i = s.iterator(); + Integer last = (Integer)i.next(); + assertEquals(last, one); + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) < 0); + last = k; + } + } + + /** + * values collection contains all values + */ + public void testValues() { + ConcurrentNavigableMap map = map5(); + Collection s = map.values(); + assertEquals(5, s.size()); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * keySet.toArray returns contains all keys + */ + public void testKeySetToArray() { + ConcurrentNavigableMap map = map5(); + Set s = map.keySet(); + Object[] ar = s.toArray(); + assertTrue(s.containsAll(Arrays.asList(ar))); + assertEquals(5, ar.length); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * descendingkeySet.toArray returns contains all keys + */ + public void testDescendingKeySetToArray() { + ConcurrentNavigableMap map = map5(); + Set s = map.descendingKeySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + assertTrue(s.containsAll(Arrays.asList(ar))); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * Values.toArray contains all values + */ + public void testValuesToArray() { + ConcurrentNavigableMap map = map5(); + Collection v = map.values(); + Object[] ar = v.toArray(); + ArrayList s = new ArrayList(Arrays.asList(ar)); + assertEquals(5, ar.length); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * entrySet contains all pairs + */ + public void testEntrySet() { + ConcurrentNavigableMap map = map5(); + Set s = map.entrySet(); + assertEquals(5, s.size()); + Iterator it = s.iterator(); + while (it.hasNext()) { + Map.Entry e = (Map.Entry) it.next(); + assertTrue( + (e.getKey().equals(one) && e.getValue().equals("A")) || + (e.getKey().equals(two) && e.getValue().equals("B")) || + (e.getKey().equals(three) && e.getValue().equals("C")) || + (e.getKey().equals(four) && e.getValue().equals("D")) || + (e.getKey().equals(five) && e.getValue().equals("E"))); + } + } + + /** + * putAll adds all key-value pairs from the given map + */ + public void testPutAll() { + ConcurrentNavigableMap empty = map0(); + ConcurrentNavigableMap map = map5(); + empty.putAll(map); + assertEquals(5, empty.size()); + assertTrue(empty.containsKey(one)); + assertTrue(empty.containsKey(two)); + assertTrue(empty.containsKey(three)); + assertTrue(empty.containsKey(four)); + assertTrue(empty.containsKey(five)); + } + + /** + * putIfAbsent works when the given key is not present + */ + public void testPutIfAbsent() { + ConcurrentNavigableMap map = map5(); + map.putIfAbsent(six, "Z"); + assertTrue(map.containsKey(six)); + } + + /** + * putIfAbsent does not add the pair if the key is already present + */ + public void testPutIfAbsent2() { + ConcurrentNavigableMap map = map5(); + assertEquals("A", map.putIfAbsent(one, "Z")); + } + + /** + * replace fails when the given key is not present + */ + public void testReplace() { + ConcurrentNavigableMap map = map5(); + assertNull(map.replace(six, "Z")); + assertFalse(map.containsKey(six)); + } + + /** + * replace succeeds if the key is already present + */ + public void testReplace2() { + ConcurrentNavigableMap map = map5(); + assertNotNull(map.replace(one, "Z")); + assertEquals("Z", map.get(one)); + } + + /** + * replace value fails when the given key not mapped to expected value + */ + public void testReplaceValue() { + ConcurrentNavigableMap map = map5(); + assertEquals("A", map.get(one)); + assertFalse(map.replace(one, "Z", "Z")); + assertEquals("A", map.get(one)); + } + + /** + * replace value succeeds when the given key mapped to expected value + */ + public void testReplaceValue2() { + ConcurrentNavigableMap map = map5(); + assertEquals("A", map.get(one)); + assertTrue(map.replace(one, "A", "Z")); + assertEquals("Z", map.get(one)); + } + + /** + * remove removes the correct key-value pair from the map + */ + public void testRemove() { + ConcurrentNavigableMap map = map5(); + map.remove(five); + assertEquals(4, map.size()); + assertFalse(map.containsKey(five)); + } + + /** + * remove(key,value) removes only if pair present + */ + public void testRemove2() { + ConcurrentNavigableMap map = map5(); + assertTrue(map.containsKey(five)); + assertEquals("E", map.get(five)); + map.remove(five, "E"); + assertEquals(4, map.size()); + assertFalse(map.containsKey(five)); + map.remove(four, "A"); + assertEquals(4, map.size()); + assertTrue(map.containsKey(four)); + } + + /** + * lowerEntry returns preceding entry. + */ + public void testLowerEntry() { + ConcurrentNavigableMap map = map5(); + Map.Entry e1 = map.lowerEntry(three); + assertEquals(two, e1.getKey()); + + Map.Entry e2 = map.lowerEntry(six); + assertEquals(five, e2.getKey()); + + Map.Entry e3 = map.lowerEntry(one); + assertNull(e3); + + Map.Entry e4 = map.lowerEntry(zero); + assertNull(e4); + } + + /** + * higherEntry returns next entry. + */ + public void testHigherEntry() { + ConcurrentNavigableMap map = map5(); + Map.Entry e1 = map.higherEntry(three); + assertEquals(four, e1.getKey()); + + Map.Entry e2 = map.higherEntry(zero); + assertEquals(one, e2.getKey()); + + Map.Entry e3 = map.higherEntry(five); + assertNull(e3); + + Map.Entry e4 = map.higherEntry(six); + assertNull(e4); + } + + /** + * floorEntry returns preceding entry. + */ + public void testFloorEntry() { + ConcurrentNavigableMap map = map5(); + Map.Entry e1 = map.floorEntry(three); + assertEquals(three, e1.getKey()); + + Map.Entry e2 = map.floorEntry(six); + assertEquals(five, e2.getKey()); + + Map.Entry e3 = map.floorEntry(one); + assertEquals(one, e3.getKey()); + + Map.Entry e4 = map.floorEntry(zero); + assertNull(e4); + } + + /** + * ceilingEntry returns next entry. + */ + public void testCeilingEntry() { + ConcurrentNavigableMap map = map5(); + Map.Entry e1 = map.ceilingEntry(three); + assertEquals(three, e1.getKey()); + + Map.Entry e2 = map.ceilingEntry(zero); + assertEquals(one, e2.getKey()); + + Map.Entry e3 = map.ceilingEntry(five); + assertEquals(five, e3.getKey()); + + Map.Entry e4 = map.ceilingEntry(six); + assertNull(e4); + } + + /** + * pollFirstEntry returns entries in order + */ + public void testPollFirstEntry() { + ConcurrentNavigableMap map = map5(); + Map.Entry e = map.pollFirstEntry(); + assertEquals(one, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(two, e.getKey()); + map.put(one, "A"); + e = map.pollFirstEntry(); + assertEquals(one, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(three, e.getKey()); + map.remove(four); + e = map.pollFirstEntry(); + assertEquals(five, e.getKey()); + try { + e.setValue("A"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollFirstEntry(); + assertNull(e); + } + + /** + * pollLastEntry returns entries in order + */ + public void testPollLastEntry() { + ConcurrentNavigableMap map = map5(); + Map.Entry e = map.pollLastEntry(); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(four, e.getKey()); + map.put(five, "E"); + e = map.pollLastEntry(); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(three, e.getKey()); + map.remove(two); + e = map.pollLastEntry(); + assertEquals(one, e.getKey()); + try { + e.setValue("E"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollLastEntry(); + assertNull(e); + } + + /** + * size returns the correct values + */ + public void testSize() { + ConcurrentNavigableMap map = map5(); + ConcurrentNavigableMap empty = map0(); + assertEquals(0, empty.size()); + assertEquals(5, map.size()); + } + + /** + * toString contains toString of elements + */ + public void testToString() { + ConcurrentNavigableMap map = map5(); + String s = map.toString(); + for (int i = 1; i <= 5; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + // Exception tests + + /** + * get(null) of nonempty map throws NPE + */ + public void testGet_NullPointerException() { + try { + ConcurrentNavigableMap c = map5(); + c.get(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsKey(null) of nonempty map throws NPE + */ + public void testContainsKey_NullPointerException() { + try { + ConcurrentNavigableMap c = map5(); + c.containsKey(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsValue(null) throws NPE + */ + public void testContainsValue_NullPointerException() { + try { + ConcurrentNavigableMap c = map0(); + c.containsValue(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * put(null,x) throws NPE + */ + public void testPut1_NullPointerException() { + try { + ConcurrentNavigableMap c = map5(); + c.put(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * putIfAbsent(null, x) throws NPE + */ + public void testPutIfAbsent1_NullPointerException() { + try { + ConcurrentNavigableMap c = map5(); + c.putIfAbsent(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(null, x) throws NPE + */ + public void testReplace_NullPointerException() { + try { + ConcurrentNavigableMap c = map5(); + c.replace(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(null, x, y) throws NPE + */ + public void testReplaceValue_NullPointerException() { + try { + ConcurrentNavigableMap c = map5(); + c.replace(null, one, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null) throws NPE + */ + public void testRemove1_NullPointerException() { + try { + ConcurrentNavigableMap c = map5(); + c.remove(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null, x) throws NPE + */ + public void testRemove2_NullPointerException() { + try { + ConcurrentNavigableMap c = map5(); + c.remove(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * A deserialized map equals original + */ + public void testSerialization() throws Exception { + NavigableMap x = map5(); + NavigableMap y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertEquals(x, y); + assertEquals(y, x); + } + + /** + * subMap returns map with keys in requested range + */ + public void testSubMapContents() { + ConcurrentNavigableMap map = map5(); + SortedMap sm = map.subMap(two, four); + assertEquals(two, sm.firstKey()); + assertEquals(three, sm.lastKey()); + assertEquals(2, sm.size()); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(two)); + assertEquals(4, map.size()); + assertEquals(1, sm.size()); + assertEquals(three, sm.firstKey()); + assertEquals(three, sm.lastKey()); + assertEquals("C", sm.remove(three)); + assertTrue(sm.isEmpty()); + assertEquals(3, map.size()); + } + + public void testSubMapContents2() { + ConcurrentNavigableMap map = map5(); + SortedMap sm = map.subMap(two, three); + assertEquals(1, sm.size()); + assertEquals(two, sm.firstKey()); + assertEquals(two, sm.lastKey()); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertFalse(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + assertFalse(i.hasNext()); + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(two)); + assertEquals(4, map.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertSame(sm.remove(three), null); + assertEquals(4, map.size()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testHeadMapContents() { + ConcurrentNavigableMap map = map5(); + SortedMap sm = map.headMap(four); + assertTrue(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(one, k); + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, map.size()); + assertEquals(four, map.firstKey()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testTailMapContents() { + ConcurrentNavigableMap map = map5(); + SortedMap sm = map.tailMap(two); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertTrue(sm.containsKey(four)); + assertTrue(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + k = (Integer)(i.next()); + assertEquals(four, k); + k = (Integer)(i.next()); + assertEquals(five, k); + assertFalse(i.hasNext()); + + Iterator ei = sm.entrySet().iterator(); + Map.Entry e; + e = (Map.Entry)(ei.next()); + assertEquals(two, e.getKey()); + assertEquals("B", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(three, e.getKey()); + assertEquals("C", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(four, e.getKey()); + assertEquals("D", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + assertFalse(i.hasNext()); + + SortedMap ssm = sm.tailMap(four); + assertEquals(four, ssm.firstKey()); + assertEquals(five, ssm.lastKey()); + assertEquals("D", ssm.remove(four)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, map.size()); + } + + /** + * clear removes all pairs + */ + public void testDescendingClear() { + ConcurrentNavigableMap map = dmap5(); + map.clear(); + assertEquals(0, map.size()); + } + + /** + * Maps with same contents are equal + */ + public void testDescendingEquals() { + ConcurrentNavigableMap map1 = dmap5(); + ConcurrentNavigableMap map2 = dmap5(); + assertEquals(map1, map2); + assertEquals(map2, map1); + map1.clear(); + assertFalse(map1.equals(map2)); + assertFalse(map2.equals(map1)); + } + + /** + * containsKey returns true for contained key + */ + public void testDescendingContainsKey() { + ConcurrentNavigableMap map = dmap5(); + assertTrue(map.containsKey(m1)); + assertFalse(map.containsKey(zero)); + } + + /** + * containsValue returns true for held values + */ + public void testDescendingContainsValue() { + ConcurrentNavigableMap map = dmap5(); + assertTrue(map.containsValue("A")); + assertFalse(map.containsValue("Z")); + } + + /** + * get returns the correct element at the given key, + * or null if not present + */ + public void testDescendingGet() { + ConcurrentNavigableMap map = dmap5(); + assertEquals("A", (String)map.get(m1)); + ConcurrentNavigableMap empty = dmap0(); + assertNull(empty.get(m1)); + } + + /** + * isEmpty is true of empty map and false for non-empty + */ + public void testDescendingIsEmpty() { + ConcurrentNavigableMap empty = dmap0(); + ConcurrentNavigableMap map = dmap5(); + assertTrue(empty.isEmpty()); + assertFalse(map.isEmpty()); + } + + /** + * firstKey returns first key + */ + public void testDescendingFirstKey() { + ConcurrentNavigableMap map = dmap5(); + assertEquals(m1, map.firstKey()); + } + + /** + * lastKey returns last key + */ + public void testDescendingLastKey() { + ConcurrentNavigableMap map = dmap5(); + assertEquals(m5, map.lastKey()); + } + + /** + * keySet returns a Set containing all the keys + */ + public void testDescendingKeySet() { + ConcurrentNavigableMap map = dmap5(); + Set s = map.keySet(); + assertEquals(5, s.size()); + assertTrue(s.contains(m1)); + assertTrue(s.contains(m2)); + assertTrue(s.contains(m3)); + assertTrue(s.contains(m4)); + assertTrue(s.contains(m5)); + } + + /** + * keySet is ordered + */ + public void testDescendingKeySetOrder() { + ConcurrentNavigableMap map = dmap5(); + Set s = map.keySet(); + Iterator i = s.iterator(); + Integer last = (Integer)i.next(); + assertEquals(last, m1); + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) > 0); + last = k; + } + } + + /** + * values collection contains all values + */ + public void testDescendingValues() { + ConcurrentNavigableMap map = dmap5(); + Collection s = map.values(); + assertEquals(5, s.size()); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * keySet.toArray returns contains all keys + */ + public void testDescendingAscendingKeySetToArray() { + ConcurrentNavigableMap map = dmap5(); + Set s = map.keySet(); + Object[] ar = s.toArray(); + assertTrue(s.containsAll(Arrays.asList(ar))); + assertEquals(5, ar.length); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * descendingkeySet.toArray returns contains all keys + */ + public void testDescendingDescendingKeySetToArray() { + ConcurrentNavigableMap map = dmap5(); + Set s = map.descendingKeySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + assertTrue(s.containsAll(Arrays.asList(ar))); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * Values.toArray contains all values + */ + public void testDescendingValuesToArray() { + ConcurrentNavigableMap map = dmap5(); + Collection v = map.values(); + Object[] ar = v.toArray(); + ArrayList s = new ArrayList(Arrays.asList(ar)); + assertEquals(5, ar.length); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * entrySet contains all pairs + */ + public void testDescendingEntrySet() { + ConcurrentNavigableMap map = dmap5(); + Set s = map.entrySet(); + assertEquals(5, s.size()); + Iterator it = s.iterator(); + while (it.hasNext()) { + Map.Entry e = (Map.Entry) it.next(); + assertTrue( + (e.getKey().equals(m1) && e.getValue().equals("A")) || + (e.getKey().equals(m2) && e.getValue().equals("B")) || + (e.getKey().equals(m3) && e.getValue().equals("C")) || + (e.getKey().equals(m4) && e.getValue().equals("D")) || + (e.getKey().equals(m5) && e.getValue().equals("E"))); + } + } + + /** + * putAll adds all key-value pairs from the given map + */ + public void testDescendingPutAll() { + ConcurrentNavigableMap empty = dmap0(); + ConcurrentNavigableMap map = dmap5(); + empty.putAll(map); + assertEquals(5, empty.size()); + assertTrue(empty.containsKey(m1)); + assertTrue(empty.containsKey(m2)); + assertTrue(empty.containsKey(m3)); + assertTrue(empty.containsKey(m4)); + assertTrue(empty.containsKey(m5)); + } + + /** + * putIfAbsent works when the given key is not present + */ + public void testDescendingPutIfAbsent() { + ConcurrentNavigableMap map = dmap5(); + map.putIfAbsent(six, "Z"); + assertTrue(map.containsKey(six)); + } + + /** + * putIfAbsent does not add the pair if the key is already present + */ + public void testDescendingPutIfAbsent2() { + ConcurrentNavigableMap map = dmap5(); + assertEquals("A", map.putIfAbsent(m1, "Z")); + } + + /** + * replace fails when the given key is not present + */ + public void testDescendingReplace() { + ConcurrentNavigableMap map = dmap5(); + assertNull(map.replace(six, "Z")); + assertFalse(map.containsKey(six)); + } + + /** + * replace succeeds if the key is already present + */ + public void testDescendingReplace2() { + ConcurrentNavigableMap map = dmap5(); + assertNotNull(map.replace(m1, "Z")); + assertEquals("Z", map.get(m1)); + } + + /** + * replace value fails when the given key not mapped to expected value + */ + public void testDescendingReplaceValue() { + ConcurrentNavigableMap map = dmap5(); + assertEquals("A", map.get(m1)); + assertFalse(map.replace(m1, "Z", "Z")); + assertEquals("A", map.get(m1)); + } + + /** + * replace value succeeds when the given key mapped to expected value + */ + public void testDescendingReplaceValue2() { + ConcurrentNavigableMap map = dmap5(); + assertEquals("A", map.get(m1)); + assertTrue(map.replace(m1, "A", "Z")); + assertEquals("Z", map.get(m1)); + } + + /** + * remove removes the correct key-value pair from the map + */ + public void testDescendingRemove() { + ConcurrentNavigableMap map = dmap5(); + map.remove(m5); + assertEquals(4, map.size()); + assertFalse(map.containsKey(m5)); + } + + /** + * remove(key,value) removes only if pair present + */ + public void testDescendingRemove2() { + ConcurrentNavigableMap map = dmap5(); + assertTrue(map.containsKey(m5)); + assertEquals("E", map.get(m5)); + map.remove(m5, "E"); + assertEquals(4, map.size()); + assertFalse(map.containsKey(m5)); + map.remove(m4, "A"); + assertEquals(4, map.size()); + assertTrue(map.containsKey(m4)); + } + + /** + * lowerEntry returns preceding entry. + */ + public void testDescendingLowerEntry() { + ConcurrentNavigableMap map = dmap5(); + Map.Entry e1 = map.lowerEntry(m3); + assertEquals(m2, e1.getKey()); + + Map.Entry e2 = map.lowerEntry(m6); + assertEquals(m5, e2.getKey()); + + Map.Entry e3 = map.lowerEntry(m1); + assertNull(e3); + + Map.Entry e4 = map.lowerEntry(zero); + assertNull(e4); + } + + /** + * higherEntry returns next entry. + */ + public void testDescendingHigherEntry() { + ConcurrentNavigableMap map = dmap5(); + Map.Entry e1 = map.higherEntry(m3); + assertEquals(m4, e1.getKey()); + + Map.Entry e2 = map.higherEntry(zero); + assertEquals(m1, e2.getKey()); + + Map.Entry e3 = map.higherEntry(m5); + assertNull(e3); + + Map.Entry e4 = map.higherEntry(m6); + assertNull(e4); + } + + /** + * floorEntry returns preceding entry. + */ + public void testDescendingFloorEntry() { + ConcurrentNavigableMap map = dmap5(); + Map.Entry e1 = map.floorEntry(m3); + assertEquals(m3, e1.getKey()); + + Map.Entry e2 = map.floorEntry(m6); + assertEquals(m5, e2.getKey()); + + Map.Entry e3 = map.floorEntry(m1); + assertEquals(m1, e3.getKey()); + + Map.Entry e4 = map.floorEntry(zero); + assertNull(e4); + } + + /** + * ceilingEntry returns next entry. + */ + public void testDescendingCeilingEntry() { + ConcurrentNavigableMap map = dmap5(); + Map.Entry e1 = map.ceilingEntry(m3); + assertEquals(m3, e1.getKey()); + + Map.Entry e2 = map.ceilingEntry(zero); + assertEquals(m1, e2.getKey()); + + Map.Entry e3 = map.ceilingEntry(m5); + assertEquals(m5, e3.getKey()); + + Map.Entry e4 = map.ceilingEntry(m6); + assertNull(e4); + } + + /** + * pollFirstEntry returns entries in order + */ + public void testDescendingPollFirstEntry() { + ConcurrentNavigableMap map = dmap5(); + Map.Entry e = map.pollFirstEntry(); + assertEquals(m1, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(m2, e.getKey()); + map.put(m1, "A"); + e = map.pollFirstEntry(); + assertEquals(m1, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(m3, e.getKey()); + map.remove(m4); + e = map.pollFirstEntry(); + assertEquals(m5, e.getKey()); + try { + e.setValue("A"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollFirstEntry(); + assertNull(e); + } + + /** + * pollLastEntry returns entries in order + */ + public void testDescendingPollLastEntry() { + ConcurrentNavigableMap map = dmap5(); + Map.Entry e = map.pollLastEntry(); + assertEquals(m5, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(m4, e.getKey()); + map.put(m5, "E"); + e = map.pollLastEntry(); + assertEquals(m5, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(m3, e.getKey()); + map.remove(m2); + e = map.pollLastEntry(); + assertEquals(m1, e.getKey()); + try { + e.setValue("E"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollLastEntry(); + assertNull(e); + } + + /** + * size returns the correct values + */ + public void testDescendingSize() { + ConcurrentNavigableMap map = dmap5(); + ConcurrentNavigableMap empty = dmap0(); + assertEquals(0, empty.size()); + assertEquals(5, map.size()); + } + + /** + * toString contains toString of elements + */ + public void testDescendingToString() { + ConcurrentNavigableMap map = dmap5(); + String s = map.toString(); + for (int i = 1; i <= 5; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + // Exception testDescendings + + /** + * get(null) of empty map throws NPE + */ + public void testDescendingGet_NullPointerException() { + try { + ConcurrentNavigableMap c = dmap5(); + c.get(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsKey(null) of empty map throws NPE + */ + public void testDescendingContainsKey_NullPointerException() { + try { + ConcurrentNavigableMap c = dmap5(); + c.containsKey(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsValue(null) throws NPE + */ + public void testDescendingContainsValue_NullPointerException() { + try { + ConcurrentNavigableMap c = dmap0(); + c.containsValue(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * put(null,x) throws NPE + */ + public void testDescendingPut1_NullPointerException() { + try { + ConcurrentNavigableMap c = dmap5(); + c.put(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * putIfAbsent(null, x) throws NPE + */ + public void testDescendingPutIfAbsent1_NullPointerException() { + try { + ConcurrentNavigableMap c = dmap5(); + c.putIfAbsent(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(null, x) throws NPE + */ + public void testDescendingReplace_NullPointerException() { + try { + ConcurrentNavigableMap c = dmap5(); + c.replace(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * replace(null, x, y) throws NPE + */ + public void testDescendingReplaceValue_NullPointerException() { + try { + ConcurrentNavigableMap c = dmap5(); + c.replace(null, m1, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null) throws NPE + */ + public void testDescendingRemove1_NullPointerException() { + try { + ConcurrentNavigableMap c = dmap5(); + c.remove(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null, x) throws NPE + */ + public void testDescendingRemove2_NullPointerException() { + try { + ConcurrentNavigableMap c = dmap5(); + c.remove(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * A deserialized map equals original + */ + public void testDescendingSerialization() throws Exception { + NavigableMap x = dmap5(); + NavigableMap y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertEquals(x, y); + assertEquals(y, x); + } + + /** + * subMap returns map with keys in requested range + */ + public void testDescendingSubMapContents() { + ConcurrentNavigableMap map = dmap5(); + SortedMap sm = map.subMap(m2, m4); + assertEquals(m2, sm.firstKey()); + assertEquals(m3, sm.lastKey()); + assertEquals(2, sm.size()); + assertFalse(sm.containsKey(m1)); + assertTrue(sm.containsKey(m2)); + assertTrue(sm.containsKey(m3)); + assertFalse(sm.containsKey(m4)); + assertFalse(sm.containsKey(m5)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + assertFalse(i.hasNext()); + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(m2)); + assertEquals(4, map.size()); + assertEquals(1, sm.size()); + assertEquals(m3, sm.firstKey()); + assertEquals(m3, sm.lastKey()); + assertEquals("C", sm.remove(m3)); + assertTrue(sm.isEmpty()); + assertEquals(3, map.size()); + } + + public void testDescendingSubMapContents2() { + ConcurrentNavigableMap map = dmap5(); + SortedMap sm = map.subMap(m2, m3); + assertEquals(1, sm.size()); + assertEquals(m2, sm.firstKey()); + assertEquals(m2, sm.lastKey()); + assertFalse(sm.containsKey(m1)); + assertTrue(sm.containsKey(m2)); + assertFalse(sm.containsKey(m3)); + assertFalse(sm.containsKey(m4)); + assertFalse(sm.containsKey(m5)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + assertFalse(i.hasNext()); + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(m2)); + assertEquals(4, map.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertSame(sm.remove(m3), null); + assertEquals(4, map.size()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testDescendingHeadMapContents() { + ConcurrentNavigableMap map = dmap5(); + SortedMap sm = map.headMap(m4); + assertTrue(sm.containsKey(m1)); + assertTrue(sm.containsKey(m2)); + assertTrue(sm.containsKey(m3)); + assertFalse(sm.containsKey(m4)); + assertFalse(sm.containsKey(m5)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m1, k); + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, map.size()); + assertEquals(m4, map.firstKey()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testDescendingTailMapContents() { + ConcurrentNavigableMap map = dmap5(); + SortedMap sm = map.tailMap(m2); + assertFalse(sm.containsKey(m1)); + assertTrue(sm.containsKey(m2)); + assertTrue(sm.containsKey(m3)); + assertTrue(sm.containsKey(m4)); + assertTrue(sm.containsKey(m5)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + k = (Integer)(i.next()); + assertEquals(m4, k); + k = (Integer)(i.next()); + assertEquals(m5, k); + assertFalse(i.hasNext()); + + Iterator ei = sm.entrySet().iterator(); + Map.Entry e; + e = (Map.Entry)(ei.next()); + assertEquals(m2, e.getKey()); + assertEquals("B", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(m3, e.getKey()); + assertEquals("C", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(m4, e.getKey()); + assertEquals("D", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(m5, e.getKey()); + assertEquals("E", e.getValue()); + assertFalse(i.hasNext()); + + SortedMap ssm = sm.tailMap(m4); + assertEquals(m4, ssm.firstKey()); + assertEquals(m5, ssm.lastKey()); + assertEquals("D", ssm.remove(m4)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, map.size()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java new file mode 100644 index 00000000000..bad618f3fab --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java @@ -0,0 +1,1141 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentSkipListSet; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ConcurrentSkipListSubSetTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ConcurrentSkipListSubSetTest.class); + } + + static class MyReverseComparator implements Comparator { + public int compare(Object x, Object y) { + return ((Comparable)y).compareTo(x); + } + } + + /** + * Returns a new set of given size containing consecutive + * Integers 0 ... n. + */ + private NavigableSet populatedSet(int n) { + ConcurrentSkipListSet q = + new ConcurrentSkipListSet(); + assertTrue(q.isEmpty()); + + for (int i = n - 1; i >= 0; i -= 2) + assertTrue(q.add(new Integer(i))); + for (int i = (n & 1); i < n; i += 2) + assertTrue(q.add(new Integer(i))); + assertTrue(q.add(new Integer(-n))); + assertTrue(q.add(new Integer(n))); + NavigableSet s = q.subSet(new Integer(0), true, new Integer(n), false); + assertFalse(s.isEmpty()); + assertEquals(n, s.size()); + return s; + } + + /** + * Returns a new set of first 5 ints. + */ + private NavigableSet set5() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + assertTrue(q.isEmpty()); + q.add(one); + q.add(two); + q.add(three); + q.add(four); + q.add(five); + q.add(zero); + q.add(seven); + NavigableSet s = q.subSet(one, true, seven, false); + assertEquals(5, s.size()); + return s; + } + + /** + * Returns a new set of first 5 negative ints. + */ + private NavigableSet dset5() { + ConcurrentSkipListSet q = new ConcurrentSkipListSet(); + assertTrue(q.isEmpty()); + q.add(m1); + q.add(m2); + q.add(m3); + q.add(m4); + q.add(m5); + NavigableSet s = q.descendingSet(); + assertEquals(5, s.size()); + return s; + } + + private static NavigableSet set0() { + ConcurrentSkipListSet set = new ConcurrentSkipListSet(); + assertTrue(set.isEmpty()); + return set.tailSet(m1, true); + } + + private static NavigableSet dset0() { + ConcurrentSkipListSet set = new ConcurrentSkipListSet(); + assertTrue(set.isEmpty()); + return set; + } + + /** + * A new set has unbounded capacity + */ + public void testConstructor1() { + assertEquals(0, set0().size()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + NavigableSet q = set0(); + assertTrue(q.isEmpty()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.add(new Integer(2)); + q.pollFirst(); + q.pollFirst(); + assertTrue(q.isEmpty()); + } + + /** + * size changes when elements added and removed + */ + public void testSize() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.pollFirst(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * add(null) throws NPE + */ + public void testAddNull() { + NavigableSet q = set0(); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Add of comparable element succeeds + */ + public void testAdd() { + NavigableSet q = set0(); + assertTrue(q.add(six)); + } + + /** + * Add of duplicate element fails + */ + public void testAddDup() { + NavigableSet q = set0(); + assertTrue(q.add(six)); + assertFalse(q.add(six)); + } + + /** + * Add of non-Comparable throws CCE + */ + public void testAddNonComparable() { + NavigableSet q = set0(); + try { + q.add(new Object()); + q.add(new Object()); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + NavigableSet q = set0(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testAddAll2() { + NavigableSet q = set0(); + Integer[] ints = new Integer[SIZE]; + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + NavigableSet q = set0(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i + SIZE); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Set contains all elements of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(SIZE - 1 - i); + NavigableSet q = set0(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(new Integer(i), q.pollFirst()); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst()); + } + assertNull(q.pollFirst()); + } + + /** + * remove(x) removes x and returns true if present + */ + public void testRemoveElement() { + NavigableSet q = populatedSet(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertTrue(q.contains(i - 1)); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertFalse(q.remove(i + 1)); + assertFalse(q.contains(i + 1)); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.pollFirst(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + NavigableSet q = populatedSet(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = set0(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.pollFirst(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = populatedSet(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.pollFirst()); + assertFalse(q.contains(x)); + } + } + } + + /** + * lower returns preceding element + */ + public void testLower() { + NavigableSet q = set5(); + Object e1 = q.lower(three); + assertEquals(two, e1); + + Object e2 = q.lower(six); + assertEquals(five, e2); + + Object e3 = q.lower(one); + assertNull(e3); + + Object e4 = q.lower(zero); + assertNull(e4); + } + + /** + * higher returns next element + */ + public void testHigher() { + NavigableSet q = set5(); + Object e1 = q.higher(three); + assertEquals(four, e1); + + Object e2 = q.higher(zero); + assertEquals(one, e2); + + Object e3 = q.higher(five); + assertNull(e3); + + Object e4 = q.higher(six); + assertNull(e4); + } + + /** + * floor returns preceding element + */ + public void testFloor() { + NavigableSet q = set5(); + Object e1 = q.floor(three); + assertEquals(three, e1); + + Object e2 = q.floor(six); + assertEquals(five, e2); + + Object e3 = q.floor(one); + assertEquals(one, e3); + + Object e4 = q.floor(zero); + assertNull(e4); + } + + /** + * ceiling returns next element + */ + public void testCeiling() { + NavigableSet q = set5(); + Object e1 = q.ceiling(three); + assertEquals(three, e1); + + Object e2 = q.ceiling(zero); + assertEquals(one, e2); + + Object e3 = q.ceiling(five); + assertEquals(five, e3); + + Object e4 = q.ceiling(six); + assertNull(e4); + } + + /** + * toArray contains all elements in sorted order + */ + public void testToArray() { + NavigableSet q = populatedSet(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.pollFirst()); + } + + /** + * toArray(a) contains all elements in sorted order + */ + public void testToArray2() { + NavigableSet q = populatedSet(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.pollFirst()); + } + + /** + * iterator iterates through all elements + */ + public void testIterator() { + NavigableSet q = populatedSet(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty set has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(set0().iterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final NavigableSet q = set0(); + q.add(new Integer(2)); + q.add(new Integer(1)); + q.add(new Integer(3)); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertEquals(it.next(), new Integer(2)); + assertEquals(it.next(), new Integer(3)); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + NavigableSet q = populatedSet(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized set has same elements + */ + public void testSerialization() throws Exception { + NavigableSet x = populatedSet(SIZE); + NavigableSet y = serialClone(x); + + assertNotSame(y, x); + assertEquals(x.size(), y.size()); + assertEquals(x, y); + assertEquals(y, x); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.pollFirst(), y.pollFirst()); + } + assertTrue(y.isEmpty()); + } + + /** + * subSet returns set with keys in requested range + */ + public void testSubSetContents() { + NavigableSet set = set5(); + SortedSet sm = set.subSet(two, four); + assertEquals(two, sm.first()); + assertEquals(three, sm.last()); + assertEquals(2, sm.size()); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(two)); + assertEquals(4, set.size()); + assertEquals(1, sm.size()); + assertEquals(three, sm.first()); + assertEquals(three, sm.last()); + assertTrue(sm.remove(three)); + assertTrue(sm.isEmpty()); + assertEquals(3, set.size()); + } + + public void testSubSetContents2() { + NavigableSet set = set5(); + SortedSet sm = set.subSet(two, three); + assertEquals(1, sm.size()); + assertEquals(two, sm.first()); + assertEquals(two, sm.last()); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertFalse(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(two)); + assertEquals(4, set.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertFalse(sm.remove(three)); + assertEquals(4, set.size()); + } + + /** + * headSet returns set with keys in requested range + */ + public void testHeadSetContents() { + NavigableSet set = set5(); + SortedSet sm = set.headSet(four); + assertTrue(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(one, k); + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, set.size()); + assertEquals(four, set.first()); + } + + /** + * tailSet returns set with keys in requested range + */ + public void testTailSetContents() { + NavigableSet set = set5(); + SortedSet sm = set.tailSet(two); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertTrue(sm.contains(four)); + assertTrue(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + k = (Integer)(i.next()); + assertEquals(four, k); + k = (Integer)(i.next()); + assertEquals(five, k); + assertFalse(i.hasNext()); + + SortedSet ssm = sm.tailSet(four); + assertEquals(four, ssm.first()); + assertEquals(five, ssm.last()); + assertTrue(ssm.remove(four)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, set.size()); + } + + /** + * size changes when elements added and removed + */ + public void testDescendingSize() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.pollFirst(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * add(null) throws NPE + */ + public void testDescendingAddNull() { + NavigableSet q = dset0(); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Add of comparable element succeeds + */ + public void testDescendingAdd() { + NavigableSet q = dset0(); + assertTrue(q.add(m6)); + } + + /** + * Add of duplicate element fails + */ + public void testDescendingAddDup() { + NavigableSet q = dset0(); + assertTrue(q.add(m6)); + assertFalse(q.add(m6)); + } + + /** + * Add of non-Comparable throws CCE + */ + public void testDescendingAddNonComparable() { + NavigableSet q = dset0(); + try { + q.add(new Object()); + q.add(new Object()); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * addAll(null) throws NPE + */ + public void testDescendingAddAll1() { + NavigableSet q = dset0(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testDescendingAddAll2() { + NavigableSet q = dset0(); + Integer[] ints = new Integer[SIZE]; + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testDescendingAddAll3() { + NavigableSet q = dset0(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i + SIZE); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Set contains all elements of successful addAll + */ + public void testDescendingAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(SIZE - 1 - i); + NavigableSet q = dset0(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(new Integer(i), q.pollFirst()); + } + + /** + * poll succeeds unless empty + */ + public void testDescendingPoll() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst()); + } + assertNull(q.pollFirst()); + } + + /** + * remove(x) removes x and returns true if present + */ + public void testDescendingRemoveElement() { + NavigableSet q = populatedSet(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.remove(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2 ) { + assertTrue(q.remove(new Integer(i))); + assertFalse(q.remove(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testDescendingContains() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.pollFirst(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testDescendingClear() { + NavigableSet q = populatedSet(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testDescendingContainsAll() { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = dset0(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testDescendingRetainAll() { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.pollFirst(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testDescendingRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = populatedSet(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.pollFirst()); + assertFalse(q.contains(x)); + } + } + } + + /** + * lower returns preceding element + */ + public void testDescendingLower() { + NavigableSet q = dset5(); + Object e1 = q.lower(m3); + assertEquals(m2, e1); + + Object e2 = q.lower(m6); + assertEquals(m5, e2); + + Object e3 = q.lower(m1); + assertNull(e3); + + Object e4 = q.lower(zero); + assertNull(e4); + } + + /** + * higher returns next element + */ + public void testDescendingHigher() { + NavigableSet q = dset5(); + Object e1 = q.higher(m3); + assertEquals(m4, e1); + + Object e2 = q.higher(zero); + assertEquals(m1, e2); + + Object e3 = q.higher(m5); + assertNull(e3); + + Object e4 = q.higher(m6); + assertNull(e4); + } + + /** + * floor returns preceding element + */ + public void testDescendingFloor() { + NavigableSet q = dset5(); + Object e1 = q.floor(m3); + assertEquals(m3, e1); + + Object e2 = q.floor(m6); + assertEquals(m5, e2); + + Object e3 = q.floor(m1); + assertEquals(m1, e3); + + Object e4 = q.floor(zero); + assertNull(e4); + } + + /** + * ceiling returns next element + */ + public void testDescendingCeiling() { + NavigableSet q = dset5(); + Object e1 = q.ceiling(m3); + assertEquals(m3, e1); + + Object e2 = q.ceiling(zero); + assertEquals(m1, e2); + + Object e3 = q.ceiling(m5); + assertEquals(m5, e3); + + Object e4 = q.ceiling(m6); + assertNull(e4); + } + + /** + * toArray contains all elements + */ + public void testDescendingToArray() { + NavigableSet q = populatedSet(SIZE); + Object[] o = q.toArray(); + Arrays.sort(o); + for (int i = 0; i < o.length; i++) + assertEquals(o[i], q.pollFirst()); + } + + /** + * toArray(a) contains all elements + */ + public void testDescendingToArray2() { + NavigableSet q = populatedSet(SIZE); + Integer[] ints = new Integer[SIZE]; + assertSame(ints, q.toArray(ints)); + Arrays.sort(ints); + for (int i = 0; i < ints.length; i++) + assertEquals(ints[i], q.pollFirst()); + } + + /** + * iterator iterates through all elements + */ + public void testDescendingIterator() { + NavigableSet q = populatedSet(SIZE); + int i = 0; + Iterator it = q.iterator(); + while (it.hasNext()) { + assertTrue(q.contains(it.next())); + ++i; + } + assertEquals(i, SIZE); + } + + /** + * iterator of empty set has no elements + */ + public void testDescendingEmptyIterator() { + NavigableSet q = dset0(); + int i = 0; + Iterator it = q.iterator(); + while (it.hasNext()) { + assertTrue(q.contains(it.next())); + ++i; + } + assertEquals(0, i); + } + + /** + * iterator.remove removes current element + */ + public void testDescendingIteratorRemove() { + final NavigableSet q = dset0(); + q.add(new Integer(2)); + q.add(new Integer(1)); + q.add(new Integer(3)); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertEquals(it.next(), new Integer(2)); + assertEquals(it.next(), new Integer(3)); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testDescendingToString() { + NavigableSet q = populatedSet(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized set has same elements + */ + public void testDescendingSerialization() throws Exception { + NavigableSet x = dset5(); + NavigableSet y = serialClone(x); + + assertNotSame(y, x); + assertEquals(x.size(), y.size()); + assertEquals(x, y); + assertEquals(y, x); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.pollFirst(), y.pollFirst()); + } + assertTrue(y.isEmpty()); + } + + /** + * subSet returns set with keys in requested range + */ + public void testDescendingSubSetContents() { + NavigableSet set = dset5(); + SortedSet sm = set.subSet(m2, m4); + assertEquals(m2, sm.first()); + assertEquals(m3, sm.last()); + assertEquals(2, sm.size()); + assertFalse(sm.contains(m1)); + assertTrue(sm.contains(m2)); + assertTrue(sm.contains(m3)); + assertFalse(sm.contains(m4)); + assertFalse(sm.contains(m5)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(m2)); + assertEquals(4, set.size()); + assertEquals(1, sm.size()); + assertEquals(m3, sm.first()); + assertEquals(m3, sm.last()); + assertTrue(sm.remove(m3)); + assertTrue(sm.isEmpty()); + assertEquals(3, set.size()); + } + + public void testDescendingSubSetContents2() { + NavigableSet set = dset5(); + SortedSet sm = set.subSet(m2, m3); + assertEquals(1, sm.size()); + assertEquals(m2, sm.first()); + assertEquals(m2, sm.last()); + assertFalse(sm.contains(m1)); + assertTrue(sm.contains(m2)); + assertFalse(sm.contains(m3)); + assertFalse(sm.contains(m4)); + assertFalse(sm.contains(m5)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(m2)); + assertEquals(4, set.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertFalse(sm.remove(m3)); + assertEquals(4, set.size()); + } + + /** + * headSet returns set with keys in requested range + */ + public void testDescendingHeadSetContents() { + NavigableSet set = dset5(); + SortedSet sm = set.headSet(m4); + assertTrue(sm.contains(m1)); + assertTrue(sm.contains(m2)); + assertTrue(sm.contains(m3)); + assertFalse(sm.contains(m4)); + assertFalse(sm.contains(m5)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m1, k); + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, set.size()); + assertEquals(m4, set.first()); + } + + /** + * tailSet returns set with keys in requested range + */ + public void testDescendingTailSetContents() { + NavigableSet set = dset5(); + SortedSet sm = set.tailSet(m2); + assertFalse(sm.contains(m1)); + assertTrue(sm.contains(m2)); + assertTrue(sm.contains(m3)); + assertTrue(sm.contains(m4)); + assertTrue(sm.contains(m5)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + k = (Integer)(i.next()); + assertEquals(m4, k); + k = (Integer)(i.next()); + assertEquals(m5, k); + assertFalse(i.hasNext()); + + SortedSet ssm = sm.tailSet(m4); + assertEquals(m4, ssm.first()); + assertEquals(m5, ssm.last()); + assertTrue(ssm.remove(m4)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, set.size()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java new file mode 100644 index 00000000000..75cfb1435fc --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java @@ -0,0 +1,783 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.concurrent.CopyOnWriteArrayList; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class CopyOnWriteArrayListTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(CopyOnWriteArrayListTest.class); + } + + static CopyOnWriteArrayList populatedArray(int n) { + CopyOnWriteArrayList a = new CopyOnWriteArrayList(); + assertTrue(a.isEmpty()); + for (int i = 0; i < n; i++) + a.add(i); + assertFalse(a.isEmpty()); + assertEquals(n, a.size()); + return a; + } + + static CopyOnWriteArrayList populatedArray(Integer[] elements) { + CopyOnWriteArrayList a = new CopyOnWriteArrayList(); + assertTrue(a.isEmpty()); + for (int i = 0; i < elements.length; i++) + a.add(elements[i]); + assertFalse(a.isEmpty()); + assertEquals(elements.length, a.size()); + return a; + } + + /** + * a new list is empty + */ + public void testConstructor() { + CopyOnWriteArrayList a = new CopyOnWriteArrayList(); + assertTrue(a.isEmpty()); + } + + /** + * new list contains all elements of initializing array + */ + public void testConstructor2() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + CopyOnWriteArrayList a = new CopyOnWriteArrayList(ints); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], a.get(i)); + } + + /** + * new list contains all elements of initializing collection + */ + public void testConstructor3() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + CopyOnWriteArrayList a = new CopyOnWriteArrayList(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], a.get(i)); + } + + /** + * addAll adds each element from the given collection, including duplicates + */ + public void testAddAll() { + CopyOnWriteArrayList full = populatedArray(3); + assertTrue(full.addAll(Arrays.asList(three, four, five))); + assertEquals(6, full.size()); + assertTrue(full.addAll(Arrays.asList(three, four, five))); + assertEquals(9, full.size()); + } + + /** + * addAllAbsent adds each element from the given collection that did not + * already exist in the List + */ + public void testAddAllAbsent() { + CopyOnWriteArrayList full = populatedArray(3); + // "one" is duplicate and will not be added + assertEquals(2, full.addAllAbsent(Arrays.asList(three, four, one))); + assertEquals(5, full.size()); + assertEquals(0, full.addAllAbsent(Arrays.asList(three, four, one))); + assertEquals(5, full.size()); + } + + /** + * addIfAbsent will not add the element if it already exists in the list + */ + public void testAddIfAbsent() { + CopyOnWriteArrayList full = populatedArray(SIZE); + full.addIfAbsent(one); + assertEquals(SIZE, full.size()); + } + + /** + * addIfAbsent adds the element when it does not exist in the list + */ + public void testAddIfAbsent2() { + CopyOnWriteArrayList full = populatedArray(SIZE); + full.addIfAbsent(three); + assertTrue(full.contains(three)); + } + + /** + * clear removes all elements from the list + */ + public void testClear() { + CopyOnWriteArrayList full = populatedArray(SIZE); + full.clear(); + assertEquals(0, full.size()); + } + + /** + * Cloned list is equal + */ + public void testClone() { + CopyOnWriteArrayList l1 = populatedArray(SIZE); + CopyOnWriteArrayList l2 = (CopyOnWriteArrayList)(l1.clone()); + assertEquals(l1, l2); + l1.clear(); + assertFalse(l1.equals(l2)); + } + + /** + * contains is true for added elements + */ + public void testContains() { + CopyOnWriteArrayList full = populatedArray(3); + assertTrue(full.contains(one)); + assertFalse(full.contains(five)); + } + + /** + * adding at an index places it in the indicated index + */ + public void testAddIndex() { + CopyOnWriteArrayList full = populatedArray(3); + full.add(0, m1); + assertEquals(4, full.size()); + assertEquals(m1, full.get(0)); + assertEquals(zero, full.get(1)); + + full.add(2, m2); + assertEquals(5, full.size()); + assertEquals(m2, full.get(2)); + assertEquals(two, full.get(4)); + } + + /** + * lists with same elements are equal and have same hashCode + */ + public void testEquals() { + CopyOnWriteArrayList a = populatedArray(3); + CopyOnWriteArrayList b = populatedArray(3); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + assertTrue(a.containsAll(b)); + assertTrue(b.containsAll(a)); + assertEquals(a.hashCode(), b.hashCode()); + a.add(m1); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + assertTrue(a.containsAll(b)); + assertFalse(b.containsAll(a)); + b.add(m1); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + assertTrue(a.containsAll(b)); + assertTrue(b.containsAll(a)); + assertEquals(a.hashCode(), b.hashCode()); + + assertFalse(a.equals(null)); + } + + /** + * containsAll returns true for collections with subset of elements + */ + public void testContainsAll() { + CopyOnWriteArrayList full = populatedArray(3); + assertTrue(full.containsAll(Arrays.asList())); + assertTrue(full.containsAll(Arrays.asList(one))); + assertTrue(full.containsAll(Arrays.asList(one, two))); + assertFalse(full.containsAll(Arrays.asList(one, two, six))); + assertFalse(full.containsAll(Arrays.asList(six))); + + try { + full.containsAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * get returns the value at the given index + */ + public void testGet() { + CopyOnWriteArrayList full = populatedArray(3); + assertEquals(0, full.get(0)); + } + + /** + * indexOf gives the index for the given object + */ + public void testIndexOf() { + CopyOnWriteArrayList full = populatedArray(3); + assertEquals(1, full.indexOf(one)); + assertEquals(-1, full.indexOf("puppies")); + } + + /** + * indexOf gives the index based on the given index + * at which to start searching + */ + public void testIndexOf2() { + CopyOnWriteArrayList full = populatedArray(3); + assertEquals(1, full.indexOf(one, 0)); + assertEquals(-1, full.indexOf(one, 2)); + } + + /** + * isEmpty returns true when empty, else false + */ + public void testIsEmpty() { + CopyOnWriteArrayList empty = new CopyOnWriteArrayList(); + CopyOnWriteArrayList full = populatedArray(SIZE); + assertTrue(empty.isEmpty()); + assertFalse(full.isEmpty()); + } + + /** + * iterator() returns an iterator containing the elements of the + * list in insertion order + */ + public void testIterator() { + Collection empty = new CopyOnWriteArrayList(); + assertFalse(empty.iterator().hasNext()); + try { + empty.iterator().next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + + Integer[] elements = new Integer[SIZE]; + for (int i = 0; i < SIZE; i++) + elements[i] = i; + Collections.shuffle(Arrays.asList(elements)); + Collection full = populatedArray(elements); + + Iterator it = full.iterator(); + for (int j = 0; j < SIZE; j++) { + assertTrue(it.hasNext()); + assertEquals(elements[j], it.next()); + } + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + Collection c = new CopyOnWriteArrayList(); + assertIteratorExhausted(c.iterator()); + } + + /** + * iterator.remove throws UnsupportedOperationException + */ + public void testIteratorRemove() { + CopyOnWriteArrayList full = populatedArray(SIZE); + Iterator it = full.iterator(); + it.next(); + try { + it.remove(); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + } + + /** + * toString contains toString of elements + */ + public void testToString() { + assertEquals("[]", new CopyOnWriteArrayList().toString()); + CopyOnWriteArrayList full = populatedArray(3); + String s = full.toString(); + for (int i = 0; i < 3; ++i) + assertTrue(s.contains(String.valueOf(i))); + assertEquals(new ArrayList(full).toString(), + full.toString()); + } + + /** + * lastIndexOf returns the index for the given object + */ + public void testLastIndexOf1() { + CopyOnWriteArrayList full = populatedArray(3); + full.add(one); + full.add(three); + assertEquals(3, full.lastIndexOf(one)); + assertEquals(-1, full.lastIndexOf(six)); + } + + /** + * lastIndexOf returns the index from the given starting point + */ + public void testLastIndexOf2() { + CopyOnWriteArrayList full = populatedArray(3); + full.add(one); + full.add(three); + assertEquals(3, full.lastIndexOf(one, 4)); + assertEquals(-1, full.lastIndexOf(three, 3)); + } + + /** + * listIterator traverses all elements + */ + public void testListIterator1() { + CopyOnWriteArrayList full = populatedArray(SIZE); + ListIterator i = full.listIterator(); + int j; + for (j = 0; i.hasNext(); j++) + assertEquals(j, i.next()); + assertEquals(SIZE, j); + } + + /** + * listIterator only returns those elements after the given index + */ + public void testListIterator2() { + CopyOnWriteArrayList full = populatedArray(3); + ListIterator i = full.listIterator(1); + int j; + for (j = 0; i.hasNext(); j++) + assertEquals(j + 1, i.next()); + assertEquals(2, j); + } + + /** + * remove(int) removes and returns the object at the given index + */ + public void testRemove_int() { + int SIZE = 3; + for (int i = 0; i < SIZE; i++) { + CopyOnWriteArrayList full = populatedArray(SIZE); + assertEquals(i, full.remove(i)); + assertEquals(SIZE - 1, full.size()); + assertFalse(full.contains(new Integer(i))); + } + } + + /** + * remove(Object) removes the object if found and returns true + */ + public void testRemove_Object() { + int SIZE = 3; + for (int i = 0; i < SIZE; i++) { + CopyOnWriteArrayList full = populatedArray(SIZE); + assertFalse(full.remove(new Integer(-42))); + assertTrue(full.remove(new Integer(i))); + assertEquals(SIZE - 1, full.size()); + assertFalse(full.contains(new Integer(i))); + } + CopyOnWriteArrayList x = new CopyOnWriteArrayList(Arrays.asList(4, 5, 6)); + assertTrue(x.remove(new Integer(6))); + assertEquals(x, Arrays.asList(4, 5)); + assertTrue(x.remove(new Integer(4))); + assertEquals(x, Arrays.asList(5)); + assertTrue(x.remove(new Integer(5))); + assertEquals(x, Arrays.asList()); + assertFalse(x.remove(new Integer(5))); + } + + /** + * removeAll removes all elements from the given collection + */ + public void testRemoveAll() { + CopyOnWriteArrayList full = populatedArray(3); + assertTrue(full.removeAll(Arrays.asList(one, two))); + assertEquals(1, full.size()); + assertFalse(full.removeAll(Arrays.asList(one, two))); + assertEquals(1, full.size()); + } + + /** + * set changes the element at the given index + */ + public void testSet() { + CopyOnWriteArrayList full = populatedArray(3); + assertEquals(2, full.set(2, four)); + assertEquals(4, full.get(2)); + } + + /** + * size returns the number of elements + */ + public void testSize() { + CopyOnWriteArrayList empty = new CopyOnWriteArrayList(); + CopyOnWriteArrayList full = populatedArray(SIZE); + assertEquals(SIZE, full.size()); + assertEquals(0, empty.size()); + } + + /** + * toArray() returns an Object array containing all elements from + * the list in insertion order + */ + public void testToArray() { + Object[] a = new CopyOnWriteArrayList().toArray(); + assertTrue(Arrays.equals(new Object[0], a)); + assertSame(Object[].class, a.getClass()); + + Integer[] elements = new Integer[SIZE]; + for (int i = 0; i < SIZE; i++) + elements[i] = i; + Collections.shuffle(Arrays.asList(elements)); + Collection full = populatedArray(elements); + + assertTrue(Arrays.equals(elements, full.toArray())); + assertSame(Object[].class, full.toArray().getClass()); + } + + /** + * toArray(Integer array) returns an Integer array containing all + * elements from the list in insertion order + */ + public void testToArray2() { + Collection empty = new CopyOnWriteArrayList(); + Integer[] a; + + a = new Integer[0]; + assertSame(a, empty.toArray(a)); + + a = new Integer[SIZE / 2]; + Arrays.fill(a, 42); + assertSame(a, empty.toArray(a)); + assertNull(a[0]); + for (int i = 1; i < a.length; i++) + assertEquals(42, (int) a[i]); + + Integer[] elements = new Integer[SIZE]; + for (int i = 0; i < SIZE; i++) + elements[i] = i; + Collections.shuffle(Arrays.asList(elements)); + Collection full = populatedArray(elements); + + Arrays.fill(a, 42); + assertTrue(Arrays.equals(elements, full.toArray(a))); + for (int i = 0; i < a.length; i++) + assertEquals(42, (int) a[i]); + assertSame(Integer[].class, full.toArray(a).getClass()); + + a = new Integer[SIZE]; + Arrays.fill(a, 42); + assertSame(a, full.toArray(a)); + assertTrue(Arrays.equals(elements, a)); + + a = new Integer[2 * SIZE]; + Arrays.fill(a, 42); + assertSame(a, full.toArray(a)); + assertTrue(Arrays.equals(elements, Arrays.copyOf(a, SIZE))); + assertNull(a[SIZE]); + for (int i = SIZE + 1; i < a.length; i++) + assertEquals(42, (int) a[i]); + } + + /** + * sublists contains elements at indexes offset from their base + */ + public void testSubList() { + CopyOnWriteArrayList a = populatedArray(10); + assertTrue(a.subList(1,1).isEmpty()); + for (int j = 0; j < 9; ++j) { + for (int i = j ; i < 10; ++i) { + List b = a.subList(j,i); + for (int k = j; k < i; ++k) { + assertEquals(new Integer(k), b.get(k-j)); + } + } + } + + List s = a.subList(2, 5); + assertEquals(3, s.size()); + s.set(2, m1); + assertEquals(a.get(4), m1); + s.clear(); + assertEquals(7, a.size()); + } + + // Exception tests + + /** + * toArray throws an ArrayStoreException when the given array + * can not store the objects inside the list + */ + public void testToArray_ArrayStoreException() { + CopyOnWriteArrayList c = new CopyOnWriteArrayList(); + c.add("zfasdfsdf"); + c.add("asdadasd"); + try { + c.toArray(new Long[5]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * get throws an IndexOutOfBoundsException on a negative index + */ + public void testGet1_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.get(-1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * get throws an IndexOutOfBoundsException on a too high index + */ + public void testGet2_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.get(list.size()); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * set throws an IndexOutOfBoundsException on a negative index + */ + public void testSet1_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.set(-1, "qwerty"); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * set throws an IndexOutOfBoundsException on a too high index + */ + public void testSet2() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.set(list.size(), "qwerty"); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * add throws an IndexOutOfBoundsException on a negative index + */ + public void testAdd1_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.add(-1, "qwerty"); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * add throws an IndexOutOfBoundsException on a too high index + */ + public void testAdd2_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.add(list.size() + 1, "qwerty"); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * remove throws an IndexOutOfBoundsException on a negative index + */ + public void testRemove1_IndexOutOfBounds() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.remove(-1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * remove throws an IndexOutOfBoundsException on a too high index + */ + public void testRemove2_IndexOutOfBounds() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.remove(list.size()); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * addAll throws an IndexOutOfBoundsException on a negative index + */ + public void testAddAll1_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.addAll(-1, new LinkedList()); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * addAll throws an IndexOutOfBoundsException on a too high index + */ + public void testAddAll2_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.addAll(list.size() + 1, new LinkedList()); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * listIterator throws an IndexOutOfBoundsException on a negative index + */ + public void testListIterator1_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.listIterator(-1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * listIterator throws an IndexOutOfBoundsException on a too high index + */ + public void testListIterator2_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.listIterator(list.size() + 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * subList throws an IndexOutOfBoundsException on a negative index + */ + public void testSubList1_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.subList(-1, list.size()); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * subList throws an IndexOutOfBoundsException on a too high index + */ + public void testSubList2_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.subList(0, list.size() + 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * subList throws IndexOutOfBoundsException when the second index + * is lower then the first + */ + public void testSubList3_IndexOutOfBoundsException() { + CopyOnWriteArrayList c = populatedArray(5); + List[] lists = { c, c.subList(1, c.size() - 1) }; + for (List list : lists) { + try { + list.subList(list.size() - 1, 1); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + } + + /** + * a deserialized serialized list is equal + */ + public void testSerialization() throws Exception { + List x = populatedArray(SIZE); + List y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + assertEquals(x, y); + assertEquals(y, x); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(0), y.remove(0)); + } + assertTrue(y.isEmpty()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java b/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java new file mode 100644 index 00000000000..bd9a7e3da43 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java @@ -0,0 +1,432 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class CopyOnWriteArraySetTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(CopyOnWriteArraySetTest.class); + } + + static CopyOnWriteArraySet populatedSet(int n) { + CopyOnWriteArraySet a = new CopyOnWriteArraySet(); + assertTrue(a.isEmpty()); + for (int i = 0; i < n; i++) + a.add(i); + assertEquals(n == 0, a.isEmpty()); + assertEquals(n, a.size()); + return a; + } + + static CopyOnWriteArraySet populatedSet(Integer[] elements) { + CopyOnWriteArraySet a = new CopyOnWriteArraySet(); + assertTrue(a.isEmpty()); + for (int i = 0; i < elements.length; i++) + a.add(elements[i]); + assertFalse(a.isEmpty()); + assertEquals(elements.length, a.size()); + return a; + } + + /** + * Default-constructed set is empty + */ + public void testConstructor() { + CopyOnWriteArraySet a = new CopyOnWriteArraySet(); + assertTrue(a.isEmpty()); + } + + /** + * Collection-constructed set holds all of its elements + */ + public void testConstructor3() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + CopyOnWriteArraySet a = new CopyOnWriteArraySet(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertTrue(a.contains(ints[i])); + } + + /** + * addAll adds each non-duplicate element from the given collection + */ + public void testAddAll() { + Set full = populatedSet(3); + assertTrue(full.addAll(Arrays.asList(three, four, five))); + assertEquals(6, full.size()); + assertFalse(full.addAll(Arrays.asList(three, four, five))); + assertEquals(6, full.size()); + } + + /** + * addAll adds each non-duplicate element from the given collection + */ + public void testAddAll2() { + Set full = populatedSet(3); + // "one" is duplicate and will not be added + assertTrue(full.addAll(Arrays.asList(three, four, one))); + assertEquals(5, full.size()); + assertFalse(full.addAll(Arrays.asList(three, four, one))); + assertEquals(5, full.size()); + } + + /** + * add will not add the element if it already exists in the set + */ + public void testAdd2() { + Set full = populatedSet(3); + full.add(one); + assertEquals(3, full.size()); + } + + /** + * add adds the element when it does not exist in the set + */ + public void testAdd3() { + Set full = populatedSet(3); + full.add(three); + assertTrue(full.contains(three)); + } + + /** + * clear removes all elements from the set + */ + public void testClear() { + Collection full = populatedSet(3); + full.clear(); + assertEquals(0, full.size()); + assertTrue(full.isEmpty()); + } + + /** + * contains returns true for added elements + */ + public void testContains() { + Collection full = populatedSet(3); + assertTrue(full.contains(one)); + assertFalse(full.contains(five)); + } + + /** + * Sets with equal elements are equal + */ + public void testEquals() { + CopyOnWriteArraySet a = populatedSet(3); + CopyOnWriteArraySet b = populatedSet(3); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + assertTrue(a.containsAll(b)); + assertTrue(b.containsAll(a)); + assertEquals(a.hashCode(), b.hashCode()); + assertEquals(a.size(), b.size()); + + a.add(m1); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + assertTrue(a.containsAll(b)); + assertFalse(b.containsAll(a)); + b.add(m1); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + assertTrue(a.containsAll(b)); + assertTrue(b.containsAll(a)); + assertEquals(a.hashCode(), b.hashCode()); + + Object x = a.iterator().next(); + a.remove(x); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + assertFalse(a.containsAll(b)); + assertTrue(b.containsAll(a)); + a.add(x); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + assertTrue(a.containsAll(b)); + assertTrue(b.containsAll(a)); + assertEquals(a.hashCode(), b.hashCode()); + assertEquals(a.size(), b.size()); + + CopyOnWriteArraySet empty1 = new CopyOnWriteArraySet(Arrays.asList()); + CopyOnWriteArraySet empty2 = new CopyOnWriteArraySet(Arrays.asList()); + assertTrue(empty1.equals(empty1)); + assertTrue(empty1.equals(empty2)); + + assertFalse(empty1.equals(a)); + assertFalse(a.equals(empty1)); + + assertFalse(a.equals(null)); + } + + /** + * containsAll returns true for collections with subset of elements + */ + public void testContainsAll() { + Collection full = populatedSet(3); + assertTrue(full.containsAll(full)); + assertTrue(full.containsAll(Arrays.asList())); + assertTrue(full.containsAll(Arrays.asList(one))); + assertTrue(full.containsAll(Arrays.asList(one, two))); + assertFalse(full.containsAll(Arrays.asList(one, two, six))); + assertFalse(full.containsAll(Arrays.asList(six))); + + CopyOnWriteArraySet empty1 = new CopyOnWriteArraySet(Arrays.asList()); + CopyOnWriteArraySet empty2 = new CopyOnWriteArraySet(Arrays.asList()); + assertTrue(empty1.containsAll(empty2)); + assertTrue(empty1.containsAll(empty1)); + assertFalse(empty1.containsAll(full)); + assertTrue(full.containsAll(empty1)); + + try { + full.containsAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * isEmpty is true when empty, else false + */ + public void testIsEmpty() { + assertTrue(populatedSet(0).isEmpty()); + assertFalse(populatedSet(3).isEmpty()); + } + + /** + * iterator() returns an iterator containing the elements of the + * set in insertion order + */ + public void testIterator() { + Collection empty = new CopyOnWriteArraySet(); + assertFalse(empty.iterator().hasNext()); + try { + empty.iterator().next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + + Integer[] elements = new Integer[SIZE]; + for (int i = 0; i < SIZE; i++) + elements[i] = i; + Collections.shuffle(Arrays.asList(elements)); + Collection full = populatedSet(elements); + + Iterator it = full.iterator(); + for (int j = 0; j < SIZE; j++) { + assertTrue(it.hasNext()); + assertEquals(elements[j], it.next()); + } + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new CopyOnWriteArraySet().iterator()); + } + + /** + * iterator remove is unsupported + */ + public void testIteratorRemove() { + Collection full = populatedSet(3); + Iterator it = full.iterator(); + it.next(); + try { + it.remove(); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + } + + /** + * toString holds toString of elements + */ + public void testToString() { + assertEquals("[]", new CopyOnWriteArraySet().toString()); + Collection full = populatedSet(3); + String s = full.toString(); + for (int i = 0; i < 3; ++i) + assertTrue(s.contains(String.valueOf(i))); + assertEquals(new ArrayList(full).toString(), + full.toString()); + } + + /** + * removeAll removes all elements from the given collection + */ + public void testRemoveAll() { + Set full = populatedSet(3); + assertTrue(full.removeAll(Arrays.asList(one, two))); + assertEquals(1, full.size()); + assertFalse(full.removeAll(Arrays.asList(one, two))); + assertEquals(1, full.size()); + } + + /** + * remove removes an element + */ + public void testRemove() { + Collection full = populatedSet(3); + full.remove(one); + assertFalse(full.contains(one)); + assertEquals(2, full.size()); + } + + /** + * size returns the number of elements + */ + public void testSize() { + Collection empty = new CopyOnWriteArraySet(); + Collection full = populatedSet(3); + assertEquals(3, full.size()); + assertEquals(0, empty.size()); + } + + /** + * toArray() returns an Object array containing all elements from + * the set in insertion order + */ + public void testToArray() { + Object[] a = new CopyOnWriteArraySet().toArray(); + assertTrue(Arrays.equals(new Object[0], a)); + assertSame(Object[].class, a.getClass()); + + Integer[] elements = new Integer[SIZE]; + for (int i = 0; i < SIZE; i++) + elements[i] = i; + Collections.shuffle(Arrays.asList(elements)); + Collection full = populatedSet(elements); + + assertTrue(Arrays.equals(elements, full.toArray())); + assertSame(Object[].class, full.toArray().getClass()); + } + + /** + * toArray(Integer array) returns an Integer array containing all + * elements from the set in insertion order + */ + public void testToArray2() { + Collection empty = new CopyOnWriteArraySet(); + Integer[] a; + + a = new Integer[0]; + assertSame(a, empty.toArray(a)); + + a = new Integer[SIZE / 2]; + Arrays.fill(a, 42); + assertSame(a, empty.toArray(a)); + assertNull(a[0]); + for (int i = 1; i < a.length; i++) + assertEquals(42, (int) a[i]); + + Integer[] elements = new Integer[SIZE]; + for (int i = 0; i < SIZE; i++) + elements[i] = i; + Collections.shuffle(Arrays.asList(elements)); + Collection full = populatedSet(elements); + + Arrays.fill(a, 42); + assertTrue(Arrays.equals(elements, full.toArray(a))); + for (int i = 0; i < a.length; i++) + assertEquals(42, (int) a[i]); + assertSame(Integer[].class, full.toArray(a).getClass()); + + a = new Integer[SIZE]; + Arrays.fill(a, 42); + assertSame(a, full.toArray(a)); + assertTrue(Arrays.equals(elements, a)); + + a = new Integer[2 * SIZE]; + Arrays.fill(a, 42); + assertSame(a, full.toArray(a)); + assertTrue(Arrays.equals(elements, Arrays.copyOf(a, SIZE))); + assertNull(a[SIZE]); + for (int i = SIZE + 1; i < a.length; i++) + assertEquals(42, (int) a[i]); + } + + /** + * toArray throws an ArrayStoreException when the given array can + * not store the objects inside the set + */ + public void testToArray_ArrayStoreException() { + CopyOnWriteArraySet c = new CopyOnWriteArraySet(); + c.add("zfasdfsdf"); + c.add("asdadasd"); + try { + c.toArray(new Long[5]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * A deserialized serialized set is equal + */ + public void testSerialization() throws Exception { + Set x = populatedSet(SIZE); + Set y = serialClone(x); + + assertNotSame(y, x); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + assertEquals(x, y); + assertEquals(y, x); + } + + /** + * addAll is idempotent + */ + public void testAddAll_idempotent() throws Exception { + Set x = populatedSet(SIZE); + Set y = new CopyOnWriteArraySet(x); + y.addAll(x); + assertEquals(x, y); + assertEquals(y, x); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/CountDownLatchTest.java b/jdk/test/java/util/concurrent/tck/CountDownLatchTest.java new file mode 100644 index 00000000000..e286d00cdf9 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/CountDownLatchTest.java @@ -0,0 +1,223 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.concurrent.CountDownLatch; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class CountDownLatchTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(CountDownLatchTest.class); + } + + /** + * negative constructor argument throws IAE + */ + public void testConstructor() { + try { + new CountDownLatch(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * getCount returns initial count and decreases after countDown + */ + public void testGetCount() { + final CountDownLatch l = new CountDownLatch(2); + assertEquals(2, l.getCount()); + l.countDown(); + assertEquals(1, l.getCount()); + } + + /** + * countDown decrements count when positive and has no effect when zero + */ + public void testCountDown() { + final CountDownLatch l = new CountDownLatch(1); + assertEquals(1, l.getCount()); + l.countDown(); + assertEquals(0, l.getCount()); + l.countDown(); + assertEquals(0, l.getCount()); + } + + /** + * await returns after countDown to zero, but not before + */ + public void testAwait() { + final CountDownLatch l = new CountDownLatch(2); + final CountDownLatch pleaseCountDown = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertEquals(2, l.getCount()); + pleaseCountDown.countDown(); + l.await(); + assertEquals(0, l.getCount()); + }}); + + await(pleaseCountDown); + assertEquals(2, l.getCount()); + l.countDown(); + assertEquals(1, l.getCount()); + assertThreadStaysAlive(t); + l.countDown(); + assertEquals(0, l.getCount()); + awaitTermination(t); + } + + /** + * timed await returns after countDown to zero + */ + public void testTimedAwait() { + final CountDownLatch l = new CountDownLatch(2); + final CountDownLatch pleaseCountDown = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertEquals(2, l.getCount()); + pleaseCountDown.countDown(); + assertTrue(l.await(LONG_DELAY_MS, MILLISECONDS)); + assertEquals(0, l.getCount()); + }}); + + await(pleaseCountDown); + assertEquals(2, l.getCount()); + l.countDown(); + assertEquals(1, l.getCount()); + assertThreadStaysAlive(t); + l.countDown(); + assertEquals(0, l.getCount()); + awaitTermination(t); + } + + /** + * await throws IE if interrupted before counted down + */ + public void testAwait_Interruptible() { + final CountDownLatch l = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + Thread.currentThread().interrupt(); + try { + l.await(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + l.await(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + assertEquals(1, l.getCount()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * timed await throws IE if interrupted before counted down + */ + public void testTimedAwait_Interruptible() { + final CountDownLatch l = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + Thread.currentThread().interrupt(); + try { + l.await(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + l.await(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + assertEquals(1, l.getCount()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * timed await times out if not counted down before timeout + */ + public void testAwaitTimeout() throws InterruptedException { + final CountDownLatch l = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertEquals(1, l.getCount()); + assertFalse(l.await(timeoutMillis(), MILLISECONDS)); + assertEquals(1, l.getCount()); + }}); + + awaitTermination(t); + assertEquals(1, l.getCount()); + } + + /** + * toString indicates current count + */ + public void testToString() { + CountDownLatch s = new CountDownLatch(2); + assertTrue(s.toString().contains("Count = 2")); + s.countDown(); + assertTrue(s.toString().contains("Count = 1")); + s.countDown(); + assertTrue(s.toString().contains("Count = 0")); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java b/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java new file mode 100644 index 00000000000..8be66850920 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java @@ -0,0 +1,1872 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.HashSet; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountedCompleter; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class CountedCompleterTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(CountedCompleterTest.class); + } + + // Runs with "mainPool" use > 1 thread. singletonPool tests use 1 + static final int mainPoolSize = + Math.max(2, Runtime.getRuntime().availableProcessors()); + + private static ForkJoinPool mainPool() { + return new ForkJoinPool(mainPoolSize); + } + + private static ForkJoinPool singletonPool() { + return new ForkJoinPool(1); + } + + private static ForkJoinPool asyncSingletonPool() { + return new ForkJoinPool(1, + ForkJoinPool.defaultForkJoinWorkerThreadFactory, + null, true); + } + + private void testInvokeOnPool(ForkJoinPool pool, ForkJoinTask a) { + try (PoolCleaner cleaner = cleaner(pool)) { + assertFalse(a.isDone()); + assertFalse(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + + assertNull(pool.invoke(a)); + + assertTrue(a.isDone()); + assertTrue(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + } + } + + void checkNotDone(CountedCompleter a) { + assertFalse(a.isDone()); + assertFalse(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + + try { + a.get(0L, SECONDS); + shouldThrow(); + } catch (TimeoutException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedNormally(CountedCompleter a) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertTrue(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + + { + Thread.currentThread().interrupt(); + long startTime = System.nanoTime(); + assertNull(a.join()); + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + Thread.interrupted(); + } + + { + Thread.currentThread().interrupt(); + long startTime = System.nanoTime(); + a.quietlyJoin(); // should be no-op + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + Thread.interrupted(); + } + + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + try { + assertNull(a.get()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertNull(a.get(5L, SECONDS)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCancelled(CountedCompleter a) { + assertTrue(a.isDone()); + assertTrue(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertTrue(a.getException() instanceof CancellationException); + assertNull(a.getRawResult()); + assertTrue(a.cancel(false)); + assertTrue(a.cancel(true)); + + try { + Thread.currentThread().interrupt(); + a.join(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + Thread.interrupted(); + + { + long startTime = System.nanoTime(); + a.quietlyJoin(); // should be no-op + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + } + + try { + a.get(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedAbnormally(CountedCompleter a, Throwable t) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertSame(t.getClass(), a.getException().getClass()); + assertNull(a.getRawResult()); + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + + try { + Thread.currentThread().interrupt(); + a.join(); + shouldThrow(); + } catch (Throwable expected) { + assertSame(t.getClass(), expected.getClass()); + } + Thread.interrupted(); + + { + long startTime = System.nanoTime(); + a.quietlyJoin(); // should be no-op + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + } + + try { + a.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.invoke(); + shouldThrow(); + } catch (Throwable success) { + assertSame(t, success); + } + } + + public static final class FJException extends RuntimeException { + FJException() { super(); } + } + + abstract class CheckedCC extends CountedCompleter { + final AtomicInteger computeN = new AtomicInteger(0); + final AtomicInteger onCompletionN = new AtomicInteger(0); + final AtomicInteger onExceptionalCompletionN = new AtomicInteger(0); + final AtomicInteger setRawResultN = new AtomicInteger(0); + final AtomicReference rawResult = new AtomicReference(null); + int computeN() { return computeN.get(); } + int onCompletionN() { return onCompletionN.get(); } + int onExceptionalCompletionN() { return onExceptionalCompletionN.get(); } + int setRawResultN() { return setRawResultN.get(); } + + CheckedCC() { super(); } + CheckedCC(CountedCompleter p) { super(p); } + CheckedCC(CountedCompleter p, int n) { super(p, n); } + abstract void realCompute(); + public final void compute() { + computeN.incrementAndGet(); + realCompute(); + } + public void onCompletion(CountedCompleter caller) { + onCompletionN.incrementAndGet(); + super.onCompletion(caller); + } + public boolean onExceptionalCompletion(Throwable ex, + CountedCompleter caller) { + onExceptionalCompletionN.incrementAndGet(); + assertNotNull(ex); + assertTrue(isCompletedAbnormally()); + assertTrue(super.onExceptionalCompletion(ex, caller)); + return true; + } + protected void setRawResult(Object t) { + setRawResultN.incrementAndGet(); + rawResult.set(t); + super.setRawResult(t); + } + void checkIncomplete() { + assertEquals(0, computeN()); + assertEquals(0, onCompletionN()); + assertEquals(0, onExceptionalCompletionN()); + assertEquals(0, setRawResultN()); + checkNotDone(this); + } + void checkCompletes(Object rawResult) { + checkIncomplete(); + int pendingCount = getPendingCount(); + complete(rawResult); + assertEquals(pendingCount, getPendingCount()); + assertEquals(0, computeN()); + assertEquals(1, onCompletionN()); + assertEquals(0, onExceptionalCompletionN()); + assertEquals(1, setRawResultN()); + assertSame(rawResult, this.rawResult.get()); + checkCompletedNormally(this); + } + void checkCompletesExceptionally(Throwable ex) { + checkIncomplete(); + completeExceptionally(ex); + checkCompletedExceptionally(ex); + } + void checkCompletedExceptionally(Throwable ex) { + assertEquals(0, computeN()); + assertEquals(0, onCompletionN()); + assertEquals(1, onExceptionalCompletionN()); + assertEquals(0, setRawResultN()); + assertNull(this.rawResult.get()); + checkCompletedAbnormally(this, ex); + } + } + + final class NoopCC extends CheckedCC { + NoopCC() { super(); } + NoopCC(CountedCompleter p) { super(p); } + NoopCC(CountedCompleter p, int initialPendingCount) { + super(p, initialPendingCount); + } + protected void realCompute() {} + } + + /** + * A newly constructed CountedCompleter is not completed; + * complete() causes completion. pendingCount is ignored. + */ + public void testComplete() { + for (Object x : new Object[] { Boolean.TRUE, null }) { + for (int pendingCount : new int[] { 0, 42 }) { + testComplete(new NoopCC(), x, pendingCount); + testComplete(new NoopCC(new NoopCC()), x, pendingCount); + } + } + } + void testComplete(NoopCC cc, Object x, int pendingCount) { + cc.setPendingCount(pendingCount); + cc.checkCompletes(x); + assertEquals(pendingCount, cc.getPendingCount()); + } + + /** + * completeExceptionally completes exceptionally + */ + public void testCompleteExceptionally() { + new NoopCC() + .checkCompletesExceptionally(new FJException()); + new NoopCC(new NoopCC()) + .checkCompletesExceptionally(new FJException()); + } + + /** + * completeExceptionally(null) surprisingly has the same effect as + * completeExceptionally(new RuntimeException()) + */ + public void testCompleteExceptionally_null() { + NoopCC a = new NoopCC(); + a.completeExceptionally(null); + try { + a.invoke(); + shouldThrow(); + } catch (RuntimeException success) { + assertSame(success.getClass(), RuntimeException.class); + assertNull(success.getCause()); + a.checkCompletedExceptionally(success); + } + } + + /** + * setPendingCount sets the reported pending count + */ + public void testSetPendingCount() { + NoopCC a = new NoopCC(); + assertEquals(0, a.getPendingCount()); + int[] vals = { + -1, 0, 1, + Integer.MIN_VALUE, + Integer.MAX_VALUE, + }; + for (int val : vals) { + a.setPendingCount(val); + assertEquals(val, a.getPendingCount()); + } + } + + /** + * addToPendingCount adds to the reported pending count + */ + public void testAddToPendingCount() { + NoopCC a = new NoopCC(); + assertEquals(0, a.getPendingCount()); + a.addToPendingCount(1); + assertEquals(1, a.getPendingCount()); + a.addToPendingCount(27); + assertEquals(28, a.getPendingCount()); + a.addToPendingCount(-28); + assertEquals(0, a.getPendingCount()); + } + + /** + * decrementPendingCountUnlessZero decrements reported pending + * count unless zero + */ + public void testDecrementPendingCountUnlessZero() { + NoopCC a = new NoopCC(null, 2); + assertEquals(2, a.getPendingCount()); + assertEquals(2, a.decrementPendingCountUnlessZero()); + assertEquals(1, a.getPendingCount()); + assertEquals(1, a.decrementPendingCountUnlessZero()); + assertEquals(0, a.getPendingCount()); + assertEquals(0, a.decrementPendingCountUnlessZero()); + assertEquals(0, a.getPendingCount()); + a.setPendingCount(-1); + assertEquals(-1, a.decrementPendingCountUnlessZero()); + assertEquals(-2, a.getPendingCount()); + } + + /** + * compareAndSetPendingCount compares and sets the reported + * pending count + */ + public void testCompareAndSetPendingCount() { + NoopCC a = new NoopCC(); + assertEquals(0, a.getPendingCount()); + assertTrue(a.compareAndSetPendingCount(0, 1)); + assertEquals(1, a.getPendingCount()); + assertTrue(a.compareAndSetPendingCount(1, 2)); + assertEquals(2, a.getPendingCount()); + assertFalse(a.compareAndSetPendingCount(1, 3)); + assertEquals(2, a.getPendingCount()); + } + + /** + * getCompleter returns parent or null if at root + */ + public void testGetCompleter() { + NoopCC a = new NoopCC(); + assertNull(a.getCompleter()); + CountedCompleter b = new NoopCC(a); + assertSame(a, b.getCompleter()); + CountedCompleter c = new NoopCC(b); + assertSame(b, c.getCompleter()); + } + + /** + * getRoot returns self if no parent, else parent's root + */ + public void testGetRoot() { + NoopCC a = new NoopCC(); + NoopCC b = new NoopCC(a); + NoopCC c = new NoopCC(b); + assertSame(a, a.getRoot()); + assertSame(a, b.getRoot()); + assertSame(a, c.getRoot()); + } + + /** + * tryComplete decrements pending count unless zero, in which case + * causes completion + */ + public void testTryComplete() { + NoopCC a = new NoopCC(); + assertEquals(0, a.getPendingCount()); + int n = 3; + a.setPendingCount(n); + for (; n > 0; n--) { + assertEquals(n, a.getPendingCount()); + a.tryComplete(); + a.checkIncomplete(); + assertEquals(n - 1, a.getPendingCount()); + } + a.tryComplete(); + assertEquals(0, a.computeN()); + assertEquals(1, a.onCompletionN()); + assertEquals(0, a.onExceptionalCompletionN()); + assertEquals(0, a.setRawResultN()); + checkCompletedNormally(a); + } + + /** + * propagateCompletion decrements pending count unless zero, in + * which case causes completion, without invoking onCompletion + */ + public void testPropagateCompletion() { + NoopCC a = new NoopCC(); + assertEquals(0, a.getPendingCount()); + int n = 3; + a.setPendingCount(n); + for (; n > 0; n--) { + assertEquals(n, a.getPendingCount()); + a.propagateCompletion(); + a.checkIncomplete(); + assertEquals(n - 1, a.getPendingCount()); + } + a.propagateCompletion(); + assertEquals(0, a.computeN()); + assertEquals(0, a.onCompletionN()); + assertEquals(0, a.onExceptionalCompletionN()); + assertEquals(0, a.setRawResultN()); + checkCompletedNormally(a); + } + + /** + * firstComplete returns this if pending count is zero else null + */ + public void testFirstComplete() { + NoopCC a = new NoopCC(); + a.setPendingCount(1); + assertNull(a.firstComplete()); + a.checkIncomplete(); + assertSame(a, a.firstComplete()); + a.checkIncomplete(); + } + + /** + * firstComplete.nextComplete returns parent if pending count is + * zero else null + */ + public void testNextComplete() { + NoopCC a = new NoopCC(); + NoopCC b = new NoopCC(a); + a.setPendingCount(1); + b.setPendingCount(1); + assertNull(b.firstComplete()); + assertSame(b, b.firstComplete()); + assertNull(b.nextComplete()); + a.checkIncomplete(); + b.checkIncomplete(); + assertSame(a, b.nextComplete()); + assertSame(a, b.nextComplete()); + a.checkIncomplete(); + b.checkIncomplete(); + assertNull(a.nextComplete()); + b.checkIncomplete(); + checkCompletedNormally(a); + } + + /** + * quietlyCompleteRoot completes root task and only root task + */ + public void testQuietlyCompleteRoot() { + NoopCC a = new NoopCC(); + NoopCC b = new NoopCC(a); + NoopCC c = new NoopCC(b); + a.setPendingCount(1); + b.setPendingCount(1); + c.setPendingCount(1); + c.quietlyCompleteRoot(); + assertTrue(a.isDone()); + assertFalse(b.isDone()); + assertFalse(c.isDone()); + } + + // Invocation tests use some interdependent task classes + // to better test propagation etc + + /** + * Version of Fibonacci with different classes for left vs right forks + */ + abstract class CCF extends CheckedCC { + int number; + int rnumber; + + public CCF(CountedCompleter parent, int n) { + super(parent, 1); + this.number = n; + } + + protected final void realCompute() { + CCF f = this; + int n = number; + while (n >= 2) { + new RCCF(f, n - 2).fork(); + f = new LCCF(f, --n); + } + f.complete(null); + } + } + + final class LCCF extends CCF { + public LCCF(int n) { this(null, n); } + public LCCF(CountedCompleter parent, int n) { + super(parent, n); + } + public final void onCompletion(CountedCompleter caller) { + super.onCompletion(caller); + CCF p = (CCF)getCompleter(); + int n = number + rnumber; + if (p != null) + p.number = n; + else + number = n; + } + } + final class RCCF extends CCF { + public RCCF(CountedCompleter parent, int n) { + super(parent, n); + } + public final void onCompletion(CountedCompleter caller) { + super.onCompletion(caller); + CCF p = (CCF)getCompleter(); + int n = number + rnumber; + if (p != null) + p.rnumber = n; + else + number = n; + } + } + + // Version of CCF with forced failure in left completions + abstract class FailingCCF extends CheckedCC { + int number; + int rnumber; + + public FailingCCF(CountedCompleter parent, int n) { + super(parent, 1); + this.number = n; + } + + protected final void realCompute() { + FailingCCF f = this; + int n = number; + while (n >= 2) { + new RFCCF(f, n - 2).fork(); + f = new LFCCF(f, --n); + } + f.complete(null); + } + } + + final class LFCCF extends FailingCCF { + public LFCCF(int n) { this(null, n); } + public LFCCF(CountedCompleter parent, int n) { + super(parent, n); + } + public final void onCompletion(CountedCompleter caller) { + super.onCompletion(caller); + FailingCCF p = (FailingCCF)getCompleter(); + int n = number + rnumber; + if (p != null) + p.number = n; + else + number = n; + } + } + final class RFCCF extends FailingCCF { + public RFCCF(CountedCompleter parent, int n) { + super(parent, n); + } + public final void onCompletion(CountedCompleter caller) { + super.onCompletion(caller); + completeExceptionally(new FJException()); + } + } + + /** + * invoke returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks; getRawResult returns null. + */ + public void testInvoke() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertNull(f.invoke()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyInvoke task returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks + */ + public void testQuietlyInvoke() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + f.quietlyInvoke(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join of a forked task returns when task completes + */ + public void testForkJoin() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertNull(f.join()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * get of a forked task returns when task completes + */ + public void testForkGet() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertNull(f.get()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get of a forked task returns when task completes + */ + public void testForkTimedGet() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get with null time unit throws NPE + */ + public void testForkTimedGetNPE() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + try { + f.get(5L, null); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes + */ + public void testForkQuietlyJoin() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * helpQuiesce returns when tasks are complete. + * getQueuedTaskCount returns 0 when quiescent + */ + public void testForkHelpQuiesce() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + helpQuiesce(); + assertEquals(21, f.number); + assertEquals(0, getQueuedTaskCount()); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invoke task throws exception when task completes abnormally + */ + public void testAbnormalInvoke() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyInvoke task returns when task completes abnormally + */ + public void testAbnormalQuietlyInvoke() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + f.quietlyInvoke(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkJoin() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkGet() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingCCF f = new LFCCF(8); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkTimedGet() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingCCF f = new LFCCF(8); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes abnormally + */ + public void testAbnormalForkQuietlyJoin() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invoke task throws exception when task cancelled + */ + public void testCancelledInvoke() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + try { + f.invoke(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join of a forked task throws exception when task cancelled + */ + public void testCancelledForkJoin() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * get of a forked task throws exception when task cancelled + */ + public void testCancelledForkGet() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get of a forked task throws exception when task cancelled + */ + public void testCancelledForkTimedGet() throws Exception { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task cancelled + */ + public void testCancelledForkQuietlyJoin() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + f.quietlyJoin(); + checkCancelled(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * getPool of executing task returns its pool + */ + public void testGetPool() { + final ForkJoinPool mainPool = mainPool(); + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + assertSame(mainPool, getPool()); + }}; + testInvokeOnPool(mainPool, a); + } + + /** + * getPool of non-FJ task returns null + */ + public void testGetPool2() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + assertNull(getPool()); + }}; + assertNull(a.invoke()); + } + + /** + * inForkJoinPool of executing task returns true + */ + public void testInForkJoinPool() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + assertTrue(inForkJoinPool()); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * inForkJoinPool of non-FJ task returns false + */ + public void testInForkJoinPool2() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + assertFalse(inForkJoinPool()); + }}; + assertNull(a.invoke()); + } + + /** + * setRawResult(null) succeeds + */ + public void testSetRawResult() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + setRawResult(null); + assertNull(getRawResult()); + }}; + assertNull(a.invoke()); + } + + /** + * invoke task throws exception after invoking completeExceptionally + */ + public void testCompleteExceptionally2() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF n = new LCCF(8); + CCF f = new LCCF(n, 8); + FJException ex = new FJException(); + f.completeExceptionally(ex); + f.checkCompletedExceptionally(ex); + n.checkCompletedExceptionally(ex); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(t1, t2) invokes all task arguments + */ + public void testInvokeAll2() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + CCF g = new LCCF(9); + invokeAll(f, g); + assertEquals(21, f.number); + assertEquals(34, g.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument invokes task + */ + public void testInvokeAll1() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + invokeAll(f); + checkCompletedNormally(f); + assertEquals(21, f.number); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument invokes tasks + */ + public void testInvokeAll3() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + CCF g = new LCCF(9); + CCF h = new LCCF(7); + invokeAll(f, g, h); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(collection) invokes all tasks in the collection + */ + public void testInvokeAllCollection() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + CCF g = new LCCF(9); + CCF h = new LCCF(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + invokeAll(set); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with any null task throws NPE + */ + public void testInvokeAllNPE() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + CCF g = new LCCF(9); + CCF h = null; + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(t1, t2) throw exception if any task does + */ + public void testAbnormalInvokeAll2() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + FailingCCF g = new LFCCF(9); + try { + invokeAll(f, g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument throws exception if task does + */ + public void testAbnormalInvokeAll1() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF g = new LFCCF(9); + try { + invokeAll(g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument throws exception if any task does + */ + public void testAbnormalInvokeAll3() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + FailingCCF g = new LFCCF(9); + CCF h = new LCCF(7); + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(collection) throws exception if any task does + */ + public void testAbnormalInvokeAllCollection() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + CCF g = new LCCF(9); + CCF h = new LCCF(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + try { + invokeAll(set); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * tryUnfork returns true for most recent unexecuted task, + * and suppresses execution + */ + public void testTryUnfork() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF g = new LCCF(9); + assertSame(g, g.fork()); + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertTrue(f.tryUnfork()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * getSurplusQueuedTaskCount returns > 0 when + * there are more tasks than threads + */ + public void testGetSurplusQueuedTaskCount() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF h = new LCCF(7); + assertSame(h, h.fork()); + CCF g = new LCCF(9); + assertSame(g, g.fork()); + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertTrue(getSurplusQueuedTaskCount() > 0); + helpQuiesce(); + assertEquals(0, getSurplusQueuedTaskCount()); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * peekNextLocalTask returns most recent unexecuted task. + */ + public void testPeekNextLocalTask() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF g = new LCCF(9); + assertSame(g, g.fork()); + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertSame(f, peekNextLocalTask()); + assertNull(f.join()); + checkCompletedNormally(f); + helpQuiesce(); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * pollNextLocalTask returns most recent unexecuted task without + * executing it + */ + public void testPollNextLocalTask() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF g = new LCCF(9); + assertSame(g, g.fork()); + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertSame(f, pollNextLocalTask()); + helpQuiesce(); + checkNotDone(f); + assertEquals(34, g.number); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * pollTask returns an unexecuted task without executing it + */ + public void testPollTask() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF g = new LCCF(9); + assertSame(g, g.fork()); + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertSame(f, pollTask()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * peekNextLocalTask returns least recent unexecuted task in async mode + */ + public void testPeekNextLocalTaskAsync() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF g = new LCCF(9); + assertSame(g, g.fork()); + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertSame(g, peekNextLocalTask()); + assertNull(f.join()); + helpQuiesce(); + checkCompletedNormally(f); + assertEquals(34, g.number); + checkCompletedNormally(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** + * pollNextLocalTask returns least recent unexecuted task without + * executing it, in async mode + */ + public void testPollNextLocalTaskAsync() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF g = new LCCF(9); + assertSame(g, g.fork()); + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertSame(g, pollNextLocalTask()); + helpQuiesce(); + assertEquals(21, f.number); + checkCompletedNormally(f); + checkNotDone(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** + * pollTask returns an unexecuted task without executing it, in + * async mode + */ + public void testPollTaskAsync() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF g = new LCCF(9); + assertSame(g, g.fork()); + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertSame(g, pollTask()); + helpQuiesce(); + assertEquals(21, f.number); + checkCompletedNormally(f); + checkNotDone(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + // versions for singleton pools + + /** + * invoke returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks; getRawResult returns null. + */ + public void testInvokeSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertNull(f.invoke()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyInvoke task returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks + */ + public void testQuietlyInvokeSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + f.quietlyInvoke(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * join of a forked task returns when task completes + */ + public void testForkJoinSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertNull(f.join()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * get of a forked task returns when task completes + */ + public void testForkGetSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertNull(f.get()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * timed get of a forked task returns when task completes + */ + public void testForkTimedGetSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * timed get with null time unit throws NPE + */ + public void testForkTimedGetNPESingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + try { + f.get(5L, null); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes + */ + public void testForkQuietlyJoinSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * helpQuiesce returns when tasks are complete. + * getQueuedTaskCount returns 0 when quiescent + */ + public void testForkHelpQuiesceSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertSame(f, f.fork()); + helpQuiesce(); + assertEquals(0, getQueuedTaskCount()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invoke task throws exception when task completes abnormally + */ + public void testAbnormalInvokeSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyInvoke task returns when task completes abnormally + */ + public void testAbnormalQuietlyInvokeSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + f.quietlyInvoke(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * join of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkJoinSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkGetSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingCCF f = new LFCCF(8); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * timed get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkTimedGetSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingCCF f = new LFCCF(8); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes abnormally + */ + public void testAbnormalForkQuietlyJoinSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invoke task throws exception when task cancelled + */ + public void testCancelledInvokeSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + try { + f.invoke(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * join of a forked task throws exception when task cancelled + */ + public void testCancelledForkJoinSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * get of a forked task throws exception when task cancelled + */ + public void testCancelledForkGetSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * timed get of a forked task throws exception when task cancelled + */ + public void testCancelledForkTimedGetSingleton() throws Exception { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task cancelled + */ + public void testCancelledForkQuietlyJoinSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + f.quietlyJoin(); + checkCancelled(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invoke task throws exception after invoking completeExceptionally + */ + public void testCompleteExceptionallySingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF n = new LCCF(8); + CCF f = new LCCF(n, 8); + FJException ex = new FJException(); + f.completeExceptionally(ex); + f.checkCompletedExceptionally(ex); + n.checkCompletedExceptionally(ex); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(t1, t2) invokes all task arguments + */ + public void testInvokeAll2Singleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + CCF g = new LCCF(9); + invokeAll(f, g); + assertEquals(21, f.number); + assertEquals(34, g.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument invokes task + */ + public void testInvokeAll1Singleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + invokeAll(f); + checkCompletedNormally(f); + assertEquals(21, f.number); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument invokes tasks + */ + public void testInvokeAll3Singleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + CCF g = new LCCF(9); + CCF h = new LCCF(7); + invokeAll(f, g, h); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(collection) invokes all tasks in the collection + */ + public void testInvokeAllCollectionSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + CCF g = new LCCF(9); + CCF h = new LCCF(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + invokeAll(set); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with any null task throws NPE + */ + public void testInvokeAllNPESingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + CCF g = new LCCF(9); + CCF h = null; + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(t1, t2) throw exception if any task does + */ + public void testAbnormalInvokeAll2Singleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + FailingCCF g = new LFCCF(9); + try { + invokeAll(f, g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument throws exception if task does + */ + public void testAbnormalInvokeAll1Singleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF g = new LFCCF(9); + try { + invokeAll(g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument throws exception if any task does + */ + public void testAbnormalInvokeAll3Singleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(8); + FailingCCF g = new LFCCF(9); + CCF h = new LCCF(7); + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(collection) throws exception if any task does + */ + public void testAbnormalInvokeAllCollectionSingleton() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(8); + CCF g = new LCCF(9); + CCF h = new LCCF(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + try { + invokeAll(set); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/CyclicBarrierTest.java b/jdk/test/java/util/concurrent/tck/CyclicBarrierTest.java new file mode 100644 index 00000000000..bfae2ee323b --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/CyclicBarrierTest.java @@ -0,0 +1,491 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class CyclicBarrierTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(CyclicBarrierTest.class); + } + + private volatile int countAction; + private class MyAction implements Runnable { + public void run() { ++countAction; } + } + + /** + * Spin-waits till the number of waiters == numberOfWaiters. + */ + void awaitNumberWaiting(CyclicBarrier barrier, int numberOfWaiters) { + long startTime = System.nanoTime(); + while (barrier.getNumberWaiting() != numberOfWaiters) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + } + + /** + * Creating with negative parties throws IAE + */ + public void testConstructor1() { + try { + new CyclicBarrier(-1, (Runnable)null); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Creating with negative parties and no action throws IAE + */ + public void testConstructor2() { + try { + new CyclicBarrier(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * getParties returns the number of parties given in constructor + */ + public void testGetParties() { + CyclicBarrier b = new CyclicBarrier(2); + assertEquals(2, b.getParties()); + assertEquals(0, b.getNumberWaiting()); + } + + /** + * A 1-party barrier triggers after single await + */ + public void testSingleParty() throws Exception { + CyclicBarrier b = new CyclicBarrier(1); + assertEquals(1, b.getParties()); + assertEquals(0, b.getNumberWaiting()); + b.await(); + b.await(); + assertEquals(0, b.getNumberWaiting()); + } + + /** + * The supplied barrier action is run at barrier + */ + public void testBarrierAction() throws Exception { + countAction = 0; + CyclicBarrier b = new CyclicBarrier(1, new MyAction()); + assertEquals(1, b.getParties()); + assertEquals(0, b.getNumberWaiting()); + b.await(); + b.await(); + assertEquals(0, b.getNumberWaiting()); + assertEquals(2, countAction); + } + + /** + * A 2-party/thread barrier triggers after both threads invoke await + */ + public void testTwoParties() throws Exception { + final CyclicBarrier b = new CyclicBarrier(2); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + b.await(); + b.await(); + b.await(); + b.await(); + }}); + + b.await(); + b.await(); + b.await(); + b.await(); + awaitTermination(t); + } + + /** + * An interruption in one party causes others waiting in await to + * throw BrokenBarrierException + */ + public void testAwait1_Interrupted_BrokenBarrier() { + final CyclicBarrier c = new CyclicBarrier(3); + final CountDownLatch pleaseInterrupt = new CountDownLatch(2); + Thread t1 = new ThreadShouldThrow(InterruptedException.class) { + public void realRun() throws Exception { + pleaseInterrupt.countDown(); + c.await(); + }}; + Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { + public void realRun() throws Exception { + pleaseInterrupt.countDown(); + c.await(); + }}; + + t1.start(); + t2.start(); + await(pleaseInterrupt); + t1.interrupt(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * An interruption in one party causes others waiting in timed await to + * throw BrokenBarrierException + */ + public void testAwait2_Interrupted_BrokenBarrier() throws Exception { + final CyclicBarrier c = new CyclicBarrier(3); + final CountDownLatch pleaseInterrupt = new CountDownLatch(2); + Thread t1 = new ThreadShouldThrow(InterruptedException.class) { + public void realRun() throws Exception { + pleaseInterrupt.countDown(); + c.await(LONG_DELAY_MS, MILLISECONDS); + }}; + Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { + public void realRun() throws Exception { + pleaseInterrupt.countDown(); + c.await(LONG_DELAY_MS, MILLISECONDS); + }}; + + t1.start(); + t2.start(); + await(pleaseInterrupt); + t1.interrupt(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * A timeout in timed await throws TimeoutException + */ + public void testAwait3_TimeoutException() throws InterruptedException { + final CyclicBarrier c = new CyclicBarrier(2); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + long startTime = System.nanoTime(); + try { + c.await(timeoutMillis(), MILLISECONDS); + shouldThrow(); + } catch (TimeoutException success) {} + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}); + + awaitTermination(t); + } + + /** + * A timeout in one party causes others waiting in timed await to + * throw BrokenBarrierException + */ + public void testAwait4_Timeout_BrokenBarrier() throws InterruptedException { + final CyclicBarrier c = new CyclicBarrier(3); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + try { + c.await(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (BrokenBarrierException success) {} + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + awaitNumberWaiting(c, 1); + long startTime = System.nanoTime(); + try { + c.await(timeoutMillis(), MILLISECONDS); + shouldThrow(); + } catch (TimeoutException success) {} + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}); + + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * A timeout in one party causes others waiting in await to + * throw BrokenBarrierException + */ + public void testAwait5_Timeout_BrokenBarrier() throws InterruptedException { + final CyclicBarrier c = new CyclicBarrier(3); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + try { + c.await(); + shouldThrow(); + } catch (BrokenBarrierException success) {} + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + awaitNumberWaiting(c, 1); + long startTime = System.nanoTime(); + try { + c.await(timeoutMillis(), MILLISECONDS); + shouldThrow(); + } catch (TimeoutException success) {} + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}); + + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * A reset of an active barrier causes waiting threads to throw + * BrokenBarrierException + */ + public void testReset_BrokenBarrier() throws InterruptedException { + final CyclicBarrier c = new CyclicBarrier(3); + final CountDownLatch pleaseReset = new CountDownLatch(2); + Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) { + public void realRun() throws Exception { + pleaseReset.countDown(); + c.await(); + }}; + Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { + public void realRun() throws Exception { + pleaseReset.countDown(); + c.await(); + }}; + + t1.start(); + t2.start(); + await(pleaseReset); + + awaitNumberWaiting(c, 2); + c.reset(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * A reset before threads enter barrier does not throw + * BrokenBarrierException + */ + public void testReset_NoBrokenBarrier() throws Exception { + final CyclicBarrier c = new CyclicBarrier(3); + c.reset(); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + c.await(); + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + c.await(); + }}); + + c.await(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * All threads block while a barrier is broken. + */ + public void testReset_Leakage() throws InterruptedException { + final CyclicBarrier c = new CyclicBarrier(2); + final AtomicBoolean done = new AtomicBoolean(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + while (!done.get()) { + try { + while (c.isBroken()) + c.reset(); + + c.await(); + shouldThrow(); + } + catch (BrokenBarrierException ok) {} + catch (InterruptedException ok) {} + }}}); + + for (int i = 0; i < 4; i++) { + delay(timeoutMillis()); + t.interrupt(); + } + done.set(true); + t.interrupt(); + awaitTermination(t); + } + + /** + * Reset of a non-broken barrier does not break barrier + */ + public void testResetWithoutBreakage() throws Exception { + final CyclicBarrier barrier = new CyclicBarrier(3); + for (int i = 0; i < 3; i++) { + final CyclicBarrier start = new CyclicBarrier(3); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + start.await(); + barrier.await(); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + start.await(); + barrier.await(); + }}); + + start.await(); + barrier.await(); + awaitTermination(t1); + awaitTermination(t2); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + if (i == 1) barrier.reset(); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + } + } + + /** + * Reset of a barrier after interruption reinitializes it. + */ + public void testResetAfterInterrupt() throws Exception { + final CyclicBarrier barrier = new CyclicBarrier(3); + for (int i = 0; i < 2; i++) { + final CyclicBarrier start = new CyclicBarrier(3); + Thread t1 = new ThreadShouldThrow(InterruptedException.class) { + public void realRun() throws Exception { + start.await(); + barrier.await(); + }}; + + Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { + public void realRun() throws Exception { + start.await(); + barrier.await(); + }}; + + t1.start(); + t2.start(); + start.await(); + t1.interrupt(); + awaitTermination(t1); + awaitTermination(t2); + assertTrue(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + barrier.reset(); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + } + } + + /** + * Reset of a barrier after timeout reinitializes it. + */ + public void testResetAfterTimeout() throws Exception { + final CyclicBarrier barrier = new CyclicBarrier(3); + for (int i = 0; i < 2; i++) { + assertEquals(0, barrier.getNumberWaiting()); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + try { + barrier.await(); + shouldThrow(); + } catch (BrokenBarrierException success) {} + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + awaitNumberWaiting(barrier, 1); + long startTime = System.nanoTime(); + try { + barrier.await(timeoutMillis(), MILLISECONDS); + shouldThrow(); + } catch (TimeoutException success) {} + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}); + + awaitTermination(t1); + awaitTermination(t2); + assertEquals(0, barrier.getNumberWaiting()); + assertTrue(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + barrier.reset(); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + } + } + + /** + * Reset of a barrier after a failed command reinitializes it. + */ + public void testResetAfterCommandException() throws Exception { + final CyclicBarrier barrier = + new CyclicBarrier(3, new Runnable() { + public void run() { + throw new NullPointerException(); }}); + for (int i = 0; i < 2; i++) { + final CyclicBarrier start = new CyclicBarrier(3); + Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) { + public void realRun() throws Exception { + start.await(); + barrier.await(); + }}; + + Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) { + public void realRun() throws Exception { + start.await(); + barrier.await(); + }}; + + t1.start(); + t2.start(); + start.await(); + awaitNumberWaiting(barrier, 2); + try { + barrier.await(); + shouldThrow(); + } catch (NullPointerException success) {} + awaitTermination(t1); + awaitTermination(t2); + assertTrue(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + barrier.reset(); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + } + } +} diff --git a/jdk/test/java/util/concurrent/tck/DelayQueueTest.java b/jdk/test/java/util/concurrent/tck/DelayQueueTest.java new file mode 100644 index 00000000000..4d05c864554 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/DelayQueueTest.java @@ -0,0 +1,820 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Delayed; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; + +import junit.framework.Test; + +public class DelayQueueTest extends JSR166TestCase { + + public static class Generic extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new DelayQueue(); + } + protected PDelay makeElement(int i) { + return new PDelay(i); + } + } + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return newTestSuite(DelayQueueTest.class, + new Generic().testSuite()); + } + + /** + * A delayed implementation for testing. + * Most tests use Pseudodelays, where delays are all elapsed + * (so, no blocking solely for delays) but are still ordered + */ + static class PDelay implements Delayed { + int pseudodelay; + PDelay(int i) { pseudodelay = i; } + public int compareTo(PDelay other) { + int a = this.pseudodelay; + int b = other.pseudodelay; + return (a < b) ? -1 : (a > b) ? 1 : 0; + } + public int compareTo(Delayed y) { + return compareTo((PDelay)y); + } + public boolean equals(Object other) { + return (other instanceof PDelay) && + this.pseudodelay == ((PDelay)other).pseudodelay; + } + // suppress [overrides] javac warning + public int hashCode() { return pseudodelay; } + public long getDelay(TimeUnit ignore) { + return Integer.MIN_VALUE + pseudodelay; + } + public String toString() { + return String.valueOf(pseudodelay); + } + } + + /** + * Delayed implementation that actually delays + */ + static class NanoDelay implements Delayed { + long trigger; + NanoDelay(long i) { + trigger = System.nanoTime() + i; + } + public int compareTo(NanoDelay y) { + long i = trigger; + long j = y.trigger; + if (i < j) return -1; + if (i > j) return 1; + return 0; + } + + public int compareTo(Delayed y) { + return compareTo((NanoDelay)y); + } + + public boolean equals(Object other) { + return equals((NanoDelay)other); + } + public boolean equals(NanoDelay other) { + return other.trigger == trigger; + } + + // suppress [overrides] javac warning + public int hashCode() { return (int) trigger; } + + public long getDelay(TimeUnit unit) { + long n = trigger - System.nanoTime(); + return unit.convert(n, TimeUnit.NANOSECONDS); + } + + public long getTriggerTime() { + return trigger; + } + + public String toString() { + return String.valueOf(trigger); + } + } + + /** + * Returns a new queue of given size containing consecutive + * PDelays 0 ... n. + */ + private DelayQueue populatedQueue(int n) { + DelayQueue q = new DelayQueue(); + assertTrue(q.isEmpty()); + for (int i = n - 1; i >= 0; i -= 2) + assertTrue(q.offer(new PDelay(i))); + for (int i = (n & 1); i < n; i += 2) + assertTrue(q.offer(new PDelay(i))); + assertFalse(q.isEmpty()); + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + assertEquals(n, q.size()); + return q; + } + + /** + * A new queue has unbounded capacity + */ + public void testConstructor1() { + assertEquals(Integer.MAX_VALUE, new DelayQueue().remainingCapacity()); + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new DelayQueue(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NPE + */ + public void testConstructor4() { + try { + new DelayQueue(Arrays.asList(new PDelay[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws NPE + */ + public void testConstructor5() { + PDelay[] a = new PDelay[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + a[i] = new PDelay(i); + try { + new DelayQueue(Arrays.asList(a)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of collection used to initialize + */ + public void testConstructor6() { + PDelay[] ints = new PDelay[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new PDelay(i); + DelayQueue q = new DelayQueue(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + DelayQueue q = new DelayQueue(); + assertTrue(q.isEmpty()); + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + q.add(new PDelay(1)); + assertFalse(q.isEmpty()); + q.add(new PDelay(2)); + q.remove(); + q.remove(); + assertTrue(q.isEmpty()); + } + + /** + * remainingCapacity() always returns Integer.MAX_VALUE + */ + public void testRemainingCapacity() { + BlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + assertEquals(SIZE - i, q.size()); + assertTrue(q.remove() instanceof PDelay); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + assertEquals(i, q.size()); + assertTrue(q.add(new PDelay(i))); + } + } + + /** + * offer non-null succeeds + */ + public void testOffer() { + DelayQueue q = new DelayQueue(); + assertTrue(q.offer(new PDelay(0))); + assertTrue(q.offer(new PDelay(1))); + } + + /** + * add succeeds + */ + public void testAdd() { + DelayQueue q = new DelayQueue(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + assertTrue(q.add(new PDelay(i))); + } + } + + /** + * addAll(this) throws IAE + */ + public void testAddAllSelf() { + DelayQueue q = populatedQueue(SIZE); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + DelayQueue q = new DelayQueue(); + PDelay[] a = new PDelay[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + a[i] = new PDelay(i); + try { + q.addAll(Arrays.asList(a)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of successful addAll + */ + public void testAddAll5() { + PDelay[] empty = new PDelay[0]; + PDelay[] ints = new PDelay[SIZE]; + for (int i = SIZE - 1; i >= 0; --i) + ints[i] = new PDelay(i); + DelayQueue q = new DelayQueue(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * all elements successfully put are contained + */ + public void testPut() { + DelayQueue q = new DelayQueue(); + for (int i = 0; i < SIZE; ++i) { + PDelay x = new PDelay(i); + q.put(x); + assertTrue(q.contains(x)); + } + assertEquals(SIZE, q.size()); + } + + /** + * put doesn't block waiting for take + */ + public void testPutWithTake() throws InterruptedException { + final DelayQueue q = new DelayQueue(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + q.put(new PDelay(0)); + q.put(new PDelay(0)); + q.put(new PDelay(0)); + q.put(new PDelay(0)); + }}); + + awaitTermination(t); + assertEquals(4, q.size()); + } + + /** + * timed offer does not time out + */ + public void testTimedOffer() throws InterruptedException { + final DelayQueue q = new DelayQueue(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(new PDelay(0)); + q.put(new PDelay(0)); + assertTrue(q.offer(new PDelay(0), SHORT_DELAY_MS, MILLISECONDS)); + assertTrue(q.offer(new PDelay(0), LONG_DELAY_MS, MILLISECONDS)); + }}); + + awaitTermination(t); + } + + /** + * take retrieves elements in priority order + */ + public void testTake() throws InterruptedException { + DelayQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(new PDelay(i), q.take()); + } + } + + /** + * Take removes existing elements until empty, then blocks interruptibly + */ + public void testBlockingTake() throws InterruptedException { + final DelayQueue q = populatedQueue(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) { + assertEquals(new PDelay(i), ((PDelay)q.take())); + } + + Thread.currentThread().interrupt(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + DelayQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(new PDelay(i), q.poll()); + } + assertNull(q.poll()); + } + + /** + * timed poll with zero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll0() throws InterruptedException { + DelayQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(new PDelay(i), q.poll(0, MILLISECONDS)); + } + assertNull(q.poll(0, MILLISECONDS)); + } + + /** + * timed poll with nonzero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll() throws InterruptedException { + DelayQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + long startTime = System.nanoTime(); + assertEquals(new PDelay(i), q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + long startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + checkEmpty(q); + } + + /** + * Interrupted timed poll throws InterruptedException instead of + * returning timeout status + */ + public void testInterruptedTimedPoll() throws InterruptedException { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + final DelayQueue q = populatedQueue(SIZE); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(new PDelay(i), + ((PDelay)q.poll(LONG_DELAY_MS, MILLISECONDS))); + } + + Thread.currentThread().interrupt(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + checkEmpty(q); + } + + /** + * peek returns next element, or null if empty + */ + public void testPeek() { + DelayQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(new PDelay(i), q.peek()); + assertEquals(new PDelay(i), q.poll()); + if (q.isEmpty()) + assertNull(q.peek()); + else + assertFalse(new PDelay(i).equals(q.peek())); + } + assertNull(q.peek()); + } + + /** + * element returns next element, or throws NSEE if empty + */ + public void testElement() { + DelayQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(new PDelay(i), q.element()); + q.poll(); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove removes next element, or throws NSEE if empty + */ + public void testRemove() { + DelayQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(new PDelay(i), q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + DelayQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new PDelay(i))); + q.poll(); + assertFalse(q.contains(new PDelay(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + DelayQueue q = populatedQueue(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + PDelay x = new PDelay(1); + q.add(x); + assertFalse(q.isEmpty()); + assertTrue(q.contains(x)); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + DelayQueue q = populatedQueue(SIZE); + DelayQueue p = new DelayQueue(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new PDelay(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + DelayQueue q = populatedQueue(SIZE); + DelayQueue p = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + DelayQueue q = populatedQueue(SIZE); + DelayQueue p = populatedQueue(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + PDelay x = (PDelay)(p.remove()); + assertFalse(q.contains(x)); + } + } + } + + /** + * toArray contains all elements + */ + public void testToArray() throws InterruptedException { + DelayQueue q = populatedQueue(SIZE); + Object[] o = q.toArray(); + Arrays.sort(o); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.take()); + } + + /** + * toArray(a) contains all elements + */ + public void testToArray2() { + DelayQueue q = populatedQueue(SIZE); + PDelay[] ints = new PDelay[SIZE]; + PDelay[] array = q.toArray(ints); + assertSame(ints, array); + Arrays.sort(ints); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.remove()); + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + DelayQueue q = populatedQueue(SIZE); + try { + q.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * iterator iterates through all elements + */ + public void testIterator() { + DelayQueue q = populatedQueue(SIZE); + int i = 0; + Iterator it = q.iterator(); + while (it.hasNext()) { + assertTrue(q.contains(it.next())); + ++i; + } + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new DelayQueue().iterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final DelayQueue q = new DelayQueue(); + q.add(new PDelay(2)); + q.add(new PDelay(1)); + q.add(new PDelay(3)); + Iterator it = q.iterator(); + it.next(); + it.remove(); + it = q.iterator(); + assertEquals(new PDelay(2), it.next()); + assertEquals(new PDelay(3), it.next()); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + DelayQueue q = populatedQueue(SIZE); + String s = q.toString(); + for (Object e : q) + assertTrue(s.contains(e.toString())); + } + + /** + * timed poll transfers elements across Executor tasks + */ + public void testPollInExecutor() { + final DelayQueue q = new DelayQueue(); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertNull(q.poll()); + threadsStarted.await(); + assertNotNull(q.poll(LONG_DELAY_MS, MILLISECONDS)); + checkEmpty(q); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + q.put(new PDelay(1)); + }}); + } + } + + /** + * Delayed actions do not occur until their delay elapses + */ + public void testDelay() throws InterruptedException { + DelayQueue q = new DelayQueue(); + for (int i = 0; i < SIZE; ++i) + q.add(new NanoDelay(1000000L * (SIZE - i))); + + long last = 0; + for (int i = 0; i < SIZE; ++i) { + NanoDelay e = q.take(); + long tt = e.getTriggerTime(); + assertTrue(System.nanoTime() - tt >= 0); + if (i != 0) + assertTrue(tt >= last); + last = tt; + } + assertTrue(q.isEmpty()); + } + + /** + * peek of a non-empty queue returns non-null even if not expired + */ + public void testPeekDelayed() { + DelayQueue q = new DelayQueue(); + q.add(new NanoDelay(Long.MAX_VALUE)); + assertNotNull(q.peek()); + } + + /** + * poll of a non-empty queue returns null if no expired elements. + */ + public void testPollDelayed() { + DelayQueue q = new DelayQueue(); + q.add(new NanoDelay(Long.MAX_VALUE)); + assertNull(q.poll()); + } + + /** + * timed poll of a non-empty queue returns null if no expired elements. + */ + public void testTimedPollDelayed() throws InterruptedException { + DelayQueue q = new DelayQueue(); + q.add(new NanoDelay(LONG_DELAY_MS * 1000000L)); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + } + + /** + * drainTo(c) empties queue into another collection c + */ + public void testDrainTo() { + DelayQueue q = new DelayQueue(); + PDelay[] elems = new PDelay[SIZE]; + for (int i = 0; i < SIZE; ++i) { + elems[i] = new PDelay(i); + q.add(elems[i]); + } + ArrayList l = new ArrayList(); + q.drainTo(l); + assertEquals(0, q.size()); + for (int i = 0; i < SIZE; ++i) + assertEquals(elems[i], l.get(i)); + q.add(elems[0]); + q.add(elems[1]); + assertFalse(q.isEmpty()); + assertTrue(q.contains(elems[0])); + assertTrue(q.contains(elems[1])); + l.clear(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(2, l.size()); + for (int i = 0; i < 2; ++i) + assertEquals(elems[i], l.get(i)); + } + + /** + * drainTo empties queue + */ + public void testDrainToWithActivePut() throws InterruptedException { + final DelayQueue q = populatedQueue(SIZE); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + q.put(new PDelay(SIZE + 1)); + }}); + + t.start(); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertTrue(l.size() >= SIZE); + t.join(); + assertTrue(q.size() + l.size() >= SIZE); + } + + /** + * drainTo(c, n) empties first min(n, size) elements of queue into c + */ + public void testDrainToN() { + for (int i = 0; i < SIZE + 2; ++i) { + DelayQueue q = populatedQueue(SIZE); + ArrayList l = new ArrayList(); + q.drainTo(l, i); + int k = (i < SIZE) ? i : SIZE; + assertEquals(SIZE - k, q.size()); + assertEquals(k, l.size()); + } + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Collection q = populatedQueue(SIZE); + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + } +} diff --git a/jdk/test/java/util/concurrent/tck/DoubleAccumulatorTest.java b/jdk/test/java/util/concurrent/tck/DoubleAccumulatorTest.java new file mode 100644 index 00000000000..0a7fea9eb9d --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/DoubleAccumulatorTest.java @@ -0,0 +1,183 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Phaser; +import java.util.concurrent.atomic.DoubleAccumulator; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class DoubleAccumulatorTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(DoubleAccumulatorTest.class); + } + + /** + * default constructed initializes to zero + */ + public void testConstructor() { + DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); + assertEquals(0.0, ai.get()); + } + + /** + * accumulate accumulates given value to current, and get returns current value + */ + public void testAccumulateAndGet() { + DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); + ai.accumulate(2.0); + assertEquals(2.0, ai.get()); + ai.accumulate(-4.0); + assertEquals(2.0, ai.get()); + ai.accumulate(4.0); + assertEquals(4.0, ai.get()); + } + + /** + * reset() causes subsequent get() to return zero + */ + public void testReset() { + DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); + ai.accumulate(2.0); + assertEquals(2.0, ai.get()); + ai.reset(); + assertEquals(0.0, ai.get()); + } + + /** + * getThenReset() returns current value; subsequent get() returns zero + */ + public void testGetThenReset() { + DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); + ai.accumulate(2.0); + assertEquals(2.0, ai.get()); + assertEquals(2.0, ai.getThenReset()); + assertEquals(0.0, ai.get()); + } + + /** + * toString returns current value. + */ + public void testToString() { + DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); + assertEquals("0.0", ai.toString()); + ai.accumulate(1.0); + assertEquals(Double.toString(1.0), ai.toString()); + } + + /** + * intValue returns current value. + */ + public void testIntValue() { + DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); + assertEquals(0, ai.intValue()); + ai.accumulate(1.0); + assertEquals(1, ai.intValue()); + } + + /** + * longValue returns current value. + */ + public void testLongValue() { + DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); + assertEquals(0, ai.longValue()); + ai.accumulate(1.0); + assertEquals(1, ai.longValue()); + } + + /** + * floatValue returns current value. + */ + public void testFloatValue() { + DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); + assertEquals(0.0f, ai.floatValue()); + ai.accumulate(1.0); + assertEquals(1.0f, ai.floatValue()); + } + + /** + * doubleValue returns current value. + */ + public void testDoubleValue() { + DoubleAccumulator ai = new DoubleAccumulator(Double::max, 0.0); + assertEquals(0.0, ai.doubleValue()); + ai.accumulate(1.0); + assertEquals(1.0, ai.doubleValue()); + } + + /** + * accumulates by multiple threads produce correct result + */ + public void testAccumulateAndGetMT() { + final int incs = 1000000; + final int nthreads = 4; + final ExecutorService pool = Executors.newCachedThreadPool(); + DoubleAccumulator a = new DoubleAccumulator(Double::max, 0.0); + Phaser phaser = new Phaser(nthreads + 1); + for (int i = 0; i < nthreads; ++i) + pool.execute(new AccTask(a, phaser, incs)); + phaser.arriveAndAwaitAdvance(); + phaser.arriveAndAwaitAdvance(); + double expected = incs - 1; + double result = a.get(); + assertEquals(expected, result); + pool.shutdown(); + } + + static final class AccTask implements Runnable { + final DoubleAccumulator acc; + final Phaser phaser; + final int incs; + volatile double result; + AccTask(DoubleAccumulator acc, Phaser phaser, int incs) { + this.acc = acc; + this.phaser = phaser; + this.incs = incs; + } + + public void run() { + phaser.arriveAndAwaitAdvance(); + DoubleAccumulator a = acc; + for (int i = 0; i < incs; ++i) + a.accumulate(i); + result = a.get(); + phaser.arrive(); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/DoubleAdderTest.java b/jdk/test/java/util/concurrent/tck/DoubleAdderTest.java new file mode 100644 index 00000000000..fc7d1f47834 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/DoubleAdderTest.java @@ -0,0 +1,197 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.DoubleAdder; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class DoubleAdderTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(DoubleAdderTest.class); + } + + /** + * default constructed initializes to zero + */ + public void testConstructor() { + DoubleAdder ai = new DoubleAdder(); + assertEquals(0.0, ai.sum()); + } + + /** + * add adds given value to current, and sum returns current value + */ + public void testAddAndSum() { + DoubleAdder ai = new DoubleAdder(); + ai.add(2.0); + assertEquals(2.0, ai.sum()); + ai.add(-4.0); + assertEquals(-2.0, ai.sum()); + } + + /** + * reset() causes subsequent sum() to return zero + */ + public void testReset() { + DoubleAdder ai = new DoubleAdder(); + ai.add(2.0); + assertEquals(2.0, ai.sum()); + ai.reset(); + assertEquals(0.0, ai.sum()); + } + + /** + * sumThenReset() returns sum; subsequent sum() returns zero + */ + public void testSumThenReset() { + DoubleAdder ai = new DoubleAdder(); + ai.add(2.0); + assertEquals(2.0, ai.sum()); + assertEquals(2.0, ai.sumThenReset()); + assertEquals(0.0, ai.sum()); + } + + /** + * a deserialized serialized adder holds same value + */ + public void testSerialization() throws Exception { + DoubleAdder x = new DoubleAdder(); + DoubleAdder y = serialClone(x); + assertNotSame(x, y); + x.add(-22.0); + DoubleAdder z = serialClone(x); + assertEquals(-22.0, x.sum()); + assertEquals(0.0, y.sum()); + assertEquals(-22.0, z.sum()); + } + + /** + * toString returns current value. + */ + public void testToString() { + DoubleAdder ai = new DoubleAdder(); + assertEquals(Double.toString(0.0), ai.toString()); + ai.add(1.0); + assertEquals(Double.toString(1.0), ai.toString()); + } + + /** + * intValue returns current value. + */ + public void testIntValue() { + DoubleAdder ai = new DoubleAdder(); + assertEquals(0, ai.intValue()); + ai.add(1.0); + assertEquals(1, ai.intValue()); + } + + /** + * longValue returns current value. + */ + public void testLongValue() { + DoubleAdder ai = new DoubleAdder(); + assertEquals(0, ai.longValue()); + ai.add(1.0); + assertEquals(1, ai.longValue()); + } + + /** + * floatValue returns current value. + */ + public void testFloatValue() { + DoubleAdder ai = new DoubleAdder(); + assertEquals(0.0f, ai.floatValue()); + ai.add(1.0); + assertEquals(1.0f, ai.floatValue()); + } + + /** + * doubleValue returns current value. + */ + public void testDoubleValue() { + DoubleAdder ai = new DoubleAdder(); + assertEquals(0.0, ai.doubleValue()); + ai.add(1.0); + assertEquals(1.0, ai.doubleValue()); + } + + /** + * adds by multiple threads produce correct sum + */ + public void testAddAndSumMT() throws Throwable { + final int incs = 1000000; + final int nthreads = 4; + final ExecutorService pool = Executors.newCachedThreadPool(); + DoubleAdder a = new DoubleAdder(); + CyclicBarrier barrier = new CyclicBarrier(nthreads + 1); + for (int i = 0; i < nthreads; ++i) + pool.execute(new AdderTask(a, barrier, incs)); + barrier.await(); + barrier.await(); + double total = (long)nthreads * incs; + double sum = a.sum(); + assertEquals(sum, total); + pool.shutdown(); + } + + static final class AdderTask implements Runnable { + final DoubleAdder adder; + final CyclicBarrier barrier; + final int incs; + volatile double result; + AdderTask(DoubleAdder adder, CyclicBarrier barrier, int incs) { + this.adder = adder; + this.barrier = barrier; + this.incs = incs; + } + + public void run() { + try { + barrier.await(); + DoubleAdder a = adder; + for (int i = 0; i < incs; ++i) + a.add(1.0); + result = a.sum(); + barrier.await(); + } catch (Throwable t) { throw new Error(t); } + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/EntryTest.java b/jdk/test/java/util/concurrent/tck/EntryTest.java new file mode 100644 index 00000000000..dcd696d8d12 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/EntryTest.java @@ -0,0 +1,157 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.AbstractMap; +import java.util.Map; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class EntryTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(EntryTest.class); + } + + static final String k1 = "1"; + static final String v1 = "a"; + static final String k2 = "2"; + static final String v2 = "b"; + + /** + * A new SimpleEntry(k, v) holds k, v. + */ + public void testConstructor1() { + Map.Entry e = new AbstractMap.SimpleEntry(k1, v1); + assertEquals(k1, e.getKey()); + assertEquals(v1, e.getValue()); + } + + /** + * A new SimpleImmutableEntry(k, v) holds k, v. + */ + public void testConstructor2() { + Map.Entry s = new AbstractMap.SimpleImmutableEntry(k1, v1); + assertEquals(k1, s.getKey()); + assertEquals(v1, s.getValue()); + } + + /** + * A new SimpleEntry(entry(k, v)) holds k, v. + */ + public void testConstructor3() { + Map.Entry e2 = new AbstractMap.SimpleEntry(k1, v1); + Map.Entry e = new AbstractMap.SimpleEntry(e2); + assertEquals(k1, e.getKey()); + assertEquals(v1, e.getValue()); + } + + /** + * A new SimpleImmutableEntry(entry(k, v)) holds k, v. + */ + public void testConstructor4() { + Map.Entry s2 = new AbstractMap.SimpleImmutableEntry(k1, v1); + Map.Entry s = new AbstractMap.SimpleImmutableEntry(s2); + assertEquals(k1, s.getKey()); + assertEquals(v1, s.getValue()); + } + + /** + * Entries with same key-value pairs are equal and have same + * hashcodes + */ + public void testEquals() { + Map.Entry e2 = new AbstractMap.SimpleEntry(k1, v1); + Map.Entry e = new AbstractMap.SimpleEntry(e2); + Map.Entry s2 = new AbstractMap.SimpleImmutableEntry(k1, v1); + Map.Entry s = new AbstractMap.SimpleImmutableEntry(s2); + assertEquals(e2, e); + assertEquals(e2.hashCode(), e.hashCode()); + assertEquals(s2, s); + assertEquals(s2.hashCode(), s.hashCode()); + assertEquals(e2, s2); + assertEquals(e2.hashCode(), s2.hashCode()); + assertEquals(e, s); + assertEquals(e.hashCode(), s.hashCode()); + } + + /** + * Entries with different key-value pairs are not equal + */ + public void testNotEquals() { + Map.Entry e2 = new AbstractMap.SimpleEntry(k1, v1); + Map.Entry e = new AbstractMap.SimpleEntry(k2, v1); + assertFalse(e2.equals(e)); + e = new AbstractMap.SimpleEntry(k1, v2); + assertFalse(e2.equals(e)); + e = new AbstractMap.SimpleEntry(k2, v2); + assertFalse(e2.equals(e)); + + Map.Entry s2 = new AbstractMap.SimpleImmutableEntry(k1, v1); + Map.Entry s = new AbstractMap.SimpleImmutableEntry(k2, v1); + assertFalse(s2.equals(s)); + s = new AbstractMap.SimpleImmutableEntry(k1, v2); + assertFalse(s2.equals(s)); + s = new AbstractMap.SimpleImmutableEntry(k2, v2); + assertFalse(s2.equals(s)); + } + + /** + * getValue returns last setValue for SimpleEntry + */ + public void testSetValue1() { + Map.Entry e2 = new AbstractMap.SimpleEntry(k1, v1); + Map.Entry e = new AbstractMap.SimpleEntry(e2); + assertEquals(k1, e.getKey()); + assertEquals(v1, e.getValue()); + e.setValue(k2); + assertEquals(k2, e.getValue()); + assertFalse(e2.equals(e)); + } + + /** + * setValue for SimpleImmutableEntry throws UnsupportedOperationException + */ + public void testSetValue2() { + Map.Entry s2 = new AbstractMap.SimpleImmutableEntry(k1, v1); + Map.Entry s = new AbstractMap.SimpleImmutableEntry(s2); + assertEquals(k1, s.getKey()); + assertEquals(v1, s.getValue()); + try { + s.setValue(k2); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + } +} diff --git a/jdk/test/java/util/concurrent/tck/ExchangerTest.java b/jdk/test/java/util/concurrent/tck/ExchangerTest.java new file mode 100644 index 00000000000..ba6c5443623 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ExchangerTest.java @@ -0,0 +1,180 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Exchanger; +import java.util.concurrent.TimeoutException; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ExchangerTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ExchangerTest.class); + } + + /** + * exchange exchanges objects across two threads + */ + public void testExchange() { + final Exchanger e = new Exchanger(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertSame(one, e.exchange(two)); + assertSame(two, e.exchange(one)); + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertSame(two, e.exchange(one)); + assertSame(one, e.exchange(two)); + }}); + + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * timed exchange exchanges objects across two threads + */ + public void testTimedExchange() { + final Exchanger e = new Exchanger(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + assertSame(one, e.exchange(two, LONG_DELAY_MS, MILLISECONDS)); + assertSame(two, e.exchange(one, LONG_DELAY_MS, MILLISECONDS)); + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + assertSame(two, e.exchange(one, LONG_DELAY_MS, MILLISECONDS)); + assertSame(one, e.exchange(two, LONG_DELAY_MS, MILLISECONDS)); + }}); + + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * interrupt during wait for exchange throws IE + */ + public void testExchange_InterruptedException() { + final Exchanger e = new Exchanger(); + final CountDownLatch threadStarted = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + e.exchange(one); + }}); + + await(threadStarted); + t.interrupt(); + awaitTermination(t); + } + + /** + * interrupt during wait for timed exchange throws IE + */ + public void testTimedExchange_InterruptedException() { + final Exchanger e = new Exchanger(); + final CountDownLatch threadStarted = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws Exception { + threadStarted.countDown(); + e.exchange(null, LONG_DELAY_MS, MILLISECONDS); + }}); + + await(threadStarted); + t.interrupt(); + awaitTermination(t); + } + + /** + * timeout during wait for timed exchange throws TimeoutException + */ + public void testExchange_TimeoutException() { + final Exchanger e = new Exchanger(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + long startTime = System.nanoTime(); + try { + e.exchange(null, timeoutMillis(), MILLISECONDS); + shouldThrow(); + } catch (TimeoutException success) {} + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}); + + awaitTermination(t); + } + + /** + * If one exchanging thread is interrupted, another succeeds. + */ + public void testReplacementAfterExchange() { + final Exchanger e = new Exchanger(); + final CountDownLatch exchanged = new CountDownLatch(2); + final CountDownLatch interrupted = new CountDownLatch(1); + Thread t1 = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + assertSame(two, e.exchange(one)); + exchanged.countDown(); + e.exchange(two); + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertSame(one, e.exchange(two)); + exchanged.countDown(); + interrupted.await(); + assertSame(three, e.exchange(one)); + }}); + Thread t3 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + interrupted.await(); + assertSame(one, e.exchange(three)); + }}); + + await(exchanged); + t1.interrupt(); + awaitTermination(t1); + interrupted.countDown(); + awaitTermination(t2); + awaitTermination(t3); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java new file mode 100644 index 00000000000..29db17a7a0d --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java @@ -0,0 +1,241 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.RunnableFuture; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ExecutorCompletionServiceTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ExecutorCompletionServiceTest.class); + } + + /** + * Creating a new ECS with null Executor throw NPE + */ + public void testConstructorNPE() { + try { + new ExecutorCompletionService(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Creating a new ECS with null queue throw NPE + */ + public void testConstructorNPE2() { + try { + ExecutorService e = Executors.newCachedThreadPool(); + new ExecutorCompletionService(e, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Submitting a null callable throws NPE + */ + public void testSubmitNPE() { + final ExecutorService e = Executors.newCachedThreadPool(); + final ExecutorCompletionService ecs = new ExecutorCompletionService(e); + try (PoolCleaner cleaner = cleaner(e)) { + Callable c = null; + try { + ecs.submit(c); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * Submitting a null runnable throws NPE + */ + public void testSubmitNPE2() { + final ExecutorService e = Executors.newCachedThreadPool(); + final ExecutorCompletionService ecs = new ExecutorCompletionService(e); + try (PoolCleaner cleaner = cleaner(e)) { + Runnable r = null; + try { + ecs.submit(r, Boolean.TRUE); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * A taken submitted task is completed + */ + public void testTake() throws InterruptedException { + final ExecutorService e = Executors.newCachedThreadPool(); + final ExecutorCompletionService ecs = new ExecutorCompletionService(e); + try (PoolCleaner cleaner = cleaner(e)) { + Callable c = new StringTask(); + ecs.submit(c); + Future f = ecs.take(); + assertTrue(f.isDone()); + } + } + + /** + * Take returns the same future object returned by submit + */ + public void testTake2() throws InterruptedException { + final ExecutorService e = Executors.newCachedThreadPool(); + final ExecutorCompletionService ecs = new ExecutorCompletionService(e); + try (PoolCleaner cleaner = cleaner(e)) { + Callable c = new StringTask(); + Future f1 = ecs.submit(c); + Future f2 = ecs.take(); + assertSame(f1, f2); + } + } + + /** + * If poll returns non-null, the returned task is completed + */ + public void testPoll1() throws Exception { + final ExecutorService e = Executors.newCachedThreadPool(); + final ExecutorCompletionService ecs = new ExecutorCompletionService(e); + try (PoolCleaner cleaner = cleaner(e)) { + assertNull(ecs.poll()); + Callable c = new StringTask(); + ecs.submit(c); + + long startTime = System.nanoTime(); + Future f; + while ((f = ecs.poll()) == null) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + assertTrue(f.isDone()); + assertSame(TEST_STRING, f.get()); + } + } + + /** + * If timed poll returns non-null, the returned task is completed + */ + public void testPoll2() throws InterruptedException { + final ExecutorService e = Executors.newCachedThreadPool(); + final ExecutorCompletionService ecs = new ExecutorCompletionService(e); + try (PoolCleaner cleaner = cleaner(e)) { + assertNull(ecs.poll()); + Callable c = new StringTask(); + ecs.submit(c); + Future f = ecs.poll(SHORT_DELAY_MS, MILLISECONDS); + if (f != null) + assertTrue(f.isDone()); + } + } + + /** + * Submitting to underlying AES that overrides newTaskFor(Callable) + * returns and eventually runs Future returned by newTaskFor. + */ + public void testNewTaskForCallable() throws InterruptedException { + final AtomicBoolean done = new AtomicBoolean(false); + class MyCallableFuture extends FutureTask { + MyCallableFuture(Callable c) { super(c); } + protected void done() { done.set(true); } + } + final ExecutorService e = + new ThreadPoolExecutor(1, 1, + 30L, TimeUnit.SECONDS, + new ArrayBlockingQueue(1)) { + protected RunnableFuture newTaskFor(Callable c) { + return new MyCallableFuture(c); + }}; + ExecutorCompletionService ecs = + new ExecutorCompletionService(e); + try (PoolCleaner cleaner = cleaner(e)) { + assertNull(ecs.poll()); + Callable c = new StringTask(); + Future f1 = ecs.submit(c); + assertTrue("submit must return MyCallableFuture", + f1 instanceof MyCallableFuture); + Future f2 = ecs.take(); + assertSame("submit and take must return same objects", f1, f2); + assertTrue("completed task must have set done", done.get()); + } + } + + /** + * Submitting to underlying AES that overrides newTaskFor(Runnable,T) + * returns and eventually runs Future returned by newTaskFor. + */ + public void testNewTaskForRunnable() throws InterruptedException { + final AtomicBoolean done = new AtomicBoolean(false); + class MyRunnableFuture extends FutureTask { + MyRunnableFuture(Runnable t, V r) { super(t, r); } + protected void done() { done.set(true); } + } + final ExecutorService e = + new ThreadPoolExecutor(1, 1, + 30L, TimeUnit.SECONDS, + new ArrayBlockingQueue(1)) { + protected RunnableFuture newTaskFor(Runnable t, T r) { + return new MyRunnableFuture(t, r); + }}; + final ExecutorCompletionService ecs = + new ExecutorCompletionService(e); + try (PoolCleaner cleaner = cleaner(e)) { + assertNull(ecs.poll()); + Runnable r = new NoOpRunnable(); + Future f1 = ecs.submit(r, null); + assertTrue("submit must return MyRunnableFuture", + f1 instanceof MyRunnableFuture); + Future f2 = ecs.take(); + assertSame("submit and take must return same objects", f1, f2); + assertTrue("completed task must have set done", done.get()); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ExecutorsTest.java b/jdk/test/java/util/concurrent/tck/ExecutorsTest.java new file mode 100644 index 00000000000..ec17b54b507 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ExecutorsTest.java @@ -0,0 +1,623 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.security.AccessControlContext; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadPoolExecutor; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ExecutorsTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ExecutorsTest.class); + } + + /** + * A newCachedThreadPool can execute runnables + */ + public void testNewCachedThreadPool1() { + final ExecutorService e = Executors.newCachedThreadPool(); + try (PoolCleaner cleaner = cleaner(e)) { + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + } + } + + /** + * A newCachedThreadPool with given ThreadFactory can execute runnables + */ + public void testNewCachedThreadPool2() { + final ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory()); + try (PoolCleaner cleaner = cleaner(e)) { + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + } + } + + /** + * A newCachedThreadPool with null ThreadFactory throws NPE + */ + public void testNewCachedThreadPool3() { + try { + ExecutorService e = Executors.newCachedThreadPool(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * A new SingleThreadExecutor can execute runnables + */ + public void testNewSingleThreadExecutor1() { + final ExecutorService e = Executors.newSingleThreadExecutor(); + try (PoolCleaner cleaner = cleaner(e)) { + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + } + } + + /** + * A new SingleThreadExecutor with given ThreadFactory can execute runnables + */ + public void testNewSingleThreadExecutor2() { + final ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory()); + try (PoolCleaner cleaner = cleaner(e)) { + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + } + } + + /** + * A new SingleThreadExecutor with null ThreadFactory throws NPE + */ + public void testNewSingleThreadExecutor3() { + try { + ExecutorService e = Executors.newSingleThreadExecutor(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * A new SingleThreadExecutor cannot be casted to concrete implementation + */ + public void testCastNewSingleThreadExecutor() { + final ExecutorService e = Executors.newSingleThreadExecutor(); + try (PoolCleaner cleaner = cleaner(e)) { + try { + ThreadPoolExecutor tpe = (ThreadPoolExecutor)e; + shouldThrow(); + } catch (ClassCastException success) {} + } + } + + /** + * A new newFixedThreadPool can execute runnables + */ + public void testNewFixedThreadPool1() { + final ExecutorService e = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(e)) { + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + } + } + + /** + * A new newFixedThreadPool with given ThreadFactory can execute runnables + */ + public void testNewFixedThreadPool2() { + final ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory()); + try (PoolCleaner cleaner = cleaner(e)) { + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + } + } + + /** + * A new newFixedThreadPool with null ThreadFactory throws NPE + */ + public void testNewFixedThreadPool3() { + try { + ExecutorService e = Executors.newFixedThreadPool(2, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * A new newFixedThreadPool with 0 threads throws IAE + */ + public void testNewFixedThreadPool4() { + try { + ExecutorService e = Executors.newFixedThreadPool(0); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * An unconfigurable newFixedThreadPool can execute runnables + */ + public void testUnconfigurableExecutorService() { + final ExecutorService e = Executors.unconfigurableExecutorService(Executors.newFixedThreadPool(2)); + try (PoolCleaner cleaner = cleaner(e)) { + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + e.execute(new NoOpRunnable()); + } + } + + /** + * unconfigurableExecutorService(null) throws NPE + */ + public void testUnconfigurableExecutorServiceNPE() { + try { + ExecutorService e = Executors.unconfigurableExecutorService(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * unconfigurableScheduledExecutorService(null) throws NPE + */ + public void testUnconfigurableScheduledExecutorServiceNPE() { + try { + ExecutorService e = Executors.unconfigurableScheduledExecutorService(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * a newSingleThreadScheduledExecutor successfully runs delayed task + */ + public void testNewSingleThreadScheduledExecutor() throws Exception { + final ScheduledExecutorService p = Executors.newSingleThreadScheduledExecutor(); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch proceed = new CountDownLatch(1); + final Runnable task = new CheckedRunnable() { + public void realRun() { + await(proceed); + }}; + long startTime = System.nanoTime(); + Future f = p.schedule(Executors.callable(task, Boolean.TRUE), + timeoutMillis(), MILLISECONDS); + assertFalse(f.isDone()); + proceed.countDown(); + assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS)); + assertSame(Boolean.TRUE, f.get()); + assertTrue(f.isDone()); + assertFalse(f.isCancelled()); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + } + + /** + * a newScheduledThreadPool successfully runs delayed task + */ + public void testNewScheduledThreadPool() throws Exception { + final ScheduledExecutorService p = Executors.newScheduledThreadPool(2); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch proceed = new CountDownLatch(1); + final Runnable task = new CheckedRunnable() { + public void realRun() { + await(proceed); + }}; + long startTime = System.nanoTime(); + Future f = p.schedule(Executors.callable(task, Boolean.TRUE), + timeoutMillis(), MILLISECONDS); + assertFalse(f.isDone()); + proceed.countDown(); + assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS)); + assertSame(Boolean.TRUE, f.get()); + assertTrue(f.isDone()); + assertFalse(f.isCancelled()); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + } + + /** + * an unconfigurable newScheduledThreadPool successfully runs delayed task + */ + public void testUnconfigurableScheduledExecutorService() throws Exception { + final ScheduledExecutorService p = + Executors.unconfigurableScheduledExecutorService + (Executors.newScheduledThreadPool(2)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch proceed = new CountDownLatch(1); + final Runnable task = new CheckedRunnable() { + public void realRun() { + await(proceed); + }}; + long startTime = System.nanoTime(); + Future f = p.schedule(Executors.callable(task, Boolean.TRUE), + timeoutMillis(), MILLISECONDS); + assertFalse(f.isDone()); + proceed.countDown(); + assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS)); + assertSame(Boolean.TRUE, f.get()); + assertTrue(f.isDone()); + assertFalse(f.isCancelled()); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + } + + /** + * Future.get on submitted tasks will time out if they compute too long. + */ + public void testTimedCallable() throws Exception { + final ExecutorService[] executors = { + Executors.newSingleThreadExecutor(), + Executors.newCachedThreadPool(), + Executors.newFixedThreadPool(2), + Executors.newScheduledThreadPool(2), + }; + + final Runnable sleeper = new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + delay(LONG_DELAY_MS); + }}; + + List threads = new ArrayList(); + for (final ExecutorService executor : executors) { + threads.add(newStartedThread(new CheckedRunnable() { + public void realRun() { + Future future = executor.submit(sleeper); + assertFutureTimesOut(future); + }})); + } + for (Thread thread : threads) + awaitTermination(thread); + for (ExecutorService executor : executors) + joinPool(executor); + } + + /** + * ThreadPoolExecutor using defaultThreadFactory has + * specified group, priority, daemon status, and name + */ + public void testDefaultThreadFactory() throws Exception { + final ThreadGroup egroup = Thread.currentThread().getThreadGroup(); + final CountDownLatch done = new CountDownLatch(1); + Runnable r = new CheckedRunnable() { + public void realRun() { + try { + Thread current = Thread.currentThread(); + assertTrue(!current.isDaemon()); + assertTrue(current.getPriority() <= Thread.NORM_PRIORITY); + ThreadGroup g = current.getThreadGroup(); + SecurityManager s = System.getSecurityManager(); + if (s != null) + assertTrue(g == s.getThreadGroup()); + else + assertTrue(g == egroup); + String name = current.getName(); + assertTrue(name.endsWith("thread-1")); + } catch (SecurityException ok) { + // Also pass if not allowed to change setting + } + done.countDown(); + }}; + ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory()); + try (PoolCleaner cleaner = cleaner(e)) { + e.execute(r); + await(done); + } + } + + /** + * ThreadPoolExecutor using privilegedThreadFactory has + * specified group, priority, daemon status, name, + * access control context and context class loader + */ + public void testPrivilegedThreadFactory() throws Exception { + final CountDownLatch done = new CountDownLatch(1); + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + final ThreadGroup egroup = Thread.currentThread().getThreadGroup(); + final ClassLoader thisccl = Thread.currentThread().getContextClassLoader(); + final AccessControlContext thisacc = AccessController.getContext(); + Runnable r = new CheckedRunnable() { + public void realRun() { + Thread current = Thread.currentThread(); + assertTrue(!current.isDaemon()); + assertTrue(current.getPriority() <= Thread.NORM_PRIORITY); + ThreadGroup g = current.getThreadGroup(); + SecurityManager s = System.getSecurityManager(); + if (s != null) + assertTrue(g == s.getThreadGroup()); + else + assertTrue(g == egroup); + String name = current.getName(); + assertTrue(name.endsWith("thread-1")); + assertSame(thisccl, current.getContextClassLoader()); + assertEquals(thisacc, AccessController.getContext()); + done.countDown(); + }}; + ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory()); + try (PoolCleaner cleaner = cleaner(e)) { + e.execute(r); + await(done); + } + }}; + + runWithPermissions(r, + new RuntimePermission("getClassLoader"), + new RuntimePermission("setContextClassLoader"), + new RuntimePermission("modifyThread")); + } + + boolean haveCCLPermissions() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + try { + sm.checkPermission(new RuntimePermission("setContextClassLoader")); + sm.checkPermission(new RuntimePermission("getClassLoader")); + } catch (AccessControlException e) { + return false; + } + } + return true; + } + + void checkCCL() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("setContextClassLoader")); + sm.checkPermission(new RuntimePermission("getClassLoader")); + } + } + + class CheckCCL implements Callable { + public Object call() { + checkCCL(); + return null; + } + } + + /** + * Without class loader permissions, creating + * privilegedCallableUsingCurrentClassLoader throws ACE + */ + public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() { + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + if (System.getSecurityManager() == null) + return; + try { + Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable()); + shouldThrow(); + } catch (AccessControlException success) {} + }}; + + runWithoutPermissions(r); + } + + /** + * With class loader permissions, calling + * privilegedCallableUsingCurrentClassLoader does not throw ACE + */ + public void testPrivilegedCallableUsingCCLWithPrivs() throws Exception { + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + Executors.privilegedCallableUsingCurrentClassLoader + (new NoOpCallable()) + .call(); + }}; + + runWithPermissions(r, + new RuntimePermission("getClassLoader"), + new RuntimePermission("setContextClassLoader")); + } + + /** + * Without permissions, calling privilegedCallable throws ACE + */ + public void testPrivilegedCallableWithNoPrivs() throws Exception { + // Avoid classloader-related SecurityExceptions in swingui.TestRunner + Executors.privilegedCallable(new CheckCCL()); + + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + if (System.getSecurityManager() == null) + return; + Callable task = Executors.privilegedCallable(new CheckCCL()); + try { + task.call(); + shouldThrow(); + } catch (AccessControlException success) {} + }}; + + runWithoutPermissions(r); + + // It seems rather difficult to test that the + // AccessControlContext of the privilegedCallable is used + // instead of its caller. Below is a failed attempt to do + // that, which does not work because the AccessController + // cannot capture the internal state of the current Policy. + // It would be much more work to differentiate based on, + // e.g. CodeSource. + +// final AccessControlContext[] noprivAcc = new AccessControlContext[1]; +// final Callable[] task = new Callable[1]; + +// runWithPermissions +// (new CheckedRunnable() { +// public void realRun() { +// if (System.getSecurityManager() == null) +// return; +// noprivAcc[0] = AccessController.getContext(); +// task[0] = Executors.privilegedCallable(new CheckCCL()); +// try { +// AccessController.doPrivileged(new PrivilegedAction() { +// public Void run() { +// checkCCL(); +// return null; +// }}, noprivAcc[0]); +// shouldThrow(); +// } catch (AccessControlException success) {} +// }}); + +// runWithPermissions +// (new CheckedRunnable() { +// public void realRun() throws Exception { +// if (System.getSecurityManager() == null) +// return; +// // Verify that we have an underprivileged ACC +// try { +// AccessController.doPrivileged(new PrivilegedAction() { +// public Void run() { +// checkCCL(); +// return null; +// }}, noprivAcc[0]); +// shouldThrow(); +// } catch (AccessControlException success) {} + +// try { +// task[0].call(); +// shouldThrow(); +// } catch (AccessControlException success) {} +// }}, +// new RuntimePermission("getClassLoader"), +// new RuntimePermission("setContextClassLoader")); + } + + /** + * With permissions, calling privilegedCallable succeeds + */ + public void testPrivilegedCallableWithPrivs() throws Exception { + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + Executors.privilegedCallable(new CheckCCL()).call(); + }}; + + runWithPermissions(r, + new RuntimePermission("getClassLoader"), + new RuntimePermission("setContextClassLoader")); + } + + /** + * callable(Runnable) returns null when called + */ + public void testCallable1() throws Exception { + Callable c = Executors.callable(new NoOpRunnable()); + assertNull(c.call()); + } + + /** + * callable(Runnable, result) returns result when called + */ + public void testCallable2() throws Exception { + Callable c = Executors.callable(new NoOpRunnable(), one); + assertSame(one, c.call()); + } + + /** + * callable(PrivilegedAction) returns its result when called + */ + public void testCallable3() throws Exception { + Callable c = Executors.callable(new PrivilegedAction() { + public Object run() { return one; }}); + assertSame(one, c.call()); + } + + /** + * callable(PrivilegedExceptionAction) returns its result when called + */ + public void testCallable4() throws Exception { + Callable c = Executors.callable(new PrivilegedExceptionAction() { + public Object run() { return one; }}); + assertSame(one, c.call()); + } + + /** + * callable(null Runnable) throws NPE + */ + public void testCallableNPE1() { + try { + Callable c = Executors.callable((Runnable) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * callable(null, result) throws NPE + */ + public void testCallableNPE2() { + try { + Callable c = Executors.callable((Runnable) null, one); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * callable(null PrivilegedAction) throws NPE + */ + public void testCallableNPE3() { + try { + Callable c = Executors.callable((PrivilegedAction) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * callable(null PrivilegedExceptionAction) throws NPE + */ + public void testCallableNPE4() { + try { + Callable c = Executors.callable((PrivilegedExceptionAction) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinPool8Test.java b/jdk/test/java/util/concurrent/tck/ForkJoinPool8Test.java new file mode 100644 index 00000000000..ee991a21c80 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ForkJoinPool8Test.java @@ -0,0 +1,1615 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.HashSet; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountedCompleter; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.TimeoutException; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ForkJoinPool8Test extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ForkJoinPool8Test.class); + } + + /** + * Common pool exists and has expected parallelism. + */ + public void testCommonPoolParallelism() { + assertEquals(ForkJoinPool.getCommonPoolParallelism(), + ForkJoinPool.commonPool().getParallelism()); + } + + /** + * Common pool cannot be shut down + */ + public void testCommonPoolShutDown() { + assertFalse(ForkJoinPool.commonPool().isShutdown()); + assertFalse(ForkJoinPool.commonPool().isTerminating()); + assertFalse(ForkJoinPool.commonPool().isTerminated()); + ForkJoinPool.commonPool().shutdown(); + assertFalse(ForkJoinPool.commonPool().isShutdown()); + assertFalse(ForkJoinPool.commonPool().isTerminating()); + assertFalse(ForkJoinPool.commonPool().isTerminated()); + ForkJoinPool.commonPool().shutdownNow(); + assertFalse(ForkJoinPool.commonPool().isShutdown()); + assertFalse(ForkJoinPool.commonPool().isTerminating()); + assertFalse(ForkJoinPool.commonPool().isTerminated()); + } + + /* + * All of the following test methods are adaptations of those for + * RecursiveAction and CountedCompleter, but with all actions + * executed in the common pool, generally implicitly via + * checkInvoke. + */ + + private void checkInvoke(ForkJoinTask a) { + checkNotDone(a); + assertNull(a.invoke()); + checkCompletedNormally(a); + } + + void checkNotDone(ForkJoinTask a) { + assertFalse(a.isDone()); + assertFalse(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + + if (! ForkJoinTask.inForkJoinPool()) { + Thread.currentThread().interrupt(); + try { + a.get(); + shouldThrow(); + } catch (InterruptedException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + Thread.currentThread().interrupt(); + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (InterruptedException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + try { + a.get(0L, SECONDS); + shouldThrow(); + } catch (TimeoutException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedNormally(ForkJoinTask a) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertTrue(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + assertNull(a.join()); + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + try { + assertNull(a.get()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertNull(a.get(5L, SECONDS)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCancelled(ForkJoinTask a) { + assertTrue(a.isDone()); + assertTrue(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertTrue(a.getException() instanceof CancellationException); + assertNull(a.getRawResult()); + + try { + a.join(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedAbnormally(ForkJoinTask a, Throwable t) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertSame(t.getClass(), a.getException().getClass()); + assertNull(a.getRawResult()); + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + + try { + a.join(); + shouldThrow(); + } catch (Throwable expected) { + assertSame(expected.getClass(), t.getClass()); + } + + try { + a.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + public static final class FJException extends RuntimeException { + public FJException() { super(); } + public FJException(Throwable cause) { super(cause); } + } + + // A simple recursive action for testing + final class FibAction extends CheckedRecursiveAction { + final int number; + int result; + FibAction(int n) { number = n; } + protected void realCompute() { + int n = number; + if (n <= 1) + result = n; + else { + FibAction f1 = new FibAction(n - 1); + FibAction f2 = new FibAction(n - 2); + invokeAll(f1, f2); + result = f1.result + f2.result; + } + } + } + + // A recursive action failing in base case + static final class FailingFibAction extends RecursiveAction { + final int number; + int result; + FailingFibAction(int n) { number = n; } + public void compute() { + int n = number; + if (n <= 1) + throw new FJException(); + else { + FailingFibAction f1 = new FailingFibAction(n - 1); + FailingFibAction f2 = new FailingFibAction(n - 2); + invokeAll(f1, f2); + result = f1.result + f2.result; + } + } + } + + /** + * invoke returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks. getRawResult of a RecursiveAction returns null; + */ + public void testInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertNull(f.invoke()); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * quietlyInvoke task returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks + */ + public void testQuietlyInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + f.quietlyInvoke(); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * join of a forked task returns when task completes + */ + public void testForkJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertNull(f.join()); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * join/quietlyJoin of a forked task succeeds in the presence of interrupts + */ + public void testJoinIgnoresInterrupts() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + final Thread myself = Thread.currentThread(); + + // test join() + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + assertNull(f.join()); + Thread.interrupted(); + assertEquals(21, f.result); + checkCompletedNormally(f); + + f = new FibAction(8); + f.cancel(true); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + Thread.interrupted(); + checkCancelled(f); + } + + f = new FibAction(8); + f.completeExceptionally(new FJException()); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + Thread.interrupted(); + checkCompletedAbnormally(f, success); + } + + // test quietlyJoin() + f = new FibAction(8); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + Thread.interrupted(); + assertEquals(21, f.result); + checkCompletedNormally(f); + + f = new FibAction(8); + f.cancel(true); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + Thread.interrupted(); + checkCancelled(f); + + f = new FibAction(8); + f.completeExceptionally(new FJException()); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + Thread.interrupted(); + checkCompletedAbnormally(f, f.getException()); + }}; + checkInvoke(a); + a.reinitialize(); + checkInvoke(a); + } + + /** + * get of a forked task returns when task completes + */ + public void testForkGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertNull(f.get()); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * timed get of a forked task returns when task completes + */ + public void testForkTimedGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertNull(f.get(5L, SECONDS)); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * timed get with null time unit throws NPE + */ + public void testForkTimedGetNPE() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + try { + f.get(5L, null); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + checkInvoke(a); + } + + /** + * quietlyJoin of a forked task returns when task completes + */ + public void testForkQuietlyJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * invoke task throws exception when task completes abnormally + */ + public void testAbnormalInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + checkInvoke(a); + } + + /** + * quietlyInvoke task returns when task completes abnormally + */ + public void testAbnormalQuietlyInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + f.quietlyInvoke(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + checkInvoke(a); + } + + /** + * join of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + checkInvoke(a); + } + + /** + * get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingFibAction f = new FailingFibAction(8); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + checkInvoke(a); + } + + /** + * timed get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkTimedGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingFibAction f = new FailingFibAction(8); + assertSame(f, f.fork()); + try { + f.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + checkInvoke(a); + } + + /** + * quietlyJoin of a forked task returns when task completes abnormally + */ + public void testAbnormalForkQuietlyJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + checkInvoke(a); + } + + /** + * invoke task throws exception when task cancelled + */ + public void testCancelledInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + try { + f.invoke(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + checkInvoke(a); + } + + /** + * join of a forked task throws exception when task cancelled + */ + public void testCancelledForkJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + checkInvoke(a); + } + + /** + * get of a forked task throws exception when task cancelled + */ + public void testCancelledForkGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + checkInvoke(a); + } + + /** + * timed get of a forked task throws exception when task cancelled + */ + public void testCancelledForkTimedGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + checkInvoke(a); + } + + /** + * quietlyJoin of a forked task returns when task cancelled + */ + public void testCancelledForkQuietlyJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + f.quietlyJoin(); + checkCancelled(f); + }}; + checkInvoke(a); + } + + /** + * inForkJoinPool of non-FJ task returns false + */ + public void testInForkJoinPool2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertFalse(inForkJoinPool()); + }}; + assertNull(a.invoke()); + } + + /** + * A reinitialized normally completed task may be re-invoked + */ + public void testReinitialize() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + checkNotDone(f); + + for (int i = 0; i < 3; i++) { + assertNull(f.invoke()); + assertEquals(21, f.result); + checkCompletedNormally(f); + f.reinitialize(); + checkNotDone(f); + } + }}; + checkInvoke(a); + } + + /** + * A reinitialized abnormally completed task may be re-invoked + */ + public void testReinitializeAbnormal() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + checkNotDone(f); + + for (int i = 0; i < 3; i++) { + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + f.reinitialize(); + checkNotDone(f); + } + }}; + checkInvoke(a); + } + + /** + * invoke task throws exception after invoking completeExceptionally + */ + public void testCompleteExceptionally() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + f.completeExceptionally(new FJException()); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + checkInvoke(a); + } + + /** + * invoke task suppresses execution invoking complete + */ + public void testComplete() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + f.complete(null); + assertNull(f.invoke()); + assertEquals(0, f.result); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * invokeAll(t1, t2) invokes all task arguments + */ + public void testInvokeAll2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FibAction g = new FibAction(9); + invokeAll(f, g); + checkCompletedNormally(f); + assertEquals(21, f.result); + checkCompletedNormally(g); + assertEquals(34, g.result); + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with 1 argument invokes task + */ + public void testInvokeAll1() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + invokeAll(f); + checkCompletedNormally(f); + assertEquals(21, f.result); + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with > 2 argument invokes tasks + */ + public void testInvokeAll3() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FibAction g = new FibAction(9); + FibAction h = new FibAction(7); + invokeAll(f, g, h); + assertTrue(f.isDone()); + assertTrue(g.isDone()); + assertTrue(h.isDone()); + checkCompletedNormally(f); + assertEquals(21, f.result); + checkCompletedNormally(g); + assertEquals(34, g.result); + checkCompletedNormally(g); + assertEquals(13, h.result); + }}; + checkInvoke(a); + } + + /** + * invokeAll(collection) invokes all tasks in the collection + */ + public void testInvokeAllCollection() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FibAction g = new FibAction(9); + FibAction h = new FibAction(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + invokeAll(set); + assertTrue(f.isDone()); + assertTrue(g.isDone()); + assertTrue(h.isDone()); + checkCompletedNormally(f); + assertEquals(21, f.result); + checkCompletedNormally(g); + assertEquals(34, g.result); + checkCompletedNormally(g); + assertEquals(13, h.result); + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with any null task throws NPE + */ + public void testInvokeAllNPE() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FibAction g = new FibAction(9); + FibAction h = null; + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + checkInvoke(a); + } + + /** + * invokeAll(t1, t2) throw exception if any task does + */ + public void testAbnormalInvokeAll2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FailingFibAction g = new FailingFibAction(9); + try { + invokeAll(f, g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with 1 argument throws exception if task does + */ + public void testAbnormalInvokeAll1() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction g = new FailingFibAction(9); + try { + invokeAll(g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with > 2 argument throws exception if any task does + */ + public void testAbnormalInvokeAll3() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FailingFibAction g = new FailingFibAction(9); + FibAction h = new FibAction(7); + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + checkInvoke(a); + } + + /** + * invokeAll(collection) throws exception if any task does + */ + public void testAbnormalInvokeAllCollection() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + FibAction g = new FibAction(9); + FibAction h = new FibAction(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + try { + invokeAll(set); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + checkInvoke(a); + } + + // CountedCompleter versions + + abstract static class CCF extends CountedCompleter { + int number; + int rnumber; + + public CCF(CountedCompleter parent, int n) { + super(parent, 1); + this.number = n; + } + + public final void compute() { + CountedCompleter p; + CCF f = this; + int n = number; + while (n >= 2) { + new RCCF(f, n - 2).fork(); + f = new LCCF(f, --n); + } + f.number = n; + f.onCompletion(f); + if ((p = f.getCompleter()) != null) + p.tryComplete(); + else + f.quietlyComplete(); + } + } + + static final class LCCF extends CCF { + public LCCF(CountedCompleter parent, int n) { + super(parent, n); + } + public final void onCompletion(CountedCompleter caller) { + CCF p = (CCF)getCompleter(); + int n = number + rnumber; + if (p != null) + p.number = n; + else + number = n; + } + } + static final class RCCF extends CCF { + public RCCF(CountedCompleter parent, int n) { + super(parent, n); + } + public final void onCompletion(CountedCompleter caller) { + CCF p = (CCF)getCompleter(); + int n = number + rnumber; + if (p != null) + p.rnumber = n; + else + number = n; + } + } + + // Version of CCF with forced failure in left completions + abstract static class FailingCCF extends CountedCompleter { + int number; + int rnumber; + + public FailingCCF(CountedCompleter parent, int n) { + super(parent, 1); + this.number = n; + } + + public final void compute() { + CountedCompleter p; + FailingCCF f = this; + int n = number; + while (n >= 2) { + new RFCCF(f, n - 2).fork(); + f = new LFCCF(f, --n); + } + f.number = n; + f.onCompletion(f); + if ((p = f.getCompleter()) != null) + p.tryComplete(); + else + f.quietlyComplete(); + } + } + + static final class LFCCF extends FailingCCF { + public LFCCF(CountedCompleter parent, int n) { + super(parent, n); + } + public final void onCompletion(CountedCompleter caller) { + FailingCCF p = (FailingCCF)getCompleter(); + int n = number + rnumber; + if (p != null) + p.number = n; + else + number = n; + } + } + static final class RFCCF extends FailingCCF { + public RFCCF(CountedCompleter parent, int n) { + super(parent, n); + } + public final void onCompletion(CountedCompleter caller) { + completeExceptionally(new FJException()); + } + } + + /** + * invoke returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks; getRawResult returns null. + */ + public void testInvokeCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + assertNull(f.invoke()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * quietlyInvoke task returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks + */ + public void testQuietlyInvokeCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + f.quietlyInvoke(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * join of a forked task returns when task completes + */ + public void testForkJoinCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + assertSame(f, f.fork()); + assertNull(f.join()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * get of a forked task returns when task completes + */ + public void testForkGetCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(null, 8); + assertSame(f, f.fork()); + assertNull(f.get()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * timed get of a forked task returns when task completes + */ + public void testForkTimedGetCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(null, 8); + assertSame(f, f.fork()); + assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * timed get with null time unit throws NPE + */ + public void testForkTimedGetNPECC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(null, 8); + assertSame(f, f.fork()); + try { + f.get(5L, null); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + checkInvoke(a); + } + + /** + * quietlyJoin of a forked task returns when task completes + */ + public void testForkQuietlyJoinCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + checkInvoke(a); + } + + /** + * invoke task throws exception when task completes abnormally + */ + public void testAbnormalInvokeCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(null, 8); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + checkInvoke(a); + } + + /** + * quietlyInvoke task returns when task completes abnormally + */ + public void testAbnormalQuietlyInvokeCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(null, 8); + f.quietlyInvoke(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + checkInvoke(a); + } + + /** + * join of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkJoinCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(null, 8); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + checkInvoke(a); + } + + /** + * get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkGetCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingCCF f = new LFCCF(null, 8); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + checkInvoke(a); + } + + /** + * timed get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkTimedGetCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingCCF f = new LFCCF(null, 8); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + checkInvoke(a); + } + + /** + * quietlyJoin of a forked task returns when task completes abnormally + */ + public void testAbnormalForkQuietlyJoinCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(null, 8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + checkInvoke(a); + } + + /** + * invoke task throws exception when task cancelled + */ + public void testCancelledInvokeCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + assertTrue(f.cancel(true)); + try { + f.invoke(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + checkInvoke(a); + } + + /** + * join of a forked task throws exception when task cancelled + */ + public void testCancelledForkJoinCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + checkInvoke(a); + } + + /** + * get of a forked task throws exception when task cancelled + */ + public void testCancelledForkGetCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(null, 8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + checkInvoke(a); + } + + /** + * timed get of a forked task throws exception when task cancelled + */ + public void testCancelledForkTimedGetCC() throws Exception { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + CCF f = new LCCF(null, 8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + checkInvoke(a); + } + + /** + * quietlyJoin of a forked task returns when task cancelled + */ + public void testCancelledForkQuietlyJoinCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + f.quietlyJoin(); + checkCancelled(f); + }}; + checkInvoke(a); + } + + /** + * getPool of non-FJ task returns null + */ + public void testGetPool2CC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + assertNull(getPool()); + }}; + assertNull(a.invoke()); + } + + /** + * inForkJoinPool of non-FJ task returns false + */ + public void testInForkJoinPool2CC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + assertFalse(inForkJoinPool()); + }}; + assertNull(a.invoke()); + } + + /** + * setRawResult(null) succeeds + */ + public void testSetRawResultCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + setRawResult(null); + assertNull(getRawResult()); + }}; + assertNull(a.invoke()); + } + + /** + * invoke task throws exception after invoking completeExceptionally + */ + public void testCompleteExceptionally2CC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + f.completeExceptionally(new FJException()); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + checkInvoke(a); + } + + /** + * invokeAll(t1, t2) invokes all task arguments + */ + public void testInvokeAll2CC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + CCF g = new LCCF(null, 9); + invokeAll(f, g); + assertEquals(21, f.number); + assertEquals(34, g.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with 1 argument invokes task + */ + public void testInvokeAll1CC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + invokeAll(f); + checkCompletedNormally(f); + assertEquals(21, f.number); + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with > 2 argument invokes tasks + */ + public void testInvokeAll3CC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + CCF g = new LCCF(null, 9); + CCF h = new LCCF(null, 7); + invokeAll(f, g, h); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + checkInvoke(a); + } + + /** + * invokeAll(collection) invokes all tasks in the collection + */ + public void testInvokeAllCollectionCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + CCF g = new LCCF(null, 9); + CCF h = new LCCF(null, 7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + invokeAll(set); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with any null task throws NPE + */ + public void testInvokeAllNPECC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + CCF g = new LCCF(null, 9); + CCF h = null; + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + checkInvoke(a); + } + + /** + * invokeAll(t1, t2) throw exception if any task does + */ + public void testAbnormalInvokeAll2CC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + FailingCCF g = new LFCCF(null, 9); + try { + invokeAll(f, g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with 1 argument throws exception if task does + */ + public void testAbnormalInvokeAll1CC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF g = new LFCCF(null, 9); + try { + invokeAll(g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + checkInvoke(a); + } + + /** + * invokeAll(tasks) with > 2 argument throws exception if any task does + */ + public void testAbnormalInvokeAll3CC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + CCF f = new LCCF(null, 8); + FailingCCF g = new LFCCF(null, 9); + CCF h = new LCCF(null, 7); + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + checkInvoke(a); + } + + /** + * invokeAll(collection) throws exception if any task does + */ + public void testAbnormalInvokeAllCollectionCC() { + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingCCF f = new LFCCF(null, 8); + CCF g = new LCCF(null, 9); + CCF h = new LCCF(null, 7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + try { + invokeAll(set); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + checkInvoke(a); + } + + /** + * awaitQuiescence by a worker is equivalent in effect to + * ForkJoinTask.helpQuiesce() + */ + public void testAwaitQuiescence1() throws Exception { + final ForkJoinPool p = new ForkJoinPool(); + try (PoolCleaner cleaner = cleaner(p)) { + final long startTime = System.nanoTime(); + assertTrue(p.isQuiescent()); + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertSame(p, ForkJoinTask.getPool()); + boolean quiescent = p.awaitQuiescence(LONG_DELAY_MS, MILLISECONDS); + assertTrue(quiescent); + assertFalse(p.isQuiescent()); + while (!f.isDone()) { + assertFalse(p.getAsyncMode()); + assertFalse(p.isShutdown()); + assertFalse(p.isTerminating()); + assertFalse(p.isTerminated()); + Thread.yield(); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + assertFalse(p.isQuiescent()); + assertEquals(0, ForkJoinTask.getQueuedTaskCount()); + assertEquals(21, f.result); + }}; + p.execute(a); + while (!a.isDone() || !p.isQuiescent()) { + assertFalse(p.getAsyncMode()); + assertFalse(p.isShutdown()); + assertFalse(p.isTerminating()); + assertFalse(p.isTerminated()); + Thread.yield(); + } + assertEquals(0, p.getQueuedTaskCount()); + assertFalse(p.getAsyncMode()); + assertEquals(0, p.getQueuedSubmissionCount()); + assertFalse(p.hasQueuedSubmissions()); + while (p.getActiveThreadCount() != 0 + && millisElapsedSince(startTime) < LONG_DELAY_MS) + Thread.yield(); + assertFalse(p.isShutdown()); + assertFalse(p.isTerminating()); + assertFalse(p.isTerminated()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * awaitQuiescence returns when pool isQuiescent() or the indicated + * timeout elapsed + */ + public void testAwaitQuiescence2() throws Exception { + /** + * """It is possible to disable or limit the use of threads in the + * common pool by setting the parallelism property to zero. However + * doing so may cause unjoined tasks to never be executed.""" + */ + if ("0".equals(System.getProperty( + "java.util.concurrent.ForkJoinPool.common.parallelism"))) + return; + final ForkJoinPool p = new ForkJoinPool(); + try (PoolCleaner cleaner = cleaner(p)) { + assertTrue(p.isQuiescent()); + final long startTime = System.nanoTime(); + ForkJoinTask a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + while (!f.isDone() + && millisElapsedSince(startTime) < LONG_DELAY_MS) { + assertFalse(p.getAsyncMode()); + assertFalse(p.isShutdown()); + assertFalse(p.isTerminating()); + assertFalse(p.isTerminated()); + Thread.yield(); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + assertEquals(0, ForkJoinTask.getQueuedTaskCount()); + assertEquals(21, f.result); + }}; + p.execute(a); + assertTrue(p.awaitQuiescence(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isQuiescent()); + assertTrue(a.isDone()); + assertEquals(0, p.getQueuedTaskCount()); + assertFalse(p.getAsyncMode()); + assertEquals(0, p.getQueuedSubmissionCount()); + assertFalse(p.hasQueuedSubmissions()); + while (p.getActiveThreadCount() != 0 + && millisElapsedSince(startTime) < LONG_DELAY_MS) + Thread.yield(); + assertFalse(p.isShutdown()); + assertFalse(p.isTerminating()); + assertFalse(p.isTerminated()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java b/jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java new file mode 100644 index 00000000000..282557d97b7 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java @@ -0,0 +1,991 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.Future; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.ReentrantLock; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ForkJoinPoolTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ForkJoinPoolTest.class); + } + + /* + * Testing coverage notes: + * + * 1. shutdown and related methods are tested via super.joinPool. + * + * 2. newTaskFor and adapters are tested in submit/invoke tests + * + * 3. We cannot portably test monitoring methods such as + * getStealCount() since they rely ultimately on random task + * stealing that may cause tasks not to be stolen/propagated + * across threads, especially on uniprocessors. + * + * 4. There are no independently testable ForkJoinWorkerThread + * methods, but they are covered here and in task tests. + */ + + // Some classes to test extension and factory methods + + static class MyHandler implements Thread.UncaughtExceptionHandler { + volatile int catches = 0; + public void uncaughtException(Thread t, Throwable e) { + ++catches; + } + } + + static class MyError extends Error {} + + // to test handlers + static class FailingFJWSubclass extends ForkJoinWorkerThread { + public FailingFJWSubclass(ForkJoinPool p) { super(p) ; } + protected void onStart() { super.onStart(); throw new MyError(); } + } + + static class FailingThreadFactory + implements ForkJoinPool.ForkJoinWorkerThreadFactory { + volatile int calls = 0; + public ForkJoinWorkerThread newThread(ForkJoinPool p) { + if (++calls > 1) return null; + return new FailingFJWSubclass(p); + } + } + + static class SubFJP extends ForkJoinPool { // to expose protected + SubFJP() { super(1); } + public int drainTasksTo(Collection> c) { + return super.drainTasksTo(c); + } + public ForkJoinTask pollSubmission() { + return super.pollSubmission(); + } + } + + static class ManagedLocker implements ForkJoinPool.ManagedBlocker { + final ReentrantLock lock; + boolean hasLock = false; + ManagedLocker(ReentrantLock lock) { this.lock = lock; } + public boolean block() { + if (!hasLock) + lock.lock(); + return true; + } + public boolean isReleasable() { + return hasLock || (hasLock = lock.tryLock()); + } + } + + // A simple recursive task for testing + static final class FibTask extends RecursiveTask { + final int number; + FibTask(int n) { number = n; } + protected Integer compute() { + int n = number; + if (n <= 1) + return n; + FibTask f1 = new FibTask(n - 1); + f1.fork(); + return (new FibTask(n - 2)).compute() + f1.join(); + } + } + + // A failing task for testing + static final class FailingTask extends ForkJoinTask { + public final Void getRawResult() { return null; } + protected final void setRawResult(Void mustBeNull) { } + protected final boolean exec() { throw new Error(); } + FailingTask() {} + } + + // Fib needlessly using locking to test ManagedBlockers + static final class LockingFibTask extends RecursiveTask { + final int number; + final ManagedLocker locker; + final ReentrantLock lock; + LockingFibTask(int n, ManagedLocker locker, ReentrantLock lock) { + number = n; + this.locker = locker; + this.lock = lock; + } + protected Integer compute() { + int n; + LockingFibTask f1 = null; + LockingFibTask f2 = null; + locker.block(); + n = number; + if (n > 1) { + f1 = new LockingFibTask(n - 1, locker, lock); + f2 = new LockingFibTask(n - 2, locker, lock); + } + lock.unlock(); + if (n <= 1) + return n; + else { + f1.fork(); + return f2.compute() + f1.join(); + } + } + } + + /** + * Successfully constructed pool reports default factory, + * parallelism and async mode policies, no active threads or + * tasks, and quiescent running state. + */ + public void testDefaultInitialState() { + ForkJoinPool p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p)) { + assertSame(ForkJoinPool.defaultForkJoinWorkerThreadFactory, + p.getFactory()); + assertFalse(p.getAsyncMode()); + assertEquals(0, p.getActiveThreadCount()); + assertEquals(0, p.getStealCount()); + assertEquals(0, p.getQueuedTaskCount()); + assertEquals(0, p.getQueuedSubmissionCount()); + assertFalse(p.hasQueuedSubmissions()); + assertFalse(p.isShutdown()); + assertFalse(p.isTerminating()); + assertFalse(p.isTerminated()); + } + } + + /** + * Constructor throws if size argument is less than zero + */ + public void testConstructor1() { + try { + new ForkJoinPool(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if factory argument is null + */ + public void testConstructor2() { + try { + new ForkJoinPool(1, null, null, false); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getParallelism returns size set in constructor + */ + public void testGetParallelism() { + ForkJoinPool p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(1, p.getParallelism()); + } + } + + /** + * getPoolSize returns number of started workers. + */ + public void testGetPoolSize() { + final CountDownLatch taskStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + final ForkJoinPool p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(0, p.getActiveThreadCount()); + final Runnable task = new CheckedRunnable() { + public void realRun() throws InterruptedException { + taskStarted.countDown(); + assertEquals(1, p.getPoolSize()); + assertEquals(1, p.getActiveThreadCount()); + done.await(); + }}; + Future future = p.submit(task); + await(taskStarted); + assertEquals(1, p.getPoolSize()); + assertEquals(1, p.getActiveThreadCount()); + done.countDown(); + } + assertEquals(0, p.getPoolSize()); + assertEquals(0, p.getActiveThreadCount()); + } + + /** + * awaitTermination on a non-shutdown pool times out + */ + public void testAwaitTermination_timesOut() throws InterruptedException { + ForkJoinPool p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p)) { + assertFalse(p.isTerminated()); + assertFalse(p.awaitTermination(Long.MIN_VALUE, NANOSECONDS)); + assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS)); + assertFalse(p.awaitTermination(-1L, NANOSECONDS)); + assertFalse(p.awaitTermination(-1L, MILLISECONDS)); + assertFalse(p.awaitTermination(0L, NANOSECONDS)); + assertFalse(p.awaitTermination(0L, MILLISECONDS)); + long timeoutNanos = 999999L; + long startTime = System.nanoTime(); + assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS)); + assertTrue(System.nanoTime() - startTime >= timeoutNanos); + assertFalse(p.isTerminated()); + startTime = System.nanoTime(); + long timeoutMillis = timeoutMillis(); + assertFalse(p.awaitTermination(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + assertFalse(p.isTerminated()); + p.shutdown(); + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + } + } + + /** + * setUncaughtExceptionHandler changes handler for uncaught exceptions. + * + * Additionally tests: Overriding ForkJoinWorkerThread.onStart + * performs its defined action + */ + public void testSetUncaughtExceptionHandler() throws InterruptedException { + final CountDownLatch uehInvoked = new CountDownLatch(1); + final Thread.UncaughtExceptionHandler ueh = + new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { + threadAssertTrue(e instanceof MyError); + threadAssertTrue(t instanceof FailingFJWSubclass); + uehInvoked.countDown(); + }}; + ForkJoinPool p = new ForkJoinPool(1, new FailingThreadFactory(), + ueh, false); + try (PoolCleaner cleaner = cleaner(p)) { + assertSame(ueh, p.getUncaughtExceptionHandler()); + try { + p.execute(new FibTask(8)); + await(uehInvoked); + } finally { + p.shutdownNow(); // failure might have prevented processing task + } + } + } + + /** + * After invoking a single task, isQuiescent eventually becomes + * true, at which time queues are empty, threads are not active, + * the task has completed successfully, and construction + * parameters continue to hold + */ + public void testIsQuiescent() throws Exception { + ForkJoinPool p = new ForkJoinPool(2); + try (PoolCleaner cleaner = cleaner(p)) { + assertTrue(p.isQuiescent()); + long startTime = System.nanoTime(); + FibTask f = new FibTask(20); + p.invoke(f); + assertSame(ForkJoinPool.defaultForkJoinWorkerThreadFactory, + p.getFactory()); + while (! p.isQuiescent()) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + throw new AssertionFailedError("timed out"); + assertFalse(p.getAsyncMode()); + assertFalse(p.isShutdown()); + assertFalse(p.isTerminating()); + assertFalse(p.isTerminated()); + Thread.yield(); + } + + assertTrue(p.isQuiescent()); + assertFalse(p.getAsyncMode()); + assertEquals(0, p.getQueuedTaskCount()); + assertEquals(0, p.getQueuedSubmissionCount()); + assertFalse(p.hasQueuedSubmissions()); + while (p.getActiveThreadCount() != 0 + && millisElapsedSince(startTime) < LONG_DELAY_MS) + Thread.yield(); + assertFalse(p.isShutdown()); + assertFalse(p.isTerminating()); + assertFalse(p.isTerminated()); + assertTrue(f.isDone()); + assertEquals(6765, (int) f.get()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * Completed submit(ForkJoinTask) returns result + */ + public void testSubmitForkJoinTask() throws Throwable { + ForkJoinPool p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p)) { + ForkJoinTask f = p.submit(new FibTask(8)); + assertEquals(21, (int) f.get()); + } + } + + /** + * A task submitted after shutdown is rejected + */ + public void testSubmitAfterShutdown() { + ForkJoinPool p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p)) { + p.shutdown(); + assertTrue(p.isShutdown()); + try { + ForkJoinTask f = p.submit(new FibTask(8)); + shouldThrow(); + } catch (RejectedExecutionException success) {} + } + } + + /** + * Pool maintains parallelism when using ManagedBlocker + */ + public void testBlockingForkJoinTask() throws Throwable { + ForkJoinPool p = new ForkJoinPool(4); + try { + ReentrantLock lock = new ReentrantLock(); + ManagedLocker locker = new ManagedLocker(lock); + ForkJoinTask f = new LockingFibTask(20, locker, lock); + p.execute(f); + assertEquals(6765, (int) f.get()); + } finally { + p.shutdownNow(); // don't wait out shutdown + } + } + + /** + * pollSubmission returns unexecuted submitted task, if present + */ + public void testPollSubmission() { + final CountDownLatch done = new CountDownLatch(1); + SubFJP p = new SubFJP(); + try (PoolCleaner cleaner = cleaner(p)) { + ForkJoinTask a = p.submit(awaiter(done)); + ForkJoinTask b = p.submit(awaiter(done)); + ForkJoinTask c = p.submit(awaiter(done)); + ForkJoinTask r = p.pollSubmission(); + assertTrue(r == a || r == b || r == c); + assertFalse(r.isDone()); + done.countDown(); + } + } + + /** + * drainTasksTo transfers unexecuted submitted tasks, if present + */ + public void testDrainTasksTo() { + final CountDownLatch done = new CountDownLatch(1); + SubFJP p = new SubFJP(); + try (PoolCleaner cleaner = cleaner(p)) { + ForkJoinTask a = p.submit(awaiter(done)); + ForkJoinTask b = p.submit(awaiter(done)); + ForkJoinTask c = p.submit(awaiter(done)); + ArrayList al = new ArrayList(); + p.drainTasksTo(al); + assertTrue(al.size() > 0); + for (ForkJoinTask r : al) { + assertTrue(r == a || r == b || r == c); + assertFalse(r.isDone()); + } + done.countDown(); + } + } + + // FJ Versions of AbstractExecutorService tests + + /** + * execute(runnable) runs it to completion + */ + public void testExecuteRunnable() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + final AtomicBoolean done = new AtomicBoolean(false); + Future future = e.submit(new CheckedRunnable() { + public void realRun() { + done.set(true); + }}); + assertNull(future.get()); + assertNull(future.get(0, MILLISECONDS)); + assertTrue(done.get()); + assertTrue(future.isDone()); + assertFalse(future.isCancelled()); + } + } + + /** + * Completed submit(callable) returns result + */ + public void testSubmitCallable() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new StringTask()); + assertSame(TEST_STRING, future.get()); + assertTrue(future.isDone()); + assertFalse(future.isCancelled()); + } + } + + /** + * Completed submit(runnable) returns successfully + */ + public void testSubmitRunnable() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable()); + assertNull(future.get()); + assertTrue(future.isDone()); + assertFalse(future.isCancelled()); + } + } + + /** + * Completed submit(runnable, result) returns result + */ + public void testSubmitRunnable2() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable(), TEST_STRING); + assertSame(TEST_STRING, future.get()); + assertTrue(future.isDone()); + assertFalse(future.isCancelled()); + } + } + + /** + * A submitted privileged action runs to completion + */ + public void testSubmitPrivilegedAction() throws Exception { + final Callable callable = Executors.callable(new PrivilegedAction() { + public Object run() { return TEST_STRING; }}); + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(callable); + assertSame(TEST_STRING, future.get()); + } + }}; + + runWithPermissions(r, new RuntimePermission("modifyThread")); + } + + /** + * A submitted privileged exception action runs to completion + */ + public void testSubmitPrivilegedExceptionAction() throws Exception { + final Callable callable = + Executors.callable(new PrivilegedExceptionAction() { + public Object run() { return TEST_STRING; }}); + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(callable); + assertSame(TEST_STRING, future.get()); + } + }}; + + runWithPermissions(r, new RuntimePermission("modifyThread")); + } + + /** + * A submitted failed privileged exception action reports exception + */ + public void testSubmitFailedPrivilegedExceptionAction() throws Exception { + final Callable callable = + Executors.callable(new PrivilegedExceptionAction() { + public Object run() { throw new IndexOutOfBoundsException(); }}); + Runnable r = new CheckedRunnable() { + public void realRun() throws Exception { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(callable); + try { + future.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof IndexOutOfBoundsException); + } + } + }}; + + runWithPermissions(r, new RuntimePermission("modifyThread")); + } + + /** + * execute(null runnable) throws NullPointerException + */ + public void testExecuteNullRunnable() { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + try { + Future future = e.submit((Runnable) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * submit(null callable) throws NullPointerException + */ + public void testSubmitNullCallable() { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + try { + Future future = e.submit((Callable) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * submit(callable).get() throws InterruptedException if interrupted + */ + public void testInterruptedSubmit() throws InterruptedException { + final CountDownLatch submitted = new CountDownLatch(1); + final CountDownLatch quittingTime = new CountDownLatch(1); + final Callable awaiter = new CheckedCallable() { + public Void realCall() throws InterruptedException { + assertTrue(quittingTime.await(2*LONG_DELAY_MS, MILLISECONDS)); + return null; + }}; + final ExecutorService p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p, quittingTime)) { + Thread t = new Thread(new CheckedInterruptedRunnable() { + public void realRun() throws Exception { + Future future = p.submit(awaiter); + submitted.countDown(); + future.get(); + }}); + t.start(); + await(submitted); + t.interrupt(); + awaitTermination(t); + } + } + + /** + * get of submit(callable) throws ExecutionException if callable + * throws exception + */ + public void testSubmitEE() throws Throwable { + ForkJoinPool p = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.submit(new Callable() { + public Object call() { throw new ArithmeticException(); }}) + .get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof ArithmeticException); + } + } + } + + /** + * invokeAny(null) throws NullPointerException + */ + public void testInvokeAny1() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAny(empty collection) throws IllegalArgumentException + */ + public void testInvokeAny2() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * invokeAny(c) throws NullPointerException if c has a single null element + */ + public void testInvokeAny3() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(null); + try { + e.invokeAny(l); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAny(c) throws NullPointerException if c has null elements + */ + public void testInvokeAny4() throws Throwable { + CountDownLatch latch = new CountDownLatch(1); + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * invokeAny(c) throws ExecutionException if no task in c completes + */ + public void testInvokeAny5() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAny(c) returns result of some task in c if at least one completes + */ + public void testInvokeAny6() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAll(null) throws NullPointerException + */ + public void testInvokeAll1() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAll(empty collection) returns empty collection + */ + public void testInvokeAll2() throws InterruptedException { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> r + = e.invokeAll(new ArrayList>()); + assertTrue(r.isEmpty()); + } + } + + /** + * invokeAll(c) throws NullPointerException if c has null elements + */ + public void testInvokeAll3() throws InterruptedException { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of returned element of invokeAll(c) throws + * ExecutionException on failed task + */ + public void testInvokeAll4() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = e.invokeAll(l); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAll(c) returns results of all completed tasks in c + */ + public void testInvokeAll5() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = e.invokeAll(l); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAny(null) throws NullPointerException + */ + public void testTimedInvokeAny1() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(null time unit) throws NullPointerException + */ + public void testTimedInvokeAnyNullTimeUnit() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(empty collection) throws IllegalArgumentException + */ + public void testTimedInvokeAny2() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * timed invokeAny(c) throws NullPointerException if c has null elements + */ + public void testTimedInvokeAny3() throws Throwable { + CountDownLatch latch = new CountDownLatch(1); + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * timed invokeAny(c) throws ExecutionException if no task completes + */ + public void testTimedInvokeAny4() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAny(c) returns result of some task in c + */ + public void testTimedInvokeAny5() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + assertSame(TEST_STRING, result); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAll(null) throws NullPointerException + */ + public void testTimedInvokeAll1() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(null time unit) throws NullPointerException + */ + public void testTimedInvokeAllNullTimeUnit() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(empty collection) returns empty collection + */ + public void testTimedInvokeAll2() throws InterruptedException { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> r + = e.invokeAll(new ArrayList>(), + MEDIUM_DELAY_MS, MILLISECONDS); + assertTrue(r.isEmpty()); + } + } + + /** + * timed invokeAll(c) throws NullPointerException if c has null elements + */ + public void testTimedInvokeAll3() throws InterruptedException { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of returned element of invokeAll(c) throws exception on failed task + */ + public void testTimedInvokeAll4() throws Throwable { + ExecutorService e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures + = e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * timed invokeAll(c) returns results of all completed tasks in c + */ + public void testTimedInvokeAll5() throws Throwable { + ForkJoinPool e = new ForkJoinPool(1); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures + = e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java b/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java new file mode 100644 index 00000000000..c8fe1bb9986 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ForkJoinTask8Test.java @@ -0,0 +1,1228 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.TimeoutException; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ForkJoinTask8Test extends JSR166TestCase { + + /* + * Testing notes: This differs from ForkJoinTaskTest mainly by + * defining a version of BinaryAsyncAction that uses JDK8 task + * tags for control state, thereby testing getForkJoinTaskTag, + * setForkJoinTaskTag, and compareAndSetForkJoinTaskTag across + * various contexts. Most of the test methods using it are + * otherwise identical, but omitting retest of those dealing with + * cancellation, which is not represented in this tag scheme. + */ + + static final short INITIAL_STATE = -1; + static final short COMPLETE_STATE = 0; + static final short EXCEPTION_STATE = 1; + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ForkJoinTask8Test.class); + } + + // Runs with "mainPool" use > 1 thread. singletonPool tests use 1 + static final int mainPoolSize = + Math.max(2, Runtime.getRuntime().availableProcessors()); + + private static ForkJoinPool mainPool() { + return new ForkJoinPool(mainPoolSize); + } + + private static ForkJoinPool singletonPool() { + return new ForkJoinPool(1); + } + + private static ForkJoinPool asyncSingletonPool() { + return new ForkJoinPool(1, + ForkJoinPool.defaultForkJoinWorkerThreadFactory, + null, true); + } + + // Compute fib naively and efficiently + final int[] fib; + { + int[] fib = new int[10]; + fib[0] = 0; + fib[1] = 1; + for (int i = 2; i < fib.length; i++) + fib[i] = fib[i - 1] + fib[i - 2]; + this.fib = fib; + } + + private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) { + try (PoolCleaner cleaner = cleaner(pool)) { + assertFalse(a.isDone()); + assertFalse(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + + assertNull(pool.invoke(a)); + + assertTrue(a.isDone()); + assertTrue(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + } + } + + void checkNotDone(ForkJoinTask a) { + assertFalse(a.isDone()); + assertFalse(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + if (a instanceof BinaryAsyncAction) + assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == INITIAL_STATE); + + try { + a.get(0L, SECONDS); + shouldThrow(); + } catch (TimeoutException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedNormally(ForkJoinTask a) { + checkCompletedNormally(a, null); + } + + void checkCompletedNormally(ForkJoinTask a, T expected) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertTrue(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertNull(a.getException()); + assertSame(expected, a.getRawResult()); + if (a instanceof BinaryAsyncAction) + assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == COMPLETE_STATE); + + { + Thread.currentThread().interrupt(); + long startTime = System.nanoTime(); + assertSame(expected, a.join()); + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + Thread.interrupted(); + } + + { + Thread.currentThread().interrupt(); + long startTime = System.nanoTime(); + a.quietlyJoin(); // should be no-op + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + Thread.interrupted(); + } + + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + try { + assertSame(expected, a.get()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertSame(expected, a.get(5L, SECONDS)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedAbnormally(ForkJoinTask a, Throwable t) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertSame(t.getClass(), a.getException().getClass()); + assertNull(a.getRawResult()); + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + if (a instanceof BinaryAsyncAction) + assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() != INITIAL_STATE); + + try { + Thread.currentThread().interrupt(); + a.join(); + shouldThrow(); + } catch (Throwable expected) { + assertSame(t.getClass(), expected.getClass()); + } + Thread.interrupted(); + + { + long startTime = System.nanoTime(); + a.quietlyJoin(); // should be no-op + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + } + + try { + a.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + public static final class FJException extends RuntimeException { + FJException() { super(); } + } + + abstract static class BinaryAsyncAction extends ForkJoinTask { + + private volatile BinaryAsyncAction parent; + + private volatile BinaryAsyncAction sibling; + + protected BinaryAsyncAction() { + setForkJoinTaskTag(INITIAL_STATE); + } + + public final Void getRawResult() { return null; } + protected final void setRawResult(Void mustBeNull) { } + + public final void linkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) { + x.parent = y.parent = this; + x.sibling = y; + y.sibling = x; + } + + protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) { + if (this.getForkJoinTaskTag() != COMPLETE_STATE || + x.getForkJoinTaskTag() != COMPLETE_STATE || + y.getForkJoinTaskTag() != COMPLETE_STATE) { + completeThisExceptionally(new FJException()); + } + } + + protected boolean onException() { + return true; + } + + public void linkAndForkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) { + linkSubtasks(x, y); + y.fork(); + x.fork(); + } + + private void completeThis() { + setForkJoinTaskTag(COMPLETE_STATE); + super.complete(null); + } + + private void completeThisExceptionally(Throwable ex) { + setForkJoinTaskTag(EXCEPTION_STATE); + super.completeExceptionally(ex); + } + + public boolean cancel(boolean mayInterruptIfRunning) { + if (super.cancel(mayInterruptIfRunning)) { + completeExceptionally(new FJException()); + return true; + } + return false; + } + + public final void complete() { + BinaryAsyncAction a = this; + for (;;) { + BinaryAsyncAction s = a.sibling; + BinaryAsyncAction p = a.parent; + a.sibling = null; + a.parent = null; + a.completeThis(); + if (p == null || + p.compareAndSetForkJoinTaskTag(INITIAL_STATE, COMPLETE_STATE)) + break; + try { + p.onComplete(a, s); + } catch (Throwable rex) { + p.completeExceptionally(rex); + return; + } + a = p; + } + } + + public final void completeExceptionally(Throwable ex) { + for (BinaryAsyncAction a = this;;) { + a.completeThisExceptionally(ex); + BinaryAsyncAction s = a.sibling; + if (s != null && !s.isDone()) + s.completeExceptionally(ex); + if ((a = a.parent) == null) + break; + } + } + + public final BinaryAsyncAction getParent() { + return parent; + } + + public BinaryAsyncAction getSibling() { + return sibling; + } + + public void reinitialize() { + parent = sibling = null; + super.reinitialize(); + } + + } + + final class AsyncFib extends BinaryAsyncAction { + int number; + int expectedResult; + public AsyncFib(int number) { + this.number = number; + this.expectedResult = fib[number]; + } + + public final boolean exec() { + try { + AsyncFib f = this; + int n = f.number; + while (n > 1) { + AsyncFib p = f; + AsyncFib r = new AsyncFib(n - 2); + f = new AsyncFib(--n); + p.linkSubtasks(r, f); + r.fork(); + } + f.complete(); + } + catch (Throwable ex) { + compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE); + } + if (getForkJoinTaskTag() == EXCEPTION_STATE) + throw new FJException(); + return false; + } + + protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) { + number = ((AsyncFib)x).number + ((AsyncFib)y).number; + super.onComplete(x, y); + } + + public void checkCompletedNormally() { + assertEquals(expectedResult, number); + ForkJoinTask8Test.this.checkCompletedNormally(this); + } + } + + static final class FailingAsyncFib extends BinaryAsyncAction { + int number; + public FailingAsyncFib(int n) { + this.number = n; + } + + public final boolean exec() { + try { + FailingAsyncFib f = this; + int n = f.number; + while (n > 1) { + FailingAsyncFib p = f; + FailingAsyncFib r = new FailingAsyncFib(n - 2); + f = new FailingAsyncFib(--n); + p.linkSubtasks(r, f); + r.fork(); + } + f.complete(); + } + catch (Throwable ex) { + compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE); + } + if (getForkJoinTaskTag() == EXCEPTION_STATE) + throw new FJException(); + return false; + } + + protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) { + completeExceptionally(new FJException()); + } + } + + /** + * invoke returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks; getRawResult returns null. + */ + public void testInvoke() { + testInvoke(mainPool()); + } + public void testInvoke_Singleton() { + testInvoke(singletonPool()); + } + public void testInvoke(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertNull(f.invoke()); + f.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * quietlyInvoke task returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks + */ + public void testQuietlyInvoke() { + testQuietlyInvoke(mainPool()); + } + public void testQuietlyInvoke_Singleton() { + testQuietlyInvoke(singletonPool()); + } + public void testQuietlyInvoke(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + f.quietlyInvoke(); + f.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * join of a forked task returns when task completes + */ + public void testForkJoin() { + testForkJoin(mainPool()); + } + public void testForkJoin_Singleton() { + testForkJoin(singletonPool()); + } + public void testForkJoin(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertNull(f.join()); + f.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * get of a forked task returns when task completes + */ + public void testForkGet() { + testForkGet(mainPool()); + } + public void testForkGet_Singleton() { + testForkGet(singletonPool()); + } + public void testForkGet(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertNull(f.get()); + f.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * timed get of a forked task returns when task completes + */ + public void testForkTimedGet() { + testForkTimedGet(mainPool()); + } + public void testForkTimedGet_Singleton() { + testForkTimedGet(singletonPool()); + } + public void testForkTimedGet(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); + f.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * timed get with null time unit throws NullPointerException + */ + public void testForkTimedGetNullTimeUnit() { + testForkTimedGetNullTimeUnit(mainPool()); + } + public void testForkTimedGetNullTimeUnit_Singleton() { + testForkTimedGet(singletonPool()); + } + public void testForkTimedGetNullTimeUnit(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + try { + f.get(5L, null); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(pool, a); + } + + /** + * quietlyJoin of a forked task returns when task completes + */ + public void testForkQuietlyJoin() { + testForkQuietlyJoin(mainPool()); + } + public void testForkQuietlyJoin_Singleton() { + testForkQuietlyJoin(singletonPool()); + } + public void testForkQuietlyJoin(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + f.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * helpQuiesce returns when tasks are complete. + * getQueuedTaskCount returns 0 when quiescent + */ + public void testForkHelpQuiesce() { + testForkHelpQuiesce(mainPool()); + } + public void testForkHelpQuiesce_Singleton() { + testForkHelpQuiesce(singletonPool()); + } + public void testForkHelpQuiesce(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + helpQuiesce(); + assertEquals(0, getQueuedTaskCount()); + f.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * invoke task throws exception when task completes abnormally + */ + public void testAbnormalInvoke() { + testAbnormalInvoke(mainPool()); + } + public void testAbnormalInvoke_Singleton() { + testAbnormalInvoke(singletonPool()); + } + public void testAbnormalInvoke(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(pool, a); + } + + /** + * quietlyInvoke task returns when task completes abnormally + */ + public void testAbnormalQuietlyInvoke() { + testAbnormalQuietlyInvoke(mainPool()); + } + public void testAbnormalQuietlyInvoke_Singleton() { + testAbnormalQuietlyInvoke(singletonPool()); + } + public void testAbnormalQuietlyInvoke(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + f.quietlyInvoke(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(pool, a); + } + + /** + * join of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkJoin() { + testAbnormalForkJoin(mainPool()); + } + public void testAbnormalForkJoin_Singleton() { + testAbnormalForkJoin(singletonPool()); + } + public void testAbnormalForkJoin(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(pool, a); + } + + /** + * get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkGet() { + testAbnormalForkGet(mainPool()); + } + public void testAbnormalForkGet_Singleton() { + testAbnormalForkJoin(singletonPool()); + } + public void testAbnormalForkGet(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(pool, a); + } + + /** + * timed get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkTimedGet() { + testAbnormalForkTimedGet(mainPool()); + } + public void testAbnormalForkTimedGet_Singleton() { + testAbnormalForkTimedGet(singletonPool()); + } + public void testAbnormalForkTimedGet(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(pool, a); + } + + /** + * quietlyJoin of a forked task returns when task completes abnormally + */ + public void testAbnormalForkQuietlyJoin() { + testAbnormalForkQuietlyJoin(mainPool()); + } + public void testAbnormalForkQuietlyJoin_Singleton() { + testAbnormalForkQuietlyJoin(singletonPool()); + } + public void testAbnormalForkQuietlyJoin(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(pool, a); + } + + /** + * getPool of executing task returns its pool + */ + public void testGetPool() { + testGetPool(mainPool()); + } + public void testGetPool_Singleton() { + testGetPool(singletonPool()); + } + public void testGetPool(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertSame(pool, getPool()); + }}; + testInvokeOnPool(pool, a); + } + + /** + * getPool of non-FJ task returns null + */ + public void testGetPool2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertNull(getPool()); + }}; + assertNull(a.invoke()); + } + + /** + * inForkJoinPool of executing task returns true + */ + public void testInForkJoinPool() { + testInForkJoinPool(mainPool()); + } + public void testInForkJoinPool_Singleton() { + testInForkJoinPool(singletonPool()); + } + public void testInForkJoinPool(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertTrue(inForkJoinPool()); + }}; + testInvokeOnPool(pool, a); + } + + /** + * inForkJoinPool of non-FJ task returns false + */ + public void testInForkJoinPool2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertFalse(inForkJoinPool()); + }}; + assertNull(a.invoke()); + } + + /** + * setRawResult(null) succeeds + */ + public void testSetRawResult() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + setRawResult(null); + assertNull(getRawResult()); + }}; + assertNull(a.invoke()); + } + + /** + * invoke task throws exception after invoking completeExceptionally + */ + public void testCompleteExceptionally() { + testCompleteExceptionally(mainPool()); + } + public void testCompleteExceptionally_Singleton() { + testCompleteExceptionally(singletonPool()); + } + public void testCompleteExceptionally(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + f.completeExceptionally(new FJException()); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(pool, a); + } + + /** + * invokeAll(tasks) with 1 argument invokes task + */ + public void testInvokeAll1() { + testInvokeAll1(mainPool()); + } + public void testInvokeAll1_Singleton() { + testInvokeAll1(singletonPool()); + } + public void testInvokeAll1(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + invokeAll(f); + f.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * invokeAll(t1, t2) invokes all task arguments + */ + public void testInvokeAll2() { + testInvokeAll2(mainPool()); + } + public void testInvokeAll2_Singleton() { + testInvokeAll2(singletonPool()); + } + public void testInvokeAll2(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib[] tasks = { + new AsyncFib(8), + new AsyncFib(9), + }; + invokeAll(tasks[0], tasks[1]); + for (AsyncFib task : tasks) assertTrue(task.isDone()); + for (AsyncFib task : tasks) task.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * invokeAll(tasks) with > 2 argument invokes tasks + */ + public void testInvokeAll3() { + testInvokeAll3(mainPool()); + } + public void testInvokeAll3_Singleton() { + testInvokeAll3(singletonPool()); + } + public void testInvokeAll3(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib[] tasks = { + new AsyncFib(8), + new AsyncFib(9), + new AsyncFib(7), + }; + invokeAll(tasks[0], tasks[1], tasks[2]); + for (AsyncFib task : tasks) assertTrue(task.isDone()); + for (AsyncFib task : tasks) task.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * invokeAll(collection) invokes all tasks in the collection + */ + public void testInvokeAllCollection() { + testInvokeAllCollection(mainPool()); + } + public void testInvokeAllCollection_Singleton() { + testInvokeAllCollection(singletonPool()); + } + public void testInvokeAllCollection(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib[] tasks = { + new AsyncFib(8), + new AsyncFib(9), + new AsyncFib(7), + }; + invokeAll(Arrays.asList(tasks)); + for (AsyncFib task : tasks) assertTrue(task.isDone()); + for (AsyncFib task : tasks) task.checkCompletedNormally(); + }}; + testInvokeOnPool(pool, a); + } + + /** + * invokeAll(tasks) with any null task throws NullPointerException + */ + public void testInvokeAllNullTask() { + testInvokeAllNullTask(mainPool()); + } + public void testInvokeAllNullTask_Singleton() { + testInvokeAllNullTask(singletonPool()); + } + public void testInvokeAllNullTask(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib nul = null; + Runnable[] throwingActions = { + () -> invokeAll(nul), + () -> invokeAll(nul, nul), + () -> invokeAll(new AsyncFib(8), new AsyncFib(9), nul), + () -> invokeAll(new AsyncFib(8), nul, new AsyncFib(9)), + () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)), + }; + assertThrows(NullPointerException.class, throwingActions); + }}; + testInvokeOnPool(pool, a); + } + + /** + * invokeAll(tasks) with 1 argument throws exception if task does + */ + public void testAbnormalInvokeAll1() { + testAbnormalInvokeAll1(mainPool()); + } + public void testAbnormalInvokeAll1_Singleton() { + testAbnormalInvokeAll1(singletonPool()); + } + public void testAbnormalInvokeAll1(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib g = new FailingAsyncFib(9); + try { + invokeAll(g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(pool, a); + } + + /** + * invokeAll(t1, t2) throw exception if any task does + */ + public void testAbnormalInvokeAll2() { + testAbnormalInvokeAll2(mainPool()); + } + public void testAbnormalInvokeAll2_Singleton() { + testAbnormalInvokeAll2(singletonPool()); + } + public void testAbnormalInvokeAll2(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + FailingAsyncFib g = new FailingAsyncFib(9); + ForkJoinTask[] tasks = { f, g }; + Collections.shuffle(Arrays.asList(tasks)); + try { + invokeAll(tasks[0], tasks[1]); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(pool, a); + } + + /** + * invokeAll(tasks) with > 2 argument throws exception if any task does + */ + public void testAbnormalInvokeAll3() { + testAbnormalInvokeAll3(mainPool()); + } + public void testAbnormalInvokeAll3_Singleton() { + testAbnormalInvokeAll3(singletonPool()); + } + public void testAbnormalInvokeAll3(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + FailingAsyncFib g = new FailingAsyncFib(9); + AsyncFib h = new AsyncFib(7); + ForkJoinTask[] tasks = { f, g, h }; + Collections.shuffle(Arrays.asList(tasks)); + try { + invokeAll(tasks[0], tasks[1], tasks[2]); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(pool, a); + } + + /** + * invokeAll(collection) throws exception if any task does + */ + public void testAbnormalInvokeAllCollection() { + testAbnormalInvokeAllCollection(mainPool()); + } + public void testAbnormalInvokeAllCollection_Singleton() { + testAbnormalInvokeAllCollection(singletonPool()); + } + public void testAbnormalInvokeAllCollection(ForkJoinPool pool) { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + AsyncFib g = new AsyncFib(9); + AsyncFib h = new AsyncFib(7); + ForkJoinTask[] tasks = { f, g, h }; + Collections.shuffle(Arrays.asList(tasks)); + try { + invokeAll(Arrays.asList(tasks)); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(pool, a); + } + + /** + * tryUnfork returns true for most recent unexecuted task, + * and suppresses execution + */ + public void testTryUnfork() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertTrue(f.tryUnfork()); + helpQuiesce(); + checkNotDone(f); + g.checkCompletedNormally(); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * getSurplusQueuedTaskCount returns > 0 when + * there are more tasks than threads + */ + public void testGetSurplusQueuedTaskCount() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib h = new AsyncFib(7); + assertSame(h, h.fork()); + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertTrue(getSurplusQueuedTaskCount() > 0); + helpQuiesce(); + assertEquals(0, getSurplusQueuedTaskCount()); + f.checkCompletedNormally(); + g.checkCompletedNormally(); + h.checkCompletedNormally(); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * peekNextLocalTask returns most recent unexecuted task. + */ + public void testPeekNextLocalTask() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(f, peekNextLocalTask()); + assertNull(f.join()); + f.checkCompletedNormally(); + helpQuiesce(); + g.checkCompletedNormally(); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * pollNextLocalTask returns most recent unexecuted task without + * executing it + */ + public void testPollNextLocalTask() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(f, pollNextLocalTask()); + helpQuiesce(); + checkNotDone(f); + g.checkCompletedNormally(); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * pollTask returns an unexecuted task without executing it + */ + public void testPollTask() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(f, pollTask()); + helpQuiesce(); + checkNotDone(f); + g.checkCompletedNormally(); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * peekNextLocalTask returns least recent unexecuted task in async mode + */ + public void testPeekNextLocalTaskAsync() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(g, peekNextLocalTask()); + assertNull(f.join()); + helpQuiesce(); + f.checkCompletedNormally(); + g.checkCompletedNormally(); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** + * pollNextLocalTask returns least recent unexecuted task without + * executing it, in async mode + */ + public void testPollNextLocalTaskAsync() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(g, pollNextLocalTask()); + helpQuiesce(); + f.checkCompletedNormally(); + checkNotDone(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** + * pollTask returns an unexecuted task without executing it, in + * async mode + */ + public void testPollTaskAsync() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(g, pollTask()); + helpQuiesce(); + f.checkCompletedNormally(); + checkNotDone(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** + * ForkJoinTask.quietlyComplete returns when task completes + * normally without setting a value. The most recent value + * established by setRawResult(V) (or null by default) is returned + * from invoke. + */ + public void testQuietlyComplete() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + f.quietlyComplete(); + assertEquals(8, f.number); + assertTrue(f.isDone()); + assertFalse(f.isCancelled()); + assertTrue(f.isCompletedNormally()); + assertFalse(f.isCompletedAbnormally()); + assertNull(f.getException()); + }}; + testInvokeOnPool(mainPool(), a); + } + + // jdk9 + + /** + * pollSubmission returns unexecuted submitted task, if present + */ + public void testPollSubmission() { + final CountDownLatch done = new CountDownLatch(1); + final ForkJoinTask a = ForkJoinTask.adapt(awaiter(done)); + final ForkJoinTask b = ForkJoinTask.adapt(awaiter(done)); + final ForkJoinTask c = ForkJoinTask.adapt(awaiter(done)); + final ForkJoinPool p = singletonPool(); + try (PoolCleaner cleaner = cleaner(p, done)) { + Thread external = new Thread(new CheckedRunnable() { + public void realRun() { + p.execute(a); + p.execute(b); + p.execute(c); + }}); + RecursiveAction s = new CheckedRecursiveAction() { + protected void realCompute() { + external.start(); + try { + external.join(); + } catch (Exception ex) { + threadUnexpectedException(ex); + } + assertTrue(p.hasQueuedSubmissions()); + assertTrue(Thread.currentThread() instanceof ForkJoinWorkerThread); + ForkJoinTask r = ForkJoinTask.pollSubmission(); + assertTrue(r == a || r == b || r == c); + assertFalse(r.isDone()); + }}; + p.invoke(s); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java b/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java new file mode 100644 index 00000000000..7000c1a4bb5 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ForkJoinTaskTest.java @@ -0,0 +1,1685 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ForkJoinTaskTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ForkJoinTaskTest.class); + } + + // Runs with "mainPool" use > 1 thread. singletonPool tests use 1 + static final int mainPoolSize = + Math.max(2, Runtime.getRuntime().availableProcessors()); + + private static ForkJoinPool mainPool() { + return new ForkJoinPool(mainPoolSize); + } + + private static ForkJoinPool singletonPool() { + return new ForkJoinPool(1); + } + + private static ForkJoinPool asyncSingletonPool() { + return new ForkJoinPool(1, + ForkJoinPool.defaultForkJoinWorkerThreadFactory, + null, true); + } + + private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) { + try (PoolCleaner cleaner = cleaner(pool)) { + assertFalse(a.isDone()); + assertFalse(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + + assertNull(pool.invoke(a)); + + assertTrue(a.isDone()); + assertTrue(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + } + } + + void checkNotDone(ForkJoinTask a) { + assertFalse(a.isDone()); + assertFalse(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + + try { + a.get(0L, SECONDS); + shouldThrow(); + } catch (TimeoutException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedNormally(ForkJoinTask a) { + checkCompletedNormally(a, null); + } + + void checkCompletedNormally(ForkJoinTask a, T expected) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertTrue(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertNull(a.getException()); + assertSame(expected, a.getRawResult()); + + { + Thread.currentThread().interrupt(); + long startTime = System.nanoTime(); + assertSame(expected, a.join()); + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + Thread.interrupted(); + } + + { + Thread.currentThread().interrupt(); + long startTime = System.nanoTime(); + a.quietlyJoin(); // should be no-op + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + Thread.interrupted(); + } + + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + try { + assertSame(expected, a.get()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertSame(expected, a.get(5L, SECONDS)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCancelled(ForkJoinTask a) { + assertTrue(a.isDone()); + assertTrue(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertTrue(a.getException() instanceof CancellationException); + assertNull(a.getRawResult()); + assertTrue(a.cancel(false)); + assertTrue(a.cancel(true)); + + try { + Thread.currentThread().interrupt(); + a.join(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + Thread.interrupted(); + + { + long startTime = System.nanoTime(); + a.quietlyJoin(); // should be no-op + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + } + + try { + a.get(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedAbnormally(ForkJoinTask a, Throwable t) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertSame(t.getClass(), a.getException().getClass()); + assertNull(a.getRawResult()); + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + + try { + Thread.currentThread().interrupt(); + a.join(); + shouldThrow(); + } catch (Throwable expected) { + assertSame(t.getClass(), expected.getClass()); + } + Thread.interrupted(); + + { + long startTime = System.nanoTime(); + a.quietlyJoin(); // should be no-op + assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS); + } + + try { + a.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + /* + * Testing coverage notes: + * + * To test extension methods and overrides, most tests use + * BinaryAsyncAction extension class that processes joins + * differently than supplied Recursive forms. + */ + + public static final class FJException extends RuntimeException { + FJException() { super(); } + } + + abstract static class BinaryAsyncAction extends ForkJoinTask { + private volatile int controlState; + + static final AtomicIntegerFieldUpdater controlStateUpdater = + AtomicIntegerFieldUpdater.newUpdater(BinaryAsyncAction.class, + "controlState"); + + private volatile BinaryAsyncAction parent; + + private volatile BinaryAsyncAction sibling; + + protected BinaryAsyncAction() { + } + + public final Void getRawResult() { return null; } + protected final void setRawResult(Void mustBeNull) { } + + public final void linkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) { + x.parent = y.parent = this; + x.sibling = y; + y.sibling = x; + } + + protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) { + } + + protected boolean onException() { + return true; + } + + public void linkAndForkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) { + linkSubtasks(x, y); + y.fork(); + x.fork(); + } + + private void completeThis() { + super.complete(null); + } + + private void completeThisExceptionally(Throwable ex) { + super.completeExceptionally(ex); + } + + public boolean cancel(boolean mayInterruptIfRunning) { + if (super.cancel(mayInterruptIfRunning)) { + completeExceptionally(new FJException()); + return true; + } + return false; + } + + public final void complete() { + BinaryAsyncAction a = this; + for (;;) { + BinaryAsyncAction s = a.sibling; + BinaryAsyncAction p = a.parent; + a.sibling = null; + a.parent = null; + a.completeThis(); + if (p == null || p.compareAndSetControlState(0, 1)) + break; + try { + p.onComplete(a, s); + } catch (Throwable rex) { + p.completeExceptionally(rex); + return; + } + a = p; + } + } + + public final void completeExceptionally(Throwable ex) { + for (BinaryAsyncAction a = this;;) { + a.completeThisExceptionally(ex); + BinaryAsyncAction s = a.sibling; + if (s != null && !s.isDone()) + s.completeExceptionally(ex); + if ((a = a.parent) == null) + break; + } + } + + public final BinaryAsyncAction getParent() { + return parent; + } + + public BinaryAsyncAction getSibling() { + return sibling; + } + + public void reinitialize() { + parent = sibling = null; + super.reinitialize(); + } + + protected final int getControlState() { + return controlState; + } + + protected final boolean compareAndSetControlState(int expect, + int update) { + return controlStateUpdater.compareAndSet(this, expect, update); + } + + protected final void setControlState(int value) { + controlState = value; + } + + protected final void incrementControlState() { + controlStateUpdater.incrementAndGet(this); + } + + protected final void decrementControlState() { + controlStateUpdater.decrementAndGet(this); + } + + } + + static final class AsyncFib extends BinaryAsyncAction { + int number; + public AsyncFib(int n) { + this.number = n; + } + + public final boolean exec() { + AsyncFib f = this; + int n = f.number; + while (n > 1) { + AsyncFib p = f; + AsyncFib r = new AsyncFib(n - 2); + f = new AsyncFib(--n); + p.linkSubtasks(r, f); + r.fork(); + } + f.complete(); + return false; + } + + protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) { + number = ((AsyncFib)x).number + ((AsyncFib)y).number; + } + } + + static final class FailingAsyncFib extends BinaryAsyncAction { + int number; + public FailingAsyncFib(int n) { + this.number = n; + } + + public final boolean exec() { + FailingAsyncFib f = this; + int n = f.number; + while (n > 1) { + FailingAsyncFib p = f; + FailingAsyncFib r = new FailingAsyncFib(n - 2); + f = new FailingAsyncFib(--n); + p.linkSubtasks(r, f); + r.fork(); + } + f.complete(); + return false; + } + + protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) { + completeExceptionally(new FJException()); + } + } + + /** + * invoke returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks; getRawResult returns null. + */ + public void testInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertNull(f.invoke()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyInvoke task returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks + */ + public void testQuietlyInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + f.quietlyInvoke(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join of a forked task returns when task completes + */ + public void testForkJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertNull(f.join()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * get of a forked task returns when task completes + */ + public void testForkGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertNull(f.get()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get of a forked task returns when task completes + */ + public void testForkTimedGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get with null time unit throws NPE + */ + public void testForkTimedGetNPE() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + try { + f.get(5L, null); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes + */ + public void testForkQuietlyJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * helpQuiesce returns when tasks are complete. + * getQueuedTaskCount returns 0 when quiescent + */ + public void testForkHelpQuiesce() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + helpQuiesce(); + assertEquals(21, f.number); + assertEquals(0, getQueuedTaskCount()); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invoke task throws exception when task completes abnormally + */ + public void testAbnormalInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyInvoke task returns when task completes abnormally + */ + public void testAbnormalQuietlyInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + f.quietlyInvoke(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkTimedGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes abnormally + */ + public void testAbnormalForkQuietlyJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invoke task throws exception when task cancelled + */ + public void testCancelledInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + try { + f.invoke(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join of a forked task throws exception when task cancelled + */ + public void testCancelledForkJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * get of a forked task throws exception when task cancelled + */ + public void testCancelledForkGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get of a forked task throws exception when task cancelled + */ + public void testCancelledForkTimedGet() throws Exception { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task cancelled + */ + public void testCancelledForkQuietlyJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + f.quietlyJoin(); + checkCancelled(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * getPool of executing task returns its pool + */ + public void testGetPool() { + final ForkJoinPool mainPool = mainPool(); + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertSame(mainPool, getPool()); + }}; + testInvokeOnPool(mainPool, a); + } + + /** + * getPool of non-FJ task returns null + */ + public void testGetPool2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertNull(getPool()); + }}; + assertNull(a.invoke()); + } + + /** + * inForkJoinPool of executing task returns true + */ + public void testInForkJoinPool() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertTrue(inForkJoinPool()); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * inForkJoinPool of non-FJ task returns false + */ + public void testInForkJoinPool2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertFalse(inForkJoinPool()); + }}; + assertNull(a.invoke()); + } + + /** + * setRawResult(null) succeeds + */ + public void testSetRawResult() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + setRawResult(null); + assertNull(getRawResult()); + }}; + assertNull(a.invoke()); + } + + /** + * invoke task throws exception after invoking completeExceptionally + */ + public void testCompleteExceptionally() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + f.completeExceptionally(new FJException()); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * completeExceptionally(null) surprisingly has the same effect as + * completeExceptionally(new RuntimeException()) + */ + public void testCompleteExceptionally_null() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + f.completeExceptionally(null); + try { + f.invoke(); + shouldThrow(); + } catch (RuntimeException success) { + assertSame(success.getClass(), RuntimeException.class); + assertNull(success.getCause()); + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(t1, t2) invokes all task arguments + */ + public void testInvokeAll2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + AsyncFib g = new AsyncFib(9); + invokeAll(f, g); + assertEquals(21, f.number); + assertEquals(34, g.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument invokes task + */ + public void testInvokeAll1() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + invokeAll(f); + checkCompletedNormally(f); + assertEquals(21, f.number); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument invokes tasks + */ + public void testInvokeAll3() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + AsyncFib g = new AsyncFib(9); + AsyncFib h = new AsyncFib(7); + invokeAll(f, g, h); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(collection) invokes all tasks in the collection + */ + public void testInvokeAllCollection() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + AsyncFib g = new AsyncFib(9); + AsyncFib h = new AsyncFib(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + invokeAll(set); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with any null task throws NPE + */ + public void testInvokeAllNPE() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + AsyncFib g = new AsyncFib(9); + AsyncFib h = null; + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(t1, t2) throw exception if any task does + */ + public void testAbnormalInvokeAll2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + FailingAsyncFib g = new FailingAsyncFib(9); + ForkJoinTask[] tasks = { f, g }; + Collections.shuffle(Arrays.asList(tasks)); + try { + invokeAll(tasks); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument throws exception if task does + */ + public void testAbnormalInvokeAll1() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib g = new FailingAsyncFib(9); + try { + invokeAll(g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument throws exception if any task does + */ + public void testAbnormalInvokeAll3() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + FailingAsyncFib g = new FailingAsyncFib(9); + AsyncFib h = new AsyncFib(7); + ForkJoinTask[] tasks = { f, g, h }; + Collections.shuffle(Arrays.asList(tasks)); + try { + invokeAll(tasks); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(collection) throws exception if any task does + */ + public void testAbnormalInvokeAllCollection() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + AsyncFib g = new AsyncFib(9); + AsyncFib h = new AsyncFib(7); + ForkJoinTask[] tasks = { f, g, h }; + List taskList = Arrays.asList(tasks); + Collections.shuffle(taskList); + try { + invokeAll(taskList); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * tryUnfork returns true for most recent unexecuted task, + * and suppresses execution + */ + public void testTryUnfork() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertTrue(f.tryUnfork()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * getSurplusQueuedTaskCount returns > 0 when + * there are more tasks than threads + */ + public void testGetSurplusQueuedTaskCount() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib h = new AsyncFib(7); + assertSame(h, h.fork()); + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertTrue(getSurplusQueuedTaskCount() > 0); + helpQuiesce(); + assertEquals(0, getSurplusQueuedTaskCount()); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * peekNextLocalTask returns most recent unexecuted task. + */ + public void testPeekNextLocalTask() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(f, peekNextLocalTask()); + assertNull(f.join()); + checkCompletedNormally(f); + helpQuiesce(); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * pollNextLocalTask returns most recent unexecuted task without + * executing it + */ + public void testPollNextLocalTask() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(f, pollNextLocalTask()); + helpQuiesce(); + checkNotDone(f); + assertEquals(34, g.number); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * pollTask returns an unexecuted task without executing it + */ + public void testPollTask() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(f, pollTask()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * peekNextLocalTask returns least recent unexecuted task in async mode + */ + public void testPeekNextLocalTaskAsync() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(g, peekNextLocalTask()); + assertNull(f.join()); + helpQuiesce(); + checkCompletedNormally(f); + assertEquals(34, g.number); + checkCompletedNormally(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** + * pollNextLocalTask returns least recent unexecuted task without + * executing it, in async mode + */ + public void testPollNextLocalTaskAsync() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(g, pollNextLocalTask()); + helpQuiesce(); + assertEquals(21, f.number); + checkCompletedNormally(f); + checkNotDone(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** + * pollTask returns an unexecuted task without executing it, in + * async mode + */ + public void testPollTaskAsync() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib g = new AsyncFib(9); + assertSame(g, g.fork()); + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertSame(g, pollTask()); + helpQuiesce(); + assertEquals(21, f.number); + checkCompletedNormally(f); + checkNotDone(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + // versions for singleton pools + + /** + * invoke returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks; getRawResult returns null. + */ + public void testInvokeSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertNull(f.invoke()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyInvoke task returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks + */ + public void testQuietlyInvokeSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + f.quietlyInvoke(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * join of a forked task returns when task completes + */ + public void testForkJoinSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertNull(f.join()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * get of a forked task returns when task completes + */ + public void testForkGetSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertNull(f.get()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * timed get of a forked task returns when task completes + */ + public void testForkTimedGetSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * timed get with null time unit throws NPE + */ + public void testForkTimedGetNPESingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + try { + f.get(5L, null); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes + */ + public void testForkQuietlyJoinSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * helpQuiesce returns when tasks are complete. + * getQueuedTaskCount returns 0 when quiescent + */ + public void testForkHelpQuiesceSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertSame(f, f.fork()); + helpQuiesce(); + assertEquals(0, getQueuedTaskCount()); + assertEquals(21, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invoke task throws exception when task completes abnormally + */ + public void testAbnormalInvokeSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyInvoke task returns when task completes abnormally + */ + public void testAbnormalQuietlyInvokeSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + f.quietlyInvoke(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * join of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkJoinSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkGetSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * timed get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkTimedGetSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes abnormally + */ + public void testAbnormalForkQuietlyJoinSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invoke task throws exception when task cancelled + */ + public void testCancelledInvokeSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + try { + f.invoke(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * join of a forked task throws exception when task cancelled + */ + public void testCancelledForkJoinSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * get of a forked task throws exception when task cancelled + */ + public void testCancelledForkGetSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * timed get of a forked task throws exception when task cancelled + */ + public void testCancelledForkTimedGetSingleton() throws Exception { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task cancelled + */ + public void testCancelledForkQuietlyJoinSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + f.quietlyJoin(); + checkCancelled(f); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invoke task throws exception after invoking completeExceptionally + */ + public void testCompleteExceptionallySingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + f.completeExceptionally(new FJException()); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(t1, t2) invokes all task arguments + */ + public void testInvokeAll2Singleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + AsyncFib g = new AsyncFib(9); + invokeAll(f, g); + assertEquals(21, f.number); + assertEquals(34, g.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument invokes task + */ + public void testInvokeAll1Singleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + invokeAll(f); + checkCompletedNormally(f); + assertEquals(21, f.number); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument invokes tasks + */ + public void testInvokeAll3Singleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + AsyncFib g = new AsyncFib(9); + AsyncFib h = new AsyncFib(7); + invokeAll(f, g, h); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(collection) invokes all tasks in the collection + */ + public void testInvokeAllCollectionSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + AsyncFib g = new AsyncFib(9); + AsyncFib h = new AsyncFib(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + invokeAll(set); + assertEquals(21, f.number); + assertEquals(34, g.number); + assertEquals(13, h.number); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with any null task throws NPE + */ + public void testInvokeAllNPESingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + AsyncFib g = new AsyncFib(9); + AsyncFib h = null; + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(t1, t2) throw exception if any task does + */ + public void testAbnormalInvokeAll2Singleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + FailingAsyncFib g = new FailingAsyncFib(9); + ForkJoinTask[] tasks = { f, g }; + Collections.shuffle(Arrays.asList(tasks)); + try { + invokeAll(tasks); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument throws exception if task does + */ + public void testAbnormalInvokeAll1Singleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib g = new FailingAsyncFib(9); + try { + invokeAll(g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument throws exception if any task does + */ + public void testAbnormalInvokeAll3Singleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + FailingAsyncFib g = new FailingAsyncFib(9); + AsyncFib h = new AsyncFib(7); + ForkJoinTask[] tasks = { f, g, h }; + Collections.shuffle(Arrays.asList(tasks)); + try { + invokeAll(tasks); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * invokeAll(collection) throws exception if any task does + */ + public void testAbnormalInvokeAllCollectionSingleton() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingAsyncFib f = new FailingAsyncFib(8); + AsyncFib g = new AsyncFib(9); + AsyncFib h = new AsyncFib(7); + ForkJoinTask[] tasks = { f, g, h }; + List taskList = Arrays.asList(tasks); + Collections.shuffle(taskList); + try { + invokeAll(taskList); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * ForkJoinTask.quietlyComplete returns when task completes + * normally without setting a value. The most recent value + * established by setRawResult(V) (or null by default) is returned + * from invoke. + */ + public void testQuietlyComplete() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + AsyncFib f = new AsyncFib(8); + f.quietlyComplete(); + assertEquals(8, f.number); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/FutureTaskTest.java b/jdk/test/java/util/concurrent/tck/FutureTaskTest.java new file mode 100644 index 00000000000..1e858bfdbc1 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/FutureTaskTest.java @@ -0,0 +1,866 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class FutureTaskTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(FutureTaskTest.class); + } + + void checkIsDone(Future f) { + assertTrue(f.isDone()); + assertFalse(f.cancel(false)); + assertFalse(f.cancel(true)); + if (f instanceof PublicFutureTask) { + PublicFutureTask pf = (PublicFutureTask) f; + assertEquals(1, pf.doneCount()); + assertFalse(pf.runAndReset()); + assertEquals(1, pf.doneCount()); + Object r = null; Object exInfo = null; + try { + r = f.get(); + } catch (CancellationException t) { + exInfo = CancellationException.class; + } catch (ExecutionException t) { + exInfo = t.getCause(); + } catch (Throwable t) { + threadUnexpectedException(t); + } + + // Check that run and runAndReset have no effect. + int savedRunCount = pf.runCount(); + pf.run(); + pf.runAndReset(); + assertEquals(savedRunCount, pf.runCount()); + try { + assertSame(r, f.get()); + } catch (CancellationException t) { + assertSame(exInfo, CancellationException.class); + } catch (ExecutionException t) { + assertSame(exInfo, t.getCause()); + } catch (Throwable t) { + threadUnexpectedException(t); + } + assertTrue(f.isDone()); + } + } + + void checkNotDone(Future f) { + assertFalse(f.isDone()); + assertFalse(f.isCancelled()); + if (f instanceof PublicFutureTask) { + PublicFutureTask pf = (PublicFutureTask) f; + assertEquals(0, pf.doneCount()); + assertEquals(0, pf.setCount()); + assertEquals(0, pf.setExceptionCount()); + } + } + + void checkIsRunning(Future f) { + checkNotDone(f); + if (f instanceof FutureTask) { + FutureTask ft = (FutureTask) f; + // Check that run methods do nothing + ft.run(); + if (f instanceof PublicFutureTask) { + PublicFutureTask pf = (PublicFutureTask) f; + int savedRunCount = pf.runCount(); + pf.run(); + assertFalse(pf.runAndReset()); + assertEquals(savedRunCount, pf.runCount()); + } + checkNotDone(f); + } + } + + void checkCompletedNormally(Future f, T expected) { + checkIsDone(f); + assertFalse(f.isCancelled()); + + try { + assertSame(expected, f.get()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertSame(expected, f.get(5L, SECONDS)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCancelled(Future f) { + checkIsDone(f); + assertTrue(f.isCancelled()); + + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + f.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void tryToConfuseDoneTask(PublicFutureTask pf) { + pf.set(new Object()); + pf.setException(new Error()); + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) { + pf.cancel(mayInterruptIfRunning); + } + } + + void checkCompletedAbnormally(Future f, Throwable t) { + checkIsDone(f); + assertFalse(f.isCancelled()); + + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + f.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + /** + * Subclass to expose protected methods + */ + static class PublicFutureTask extends FutureTask { + private final AtomicInteger runCount; + private final AtomicInteger doneCount = new AtomicInteger(0); + private final AtomicInteger runAndResetCount = new AtomicInteger(0); + private final AtomicInteger setCount = new AtomicInteger(0); + private final AtomicInteger setExceptionCount = new AtomicInteger(0); + public int runCount() { return runCount.get(); } + public int doneCount() { return doneCount.get(); } + public int runAndResetCount() { return runAndResetCount.get(); } + public int setCount() { return setCount.get(); } + public int setExceptionCount() { return setExceptionCount.get(); } + + PublicFutureTask(Runnable runnable) { + this(runnable, seven); + } + PublicFutureTask(Runnable runnable, Object result) { + this(runnable, result, new AtomicInteger(0)); + } + private PublicFutureTask(final Runnable runnable, Object result, + final AtomicInteger runCount) { + super(new Runnable() { + public void run() { + runCount.getAndIncrement(); + runnable.run(); + }}, result); + this.runCount = runCount; + } + PublicFutureTask(Callable callable) { + this(callable, new AtomicInteger(0)); + } + private PublicFutureTask(final Callable callable, + final AtomicInteger runCount) { + super(new Callable() { + public Object call() throws Exception { + runCount.getAndIncrement(); + return callable.call(); + }}); + this.runCount = runCount; + } + @Override public void done() { + assertTrue(isDone()); + doneCount.incrementAndGet(); + super.done(); + } + @Override public boolean runAndReset() { + runAndResetCount.incrementAndGet(); + return super.runAndReset(); + } + @Override public void set(Object x) { + setCount.incrementAndGet(); + super.set(x); + } + @Override public void setException(Throwable t) { + setExceptionCount.incrementAndGet(); + super.setException(t); + } + } + + class Counter extends CheckedRunnable { + final AtomicInteger count = new AtomicInteger(0); + public int get() { return count.get(); } + public void realRun() { + count.getAndIncrement(); + } + } + + /** + * creating a future with a null callable throws NullPointerException + */ + public void testConstructor() { + try { + new FutureTask(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * creating a future with null runnable throws NullPointerException + */ + public void testConstructor2() { + try { + new FutureTask(null, Boolean.TRUE); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * isDone is true when a task completes + */ + public void testIsDone() { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + assertFalse(task.isDone()); + task.run(); + assertTrue(task.isDone()); + checkCompletedNormally(task, Boolean.TRUE); + assertEquals(1, task.runCount()); + } + + /** + * runAndReset of a non-cancelled task succeeds + */ + public void testRunAndReset() { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + for (int i = 0; i < 3; i++) { + assertTrue(task.runAndReset()); + checkNotDone(task); + assertEquals(i + 1, task.runCount()); + assertEquals(i + 1, task.runAndResetCount()); + assertEquals(0, task.setCount()); + assertEquals(0, task.setExceptionCount()); + } + } + + /** + * runAndReset after cancellation fails + */ + public void testRunAndResetAfterCancel() { + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + assertTrue(task.cancel(mayInterruptIfRunning)); + for (int i = 0; i < 3; i++) { + assertFalse(task.runAndReset()); + assertEquals(0, task.runCount()); + assertEquals(i + 1, task.runAndResetCount()); + assertEquals(0, task.setCount()); + assertEquals(0, task.setExceptionCount()); + } + tryToConfuseDoneTask(task); + checkCancelled(task); + } + } + + /** + * setting value causes get to return it + */ + public void testSet() throws Exception { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + task.set(one); + for (int i = 0; i < 3; i++) { + assertSame(one, task.get()); + assertSame(one, task.get(LONG_DELAY_MS, MILLISECONDS)); + assertEquals(1, task.setCount()); + } + tryToConfuseDoneTask(task); + checkCompletedNormally(task, one); + assertEquals(0, task.runCount()); + } + + /** + * setException causes get to throw ExecutionException + */ + public void testSetException_get() throws Exception { + Exception nse = new NoSuchElementException(); + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + task.setException(nse); + + try { + task.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(nse, success.getCause()); + checkCompletedAbnormally(task, nse); + } + + try { + task.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(nse, success.getCause()); + checkCompletedAbnormally(task, nse); + } + + assertEquals(1, task.setExceptionCount()); + assertEquals(0, task.setCount()); + tryToConfuseDoneTask(task); + checkCompletedAbnormally(task, nse); + assertEquals(0, task.runCount()); + } + + /** + * cancel(false) before run succeeds + */ + public void testCancelBeforeRun() { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + assertTrue(task.cancel(false)); + task.run(); + assertEquals(0, task.runCount()); + assertEquals(0, task.setCount()); + assertEquals(0, task.setExceptionCount()); + assertTrue(task.isCancelled()); + assertTrue(task.isDone()); + tryToConfuseDoneTask(task); + assertEquals(0, task.runCount()); + checkCancelled(task); + } + + /** + * cancel(true) before run succeeds + */ + public void testCancelBeforeRun2() { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + assertTrue(task.cancel(true)); + task.run(); + assertEquals(0, task.runCount()); + assertEquals(0, task.setCount()); + assertEquals(0, task.setExceptionCount()); + assertTrue(task.isCancelled()); + assertTrue(task.isDone()); + tryToConfuseDoneTask(task); + assertEquals(0, task.runCount()); + checkCancelled(task); + } + + /** + * cancel(false) of a completed task fails + */ + public void testCancelAfterRun() { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + task.run(); + assertFalse(task.cancel(false)); + assertEquals(1, task.runCount()); + assertEquals(1, task.setCount()); + assertEquals(0, task.setExceptionCount()); + tryToConfuseDoneTask(task); + checkCompletedNormally(task, Boolean.TRUE); + assertEquals(1, task.runCount()); + } + + /** + * cancel(true) of a completed task fails + */ + public void testCancelAfterRun2() { + PublicFutureTask task = new PublicFutureTask(new NoOpCallable()); + task.run(); + assertFalse(task.cancel(true)); + assertEquals(1, task.runCount()); + assertEquals(1, task.setCount()); + assertEquals(0, task.setExceptionCount()); + tryToConfuseDoneTask(task); + checkCompletedNormally(task, Boolean.TRUE); + assertEquals(1, task.runCount()); + } + + /** + * cancel(true) interrupts a running task that subsequently succeeds + */ + public void testCancelInterrupt() { + final CountDownLatch pleaseCancel = new CountDownLatch(1); + final PublicFutureTask task = + new PublicFutureTask(new CheckedRunnable() { + public void realRun() { + pleaseCancel.countDown(); + try { + delay(LONG_DELAY_MS); + shouldThrow(); + } catch (InterruptedException success) {} + }}); + + Thread t = newStartedThread(task); + await(pleaseCancel); + assertTrue(task.cancel(true)); + assertTrue(task.isCancelled()); + assertTrue(task.isDone()); + awaitTermination(t); + assertEquals(1, task.runCount()); + assertEquals(1, task.setCount()); + assertEquals(0, task.setExceptionCount()); + tryToConfuseDoneTask(task); + checkCancelled(task); + } + + /** + * cancel(true) tries to interrupt a running task, but + * Thread.interrupt throws (simulating a restrictive security + * manager) + */ + public void testCancelInterrupt_ThrowsSecurityException() { + final CountDownLatch pleaseCancel = new CountDownLatch(1); + final CountDownLatch cancelled = new CountDownLatch(1); + final PublicFutureTask task = + new PublicFutureTask(new CheckedRunnable() { + public void realRun() { + pleaseCancel.countDown(); + await(cancelled); + assertFalse(Thread.interrupted()); + }}); + + final Thread t = new Thread(task) { + // Simulate a restrictive security manager. + @Override public void interrupt() { + throw new SecurityException(); + }}; + t.setDaemon(true); + t.start(); + + await(pleaseCancel); + try { + task.cancel(true); + shouldThrow(); + } catch (SecurityException expected) {} + + // We failed to deliver the interrupt, but the world retains + // its sanity, as if we had done task.cancel(false) + assertTrue(task.isCancelled()); + assertTrue(task.isDone()); + assertEquals(1, task.runCount()); + assertEquals(1, task.doneCount()); + assertEquals(0, task.setCount()); + assertEquals(0, task.setExceptionCount()); + cancelled.countDown(); + awaitTermination(t); + assertEquals(1, task.setCount()); + assertEquals(0, task.setExceptionCount()); + tryToConfuseDoneTask(task); + checkCancelled(task); + } + + /** + * cancel(true) interrupts a running task that subsequently throws + */ + public void testCancelInterrupt_taskFails() { + final CountDownLatch pleaseCancel = new CountDownLatch(1); + final PublicFutureTask task = + new PublicFutureTask(new Runnable() { + public void run() { + pleaseCancel.countDown(); + try { + delay(LONG_DELAY_MS); + threadShouldThrow(); + } catch (InterruptedException success) { + } catch (Throwable t) { threadUnexpectedException(t); } + throw new RuntimeException(); + }}); + + Thread t = newStartedThread(task); + await(pleaseCancel); + assertTrue(task.cancel(true)); + assertTrue(task.isCancelled()); + awaitTermination(t); + assertEquals(1, task.runCount()); + assertEquals(0, task.setCount()); + assertEquals(1, task.setExceptionCount()); + tryToConfuseDoneTask(task); + checkCancelled(task); + } + + /** + * cancel(false) does not interrupt a running task + */ + public void testCancelNoInterrupt() { + final CountDownLatch pleaseCancel = new CountDownLatch(1); + final CountDownLatch cancelled = new CountDownLatch(1); + final PublicFutureTask task = + new PublicFutureTask(new CheckedCallable() { + public Boolean realCall() { + pleaseCancel.countDown(); + await(cancelled); + assertFalse(Thread.interrupted()); + return Boolean.TRUE; + }}); + + Thread t = newStartedThread(task); + await(pleaseCancel); + assertTrue(task.cancel(false)); + assertTrue(task.isCancelled()); + cancelled.countDown(); + awaitTermination(t); + assertEquals(1, task.runCount()); + assertEquals(1, task.setCount()); + assertEquals(0, task.setExceptionCount()); + tryToConfuseDoneTask(task); + checkCancelled(task); + } + + /** + * run in one thread causes get in another thread to retrieve value + */ + public void testGetRun() { + final CountDownLatch pleaseRun = new CountDownLatch(2); + + final PublicFutureTask task = + new PublicFutureTask(new CheckedCallable() { + public Object realCall() { + return two; + }}); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + pleaseRun.countDown(); + assertSame(two, task.get()); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + pleaseRun.countDown(); + assertSame(two, task.get(2*LONG_DELAY_MS, MILLISECONDS)); + }}); + + await(pleaseRun); + checkNotDone(task); + assertTrue(t1.isAlive()); + assertTrue(t2.isAlive()); + task.run(); + checkCompletedNormally(task, two); + assertEquals(1, task.runCount()); + assertEquals(1, task.setCount()); + assertEquals(0, task.setExceptionCount()); + awaitTermination(t1); + awaitTermination(t2); + tryToConfuseDoneTask(task); + checkCompletedNormally(task, two); + } + + /** + * set in one thread causes get in another thread to retrieve value + */ + public void testGetSet() { + final CountDownLatch pleaseSet = new CountDownLatch(2); + + final PublicFutureTask task = + new PublicFutureTask(new CheckedCallable() { + public Object realCall() throws InterruptedException { + return two; + }}); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + pleaseSet.countDown(); + assertSame(two, task.get()); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + pleaseSet.countDown(); + assertSame(two, task.get(2*LONG_DELAY_MS, MILLISECONDS)); + }}); + + await(pleaseSet); + checkNotDone(task); + assertTrue(t1.isAlive()); + assertTrue(t2.isAlive()); + task.set(two); + assertEquals(0, task.runCount()); + assertEquals(1, task.setCount()); + assertEquals(0, task.setExceptionCount()); + tryToConfuseDoneTask(task); + checkCompletedNormally(task, two); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * Cancelling a task causes timed get in another thread to throw + * CancellationException + */ + public void testTimedGet_Cancellation() { + testTimedGet_Cancellation(false); + } + public void testTimedGet_Cancellation_interrupt() { + testTimedGet_Cancellation(true); + } + public void testTimedGet_Cancellation(final boolean mayInterruptIfRunning) { + final CountDownLatch pleaseCancel = new CountDownLatch(3); + final CountDownLatch cancelled = new CountDownLatch(1); + final Callable callable = + new CheckedCallable() { + public Object realCall() throws InterruptedException { + pleaseCancel.countDown(); + if (mayInterruptIfRunning) { + try { + delay(2*LONG_DELAY_MS); + } catch (InterruptedException success) {} + } else { + await(cancelled); + } + return two; + }}; + final PublicFutureTask task = new PublicFutureTask(callable); + + Thread t1 = new ThreadShouldThrow(CancellationException.class) { + public void realRun() throws Exception { + pleaseCancel.countDown(); + task.get(); + }}; + Thread t2 = new ThreadShouldThrow(CancellationException.class) { + public void realRun() throws Exception { + pleaseCancel.countDown(); + task.get(2*LONG_DELAY_MS, MILLISECONDS); + }}; + t1.start(); + t2.start(); + Thread t3 = newStartedThread(task); + await(pleaseCancel); + checkIsRunning(task); + task.cancel(mayInterruptIfRunning); + checkCancelled(task); + awaitTermination(t1); + awaitTermination(t2); + cancelled.countDown(); + awaitTermination(t3); + assertEquals(1, task.runCount()); + assertEquals(1, task.setCount()); + assertEquals(0, task.setExceptionCount()); + tryToConfuseDoneTask(task); + checkCancelled(task); + } + + /** + * A runtime exception in task causes get to throw ExecutionException + */ + public void testGet_ExecutionException() throws InterruptedException { + final ArithmeticException e = new ArithmeticException(); + final PublicFutureTask task = new PublicFutureTask(new Callable() { + public Object call() { + throw e; + }}); + + task.run(); + assertEquals(1, task.runCount()); + assertEquals(0, task.setCount()); + assertEquals(1, task.setExceptionCount()); + try { + task.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(e, success.getCause()); + tryToConfuseDoneTask(task); + checkCompletedAbnormally(task, success.getCause()); + } + } + + /** + * A runtime exception in task causes timed get to throw ExecutionException + */ + public void testTimedGet_ExecutionException2() throws Exception { + final ArithmeticException e = new ArithmeticException(); + final PublicFutureTask task = new PublicFutureTask(new Callable() { + public Object call() { + throw e; + }}); + + task.run(); + try { + task.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(e, success.getCause()); + tryToConfuseDoneTask(task); + checkCompletedAbnormally(task, success.getCause()); + } + } + + /** + * get is interruptible + */ + public void testGet_interruptible() { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + final FutureTask task = new FutureTask(new NoOpCallable()); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + Thread.currentThread().interrupt(); + try { + task.get(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + task.get(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + t.interrupt(); + awaitTermination(t); + checkNotDone(task); + } + + /** + * timed get is interruptible + */ + public void testTimedGet_interruptible() { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + final FutureTask task = new FutureTask(new NoOpCallable()); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + Thread.currentThread().interrupt(); + try { + task.get(2*LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + task.get(2*LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + t.interrupt(); + awaitTermination(t); + checkNotDone(task); + } + + /** + * A timed out timed get throws TimeoutException + */ + public void testGet_TimeoutException() throws Exception { + FutureTask task = new FutureTask(new NoOpCallable()); + long startTime = System.nanoTime(); + try { + task.get(timeoutMillis(), MILLISECONDS); + shouldThrow(); + } catch (TimeoutException success) { + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + } + + /** + * timed get with null TimeUnit throws NullPointerException + */ + public void testGet_NullTimeUnit() throws Exception { + FutureTask task = new FutureTask(new NoOpCallable()); + long[] timeouts = { Long.MIN_VALUE, 0L, Long.MAX_VALUE }; + + for (long timeout : timeouts) { + try { + task.get(timeout, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + task.run(); + + for (long timeout : timeouts) { + try { + task.get(timeout, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed get with most negative timeout works correctly (i.e. no + * underflow bug) + */ + public void testGet_NegativeInfinityTimeout() throws Exception { + final ExecutorService pool = Executors.newFixedThreadPool(10); + final Runnable nop = new Runnable() { public void run() {}}; + final FutureTask task = new FutureTask<>(nop, null); + final List> futures = new ArrayList<>(); + Runnable r = new Runnable() { public void run() { + for (long timeout : new long[] { 0L, -1L, Long.MIN_VALUE }) { + try { + task.get(timeout, NANOSECONDS); + shouldThrow(); + } catch (TimeoutException success) { + } catch (Throwable fail) {threadUnexpectedException(fail);}}}}; + for (int i = 0; i < 10; i++) + futures.add(pool.submit(r)); + try { + joinPool(pool); + for (Future future : futures) + checkCompletedNormally(future, null); + } finally { + task.run(); // last resort to help terminate + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java new file mode 100644 index 00000000000..8063047f8b4 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java @@ -0,0 +1,1814 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +/* + * @test + * @summary JSR-166 tck tests + * @build * + * @run junit/othervm/timeout=1000 -Djsr166.testImplementationDetails=true JSR166TestCase + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.CodeSource; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.security.SecurityPermission; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.PropertyPermission; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.Future; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.Semaphore; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestResult; +import junit.framework.TestSuite; + +/** + * Base class for JSR166 Junit TCK tests. Defines some constants, + * utility methods and classes, as well as a simple framework for + * helping to make sure that assertions failing in generated threads + * cause the associated test that generated them to itself fail (which + * JUnit does not otherwise arrange). The rules for creating such + * tests are: + * + *
            + * + *
          1. All assertions in code running in generated threads must use + * the forms {@link #threadFail}, {@link #threadAssertTrue}, {@link + * #threadAssertEquals}, or {@link #threadAssertNull}, (not + * {@code fail}, {@code assertTrue}, etc.) It is OK (but not + * particularly recommended) for other code to use these forms too. + * Only the most typically used JUnit assertion methods are defined + * this way, but enough to live with. + * + *
          2. If you override {@link #setUp} or {@link #tearDown}, make sure + * to invoke {@code super.setUp} and {@code super.tearDown} within + * them. These methods are used to clear and check for thread + * assertion failures. + * + *
          3. All delays and timeouts must use one of the constants {@code + * SHORT_DELAY_MS}, {@code SMALL_DELAY_MS}, {@code MEDIUM_DELAY_MS}, + * {@code LONG_DELAY_MS}. The idea here is that a SHORT is always + * discriminable from zero time, and always allows enough time for the + * small amounts of computation (creating a thread, calling a few + * methods, etc) needed to reach a timeout point. Similarly, a SMALL + * is always discriminable as larger than SHORT and smaller than + * MEDIUM. And so on. These constants are set to conservative values, + * but even so, if there is ever any doubt, they can all be increased + * in one spot to rerun tests on slower platforms. + * + *
          4. All threads generated must be joined inside each test case + * method (or {@code fail} to do so) before returning from the + * method. The {@code joinPool} method can be used to do this when + * using Executors. + * + *
          + * + *

          Other notes + *

            + * + *
          • Usually, there is one testcase method per JSR166 method + * covering "normal" operation, and then as many exception-testing + * methods as there are exceptions the method can throw. Sometimes + * there are multiple tests per JSR166 method when the different + * "normal" behaviors differ significantly. And sometimes testcases + * cover multiple methods when they cannot be tested in isolation. + * + *
          • The documentation style for testcases is to provide as javadoc + * a simple sentence or two describing the property that the testcase + * method purports to test. The javadocs do not say anything about how + * the property is tested. To find out, read the code. + * + *
          • These tests are "conformance tests", and do not attempt to + * test throughput, latency, scalability or other performance factors + * (see the separate "jtreg" tests for a set intended to check these + * for the most central aspects of functionality.) So, most tests use + * the smallest sensible numbers of threads, collection sizes, etc + * needed to check basic conformance. + * + *
          • The test classes currently do not declare inclusion in + * any particular package to simplify things for people integrating + * them in TCK test suites. + * + *
          • As a convenience, the {@code main} of this class (JSR166TestCase) + * runs all JSR166 unit tests. + * + *
          + */ +public class JSR166TestCase extends TestCase { + private static final boolean useSecurityManager = + Boolean.getBoolean("jsr166.useSecurityManager"); + + protected static final boolean expensiveTests = + Boolean.getBoolean("jsr166.expensiveTests"); + + /** + * If true, also run tests that are not part of the official tck + * because they test unspecified implementation details. + */ + protected static final boolean testImplementationDetails = + Boolean.getBoolean("jsr166.testImplementationDetails"); + + /** + * If true, report on stdout all "slow" tests, that is, ones that + * take more than profileThreshold milliseconds to execute. + */ + private static final boolean profileTests = + Boolean.getBoolean("jsr166.profileTests"); + + /** + * The number of milliseconds that tests are permitted for + * execution without being reported, when profileTests is set. + */ + private static final long profileThreshold = + Long.getLong("jsr166.profileThreshold", 100); + + /** + * The number of repetitions per test (for tickling rare bugs). + */ + private static final int runsPerTest = + Integer.getInteger("jsr166.runsPerTest", 1); + + /** + * The number of repetitions of the test suite (for finding leaks?). + */ + private static final int suiteRuns = + Integer.getInteger("jsr166.suiteRuns", 1); + + /** + * The scaling factor to apply to standard delays used in tests. + */ + private static final int delayFactor = + Integer.getInteger("jsr166.delay.factor", 1); + + public JSR166TestCase() { super(); } + public JSR166TestCase(String name) { super(name); } + + /** + * A filter for tests to run, matching strings of the form + * methodName(className), e.g. "testInvokeAll5(ForkJoinPoolTest)" + * Usefully combined with jsr166.runsPerTest. + */ + private static final Pattern methodFilter = methodFilter(); + + private static Pattern methodFilter() { + String regex = System.getProperty("jsr166.methodFilter"); + return (regex == null) ? null : Pattern.compile(regex); + } + + // Instrumentation to debug very rare, but very annoying hung test runs. + static volatile TestCase currentTestCase; + // static volatile int currentRun = 0; + static { + Runnable checkForWedgedTest = new Runnable() { public void run() { + // Avoid spurious reports with enormous runsPerTest. + // A single test case run should never take more than 1 second. + // But let's cap it at the high end too ... + final int timeoutMinutes = + Math.min(15, Math.max(runsPerTest / 60, 1)); + for (TestCase lastTestCase = currentTestCase;;) { + try { MINUTES.sleep(timeoutMinutes); } + catch (InterruptedException unexpected) { break; } + if (lastTestCase == currentTestCase) { + System.err.printf( + "Looks like we're stuck running test: %s%n", + lastTestCase); +// System.err.printf( +// "Looks like we're stuck running test: %s (%d/%d)%n", +// lastTestCase, currentRun, runsPerTest); +// System.err.println("availableProcessors=" + +// Runtime.getRuntime().availableProcessors()); +// System.err.printf("cpu model = %s%n", cpuModel()); + dumpTestThreads(); + // one stack dump is probably enough; more would be spam + break; + } + lastTestCase = currentTestCase; + }}}; + Thread thread = new Thread(checkForWedgedTest, "checkForWedgedTest"); + thread.setDaemon(true); + thread.start(); + } + +// public static String cpuModel() { +// try { +// Matcher matcher = Pattern.compile("model name\\s*: (.*)") +// .matcher(new String( +// Files.readAllBytes(Paths.get("/proc/cpuinfo")), "UTF-8")); +// matcher.find(); +// return matcher.group(1); +// } catch (Exception ex) { return null; } +// } + + public void runBare() throws Throwable { + currentTestCase = this; + if (methodFilter == null + || methodFilter.matcher(toString()).find()) + super.runBare(); + } + + protected void runTest() throws Throwable { + for (int i = 0; i < runsPerTest; i++) { + // currentRun = i; + if (profileTests) + runTestProfiled(); + else + super.runTest(); + } + } + + protected void runTestProfiled() throws Throwable { + for (int i = 0; i < 2; i++) { + long startTime = System.nanoTime(); + super.runTest(); + long elapsedMillis = millisElapsedSince(startTime); + if (elapsedMillis < profileThreshold) + break; + // Never report first run of any test; treat it as a + // warmup run, notably to trigger all needed classloading, + if (i > 0) + System.out.printf("%n%s: %d%n", toString(), elapsedMillis); + } + } + + /** + * Runs all JSR166 unit tests using junit.textui.TestRunner. + */ + public static void main(String[] args) { + main(suite(), args); + } + + static class PithyResultPrinter extends junit.textui.ResultPrinter { + PithyResultPrinter(java.io.PrintStream writer) { super(writer); } + long runTime; + public void startTest(Test test) {} + protected void printHeader(long runTime) { + this.runTime = runTime; // defer printing for later + } + protected void printFooter(TestResult result) { + if (result.wasSuccessful()) { + getWriter().println("OK (" + result.runCount() + " tests)" + + " Time: " + elapsedTimeAsString(runTime)); + } else { + getWriter().println("Time: " + elapsedTimeAsString(runTime)); + super.printFooter(result); + } + } + } + + /** + * Returns a TestRunner that doesn't bother with unnecessary + * fluff, like printing a "." for each test case. + */ + static junit.textui.TestRunner newPithyTestRunner() { + junit.textui.TestRunner runner = new junit.textui.TestRunner(); + runner.setPrinter(new PithyResultPrinter(System.out)); + return runner; + } + + /** + * Runs all unit tests in the given test suite. + * Actual behavior influenced by jsr166.* system properties. + */ + static void main(Test suite, String[] args) { + if (useSecurityManager) { + System.err.println("Setting a permissive security manager"); + Policy.setPolicy(permissivePolicy()); + System.setSecurityManager(new SecurityManager()); + } + for (int i = 0; i < suiteRuns; i++) { + TestResult result = newPithyTestRunner().doRun(suite); + if (!result.wasSuccessful()) + System.exit(1); + System.gc(); + System.runFinalization(); + } + } + + public static TestSuite newTestSuite(Object... suiteOrClasses) { + TestSuite suite = new TestSuite(); + for (Object suiteOrClass : suiteOrClasses) { + if (suiteOrClass instanceof TestSuite) + suite.addTest((TestSuite) suiteOrClass); + else if (suiteOrClass instanceof Class) + suite.addTest(new TestSuite((Class) suiteOrClass)); + else + throw new ClassCastException("not a test suite or class"); + } + return suite; + } + + public static void addNamedTestClasses(TestSuite suite, + String... testClassNames) { + for (String testClassName : testClassNames) { + try { + Class testClass = Class.forName(testClassName); + Method m = testClass.getDeclaredMethod("suite", + new Class[0]); + suite.addTest(newTestSuite((Test)m.invoke(null))); + } catch (Exception e) { + throw new Error("Missing test class", e); + } + } + } + + public static final double JAVA_CLASS_VERSION; + public static final String JAVA_SPECIFICATION_VERSION; + static { + try { + JAVA_CLASS_VERSION = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Double run() { + return Double.valueOf(System.getProperty("java.class.version"));}}); + JAVA_SPECIFICATION_VERSION = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public String run() { + return System.getProperty("java.specification.version");}}); + } catch (Throwable t) { + throw new Error(t); + } + } + + public static boolean atLeastJava6() { return JAVA_CLASS_VERSION >= 50.0; } + public static boolean atLeastJava7() { return JAVA_CLASS_VERSION >= 51.0; } + public static boolean atLeastJava8() { return JAVA_CLASS_VERSION >= 52.0; } + public static boolean atLeastJava9() { + return JAVA_CLASS_VERSION >= 53.0 + // As of 2015-09, java9 still uses 52.0 class file version + || JAVA_SPECIFICATION_VERSION.matches("^(1\\.)?(9|[0-9][0-9])$"); + } + public static boolean atLeastJava10() { + return JAVA_CLASS_VERSION >= 54.0 + || JAVA_SPECIFICATION_VERSION.matches("^(1\\.)?[0-9][0-9]$"); + } + + /** + * Collects all JSR166 unit tests as one suite. + */ + public static Test suite() { + // Java7+ test classes + TestSuite suite = newTestSuite( + ForkJoinPoolTest.suite(), + ForkJoinTaskTest.suite(), + RecursiveActionTest.suite(), + RecursiveTaskTest.suite(), + LinkedTransferQueueTest.suite(), + PhaserTest.suite(), + ThreadLocalRandomTest.suite(), + AbstractExecutorServiceTest.suite(), + AbstractQueueTest.suite(), + AbstractQueuedSynchronizerTest.suite(), + AbstractQueuedLongSynchronizerTest.suite(), + ArrayBlockingQueueTest.suite(), + ArrayDequeTest.suite(), + AtomicBooleanTest.suite(), + AtomicIntegerArrayTest.suite(), + AtomicIntegerFieldUpdaterTest.suite(), + AtomicIntegerTest.suite(), + AtomicLongArrayTest.suite(), + AtomicLongFieldUpdaterTest.suite(), + AtomicLongTest.suite(), + AtomicMarkableReferenceTest.suite(), + AtomicReferenceArrayTest.suite(), + AtomicReferenceFieldUpdaterTest.suite(), + AtomicReferenceTest.suite(), + AtomicStampedReferenceTest.suite(), + ConcurrentHashMapTest.suite(), + ConcurrentLinkedDequeTest.suite(), + ConcurrentLinkedQueueTest.suite(), + ConcurrentSkipListMapTest.suite(), + ConcurrentSkipListSubMapTest.suite(), + ConcurrentSkipListSetTest.suite(), + ConcurrentSkipListSubSetTest.suite(), + CopyOnWriteArrayListTest.suite(), + CopyOnWriteArraySetTest.suite(), + CountDownLatchTest.suite(), + CyclicBarrierTest.suite(), + DelayQueueTest.suite(), + EntryTest.suite(), + ExchangerTest.suite(), + ExecutorsTest.suite(), + ExecutorCompletionServiceTest.suite(), + FutureTaskTest.suite(), + LinkedBlockingDequeTest.suite(), + LinkedBlockingQueueTest.suite(), + LinkedListTest.suite(), + LockSupportTest.suite(), + PriorityBlockingQueueTest.suite(), + PriorityQueueTest.suite(), + ReentrantLockTest.suite(), + ReentrantReadWriteLockTest.suite(), + ScheduledExecutorTest.suite(), + ScheduledExecutorSubclassTest.suite(), + SemaphoreTest.suite(), + SynchronousQueueTest.suite(), + SystemTest.suite(), + ThreadLocalTest.suite(), + ThreadPoolExecutorTest.suite(), + ThreadPoolExecutorSubclassTest.suite(), + ThreadTest.suite(), + TimeUnitTest.suite(), + TreeMapTest.suite(), + TreeSetTest.suite(), + TreeSubMapTest.suite(), + TreeSubSetTest.suite()); + + // Java8+ test classes + if (atLeastJava8()) { + String[] java8TestClassNames = { + "Atomic8Test", + "CompletableFutureTest", + "ConcurrentHashMap8Test", + "CountedCompleterTest", + "DoubleAccumulatorTest", + "DoubleAdderTest", + "ForkJoinPool8Test", + "ForkJoinTask8Test", + "LongAccumulatorTest", + "LongAdderTest", + "SplittableRandomTest", + "StampedLockTest", + "SubmissionPublisherTest", + "ThreadLocalRandom8Test", + }; + addNamedTestClasses(suite, java8TestClassNames); + } + + // Java9+ test classes + if (atLeastJava9()) { + String[] java9TestClassNames = { + // Currently empty, but expecting varhandle tests + }; + addNamedTestClasses(suite, java9TestClassNames); + } + + return suite; + } + + /** Returns list of junit-style test method names in given class. */ + public static ArrayList testMethodNames(Class testClass) { + Method[] methods = testClass.getDeclaredMethods(); + ArrayList names = new ArrayList(methods.length); + for (Method method : methods) { + if (method.getName().startsWith("test") + && Modifier.isPublic(method.getModifiers()) + // method.getParameterCount() requires jdk8+ + && method.getParameterTypes().length == 0) { + names.add(method.getName()); + } + } + return names; + } + + /** + * Returns junit-style testSuite for the given test class, but + * parameterized by passing extra data to each test. + */ + public static Test parameterizedTestSuite + (Class testClass, + Class dataClass, + ExtraData data) { + try { + TestSuite suite = new TestSuite(); + Constructor c = + testClass.getDeclaredConstructor(dataClass, String.class); + for (String methodName : testMethodNames(testClass)) + suite.addTest((Test) c.newInstance(data, methodName)); + return suite; + } catch (Exception e) { + throw new Error(e); + } + } + + /** + * Returns junit-style testSuite for the jdk8 extension of the + * given test class, but parameterized by passing extra data to + * each test. Uses reflection to allow compilation in jdk7. + */ + public static Test jdk8ParameterizedTestSuite + (Class testClass, + Class dataClass, + ExtraData data) { + if (atLeastJava8()) { + String name = testClass.getName(); + String name8 = name.replaceAll("Test$", "8Test"); + if (name.equals(name8)) throw new Error(name); + try { + return (Test) + Class.forName(name8) + .getMethod("testSuite", new Class[] { dataClass }) + .invoke(null, data); + } catch (Exception e) { + throw new Error(e); + } + } else { + return new TestSuite(); + } + } + + // Delays for timing-dependent tests, in milliseconds. + + public static long SHORT_DELAY_MS; + public static long SMALL_DELAY_MS; + public static long MEDIUM_DELAY_MS; + public static long LONG_DELAY_MS; + + /** + * Returns the shortest timed delay. This can be scaled up for + * slow machines using the jsr166.delay.factor system property. + */ + protected long getShortDelay() { + return 50 * delayFactor; + } + + /** + * Sets delays as multiples of SHORT_DELAY. + */ + protected void setDelays() { + SHORT_DELAY_MS = getShortDelay(); + SMALL_DELAY_MS = SHORT_DELAY_MS * 5; + MEDIUM_DELAY_MS = SHORT_DELAY_MS * 10; + LONG_DELAY_MS = SHORT_DELAY_MS * 200; + } + + /** + * Returns a timeout in milliseconds to be used in tests that + * verify that operations block or time out. + */ + long timeoutMillis() { + return SHORT_DELAY_MS / 4; + } + + /** + * Returns a new Date instance representing a time at least + * delayMillis milliseconds in the future. + */ + Date delayedDate(long delayMillis) { + // Add 1 because currentTimeMillis is known to round into the past. + return new Date(System.currentTimeMillis() + delayMillis + 1); + } + + /** + * The first exception encountered if any threadAssertXXX method fails. + */ + private final AtomicReference threadFailure + = new AtomicReference(null); + + /** + * Records an exception so that it can be rethrown later in the test + * harness thread, triggering a test case failure. Only the first + * failure is recorded; subsequent calls to this method from within + * the same test have no effect. + */ + public void threadRecordFailure(Throwable t) { + System.err.println(t); + dumpTestThreads(); + threadFailure.compareAndSet(null, t); + } + + public void setUp() { + setDelays(); + } + + void tearDownFail(String format, Object... args) { + String msg = toString() + ": " + String.format(format, args); + System.err.println(msg); + dumpTestThreads(); + throw new AssertionFailedError(msg); + } + + /** + * Extra checks that get done for all test cases. + * + * Triggers test case failure if any thread assertions have failed, + * by rethrowing, in the test harness thread, any exception recorded + * earlier by threadRecordFailure. + * + * Triggers test case failure if interrupt status is set in the main thread. + */ + public void tearDown() throws Exception { + Throwable t = threadFailure.getAndSet(null); + if (t != null) { + if (t instanceof Error) + throw (Error) t; + else if (t instanceof RuntimeException) + throw (RuntimeException) t; + else if (t instanceof Exception) + throw (Exception) t; + else { + AssertionFailedError afe = + new AssertionFailedError(t.toString()); + afe.initCause(t); + throw afe; + } + } + + if (Thread.interrupted()) + tearDownFail("interrupt status set in main thread"); + + checkForkJoinPoolThreadLeaks(); + } + + /** + * Finds missing PoolCleaners + */ + void checkForkJoinPoolThreadLeaks() throws InterruptedException { + Thread[] survivors = new Thread[7]; + int count = Thread.enumerate(survivors); + for (int i = 0; i < count; i++) { + Thread thread = survivors[i]; + String name = thread.getName(); + if (name.startsWith("ForkJoinPool-")) { + // give thread some time to terminate + thread.join(LONG_DELAY_MS); + if (thread.isAlive()) + tearDownFail("Found leaked ForkJoinPool thread thread=%s", + thread); + } + } + + if (!ForkJoinPool.commonPool() + .awaitQuiescence(LONG_DELAY_MS, MILLISECONDS)) + tearDownFail("ForkJoin common pool thread stuck"); + } + + /** + * Just like fail(reason), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. + */ + public void threadFail(String reason) { + try { + fail(reason); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; + } + } + + /** + * Just like assertTrue(b), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. + */ + public void threadAssertTrue(boolean b) { + try { + assertTrue(b); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; + } + } + + /** + * Just like assertFalse(b), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. + */ + public void threadAssertFalse(boolean b) { + try { + assertFalse(b); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; + } + } + + /** + * Just like assertNull(x), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. + */ + public void threadAssertNull(Object x) { + try { + assertNull(x); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; + } + } + + /** + * Just like assertEquals(x, y), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. + */ + public void threadAssertEquals(long x, long y) { + try { + assertEquals(x, y); + } catch (AssertionFailedError t) { + threadRecordFailure(t); + throw t; + } + } + + /** + * Just like assertEquals(x, y), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. + */ + public void threadAssertEquals(Object x, Object y) { + try { + assertEquals(x, y); + } catch (AssertionFailedError fail) { + threadRecordFailure(fail); + throw fail; + } catch (Throwable fail) { + threadUnexpectedException(fail); + } + } + + /** + * Just like assertSame(x, y), but additionally recording (using + * threadRecordFailure) any AssertionFailedError thrown, so that + * the current testcase will fail. + */ + public void threadAssertSame(Object x, Object y) { + try { + assertSame(x, y); + } catch (AssertionFailedError fail) { + threadRecordFailure(fail); + throw fail; + } + } + + /** + * Calls threadFail with message "should throw exception". + */ + public void threadShouldThrow() { + threadFail("should throw exception"); + } + + /** + * Calls threadFail with message "should throw" + exceptionName. + */ + public void threadShouldThrow(String exceptionName) { + threadFail("should throw " + exceptionName); + } + + /** + * Records the given exception using {@link #threadRecordFailure}, + * then rethrows the exception, wrapping it in an + * AssertionFailedError if necessary. + */ + public void threadUnexpectedException(Throwable t) { + threadRecordFailure(t); + t.printStackTrace(); + if (t instanceof RuntimeException) + throw (RuntimeException) t; + else if (t instanceof Error) + throw (Error) t; + else { + AssertionFailedError afe = + new AssertionFailedError("unexpected exception: " + t); + afe.initCause(t); + throw afe; + } + } + + /** + * Delays, via Thread.sleep, for the given millisecond delay, but + * if the sleep is shorter than specified, may re-sleep or yield + * until time elapses. Ensures that the given time, as measured + * by System.nanoTime(), has elapsed. + */ + static void delay(long millis) throws InterruptedException { + long nanos = millis * (1000 * 1000); + final long wakeupTime = System.nanoTime() + nanos; + do { + if (millis > 0L) + Thread.sleep(millis); + else // too short to sleep + Thread.yield(); + nanos = wakeupTime - System.nanoTime(); + millis = nanos / (1000 * 1000); + } while (nanos >= 0L); + } + + /** + * Allows use of try-with-resources with per-test thread pools. + */ + class PoolCleaner implements AutoCloseable { + private final ExecutorService pool; + public PoolCleaner(ExecutorService pool) { this.pool = pool; } + public void close() { joinPool(pool); } + } + + /** + * An extension of PoolCleaner that has an action to release the pool. + */ + class PoolCleanerWithReleaser extends PoolCleaner { + private final Runnable releaser; + public PoolCleanerWithReleaser(ExecutorService pool, Runnable releaser) { + super(pool); + this.releaser = releaser; + } + public void close() { + try { + releaser.run(); + } finally { + super.close(); + } + } + } + + PoolCleaner cleaner(ExecutorService pool) { + return new PoolCleaner(pool); + } + + PoolCleaner cleaner(ExecutorService pool, Runnable releaser) { + return new PoolCleanerWithReleaser(pool, releaser); + } + + PoolCleaner cleaner(ExecutorService pool, CountDownLatch latch) { + return new PoolCleanerWithReleaser(pool, releaser(latch)); + } + + Runnable releaser(final CountDownLatch latch) { + return new Runnable() { public void run() { + do { latch.countDown(); } + while (latch.getCount() > 0); + }}; + } + + /** + * Waits out termination of a thread pool or fails doing so. + */ + void joinPool(ExecutorService pool) { + try { + pool.shutdown(); + if (!pool.awaitTermination(2 * LONG_DELAY_MS, MILLISECONDS)) { + try { + threadFail("ExecutorService " + pool + + " did not terminate in a timely manner"); + } finally { + // last resort, for the benefit of subsequent tests + pool.shutdownNow(); + pool.awaitTermination(MEDIUM_DELAY_MS, MILLISECONDS); + } + } + } catch (SecurityException ok) { + // Allowed in case test doesn't have privs + } catch (InterruptedException fail) { + threadFail("Unexpected InterruptedException"); + } + } + + /** Like Runnable, but with the freedom to throw anything */ + interface Action { public void run() throws Throwable; } + + /** + * Runs all the given actions in parallel, failing if any fail. + * Useful for running multiple variants of tests that are + * necessarily individually slow because they must block. + */ + void testInParallel(Action ... actions) { + ExecutorService pool = Executors.newCachedThreadPool(); + try (PoolCleaner cleaner = cleaner(pool)) { + ArrayList> futures = new ArrayList<>(actions.length); + for (final Action action : actions) + futures.add(pool.submit(new CheckedRunnable() { + public void realRun() throws Throwable { action.run();}})); + for (Future future : futures) + try { + assertNull(future.get(LONG_DELAY_MS, MILLISECONDS)); + } catch (ExecutionException ex) { + threadUnexpectedException(ex.getCause()); + } catch (Exception ex) { + threadUnexpectedException(ex); + } + } + } + + /** + * A debugging tool to print stack traces of most threads, as jstack does. + * Uninteresting threads are filtered out. + */ + static void dumpTestThreads() { + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + System.err.println("------ stacktrace dump start ------"); + for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) { + String name = info.getThreadName(); + if ("Signal Dispatcher".equals(name)) + continue; + if ("Reference Handler".equals(name) + && info.getLockName().startsWith("java.lang.ref.Reference$Lock")) + continue; + if ("Finalizer".equals(name) + && info.getLockName().startsWith("java.lang.ref.ReferenceQueue$Lock")) + continue; + if ("checkForWedgedTest".equals(name)) + continue; + System.err.print(info); + } + System.err.println("------ stacktrace dump end ------"); + } + + /** + * Checks that thread does not terminate within the default + * millisecond delay of {@code timeoutMillis()}. + */ + void assertThreadStaysAlive(Thread thread) { + assertThreadStaysAlive(thread, timeoutMillis()); + } + + /** + * Checks that thread does not terminate within the given millisecond delay. + */ + void assertThreadStaysAlive(Thread thread, long millis) { + try { + // No need to optimize the failing case via Thread.join. + delay(millis); + assertTrue(thread.isAlive()); + } catch (InterruptedException fail) { + threadFail("Unexpected InterruptedException"); + } + } + + /** + * Checks that the threads do not terminate within the default + * millisecond delay of {@code timeoutMillis()}. + */ + void assertThreadsStayAlive(Thread... threads) { + assertThreadsStayAlive(timeoutMillis(), threads); + } + + /** + * Checks that the threads do not terminate within the given millisecond delay. + */ + void assertThreadsStayAlive(long millis, Thread... threads) { + try { + // No need to optimize the failing case via Thread.join. + delay(millis); + for (Thread thread : threads) + assertTrue(thread.isAlive()); + } catch (InterruptedException fail) { + threadFail("Unexpected InterruptedException"); + } + } + + /** + * Checks that future.get times out, with the default timeout of + * {@code timeoutMillis()}. + */ + void assertFutureTimesOut(Future future) { + assertFutureTimesOut(future, timeoutMillis()); + } + + /** + * Checks that future.get times out, with the given millisecond timeout. + */ + void assertFutureTimesOut(Future future, long timeoutMillis) { + long startTime = System.nanoTime(); + try { + future.get(timeoutMillis, MILLISECONDS); + shouldThrow(); + } catch (TimeoutException success) { + } catch (Exception fail) { + threadUnexpectedException(fail); + } finally { future.cancel(true); } + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + } + + /** + * Fails with message "should throw exception". + */ + public void shouldThrow() { + fail("Should throw exception"); + } + + /** + * Fails with message "should throw " + exceptionName. + */ + public void shouldThrow(String exceptionName) { + fail("Should throw " + exceptionName); + } + + /** + * The number of elements to place in collections, arrays, etc. + */ + public static final int SIZE = 20; + + // Some convenient Integer constants + + public static final Integer zero = new Integer(0); + public static final Integer one = new Integer(1); + public static final Integer two = new Integer(2); + public static final Integer three = new Integer(3); + public static final Integer four = new Integer(4); + public static final Integer five = new Integer(5); + public static final Integer six = new Integer(6); + public static final Integer seven = new Integer(7); + public static final Integer eight = new Integer(8); + public static final Integer nine = new Integer(9); + public static final Integer m1 = new Integer(-1); + public static final Integer m2 = new Integer(-2); + public static final Integer m3 = new Integer(-3); + public static final Integer m4 = new Integer(-4); + public static final Integer m5 = new Integer(-5); + public static final Integer m6 = new Integer(-6); + public static final Integer m10 = new Integer(-10); + + /** + * Runs Runnable r with a security policy that permits precisely + * the specified permissions. If there is no current security + * manager, the runnable is run twice, both with and without a + * security manager. We require that any security manager permit + * getPolicy/setPolicy. + */ + public void runWithPermissions(Runnable r, Permission... permissions) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + r.run(); + } + runWithSecurityManagerWithPermissions(r, permissions); + } + + /** + * Runs Runnable r with a security policy that permits precisely + * the specified permissions. If there is no current security + * manager, a temporary one is set for the duration of the + * Runnable. We require that any security manager permit + * getPolicy/setPolicy. + */ + public void runWithSecurityManagerWithPermissions(Runnable r, + Permission... permissions) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + Policy savedPolicy = Policy.getPolicy(); + try { + Policy.setPolicy(permissivePolicy()); + System.setSecurityManager(new SecurityManager()); + runWithSecurityManagerWithPermissions(r, permissions); + } finally { + System.setSecurityManager(null); + Policy.setPolicy(savedPolicy); + } + } else { + Policy savedPolicy = Policy.getPolicy(); + AdjustablePolicy policy = new AdjustablePolicy(permissions); + Policy.setPolicy(policy); + + try { + r.run(); + } finally { + policy.addPermission(new SecurityPermission("setPolicy")); + Policy.setPolicy(savedPolicy); + } + } + } + + /** + * Runs a runnable without any permissions. + */ + public void runWithoutPermissions(Runnable r) { + runWithPermissions(r); + } + + /** + * A security policy where new permissions can be dynamically added + * or all cleared. + */ + public static class AdjustablePolicy extends java.security.Policy { + Permissions perms = new Permissions(); + AdjustablePolicy(Permission... permissions) { + for (Permission permission : permissions) + perms.add(permission); + } + void addPermission(Permission perm) { perms.add(perm); } + void clearPermissions() { perms = new Permissions(); } + public PermissionCollection getPermissions(CodeSource cs) { + return perms; + } + public PermissionCollection getPermissions(ProtectionDomain pd) { + return perms; + } + public boolean implies(ProtectionDomain pd, Permission p) { + return perms.implies(p); + } + public void refresh() {} + public String toString() { + List ps = new ArrayList(); + for (Enumeration e = perms.elements(); e.hasMoreElements();) + ps.add(e.nextElement()); + return "AdjustablePolicy with permissions " + ps; + } + } + + /** + * Returns a policy containing all the permissions we ever need. + */ + public static Policy permissivePolicy() { + return new AdjustablePolicy + // Permissions j.u.c. needs directly + (new RuntimePermission("modifyThread"), + new RuntimePermission("getClassLoader"), + new RuntimePermission("setContextClassLoader"), + // Permissions needed to change permissions! + new SecurityPermission("getPolicy"), + new SecurityPermission("setPolicy"), + new RuntimePermission("setSecurityManager"), + // Permissions needed by the junit test harness + new RuntimePermission("accessDeclaredMembers"), + new PropertyPermission("*", "read"), + new java.io.FilePermission("<>", "read")); + } + + /** + * Sleeps until the given time has elapsed. + * Throws AssertionFailedError if interrupted. + */ + void sleep(long millis) { + try { + delay(millis); + } catch (InterruptedException fail) { + AssertionFailedError afe = + new AssertionFailedError("Unexpected InterruptedException"); + afe.initCause(fail); + throw afe; + } + } + + /** + * Spin-waits up to the specified number of milliseconds for the given + * thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING. + */ + void waitForThreadToEnterWaitState(Thread thread, long timeoutMillis) { + long startTime = System.nanoTime(); + for (;;) { + Thread.State s = thread.getState(); + if (s == Thread.State.BLOCKED || + s == Thread.State.WAITING || + s == Thread.State.TIMED_WAITING) + return; + else if (s == Thread.State.TERMINATED) + fail("Unexpected thread termination"); + else if (millisElapsedSince(startTime) > timeoutMillis) { + threadAssertTrue(thread.isAlive()); + return; + } + Thread.yield(); + } + } + + /** + * Waits up to LONG_DELAY_MS for the given thread to enter a wait + * state: BLOCKED, WAITING, or TIMED_WAITING. + */ + void waitForThreadToEnterWaitState(Thread thread) { + waitForThreadToEnterWaitState(thread, LONG_DELAY_MS); + } + + /** + * Returns the number of milliseconds since time given by + * startNanoTime, which must have been previously returned from a + * call to {@link System#nanoTime()}. + */ + static long millisElapsedSince(long startNanoTime) { + return NANOSECONDS.toMillis(System.nanoTime() - startNanoTime); + } + +// void assertTerminatesPromptly(long timeoutMillis, Runnable r) { +// long startTime = System.nanoTime(); +// try { +// r.run(); +// } catch (Throwable fail) { threadUnexpectedException(fail); } +// if (millisElapsedSince(startTime) > timeoutMillis/2) +// throw new AssertionFailedError("did not return promptly"); +// } + +// void assertTerminatesPromptly(Runnable r) { +// assertTerminatesPromptly(LONG_DELAY_MS/2, r); +// } + + /** + * Checks that timed f.get() returns the expected value, and does not + * wait for the timeout to elapse before returning. + */ + void checkTimedGet(Future f, T expectedValue, long timeoutMillis) { + long startTime = System.nanoTime(); + try { + assertEquals(expectedValue, f.get(timeoutMillis, MILLISECONDS)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + if (millisElapsedSince(startTime) > timeoutMillis/2) + throw new AssertionFailedError("timed get did not return promptly"); + } + + void checkTimedGet(Future f, T expectedValue) { + checkTimedGet(f, expectedValue, LONG_DELAY_MS); + } + + /** + * Returns a new started daemon Thread running the given runnable. + */ + Thread newStartedThread(Runnable runnable) { + Thread t = new Thread(runnable); + t.setDaemon(true); + t.start(); + return t; + } + + /** + * Waits for the specified time (in milliseconds) for the thread + * to terminate (using {@link Thread#join(long)}), else interrupts + * the thread (in the hope that it may terminate later) and fails. + */ + void awaitTermination(Thread t, long timeoutMillis) { + try { + t.join(timeoutMillis); + } catch (InterruptedException fail) { + threadUnexpectedException(fail); + } finally { + if (t.getState() != Thread.State.TERMINATED) { + t.interrupt(); + threadFail("timed out waiting for thread to terminate"); + } + } + } + + /** + * Waits for LONG_DELAY_MS milliseconds for the thread to + * terminate (using {@link Thread#join(long)}), else interrupts + * the thread (in the hope that it may terminate later) and fails. + */ + void awaitTermination(Thread t) { + awaitTermination(t, LONG_DELAY_MS); + } + + // Some convenient Runnable classes + + public abstract class CheckedRunnable implements Runnable { + protected abstract void realRun() throws Throwable; + + public final void run() { + try { + realRun(); + } catch (Throwable fail) { + threadUnexpectedException(fail); + } + } + } + + public abstract class RunnableShouldThrow implements Runnable { + protected abstract void realRun() throws Throwable; + + final Class exceptionClass; + + RunnableShouldThrow(Class exceptionClass) { + this.exceptionClass = exceptionClass; + } + + public final void run() { + try { + realRun(); + threadShouldThrow(exceptionClass.getSimpleName()); + } catch (Throwable t) { + if (! exceptionClass.isInstance(t)) + threadUnexpectedException(t); + } + } + } + + public abstract class ThreadShouldThrow extends Thread { + protected abstract void realRun() throws Throwable; + + final Class exceptionClass; + + ThreadShouldThrow(Class exceptionClass) { + this.exceptionClass = exceptionClass; + } + + public final void run() { + try { + realRun(); + threadShouldThrow(exceptionClass.getSimpleName()); + } catch (Throwable t) { + if (! exceptionClass.isInstance(t)) + threadUnexpectedException(t); + } + } + } + + public abstract class CheckedInterruptedRunnable implements Runnable { + protected abstract void realRun() throws Throwable; + + public final void run() { + try { + realRun(); + threadShouldThrow("InterruptedException"); + } catch (InterruptedException success) { + threadAssertFalse(Thread.interrupted()); + } catch (Throwable fail) { + threadUnexpectedException(fail); + } + } + } + + public abstract class CheckedCallable implements Callable { + protected abstract T realCall() throws Throwable; + + public final T call() { + try { + return realCall(); + } catch (Throwable fail) { + threadUnexpectedException(fail); + return null; + } + } + } + + public abstract class CheckedInterruptedCallable + implements Callable { + protected abstract T realCall() throws Throwable; + + public final T call() { + try { + T result = realCall(); + threadShouldThrow("InterruptedException"); + return result; + } catch (InterruptedException success) { + threadAssertFalse(Thread.interrupted()); + } catch (Throwable fail) { + threadUnexpectedException(fail); + } + return null; + } + } + + public static class NoOpRunnable implements Runnable { + public void run() {} + } + + public static class NoOpCallable implements Callable { + public Object call() { return Boolean.TRUE; } + } + + public static final String TEST_STRING = "a test string"; + + public static class StringTask implements Callable { + final String value; + public StringTask() { this(TEST_STRING); } + public StringTask(String value) { this.value = value; } + public String call() { return value; } + } + + public Callable latchAwaitingStringTask(final CountDownLatch latch) { + return new CheckedCallable() { + protected String realCall() { + try { + latch.await(); + } catch (InterruptedException quittingTime) {} + return TEST_STRING; + }}; + } + + public Runnable countDowner(final CountDownLatch latch) { + return new CheckedRunnable() { + public void realRun() throws InterruptedException { + latch.countDown(); + }}; + } + + class LatchAwaiter extends CheckedRunnable { + static final int NEW = 0; + static final int RUNNING = 1; + static final int DONE = 2; + final CountDownLatch latch; + int state = NEW; + LatchAwaiter(CountDownLatch latch) { this.latch = latch; } + public void realRun() throws InterruptedException { + state = 1; + await(latch); + state = 2; + } + } + + public LatchAwaiter awaiter(CountDownLatch latch) { + return new LatchAwaiter(latch); + } + + public void await(CountDownLatch latch) { + try { + if (!latch.await(LONG_DELAY_MS, MILLISECONDS)) + fail("timed out waiting for CountDownLatch for " + + (LONG_DELAY_MS/1000) + " sec"); + } catch (Throwable fail) { + threadUnexpectedException(fail); + } + } + + public void await(Semaphore semaphore) { + try { + if (!semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS)) + fail("timed out waiting for Semaphore for " + + (LONG_DELAY_MS/1000) + " sec"); + } catch (Throwable fail) { + threadUnexpectedException(fail); + } + } + +// /** +// * Spin-waits up to LONG_DELAY_MS until flag becomes true. +// */ +// public void await(AtomicBoolean flag) { +// await(flag, LONG_DELAY_MS); +// } + +// /** +// * Spin-waits up to the specified timeout until flag becomes true. +// */ +// public void await(AtomicBoolean flag, long timeoutMillis) { +// long startTime = System.nanoTime(); +// while (!flag.get()) { +// if (millisElapsedSince(startTime) > timeoutMillis) +// throw new AssertionFailedError("timed out"); +// Thread.yield(); +// } +// } + + public static class NPETask implements Callable { + public String call() { throw new NullPointerException(); } + } + + public static class CallableOne implements Callable { + public Integer call() { return one; } + } + + public class ShortRunnable extends CheckedRunnable { + protected void realRun() throws Throwable { + delay(SHORT_DELAY_MS); + } + } + + public class ShortInterruptedRunnable extends CheckedInterruptedRunnable { + protected void realRun() throws InterruptedException { + delay(SHORT_DELAY_MS); + } + } + + public class SmallRunnable extends CheckedRunnable { + protected void realRun() throws Throwable { + delay(SMALL_DELAY_MS); + } + } + + public class SmallPossiblyInterruptedRunnable extends CheckedRunnable { + protected void realRun() { + try { + delay(SMALL_DELAY_MS); + } catch (InterruptedException ok) {} + } + } + + public class SmallCallable extends CheckedCallable { + protected Object realCall() throws InterruptedException { + delay(SMALL_DELAY_MS); + return Boolean.TRUE; + } + } + + public class MediumRunnable extends CheckedRunnable { + protected void realRun() throws Throwable { + delay(MEDIUM_DELAY_MS); + } + } + + public class MediumInterruptedRunnable extends CheckedInterruptedRunnable { + protected void realRun() throws InterruptedException { + delay(MEDIUM_DELAY_MS); + } + } + + public Runnable possiblyInterruptedRunnable(final long timeoutMillis) { + return new CheckedRunnable() { + protected void realRun() { + try { + delay(timeoutMillis); + } catch (InterruptedException ok) {} + }}; + } + + public class MediumPossiblyInterruptedRunnable extends CheckedRunnable { + protected void realRun() { + try { + delay(MEDIUM_DELAY_MS); + } catch (InterruptedException ok) {} + } + } + + public class LongPossiblyInterruptedRunnable extends CheckedRunnable { + protected void realRun() { + try { + delay(LONG_DELAY_MS); + } catch (InterruptedException ok) {} + } + } + + /** + * For use as ThreadFactory in constructors + */ + public static class SimpleThreadFactory implements ThreadFactory { + public Thread newThread(Runnable r) { + return new Thread(r); + } + } + + public interface TrackedRunnable extends Runnable { + boolean isDone(); + } + + public static TrackedRunnable trackedRunnable(final long timeoutMillis) { + return new TrackedRunnable() { + private volatile boolean done = false; + public boolean isDone() { return done; } + public void run() { + try { + delay(timeoutMillis); + done = true; + } catch (InterruptedException ok) {} + } + }; + } + + public static class TrackedShortRunnable implements Runnable { + public volatile boolean done = false; + public void run() { + try { + delay(SHORT_DELAY_MS); + done = true; + } catch (InterruptedException ok) {} + } + } + + public static class TrackedSmallRunnable implements Runnable { + public volatile boolean done = false; + public void run() { + try { + delay(SMALL_DELAY_MS); + done = true; + } catch (InterruptedException ok) {} + } + } + + public static class TrackedMediumRunnable implements Runnable { + public volatile boolean done = false; + public void run() { + try { + delay(MEDIUM_DELAY_MS); + done = true; + } catch (InterruptedException ok) {} + } + } + + public static class TrackedLongRunnable implements Runnable { + public volatile boolean done = false; + public void run() { + try { + delay(LONG_DELAY_MS); + done = true; + } catch (InterruptedException ok) {} + } + } + + public static class TrackedNoOpRunnable implements Runnable { + public volatile boolean done = false; + public void run() { + done = true; + } + } + + public static class TrackedCallable implements Callable { + public volatile boolean done = false; + public Object call() { + try { + delay(SMALL_DELAY_MS); + done = true; + } catch (InterruptedException ok) {} + return Boolean.TRUE; + } + } + + /** + * Analog of CheckedRunnable for RecursiveAction + */ + public abstract class CheckedRecursiveAction extends RecursiveAction { + protected abstract void realCompute() throws Throwable; + + @Override protected final void compute() { + try { + realCompute(); + } catch (Throwable fail) { + threadUnexpectedException(fail); + } + } + } + + /** + * Analog of CheckedCallable for RecursiveTask + */ + public abstract class CheckedRecursiveTask extends RecursiveTask { + protected abstract T realCompute() throws Throwable; + + @Override protected final T compute() { + try { + return realCompute(); + } catch (Throwable fail) { + threadUnexpectedException(fail); + return null; + } + } + } + + /** + * For use as RejectedExecutionHandler in constructors + */ + public static class NoOpREHandler implements RejectedExecutionHandler { + public void rejectedExecution(Runnable r, + ThreadPoolExecutor executor) {} + } + + /** + * A CyclicBarrier that uses timed await and fails with + * AssertionFailedErrors instead of throwing checked exceptions. + */ + public class CheckedBarrier extends CyclicBarrier { + public CheckedBarrier(int parties) { super(parties); } + + public int await() { + try { + return super.await(2 * LONG_DELAY_MS, MILLISECONDS); + } catch (TimeoutException timedOut) { + throw new AssertionFailedError("timed out"); + } catch (Exception fail) { + AssertionFailedError afe = + new AssertionFailedError("Unexpected exception: " + fail); + afe.initCause(fail); + throw afe; + } + } + } + + void checkEmpty(BlockingQueue q) { + try { + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertNull(q.peek()); + assertNull(q.poll()); + assertNull(q.poll(0, MILLISECONDS)); + assertEquals(q.toString(), "[]"); + assertTrue(Arrays.equals(q.toArray(), new Object[0])); + assertFalse(q.iterator().hasNext()); + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + try { + q.iterator().next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + } + + void assertSerialEquals(Object x, Object y) { + assertTrue(Arrays.equals(serialBytes(x), serialBytes(y))); + } + + void assertNotSerialEquals(Object x, Object y) { + assertFalse(Arrays.equals(serialBytes(x), serialBytes(y))); + } + + byte[] serialBytes(Object o) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(o); + oos.flush(); + oos.close(); + return bos.toByteArray(); + } catch (Throwable fail) { + threadUnexpectedException(fail); + return new byte[0]; + } + } + + @SuppressWarnings("unchecked") + T serialClone(T o) { + try { + ObjectInputStream ois = new ObjectInputStream + (new ByteArrayInputStream(serialBytes(o))); + T clone = (T) ois.readObject(); + assertSame(o.getClass(), clone.getClass()); + return clone; + } catch (Throwable fail) { + threadUnexpectedException(fail); + return null; + } + } + + public void assertThrows(Class expectedExceptionClass, + Runnable... throwingActions) { + for (Runnable throwingAction : throwingActions) { + boolean threw = false; + try { throwingAction.run(); } + catch (Throwable t) { + threw = true; + if (!expectedExceptionClass.isInstance(t)) { + AssertionFailedError afe = + new AssertionFailedError + ("Expected " + expectedExceptionClass.getName() + + ", got " + t.getClass().getName()); + afe.initCause(t); + threadUnexpectedException(afe); + } + } + if (!threw) + shouldThrow(expectedExceptionClass.getName()); + } + } + + public void assertIteratorExhausted(Iterator it) { + try { + it.next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertFalse(it.hasNext()); + } +} diff --git a/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java b/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java new file mode 100644 index 00000000000..138799035cb --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java @@ -0,0 +1,1848 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Deque; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.BlockingDeque; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingDeque; + +import junit.framework.Test; + +public class LinkedBlockingDequeTest extends JSR166TestCase { + + public static class Unbounded extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new LinkedBlockingDeque(); + } + } + + public static class Bounded extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new LinkedBlockingDeque(SIZE); + } + } + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return newTestSuite(LinkedBlockingDequeTest.class, + new Unbounded().testSuite(), + new Bounded().testSuite()); + } + + /** + * Returns a new deque of given size containing consecutive + * Integers 0 ... n. + */ + private LinkedBlockingDeque populatedDeque(int n) { + LinkedBlockingDeque q = + new LinkedBlockingDeque(n); + assertTrue(q.isEmpty()); + for (int i = 0; i < n; i++) + assertTrue(q.offer(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(0, q.remainingCapacity()); + assertEquals(n, q.size()); + return q; + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + LinkedBlockingDeque q = new LinkedBlockingDeque(); + assertTrue(q.isEmpty()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.add(new Integer(2)); + q.removeFirst(); + q.removeFirst(); + assertTrue(q.isEmpty()); + } + + /** + * size changes when elements added and removed + */ + public void testSize() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.removeFirst(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * offerFirst(null) throws NullPointerException + */ + public void testOfferFirstNull() { + LinkedBlockingDeque q = new LinkedBlockingDeque(); + try { + q.offerFirst(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * offerLast(null) throws NullPointerException + */ + public void testOfferLastNull() { + LinkedBlockingDeque q = new LinkedBlockingDeque(); + try { + q.offerLast(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * OfferFirst succeeds + */ + public void testOfferFirst() { + LinkedBlockingDeque q = new LinkedBlockingDeque(); + assertTrue(q.offerFirst(new Integer(0))); + assertTrue(q.offerFirst(new Integer(1))); + } + + /** + * OfferLast succeeds + */ + public void testOfferLast() { + LinkedBlockingDeque q = new LinkedBlockingDeque(); + assertTrue(q.offerLast(new Integer(0))); + assertTrue(q.offerLast(new Integer(1))); + } + + /** + * pollFirst succeeds unless empty + */ + public void testPollFirst() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst()); + } + assertNull(q.pollFirst()); + } + + /** + * pollLast succeeds unless empty + */ + public void testPollLast() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.pollLast()); + } + assertNull(q.pollLast()); + } + + /** + * peekFirst returns next element, or null if empty + */ + public void testPeekFirst() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peekFirst()); + assertEquals(i, q.pollFirst()); + assertTrue(q.peekFirst() == null || + !q.peekFirst().equals(i)); + } + assertNull(q.peekFirst()); + } + + /** + * peek returns next element, or null if empty + */ + public void testPeek() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peek()); + assertEquals(i, q.pollFirst()); + assertTrue(q.peek() == null || + !q.peek().equals(i)); + } + assertNull(q.peek()); + } + + /** + * peekLast returns next element, or null if empty + */ + public void testPeekLast() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.peekLast()); + assertEquals(i, q.pollLast()); + assertTrue(q.peekLast() == null || + !q.peekLast().equals(i)); + } + assertNull(q.peekLast()); + } + + /** + * getFirst() returns first element, or throws NSEE if empty + */ + public void testFirstElement() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.getFirst()); + assertEquals(i, q.pollFirst()); + } + try { + q.getFirst(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekFirst()); + } + + /** + * getLast() returns last element, or throws NSEE if empty + */ + public void testLastElement() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.getLast()); + assertEquals(i, q.pollLast()); + } + try { + q.getLast(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekLast()); + } + + /** + * removeFirst() removes first element, or throws NSEE if empty + */ + public void testRemoveFirst() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.removeFirst()); + } + try { + q.removeFirst(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekFirst()); + } + + /** + * removeLast() removes last element, or throws NSEE if empty + */ + public void testRemoveLast() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.removeLast()); + } + try { + q.removeLast(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekLast()); + } + + /** + * remove removes next element, or throws NSEE if empty + */ + public void testRemove() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * removeFirstOccurrence(x) removes x and returns true if present + */ + public void testRemoveFirstOccurrence() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.removeFirstOccurrence(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.removeFirstOccurrence(new Integer(i))); + assertFalse(q.removeFirstOccurrence(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + + /** + * removeLastOccurrence(x) removes x and returns true if present + */ + public void testRemoveLastOccurrence() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.removeLastOccurrence(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.removeLastOccurrence(new Integer(i))); + assertFalse(q.removeLastOccurrence(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + + /** + * peekFirst returns element inserted with addFirst + */ + public void testAddFirst() { + LinkedBlockingDeque q = populatedDeque(3); + q.pollLast(); + q.addFirst(four); + assertSame(four, q.peekFirst()); + } + + /** + * peekLast returns element inserted with addLast + */ + public void testAddLast() { + LinkedBlockingDeque q = populatedDeque(3); + q.pollLast(); + q.addLast(four); + assertSame(four, q.peekLast()); + } + + /** + * A new deque has the indicated capacity, or Integer.MAX_VALUE if + * none given + */ + public void testConstructor1() { + assertEquals(SIZE, new LinkedBlockingDeque(SIZE).remainingCapacity()); + assertEquals(Integer.MAX_VALUE, new LinkedBlockingDeque().remainingCapacity()); + } + + /** + * Constructor throws IllegalArgumentException if capacity argument nonpositive + */ + public void testConstructor2() { + try { + new LinkedBlockingDeque(0); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Initializing from null Collection throws NullPointerException + */ + public void testConstructor3() { + try { + new LinkedBlockingDeque(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NullPointerException + */ + public void testConstructor4() { + Collection elements = Arrays.asList(new Integer[SIZE]); + try { + new LinkedBlockingDeque(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws + * NullPointerException + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = i; + Collection elements = Arrays.asList(ints); + try { + new LinkedBlockingDeque(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Deque contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = i; + LinkedBlockingDeque q = new LinkedBlockingDeque(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * Deque transitions from empty to full when elements added + */ + public void testEmptyFull() { + LinkedBlockingDeque q = new LinkedBlockingDeque(2); + assertTrue(q.isEmpty()); + assertEquals("should have room for 2", 2, q.remainingCapacity()); + q.add(one); + assertFalse(q.isEmpty()); + q.add(two); + assertFalse(q.isEmpty()); + assertEquals(0, q.remainingCapacity()); + assertFalse(q.offer(three)); + } + + /** + * remainingCapacity decreases on add, increases on remove + */ + public void testRemainingCapacity() { + BlockingQueue q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remainingCapacity()); + assertEquals(SIZE, q.size() + q.remainingCapacity()); + assertEquals(i, q.remove()); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.remainingCapacity()); + assertEquals(SIZE, q.size() + q.remainingCapacity()); + assertTrue(q.add(i)); + } + } + + /** + * push(null) throws NPE + */ + public void testPushNull() { + LinkedBlockingDeque q = new LinkedBlockingDeque(1); + try { + q.push(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * push succeeds if not full; throws ISE if full + */ + public void testPush() { + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + Integer x = new Integer(i); + q.push(x); + assertEquals(x, q.peek()); + } + assertEquals(0, q.remainingCapacity()); + try { + q.push(new Integer(SIZE)); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * peekFirst returns element inserted with push + */ + public void testPushWithPeek() { + LinkedBlockingDeque q = populatedDeque(3); + q.pollLast(); + q.push(four); + assertSame(four, q.peekFirst()); + } + + /** + * pop removes next element, or throws NSEE if empty + */ + public void testPop() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pop()); + } + try { + q.pop(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * Offer succeeds if not full; fails if full + */ + public void testOffer() { + LinkedBlockingDeque q = new LinkedBlockingDeque(1); + assertTrue(q.offer(zero)); + assertFalse(q.offer(one)); + } + + /** + * add succeeds if not full; throws ISE if full + */ + public void testAdd() { + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + for (int i = 0; i < SIZE; ++i) + assertTrue(q.add(new Integer(i))); + assertEquals(0, q.remainingCapacity()); + try { + q.add(new Integer(SIZE)); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * addAll(this) throws IAE + */ + public void testAddAllSelf() { + LinkedBlockingDeque q = populatedDeque(SIZE); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + Collection elements = Arrays.asList(ints); + try { + q.addAll(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll throws IllegalStateException if not enough room + */ + public void testAddAll4() { + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE - 1); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + Collection elements = Arrays.asList(ints); + try { + q.addAll(elements); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * Deque contains all elements, in traversal order, of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * all elements successfully put are contained + */ + public void testPut() throws InterruptedException { + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + Integer x = new Integer(i); + q.put(x); + assertTrue(q.contains(x)); + } + assertEquals(0, q.remainingCapacity()); + } + + /** + * put blocks interruptibly if full + */ + public void testBlockingPut() throws InterruptedException { + final LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) + q.put(i); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + + Thread.currentThread().interrupt(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + } + + /** + * put blocks interruptibly waiting for take when full + */ + public void testPutWithTake() throws InterruptedException { + final int capacity = 2; + final LinkedBlockingDeque q = new LinkedBlockingDeque(capacity); + final CountDownLatch pleaseTake = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < capacity; i++) + q.put(i); + pleaseTake.countDown(); + q.put(86); + + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseTake); + assertEquals(0, q.remainingCapacity()); + assertEquals(0, q.take()); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(0, q.remainingCapacity()); + } + + /** + * timed offer times out if full and elements not taken + */ + public void testTimedOffer() throws InterruptedException { + final LinkedBlockingDeque q = new LinkedBlockingDeque(2); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(new Object()); + q.put(new Object()); + long startTime = System.nanoTime(); + assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + pleaseInterrupt.countDown(); + try { + q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * take retrieves elements in FIFO order + */ + public void testTake() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.take()); + } + } + + /** + * take removes existing elements until empty, then blocks interruptibly + */ + public void testBlockingTake() throws InterruptedException { + final LinkedBlockingDeque q = populatedDeque(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.take()); + } + + Thread.currentThread().interrupt(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll()); + } + assertNull(q.poll()); + } + + /** + * timed poll with zero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll0() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll(0, MILLISECONDS)); + } + assertNull(q.poll(0, MILLISECONDS)); + } + + /** + * timed poll with nonzero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + long startTime = System.nanoTime(); + assertEquals(i, q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + long startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + checkEmpty(q); + } + + /** + * Interrupted timed poll throws InterruptedException instead of + * returning timeout status + */ + public void testInterruptedTimedPoll() throws InterruptedException { + final BlockingQueue q = populatedDeque(SIZE); + final CountDownLatch aboutToWait = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); + } + aboutToWait.countDown(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) { + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + }}); + + aboutToWait.await(); + waitForThreadToEnterWaitState(t, LONG_DELAY_MS); + t.interrupt(); + awaitTermination(t); + checkEmpty(q); + } + + /** + * putFirst(null) throws NPE + */ + public void testPutFirstNull() throws InterruptedException { + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + try { + q.putFirst(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * all elements successfully putFirst are contained + */ + public void testPutFirst() throws InterruptedException { + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + Integer x = new Integer(i); + q.putFirst(x); + assertTrue(q.contains(x)); + } + assertEquals(0, q.remainingCapacity()); + } + + /** + * putFirst blocks interruptibly if full + */ + public void testBlockingPutFirst() throws InterruptedException { + final LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) + q.putFirst(i); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + + Thread.currentThread().interrupt(); + try { + q.putFirst(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.putFirst(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + } + + /** + * putFirst blocks interruptibly waiting for take when full + */ + public void testPutFirstWithTake() throws InterruptedException { + final int capacity = 2; + final LinkedBlockingDeque q = new LinkedBlockingDeque(capacity); + final CountDownLatch pleaseTake = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < capacity; i++) + q.putFirst(i); + pleaseTake.countDown(); + q.putFirst(86); + + pleaseInterrupt.countDown(); + try { + q.putFirst(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseTake); + assertEquals(0, q.remainingCapacity()); + assertEquals(capacity - 1, q.take()); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(0, q.remainingCapacity()); + } + + /** + * timed offerFirst times out if full and elements not taken + */ + public void testTimedOfferFirst() throws InterruptedException { + final LinkedBlockingDeque q = new LinkedBlockingDeque(2); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.putFirst(new Object()); + q.putFirst(new Object()); + long startTime = System.nanoTime(); + assertFalse(q.offerFirst(new Object(), timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + pleaseInterrupt.countDown(); + try { + q.offerFirst(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * take retrieves elements in FIFO order + */ + public void testTakeFirst() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.takeFirst()); + } + } + + /** + * takeFirst() blocks interruptibly when empty + */ + public void testTakeFirstFromEmptyBlocksInterruptibly() { + final BlockingDeque q = new LinkedBlockingDeque(); + final CountDownLatch threadStarted = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + threadStarted.countDown(); + try { + q.takeFirst(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(threadStarted); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * takeFirst() throws InterruptedException immediately if interrupted + * before waiting + */ + public void testTakeFirstFromEmptyAfterInterrupt() { + final BlockingDeque q = new LinkedBlockingDeque(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + Thread.currentThread().interrupt(); + try { + q.takeFirst(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + awaitTermination(t); + } + + /** + * takeLast() blocks interruptibly when empty + */ + public void testTakeLastFromEmptyBlocksInterruptibly() { + final BlockingDeque q = new LinkedBlockingDeque(); + final CountDownLatch threadStarted = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + threadStarted.countDown(); + try { + q.takeLast(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(threadStarted); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * takeLast() throws InterruptedException immediately if interrupted + * before waiting + */ + public void testTakeLastFromEmptyAfterInterrupt() { + final BlockingDeque q = new LinkedBlockingDeque(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + Thread.currentThread().interrupt(); + try { + q.takeLast(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + awaitTermination(t); + } + + /** + * takeFirst removes existing elements until empty, then blocks interruptibly + */ + public void testBlockingTakeFirst() throws InterruptedException { + final LinkedBlockingDeque q = populatedDeque(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.takeFirst()); + } + + Thread.currentThread().interrupt(); + try { + q.takeFirst(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.takeFirst(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * timed pollFirst with zero timeout succeeds when non-empty, else times out + */ + public void testTimedPollFirst0() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst(0, MILLISECONDS)); + } + assertNull(q.pollFirst(0, MILLISECONDS)); + } + + /** + * timed pollFirst with nonzero timeout succeeds when non-empty, else times out + */ + public void testTimedPollFirst() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + long startTime = System.nanoTime(); + assertEquals(i, q.pollFirst(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + long startTime = System.nanoTime(); + assertNull(q.pollFirst(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + checkEmpty(q); + } + + /** + * Interrupted timed pollFirst throws InterruptedException instead of + * returning timeout status + */ + public void testInterruptedTimedPollFirst() throws InterruptedException { + final LinkedBlockingDeque q = populatedDeque(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst(LONG_DELAY_MS, MILLISECONDS)); + } + + Thread.currentThread().interrupt(); + try { + q.pollFirst(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.pollFirst(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * timed pollFirst before a delayed offerFirst fails; after offerFirst succeeds; + * on interruption throws + */ + public void testTimedPollFirstWithOfferFirst() throws InterruptedException { + final LinkedBlockingDeque q = new LinkedBlockingDeque(2); + final CheckedBarrier barrier = new CheckedBarrier(2); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertNull(q.pollFirst(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + + barrier.await(); + + assertSame(zero, q.pollFirst(LONG_DELAY_MS, MILLISECONDS)); + + Thread.currentThread().interrupt(); + try { + q.pollFirst(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + + barrier.await(); + try { + q.pollFirst(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + barrier.await(); + long startTime = System.nanoTime(); + assertTrue(q.offerFirst(zero, LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + barrier.await(); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * putLast(null) throws NPE + */ + public void testPutLastNull() throws InterruptedException { + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + try { + q.putLast(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * all elements successfully putLast are contained + */ + public void testPutLast() throws InterruptedException { + LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + Integer x = new Integer(i); + q.putLast(x); + assertTrue(q.contains(x)); + } + assertEquals(0, q.remainingCapacity()); + } + + /** + * putLast blocks interruptibly if full + */ + public void testBlockingPutLast() throws InterruptedException { + final LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) + q.putLast(i); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + + Thread.currentThread().interrupt(); + try { + q.putLast(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.putLast(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + } + + /** + * putLast blocks interruptibly waiting for take when full + */ + public void testPutLastWithTake() throws InterruptedException { + final int capacity = 2; + final LinkedBlockingDeque q = new LinkedBlockingDeque(capacity); + final CountDownLatch pleaseTake = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < capacity; i++) + q.putLast(i); + pleaseTake.countDown(); + q.putLast(86); + + pleaseInterrupt.countDown(); + try { + q.putLast(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseTake); + assertEquals(0, q.remainingCapacity()); + assertEquals(0, q.take()); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(0, q.remainingCapacity()); + } + + /** + * timed offerLast times out if full and elements not taken + */ + public void testTimedOfferLast() throws InterruptedException { + final LinkedBlockingDeque q = new LinkedBlockingDeque(2); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.putLast(new Object()); + q.putLast(new Object()); + long startTime = System.nanoTime(); + assertFalse(q.offerLast(new Object(), timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + pleaseInterrupt.countDown(); + try { + q.offerLast(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * takeLast retrieves elements in FIFO order + */ + public void testTakeLast() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i - 1, q.takeLast()); + } + } + + /** + * takeLast removes existing elements until empty, then blocks interruptibly + */ + public void testBlockingTakeLast() throws InterruptedException { + final LinkedBlockingDeque q = populatedDeque(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i - 1, q.takeLast()); + } + + Thread.currentThread().interrupt(); + try { + q.takeLast(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.takeLast(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * timed pollLast with zero timeout succeeds when non-empty, else times out + */ + public void testTimedPollLast0() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i - 1, q.pollLast(0, MILLISECONDS)); + } + assertNull(q.pollLast(0, MILLISECONDS)); + } + + /** + * timed pollLast with nonzero timeout succeeds when non-empty, else times out + */ + public void testTimedPollLast() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + long startTime = System.nanoTime(); + assertEquals(SIZE - i - 1, q.pollLast(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + long startTime = System.nanoTime(); + assertNull(q.pollLast(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + checkEmpty(q); + } + + /** + * Interrupted timed pollLast throws InterruptedException instead of + * returning timeout status + */ + public void testInterruptedTimedPollLast() throws InterruptedException { + final LinkedBlockingDeque q = populatedDeque(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i - 1, + q.pollLast(LONG_DELAY_MS, MILLISECONDS)); + } + + Thread.currentThread().interrupt(); + try { + q.pollLast(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.pollLast(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + checkEmpty(q); + } + + /** + * timed poll before a delayed offerLast fails; after offerLast succeeds; + * on interruption throws + */ + public void testTimedPollWithOfferLast() throws InterruptedException { + final LinkedBlockingDeque q = new LinkedBlockingDeque(2); + final CheckedBarrier barrier = new CheckedBarrier(2); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + + barrier.await(); + + assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS)); + + Thread.currentThread().interrupt(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + barrier.await(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + barrier.await(); + long startTime = System.nanoTime(); + assertTrue(q.offerLast(zero, LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + + barrier.await(); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * element returns next element, or throws NSEE if empty + */ + public void testElement() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.element()); + q.poll(); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + LinkedBlockingDeque q = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.poll(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + LinkedBlockingDeque q = populatedDeque(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertEquals(SIZE, q.remainingCapacity()); + q.add(one); + assertFalse(q.isEmpty()); + assertTrue(q.contains(one)); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + LinkedBlockingDeque q = populatedDeque(SIZE); + LinkedBlockingDeque p = new LinkedBlockingDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + LinkedBlockingDeque q = populatedDeque(SIZE); + LinkedBlockingDeque p = populatedDeque(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + LinkedBlockingDeque q = populatedDeque(SIZE); + LinkedBlockingDeque p = populatedDeque(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.remove()); + assertFalse(q.contains(x)); + } + } + } + + /** + * toArray contains all elements in FIFO order + */ + public void testToArray() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.poll()); + } + + /** + * toArray(a) contains all elements in FIFO order + */ + public void testToArray2() { + LinkedBlockingDeque q = populatedDeque(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.remove()); + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + LinkedBlockingDeque q = populatedDeque(SIZE); + try { + q.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * iterator iterates through all elements + */ + public void testIterator() throws InterruptedException { + LinkedBlockingDeque q = populatedDeque(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + + it = q.iterator(); + for (i = 0; it.hasNext(); i++) + assertEquals(it.next(), q.take()); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + Deque c = new LinkedBlockingDeque(); + assertIteratorExhausted(c.iterator()); + assertIteratorExhausted(c.descendingIterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final LinkedBlockingDeque q = new LinkedBlockingDeque(3); + q.add(two); + q.add(one); + q.add(three); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertSame(it.next(), one); + assertSame(it.next(), three); + assertFalse(it.hasNext()); + } + + /** + * iterator ordering is FIFO + */ + public void testIteratorOrdering() { + final LinkedBlockingDeque q = new LinkedBlockingDeque(3); + q.add(one); + q.add(two); + q.add(three); + assertEquals(0, q.remainingCapacity()); + int k = 0; + for (Iterator it = q.iterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + assertEquals(3, k); + } + + /** + * Modifications do not cause iterators to fail + */ + public void testWeaklyConsistentIteration() { + final LinkedBlockingDeque q = new LinkedBlockingDeque(3); + q.add(one); + q.add(two); + q.add(three); + for (Iterator it = q.iterator(); it.hasNext();) { + q.remove(); + it.next(); + } + assertEquals(0, q.size()); + } + + /** + * Descending iterator iterates through all elements + */ + public void testDescendingIterator() { + LinkedBlockingDeque q = populatedDeque(SIZE); + int i = 0; + Iterator it = q.descendingIterator(); + while (it.hasNext()) { + assertTrue(q.contains(it.next())); + ++i; + } + assertEquals(i, SIZE); + assertFalse(it.hasNext()); + try { + it.next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * Descending iterator ordering is reverse FIFO + */ + public void testDescendingIteratorOrdering() { + final LinkedBlockingDeque q = new LinkedBlockingDeque(); + for (int iters = 0; iters < 100; ++iters) { + q.add(new Integer(3)); + q.add(new Integer(2)); + q.add(new Integer(1)); + int k = 0; + for (Iterator it = q.descendingIterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + + assertEquals(3, k); + q.remove(); + q.remove(); + q.remove(); + } + } + + /** + * descendingIterator.remove removes current element + */ + public void testDescendingIteratorRemove() { + final LinkedBlockingDeque q = new LinkedBlockingDeque(); + for (int iters = 0; iters < 100; ++iters) { + q.add(new Integer(3)); + q.add(new Integer(2)); + q.add(new Integer(1)); + Iterator it = q.descendingIterator(); + assertEquals(it.next(), new Integer(1)); + it.remove(); + assertEquals(it.next(), new Integer(2)); + it = q.descendingIterator(); + assertEquals(it.next(), new Integer(2)); + assertEquals(it.next(), new Integer(3)); + it.remove(); + assertFalse(it.hasNext()); + q.remove(); + } + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + LinkedBlockingDeque q = populatedDeque(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * offer transfers elements across Executor tasks + */ + public void testOfferInExecutor() { + final LinkedBlockingDeque q = new LinkedBlockingDeque(2); + q.add(one); + q.add(two); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(q.offer(three)); + threadsStarted.await(); + assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS)); + assertEquals(0, q.remainingCapacity()); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + assertSame(one, q.take()); + }}); + } + } + + /** + * timed poll retrieves elements across Executor threads + */ + public void testPollInExecutor() { + final LinkedBlockingDeque q = new LinkedBlockingDeque(2); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertNull(q.poll()); + threadsStarted.await(); + assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS)); + checkEmpty(q); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + q.put(one); + }}); + } + } + + /** + * A deserialized serialized deque has same elements in same order + */ + public void testSerialization() throws Exception { + Queue x = populatedDeque(SIZE); + Queue y = serialClone(x); + + assertNotSame(y, x); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(), y.remove()); + } + assertTrue(y.isEmpty()); + } + + /** + * drainTo(c) empties deque into another collection c + */ + public void testDrainTo() { + LinkedBlockingDeque q = populatedDeque(SIZE); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(SIZE, l.size()); + for (int i = 0; i < SIZE; ++i) + assertEquals(l.get(i), new Integer(i)); + q.add(zero); + q.add(one); + assertFalse(q.isEmpty()); + assertTrue(q.contains(zero)); + assertTrue(q.contains(one)); + l.clear(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(2, l.size()); + for (int i = 0; i < 2; ++i) + assertEquals(l.get(i), new Integer(i)); + } + + /** + * drainTo empties full deque, unblocking a waiting put. + */ + public void testDrainToWithActivePut() throws InterruptedException { + final LinkedBlockingDeque q = populatedDeque(SIZE); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(new Integer(SIZE + 1)); + }}); + + t.start(); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertTrue(l.size() >= SIZE); + for (int i = 0; i < SIZE; ++i) + assertEquals(l.get(i), new Integer(i)); + t.join(); + assertTrue(q.size() + l.size() >= SIZE); + } + + /** + * drainTo(c, n) empties first min(n, size) elements of queue into c + */ + public void testDrainToN() { + LinkedBlockingDeque q = new LinkedBlockingDeque(); + for (int i = 0; i < SIZE + 2; ++i) { + for (int j = 0; j < SIZE; j++) + assertTrue(q.offer(new Integer(j))); + ArrayList l = new ArrayList(); + q.drainTo(l, i); + int k = (i < SIZE) ? i : SIZE; + assertEquals(k, l.size()); + assertEquals(SIZE - k, q.size()); + for (int j = 0; j < k; ++j) + assertEquals(l.get(j), new Integer(j)); + do {} while (q.poll() != null); + } + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Deque[] qs = { + new LinkedBlockingDeque(), + populatedDeque(2), + }; + + for (Deque q : qs) { + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + assertFalse(q.removeFirstOccurrence(null)); + assertFalse(q.removeLastOccurrence(null)); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java new file mode 100644 index 00000000000..51246e903a6 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java @@ -0,0 +1,889 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; + +import junit.framework.Test; + +public class LinkedBlockingQueueTest extends JSR166TestCase { + + public static class Unbounded extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new LinkedBlockingQueue(); + } + } + + public static class Bounded extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new LinkedBlockingQueue(SIZE); + } + } + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return newTestSuite(LinkedBlockingQueueTest.class, + new Unbounded().testSuite(), + new Bounded().testSuite()); + } + + /** + * Returns a new queue of given size containing consecutive + * Integers 0 ... n. + */ + private LinkedBlockingQueue populatedQueue(int n) { + LinkedBlockingQueue q = + new LinkedBlockingQueue(n); + assertTrue(q.isEmpty()); + for (int i = 0; i < n; i++) + assertTrue(q.offer(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(0, q.remainingCapacity()); + assertEquals(n, q.size()); + return q; + } + + /** + * A new queue has the indicated capacity, or Integer.MAX_VALUE if + * none given + */ + public void testConstructor1() { + assertEquals(SIZE, new LinkedBlockingQueue(SIZE).remainingCapacity()); + assertEquals(Integer.MAX_VALUE, new LinkedBlockingQueue().remainingCapacity()); + } + + /** + * Constructor throws IllegalArgumentException if capacity argument nonpositive + */ + public void testConstructor2() { + try { + new LinkedBlockingQueue(0); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Initializing from null Collection throws NullPointerException + */ + public void testConstructor3() { + try { + new LinkedBlockingQueue(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NullPointerException + */ + public void testConstructor4() { + Collection elements = Arrays.asList(new Integer[SIZE]); + try { + new LinkedBlockingQueue(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws + * NullPointerException + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + Collection elements = Arrays.asList(ints); + try { + new LinkedBlockingQueue(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + LinkedBlockingQueue q = new LinkedBlockingQueue(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * Queue transitions from empty to full when elements added + */ + public void testEmptyFull() { + LinkedBlockingQueue q = new LinkedBlockingQueue(2); + assertTrue(q.isEmpty()); + assertEquals("should have room for 2", 2, q.remainingCapacity()); + q.add(one); + assertFalse(q.isEmpty()); + q.add(two); + assertFalse(q.isEmpty()); + assertEquals(0, q.remainingCapacity()); + assertFalse(q.offer(three)); + } + + /** + * remainingCapacity decreases on add, increases on remove + */ + public void testRemainingCapacity() { + BlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remainingCapacity()); + assertEquals(SIZE, q.size() + q.remainingCapacity()); + assertEquals(i, q.remove()); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.remainingCapacity()); + assertEquals(SIZE, q.size() + q.remainingCapacity()); + assertTrue(q.add(i)); + } + } + + /** + * Offer succeeds if not full; fails if full + */ + public void testOffer() { + LinkedBlockingQueue q = new LinkedBlockingQueue(1); + assertTrue(q.offer(zero)); + assertFalse(q.offer(one)); + } + + /** + * add succeeds if not full; throws IllegalStateException if full + */ + public void testAdd() { + LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE); + for (int i = 0; i < SIZE; ++i) + assertTrue(q.add(new Integer(i))); + assertEquals(0, q.remainingCapacity()); + try { + q.add(new Integer(SIZE)); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * addAll(this) throws IllegalArgumentException + */ + public void testAddAllSelf() { + LinkedBlockingQueue q = populatedQueue(SIZE); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + Collection elements = Arrays.asList(ints); + try { + q.addAll(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll throws IllegalStateException if not enough room + */ + public void testAddAll4() { + LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE - 1); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + Collection elements = Arrays.asList(ints); + try { + q.addAll(elements); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * Queue contains all elements, in traversal order, of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * all elements successfully put are contained + */ + public void testPut() throws InterruptedException { + LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + Integer x = new Integer(i); + q.put(x); + assertTrue(q.contains(x)); + } + assertEquals(0, q.remainingCapacity()); + } + + /** + * put blocks interruptibly if full + */ + public void testBlockingPut() throws InterruptedException { + final LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) + q.put(i); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + + Thread.currentThread().interrupt(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(SIZE, q.size()); + assertEquals(0, q.remainingCapacity()); + } + + /** + * put blocks interruptibly waiting for take when full + */ + public void testPutWithTake() throws InterruptedException { + final int capacity = 2; + final LinkedBlockingQueue q = new LinkedBlockingQueue(2); + final CountDownLatch pleaseTake = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < capacity; i++) + q.put(i); + pleaseTake.countDown(); + q.put(86); + + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseTake); + assertEquals(0, q.remainingCapacity()); + assertEquals(0, q.take()); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(0, q.remainingCapacity()); + } + + /** + * timed offer times out if full and elements not taken + */ + public void testTimedOffer() { + final LinkedBlockingQueue q = new LinkedBlockingQueue(2); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(new Object()); + q.put(new Object()); + long startTime = System.nanoTime(); + assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + pleaseInterrupt.countDown(); + try { + q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * take retrieves elements in FIFO order + */ + public void testTake() throws InterruptedException { + LinkedBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.take()); + } + } + + /** + * Take removes existing elements until empty, then blocks interruptibly + */ + public void testBlockingTake() throws InterruptedException { + final BlockingQueue q = populatedQueue(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.take()); + } + + Thread.currentThread().interrupt(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + LinkedBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll()); + } + assertNull(q.poll()); + } + + /** + * timed poll with zero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll0() throws InterruptedException { + LinkedBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll(0, MILLISECONDS)); + } + assertNull(q.poll(0, MILLISECONDS)); + } + + /** + * timed poll with nonzero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll() throws InterruptedException { + LinkedBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + long startTime = System.nanoTime(); + assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + long startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + checkEmpty(q); + } + + /** + * Interrupted timed poll throws InterruptedException instead of + * returning timeout status + */ + public void testInterruptedTimedPoll() throws InterruptedException { + final BlockingQueue q = populatedQueue(SIZE); + final CountDownLatch aboutToWait = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); + } + aboutToWait.countDown(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) { + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + }}); + + await(aboutToWait); + waitForThreadToEnterWaitState(t, LONG_DELAY_MS); + t.interrupt(); + awaitTermination(t); + checkEmpty(q); + } + + /** + * peek returns next element, or null if empty + */ + public void testPeek() { + LinkedBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peek()); + assertEquals(i, q.poll()); + assertTrue(q.peek() == null || + !q.peek().equals(i)); + } + assertNull(q.peek()); + } + + /** + * element returns next element, or throws NSEE if empty + */ + public void testElement() { + LinkedBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.element()); + assertEquals(i, q.poll()); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove removes next element, or throws NSEE if empty + */ + public void testRemove() { + LinkedBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * An add following remove(x) succeeds + */ + public void testRemoveElementAndAdd() throws InterruptedException { + LinkedBlockingQueue q = new LinkedBlockingQueue(); + assertTrue(q.add(new Integer(1))); + assertTrue(q.add(new Integer(2))); + assertTrue(q.remove(new Integer(1))); + assertTrue(q.remove(new Integer(2))); + assertTrue(q.add(new Integer(3))); + assertNotNull(q.take()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + LinkedBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.poll(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + LinkedBlockingQueue q = populatedQueue(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertEquals(SIZE, q.remainingCapacity()); + q.add(one); + assertFalse(q.isEmpty()); + assertTrue(q.contains(one)); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + LinkedBlockingQueue q = populatedQueue(SIZE); + LinkedBlockingQueue p = new LinkedBlockingQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + LinkedBlockingQueue q = populatedQueue(SIZE); + LinkedBlockingQueue p = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + LinkedBlockingQueue q = populatedQueue(SIZE); + LinkedBlockingQueue p = populatedQueue(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.remove()); + assertFalse(q.contains(x)); + } + } + } + + /** + * toArray contains all elements in FIFO order + */ + public void testToArray() { + LinkedBlockingQueue q = populatedQueue(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.poll()); + } + + /** + * toArray(a) contains all elements in FIFO order + */ + public void testToArray2() throws InterruptedException { + LinkedBlockingQueue q = populatedQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.poll()); + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + LinkedBlockingQueue q = populatedQueue(SIZE); + try { + q.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * iterator iterates through all elements + */ + public void testIterator() throws InterruptedException { + LinkedBlockingQueue q = populatedQueue(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + + it = q.iterator(); + for (i = 0; it.hasNext(); i++) + assertEquals(it.next(), q.take()); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new LinkedBlockingQueue().iterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final LinkedBlockingQueue q = new LinkedBlockingQueue(3); + q.add(two); + q.add(one); + q.add(three); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertSame(it.next(), one); + assertSame(it.next(), three); + assertFalse(it.hasNext()); + } + + /** + * iterator ordering is FIFO + */ + public void testIteratorOrdering() { + final LinkedBlockingQueue q = new LinkedBlockingQueue(3); + q.add(one); + q.add(two); + q.add(three); + assertEquals(0, q.remainingCapacity()); + int k = 0; + for (Iterator it = q.iterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + assertEquals(3, k); + } + + /** + * Modifications do not cause iterators to fail + */ + public void testWeaklyConsistentIteration() { + final LinkedBlockingQueue q = new LinkedBlockingQueue(3); + q.add(one); + q.add(two); + q.add(three); + for (Iterator it = q.iterator(); it.hasNext();) { + q.remove(); + it.next(); + } + assertEquals(0, q.size()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + LinkedBlockingQueue q = populatedQueue(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * offer transfers elements across Executor tasks + */ + public void testOfferInExecutor() { + final LinkedBlockingQueue q = new LinkedBlockingQueue(2); + q.add(one); + q.add(two); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(q.offer(three)); + threadsStarted.await(); + assertTrue(q.offer(three, LONG_DELAY_MS, MILLISECONDS)); + assertEquals(0, q.remainingCapacity()); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + assertSame(one, q.take()); + }}); + } + } + + /** + * timed poll retrieves elements across Executor threads + */ + public void testPollInExecutor() { + final LinkedBlockingQueue q = new LinkedBlockingQueue(2); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertNull(q.poll()); + threadsStarted.await(); + assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS)); + checkEmpty(q); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + q.put(one); + }}); + } + } + + /** + * A deserialized serialized queue has same elements in same order + */ + public void testSerialization() throws Exception { + Queue x = populatedQueue(SIZE); + Queue y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(), y.remove()); + } + assertTrue(y.isEmpty()); + } + + /** + * drainTo(c) empties queue into another collection c + */ + public void testDrainTo() { + LinkedBlockingQueue q = populatedQueue(SIZE); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(SIZE, l.size()); + for (int i = 0; i < SIZE; ++i) + assertEquals(l.get(i), new Integer(i)); + q.add(zero); + q.add(one); + assertFalse(q.isEmpty()); + assertTrue(q.contains(zero)); + assertTrue(q.contains(one)); + l.clear(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(2, l.size()); + for (int i = 0; i < 2; ++i) + assertEquals(l.get(i), new Integer(i)); + } + + /** + * drainTo empties full queue, unblocking a waiting put. + */ + public void testDrainToWithActivePut() throws InterruptedException { + final LinkedBlockingQueue q = populatedQueue(SIZE); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(new Integer(SIZE + 1)); + }}); + + t.start(); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertTrue(l.size() >= SIZE); + for (int i = 0; i < SIZE; ++i) + assertEquals(l.get(i), new Integer(i)); + t.join(); + assertTrue(q.size() + l.size() >= SIZE); + } + + /** + * drainTo(c, n) empties first min(n, size) elements of queue into c + */ + public void testDrainToN() { + LinkedBlockingQueue q = new LinkedBlockingQueue(); + for (int i = 0; i < SIZE + 2; ++i) { + for (int j = 0; j < SIZE; j++) + assertTrue(q.offer(new Integer(j))); + ArrayList l = new ArrayList(); + q.drainTo(l, i); + int k = (i < SIZE) ? i : SIZE; + assertEquals(k, l.size()); + assertEquals(SIZE - k, q.size()); + for (int j = 0; j < k; ++j) + assertEquals(l.get(j), new Integer(j)); + do {} while (q.poll() != null); + } + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Collection[] qs = { + new LinkedBlockingQueue(), + populatedQueue(2), + }; + + for (Collection q : qs) { + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/LinkedListTest.java b/jdk/test/java/util/concurrent/tck/LinkedListTest.java new file mode 100644 index 00000000000..ea0f689dc70 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/LinkedListTest.java @@ -0,0 +1,669 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.NoSuchElementException; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class LinkedListTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(LinkedListTest.class); + } + + /** + * Returns a new queue of given size containing consecutive + * Integers 0 ... n. + */ + private LinkedList populatedQueue(int n) { + LinkedList q = new LinkedList(); + assertTrue(q.isEmpty()); + for (int i = 0; i < n; ++i) + assertTrue(q.offer(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(n, q.size()); + return q; + } + + /** + * new queue is empty + */ + public void testConstructor1() { + assertEquals(0, new LinkedList().size()); + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new LinkedList((Collection)null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = i; + LinkedList q = new LinkedList(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + LinkedList q = new LinkedList(); + assertTrue(q.isEmpty()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.add(new Integer(2)); + q.remove(); + q.remove(); + assertTrue(q.isEmpty()); + } + + /** + * size changes when elements added and removed + */ + public void testSize() { + LinkedList q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.remove(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * offer(null) succeeds + */ + public void testOfferNull() { + LinkedList q = new LinkedList(); + q.offer(null); + assertNull(q.get(0)); + assertTrue(q.contains(null)); + } + + /** + * Offer succeeds + */ + public void testOffer() { + LinkedList q = new LinkedList(); + assertTrue(q.offer(new Integer(0))); + assertTrue(q.offer(new Integer(1))); + } + + /** + * add succeeds + */ + public void testAdd() { + LinkedList q = new LinkedList(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + assertTrue(q.add(new Integer(i))); + } + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + LinkedList q = new LinkedList(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements, in traversal order, of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = i; + LinkedList q = new LinkedList(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * addAll with too large an index throws IOOBE + */ + public void testAddAll2_IndexOutOfBoundsException() { + LinkedList l = new LinkedList(); + l.add(new Object()); + LinkedList m = new LinkedList(); + m.add(new Object()); + try { + l.addAll(4,m); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + + /** + * addAll with negative index throws IOOBE + */ + public void testAddAll4_BadIndex() { + LinkedList l = new LinkedList(); + l.add(new Object()); + LinkedList m = new LinkedList(); + m.add(new Object()); + try { + l.addAll(-1,m); + shouldThrow(); + } catch (IndexOutOfBoundsException success) {} + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + LinkedList q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll()); + } + assertNull(q.poll()); + } + + /** + * peek returns next element, or null if empty + */ + public void testPeek() { + LinkedList q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peek()); + assertEquals(i, q.poll()); + assertTrue(q.peek() == null || + !q.peek().equals(i)); + } + assertNull(q.peek()); + } + + /** + * element returns next element, or throws NSEE if empty + */ + public void testElement() { + LinkedList q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.element()); + assertEquals(i, q.poll()); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove removes next element, or throws NSEE if empty + */ + public void testRemove() { + LinkedList q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove(x) removes x and returns true if present + */ + public void testRemoveElement() { + LinkedList q = populatedQueue(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove((Integer)i)); + assertFalse(q.contains(i)); + assertTrue(q.contains(i - 1)); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove((Integer)i)); + assertFalse(q.contains(i)); + assertFalse(q.remove((Integer)(i + 1))); + assertFalse(q.contains(i + 1)); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + LinkedList q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.poll(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + LinkedList q = populatedQueue(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertTrue(q.add(new Integer(1))); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + LinkedList q = populatedQueue(SIZE); + LinkedList p = new LinkedList(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + assertTrue(p.add(new Integer(i))); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + LinkedList q = populatedQueue(SIZE); + LinkedList p = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + LinkedList q = populatedQueue(SIZE); + LinkedList p = populatedQueue(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.remove()); + assertFalse(q.contains(x)); + } + } + } + + /** + * toArray contains all elements in FIFO order + */ + public void testToArray() { + LinkedList q = populatedQueue(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.poll()); + } + + /** + * toArray(a) contains all elements in FIFO order + */ + public void testToArray2() { + LinkedList q = populatedQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.poll()); + } + + /** + * toArray(null) throws NullPointerException + */ + public void testToArray_NullArg() { + LinkedList l = new LinkedList(); + l.add(new Object()); + try { + l.toArray(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + LinkedList l = new LinkedList(); + l.add(new Integer(5)); + try { + l.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * iterator iterates through all elements + */ + public void testIterator() { + LinkedList q = populatedQueue(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new LinkedList().iterator()); + } + + /** + * iterator ordering is FIFO + */ + public void testIteratorOrdering() { + final LinkedList q = new LinkedList(); + q.add(new Integer(1)); + q.add(new Integer(2)); + q.add(new Integer(3)); + int k = 0; + for (Iterator it = q.iterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + + assertEquals(3, k); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final LinkedList q = new LinkedList(); + q.add(new Integer(1)); + q.add(new Integer(2)); + q.add(new Integer(3)); + Iterator it = q.iterator(); + assertEquals(1, it.next()); + it.remove(); + it = q.iterator(); + assertEquals(2, it.next()); + assertEquals(3, it.next()); + assertFalse(it.hasNext()); + } + + /** + * Descending iterator iterates through all elements + */ + public void testDescendingIterator() { + LinkedList q = populatedQueue(SIZE); + int i = 0; + Iterator it = q.descendingIterator(); + while (it.hasNext()) { + assertTrue(q.contains(it.next())); + ++i; + } + assertEquals(i, SIZE); + assertFalse(it.hasNext()); + try { + it.next(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * Descending iterator ordering is reverse FIFO + */ + public void testDescendingIteratorOrdering() { + final LinkedList q = new LinkedList(); + q.add(new Integer(3)); + q.add(new Integer(2)); + q.add(new Integer(1)); + int k = 0; + for (Iterator it = q.descendingIterator(); it.hasNext();) { + assertEquals(++k, it.next()); + } + + assertEquals(3, k); + } + + /** + * descendingIterator.remove removes current element + */ + public void testDescendingIteratorRemove() { + final LinkedList q = new LinkedList(); + q.add(three); + q.add(two); + q.add(one); + Iterator it = q.descendingIterator(); + it.next(); + it.remove(); + it = q.descendingIterator(); + assertSame(it.next(), two); + assertSame(it.next(), three); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + LinkedList q = populatedQueue(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * peek returns element inserted with addFirst + */ + public void testAddFirst() { + LinkedList q = populatedQueue(3); + q.addFirst(four); + assertSame(four, q.peek()); + } + + /** + * peekFirst returns element inserted with push + */ + public void testPush() { + LinkedList q = populatedQueue(3); + q.push(four); + assertSame(four, q.peekFirst()); + } + + /** + * pop removes next element, or throws NSEE if empty + */ + public void testPop() { + LinkedList q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pop()); + } + try { + q.pop(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * OfferFirst succeeds + */ + public void testOfferFirst() { + LinkedList q = new LinkedList(); + assertTrue(q.offerFirst(new Integer(0))); + assertTrue(q.offerFirst(new Integer(1))); + } + + /** + * OfferLast succeeds + */ + public void testOfferLast() { + LinkedList q = new LinkedList(); + assertTrue(q.offerLast(new Integer(0))); + assertTrue(q.offerLast(new Integer(1))); + } + + /** + * pollLast succeeds unless empty + */ + public void testPollLast() { + LinkedList q = populatedQueue(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.pollLast()); + } + assertNull(q.pollLast()); + } + + /** + * peekFirst returns next element, or null if empty + */ + public void testPeekFirst() { + LinkedList q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peekFirst()); + assertEquals(i, q.pollFirst()); + assertTrue(q.peekFirst() == null || + !q.peekFirst().equals(i)); + } + assertNull(q.peekFirst()); + } + + /** + * peekLast returns next element, or null if empty + */ + public void testPeekLast() { + LinkedList q = populatedQueue(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.peekLast()); + assertEquals(i, q.pollLast()); + assertTrue(q.peekLast() == null || + !q.peekLast().equals(i)); + } + assertNull(q.peekLast()); + } + + public void testFirstElement() { + LinkedList q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.getFirst()); + assertEquals(i, q.pollFirst()); + } + try { + q.getFirst(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * getLast returns next element, or throws NSEE if empty + */ + public void testLastElement() { + LinkedList q = populatedQueue(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.getLast()); + assertEquals(i, q.pollLast()); + } + try { + q.getLast(); + shouldThrow(); + } catch (NoSuchElementException success) {} + assertNull(q.peekLast()); + } + + /** + * removeFirstOccurrence(x) removes x and returns true if present + */ + public void testRemoveFirstOccurrence() { + LinkedList q = populatedQueue(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.removeFirstOccurrence(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.removeFirstOccurrence(new Integer(i))); + assertFalse(q.removeFirstOccurrence(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + + /** + * removeLastOccurrence(x) removes x and returns true if present + */ + public void testRemoveLastOccurrence() { + LinkedList q = populatedQueue(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.removeLastOccurrence(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.removeLastOccurrence(new Integer(i))); + assertFalse(q.removeLastOccurrence(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java b/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java new file mode 100644 index 00000000000..dd57870a306 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java @@ -0,0 +1,1085 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include John Vint + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedTransferQueue; + +import junit.framework.Test; + +@SuppressWarnings({"unchecked", "rawtypes"}) +public class LinkedTransferQueueTest extends JSR166TestCase { + static class Implementation implements CollectionImplementation { + public Class klazz() { return LinkedTransferQueue.class; } + public Collection emptyCollection() { return new LinkedTransferQueue(); } + public Object makeElement(int i) { return i; } + public boolean isConcurrent() { return true; } + public boolean permitsNulls() { return false; } + } + + public static class Generic extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new LinkedTransferQueue(); + } + } + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return newTestSuite(LinkedTransferQueueTest.class, + new Generic().testSuite(), + CollectionTest.testSuite(new Implementation())); + } + + /** + * Constructor builds new queue with size being zero and empty + * being true + */ + public void testConstructor1() { + assertEquals(0, new LinkedTransferQueue().size()); + assertTrue(new LinkedTransferQueue().isEmpty()); + } + + /** + * Initializing constructor with null collection throws + * NullPointerException + */ + public void testConstructor2() { + try { + new LinkedTransferQueue(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws + * NullPointerException + */ + public void testConstructor3() { + Collection elements = Arrays.asList(new Integer[SIZE]); + try { + new LinkedTransferQueue(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing constructor with a collection containing some null elements + * throws NullPointerException + */ + public void testConstructor4() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = i; + Collection elements = Arrays.asList(ints); + try { + new LinkedTransferQueue(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of the collection it is initialized by + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) { + ints[i] = i; + } + List intList = Arrays.asList(ints); + LinkedTransferQueue q + = new LinkedTransferQueue(intList); + assertEquals(q.size(), intList.size()); + assertEquals(q.toString(), intList.toString()); + assertTrue(Arrays.equals(q.toArray(), + intList.toArray())); + assertTrue(Arrays.equals(q.toArray(new Object[0]), + intList.toArray(new Object[0]))); + assertTrue(Arrays.equals(q.toArray(new Object[SIZE]), + intList.toArray(new Object[SIZE]))); + for (int i = 0; i < SIZE; ++i) { + assertEquals(ints[i], q.poll()); + } + } + + /** + * remainingCapacity() always returns Integer.MAX_VALUE + */ + public void testRemainingCapacity() { + BlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + assertEquals(SIZE - i, q.size()); + assertEquals(i, q.remove()); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + assertEquals(i, q.size()); + assertTrue(q.add(i)); + } + } + + /** + * addAll(this) throws IllegalArgumentException + */ + public void testAddAllSelf() { + LinkedTransferQueue q = populatedQueue(SIZE); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll of a collection with any null elements throws + * NullPointerException after possibly adding some elements + */ + public void testAddAll3() { + LinkedTransferQueue q = new LinkedTransferQueue(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = i; + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements, in traversal order, of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) { + ints[i] = i; + } + LinkedTransferQueue q = new LinkedTransferQueue(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) { + assertEquals(ints[i], q.poll()); + } + } + + /** + * all elements successfully put are contained + */ + public void testPut() { + LinkedTransferQueue q = new LinkedTransferQueue(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.put(i); + assertTrue(q.contains(i)); + } + } + + /** + * take retrieves elements in FIFO order + */ + public void testTake() throws InterruptedException { + LinkedTransferQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.take()); + } + } + + /** + * take removes existing elements until empty, then blocks interruptibly + */ + public void testBlockingTake() throws InterruptedException { + final BlockingQueue q = populatedQueue(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.take()); + } + + Thread.currentThread().interrupt(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() throws InterruptedException { + LinkedTransferQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.poll()); + } + assertNull(q.poll()); + checkEmpty(q); + } + + /** + * timed poll with zero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll0() throws InterruptedException { + LinkedTransferQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.poll(0, MILLISECONDS)); + } + assertNull(q.poll(0, MILLISECONDS)); + checkEmpty(q); + } + + /** + * timed poll with nonzero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll() throws InterruptedException { + LinkedTransferQueue q = populatedQueue(SIZE); + long startTime = System.nanoTime(); + for (int i = 0; i < SIZE; ++i) + assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + + startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + checkEmpty(q); + } + + /** + * Interrupted timed poll throws InterruptedException instead of + * returning timeout status + */ + public void testInterruptedTimedPoll() throws InterruptedException { + final BlockingQueue q = populatedQueue(SIZE); + final CountDownLatch aboutToWait = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + for (int i = 0; i < SIZE; ++i) + assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); + aboutToWait.countDown(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + aboutToWait.await(); + waitForThreadToEnterWaitState(t); + t.interrupt(); + awaitTermination(t); + checkEmpty(q); + } + + /** + * timed poll after thread interrupted throws InterruptedException + * instead of returning timeout status + */ + public void testTimedPollAfterInterrupt() throws InterruptedException { + final BlockingQueue q = populatedQueue(SIZE); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + Thread.currentThread().interrupt(); + for (int i = 0; i < SIZE; ++i) + assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + awaitTermination(t); + checkEmpty(q); + } + + /** + * peek returns next element, or null if empty + */ + public void testPeek() throws InterruptedException { + LinkedTransferQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.peek()); + assertEquals(i, (int) q.poll()); + assertTrue(q.peek() == null || + i != (int) q.peek()); + } + assertNull(q.peek()); + checkEmpty(q); + } + + /** + * element returns next element, or throws NoSuchElementException if empty + */ + public void testElement() throws InterruptedException { + LinkedTransferQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.element()); + assertEquals(i, (int) q.poll()); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + checkEmpty(q); + } + + /** + * remove removes next element, or throws NoSuchElementException if empty + */ + public void testRemove() throws InterruptedException { + LinkedTransferQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + checkEmpty(q); + } + + /** + * An add following remove(x) succeeds + */ + public void testRemoveElementAndAdd() throws InterruptedException { + LinkedTransferQueue q = new LinkedTransferQueue(); + assertTrue(q.add(one)); + assertTrue(q.add(two)); + assertTrue(q.remove(one)); + assertTrue(q.remove(two)); + assertTrue(q.add(three)); + assertSame(q.take(), three); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + LinkedTransferQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(i)); + assertEquals(i, (int) q.poll()); + assertFalse(q.contains(i)); + } + } + + /** + * clear removes all elements + */ + public void testClear() throws InterruptedException { + LinkedTransferQueue q = populatedQueue(SIZE); + q.clear(); + checkEmpty(q); + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + q.add(one); + assertFalse(q.isEmpty()); + assertEquals(1, q.size()); + assertTrue(q.contains(one)); + q.clear(); + checkEmpty(q); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + LinkedTransferQueue q = populatedQueue(SIZE); + LinkedTransferQueue p = new LinkedTransferQueue(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(i); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true + * if changed + */ + public void testRetainAll() { + LinkedTransferQueue q = populatedQueue(SIZE); + LinkedTransferQueue p = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) { + assertFalse(changed); + } else { + assertTrue(changed); + } + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true + * if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + LinkedTransferQueue q = populatedQueue(SIZE); + LinkedTransferQueue p = populatedQueue(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + assertFalse(q.contains(p.remove())); + } + } + } + + /** + * toArray() contains all elements in FIFO order + */ + public void testToArray() { + LinkedTransferQueue q = populatedQueue(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) { + assertSame(o[i], q.poll()); + } + } + + /** + * toArray(a) contains all elements in FIFO order + */ + public void testToArray2() { + LinkedTransferQueue q = populatedQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + for (int i = 0; i < ints.length; i++) { + assertSame(ints[i], q.poll()); + } + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + LinkedTransferQueue q = populatedQueue(SIZE); + try { + q.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * iterator iterates through all elements + */ + public void testIterator() throws InterruptedException { + LinkedTransferQueue q = populatedQueue(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + + it = q.iterator(); + for (i = 0; it.hasNext(); i++) + assertEquals(it.next(), q.take()); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new LinkedTransferQueue().iterator()); + } + + /** + * iterator.remove() removes current element + */ + public void testIteratorRemove() { + final LinkedTransferQueue q = new LinkedTransferQueue(); + q.add(two); + q.add(one); + q.add(three); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertSame(it.next(), one); + assertSame(it.next(), three); + assertFalse(it.hasNext()); + } + + /** + * iterator ordering is FIFO + */ + public void testIteratorOrdering() { + final LinkedTransferQueue q + = new LinkedTransferQueue(); + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + q.add(one); + q.add(two); + q.add(three); + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + int k = 0; + for (Integer n : q) { + assertEquals(++k, (int) n); + } + assertEquals(3, k); + } + + /** + * Modifications do not cause iterators to fail + */ + public void testWeaklyConsistentIteration() { + final LinkedTransferQueue q = new LinkedTransferQueue(); + q.add(one); + q.add(two); + q.add(three); + for (Iterator it = q.iterator(); it.hasNext();) { + q.remove(); + it.next(); + } + assertEquals(0, q.size()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + LinkedTransferQueue q = populatedQueue(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * offer transfers elements across Executor tasks + */ + public void testOfferInExecutor() { + final LinkedTransferQueue q = new LinkedTransferQueue(); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + long startTime = System.nanoTime(); + assertTrue(q.offer(one, LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + assertSame(one, q.take()); + checkEmpty(q); + }}); + } + } + + /** + * timed poll retrieves elements across Executor threads + */ + public void testPollInExecutor() { + final LinkedTransferQueue q = new LinkedTransferQueue(); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertNull(q.poll()); + threadsStarted.await(); + long startTime = System.nanoTime(); + assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + checkEmpty(q); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + q.put(one); + }}); + } + } + + /** + * A deserialized serialized queue has same elements in same order + */ + public void testSerialization() throws Exception { + Queue x = populatedQueue(SIZE); + Queue y = serialClone(x); + + assertNotSame(y, x); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertTrue(Arrays.equals(x.toArray(), y.toArray())); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(), y.remove()); + } + assertTrue(y.isEmpty()); + } + + /** + * drainTo(c) empties queue into another collection c + */ + public void testDrainTo() { + LinkedTransferQueue q = populatedQueue(SIZE); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(SIZE, l.size()); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, l.get(i)); + } + q.add(zero); + q.add(one); + assertFalse(q.isEmpty()); + assertTrue(q.contains(zero)); + assertTrue(q.contains(one)); + l.clear(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(2, l.size()); + for (int i = 0; i < 2; ++i) { + assertEquals(i, l.get(i)); + } + } + + /** + * drainTo(c) empties full queue, unblocking a waiting put. + */ + public void testDrainToWithActivePut() throws InterruptedException { + final LinkedTransferQueue q = populatedQueue(SIZE); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + q.put(SIZE + 1); + }}); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertTrue(l.size() >= SIZE); + for (int i = 0; i < SIZE; ++i) + assertEquals(i, l.get(i)); + awaitTermination(t); + assertTrue(q.size() + l.size() >= SIZE); + } + + /** + * drainTo(c, n) empties first min(n, size) elements of queue into c + */ + public void testDrainToN() { + LinkedTransferQueue q = new LinkedTransferQueue(); + for (int i = 0; i < SIZE + 2; ++i) { + for (int j = 0; j < SIZE; j++) { + assertTrue(q.offer(j)); + } + ArrayList l = new ArrayList(); + q.drainTo(l, i); + int k = (i < SIZE) ? i : SIZE; + assertEquals(k, l.size()); + assertEquals(SIZE - k, q.size()); + for (int j = 0; j < k; ++j) + assertEquals(j, l.get(j)); + do {} while (q.poll() != null); + } + } + + /** + * timed poll() or take() increments the waiting consumer count; + * offer(e) decrements the waiting consumer count + */ + public void testWaitingConsumer() throws InterruptedException { + final LinkedTransferQueue q = new LinkedTransferQueue(); + assertEquals(0, q.getWaitingConsumerCount()); + assertFalse(q.hasWaitingConsumer()); + final CountDownLatch threadStarted = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + long startTime = System.nanoTime(); + assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertEquals(0, q.getWaitingConsumerCount()); + assertFalse(q.hasWaitingConsumer()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + threadStarted.await(); + waitForThreadToEnterWaitState(t); + assertEquals(1, q.getWaitingConsumerCount()); + assertTrue(q.hasWaitingConsumer()); + + assertTrue(q.offer(one)); + assertEquals(0, q.getWaitingConsumerCount()); + assertFalse(q.hasWaitingConsumer()); + + awaitTermination(t); + } + + /** + * transfer(null) throws NullPointerException + */ + public void testTransfer1() throws InterruptedException { + try { + LinkedTransferQueue q = new LinkedTransferQueue(); + q.transfer(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * transfer waits until a poll occurs. The transfered element + * is returned by this associated poll. + */ + public void testTransfer2() throws InterruptedException { + final LinkedTransferQueue q + = new LinkedTransferQueue(); + final CountDownLatch threadStarted = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + q.transfer(five); + checkEmpty(q); + }}); + + threadStarted.await(); + waitForThreadToEnterWaitState(t); + assertEquals(1, q.size()); + assertSame(five, q.poll()); + checkEmpty(q); + awaitTermination(t); + } + + /** + * transfer waits until a poll occurs, and then transfers in fifo order + */ + public void testTransfer3() throws InterruptedException { + final LinkedTransferQueue q + = new LinkedTransferQueue(); + + Thread first = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.transfer(four); + assertTrue(!q.contains(four)); + assertEquals(1, q.size()); + }}); + + Thread interruptedThread = newStartedThread( + new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + while (q.isEmpty()) + Thread.yield(); + q.transfer(five); + }}); + + while (q.size() < 2) + Thread.yield(); + assertEquals(2, q.size()); + assertSame(four, q.poll()); + first.join(); + assertEquals(1, q.size()); + interruptedThread.interrupt(); + interruptedThread.join(); + checkEmpty(q); + } + + /** + * transfer waits until a poll occurs, at which point the polling + * thread returns the element + */ + public void testTransfer4() throws InterruptedException { + final LinkedTransferQueue q = new LinkedTransferQueue(); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.transfer(four); + assertFalse(q.contains(four)); + assertSame(three, q.poll()); + }}); + + while (q.isEmpty()) + Thread.yield(); + assertFalse(q.isEmpty()); + assertEquals(1, q.size()); + assertTrue(q.offer(three)); + assertSame(four, q.poll()); + awaitTermination(t); + } + + /** + * transfer waits until a take occurs. The transfered element + * is returned by this associated take. + */ + public void testTransfer5() throws InterruptedException { + final LinkedTransferQueue q + = new LinkedTransferQueue(); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.transfer(four); + checkEmpty(q); + }}); + + while (q.isEmpty()) + Thread.yield(); + assertFalse(q.isEmpty()); + assertEquals(1, q.size()); + assertSame(four, q.take()); + checkEmpty(q); + awaitTermination(t); + } + + /** + * tryTransfer(null) throws NullPointerException + */ + public void testTryTransfer1() { + final LinkedTransferQueue q = new LinkedTransferQueue(); + try { + q.tryTransfer(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * tryTransfer returns false and does not enqueue if there are no + * consumers waiting to poll or take. + */ + public void testTryTransfer2() throws InterruptedException { + final LinkedTransferQueue q = new LinkedTransferQueue(); + assertFalse(q.tryTransfer(new Object())); + assertFalse(q.hasWaitingConsumer()); + checkEmpty(q); + } + + /** + * If there is a consumer waiting in timed poll, tryTransfer + * returns true while successfully transfering object. + */ + public void testTryTransfer3() throws InterruptedException { + final Object hotPotato = new Object(); + final LinkedTransferQueue q = new LinkedTransferQueue(); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + while (! q.hasWaitingConsumer()) + Thread.yield(); + assertTrue(q.hasWaitingConsumer()); + checkEmpty(q); + assertTrue(q.tryTransfer(hotPotato)); + }}); + + long startTime = System.nanoTime(); + assertSame(hotPotato, q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + checkEmpty(q); + awaitTermination(t); + } + + /** + * If there is a consumer waiting in take, tryTransfer returns + * true while successfully transfering object. + */ + public void testTryTransfer4() throws InterruptedException { + final Object hotPotato = new Object(); + final LinkedTransferQueue q = new LinkedTransferQueue(); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + while (! q.hasWaitingConsumer()) + Thread.yield(); + assertTrue(q.hasWaitingConsumer()); + checkEmpty(q); + assertTrue(q.tryTransfer(hotPotato)); + }}); + + assertSame(q.take(), hotPotato); + checkEmpty(q); + awaitTermination(t); + } + + /** + * tryTransfer blocks interruptibly if no takers + */ + public void testTryTransfer5() throws InterruptedException { + final LinkedTransferQueue q = new LinkedTransferQueue(); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + assertTrue(q.isEmpty()); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + Thread.currentThread().interrupt(); + try { + q.tryTransfer(new Object(), LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.tryTransfer(new Object(), LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + checkEmpty(q); + } + + /** + * tryTransfer gives up after the timeout and returns false + */ + public void testTryTransfer6() throws InterruptedException { + final LinkedTransferQueue q = new LinkedTransferQueue(); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertFalse(q.tryTransfer(new Object(), + timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + checkEmpty(q); + }}); + + awaitTermination(t); + checkEmpty(q); + } + + /** + * tryTransfer waits for any elements previously in to be removed + * before transfering to a poll or take + */ + public void testTryTransfer7() throws InterruptedException { + final LinkedTransferQueue q = new LinkedTransferQueue(); + assertTrue(q.offer(four)); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertTrue(q.tryTransfer(five, LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + checkEmpty(q); + }}); + + while (q.size() != 2) + Thread.yield(); + assertEquals(2, q.size()); + assertSame(four, q.poll()); + assertSame(five, q.poll()); + checkEmpty(q); + awaitTermination(t); + } + + /** + * tryTransfer attempts to enqueue into the queue and fails + * returning false not enqueueing and the successive poll is null + */ + public void testTryTransfer8() throws InterruptedException { + final LinkedTransferQueue q = new LinkedTransferQueue(); + assertTrue(q.offer(four)); + assertEquals(1, q.size()); + long startTime = System.nanoTime(); + assertFalse(q.tryTransfer(five, timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + assertEquals(1, q.size()); + assertSame(four, q.poll()); + assertNull(q.poll()); + checkEmpty(q); + } + + private LinkedTransferQueue populatedQueue(int n) { + LinkedTransferQueue q = new LinkedTransferQueue(); + checkEmpty(q); + for (int i = 0; i < n; i++) { + assertEquals(i, q.size()); + assertTrue(q.offer(i)); + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + } + assertFalse(q.isEmpty()); + return q; + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Collection[] qs = { + new LinkedTransferQueue(), + populatedQueue(2), + }; + + for (Collection q : qs) { + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + } + } +} diff --git a/jdk/test/java/util/concurrent/tck/LockSupportTest.java b/jdk/test/java/util/concurrent/tck/LockSupportTest.java new file mode 100644 index 00000000000..02175ad1051 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/LockSupportTest.java @@ -0,0 +1,403 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.LockSupport; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class LockSupportTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(LockSupportTest.class); + } + + static { + // Reduce the risk of rare disastrous classloading in first call to + // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773 + Class ensureLoaded = LockSupport.class; + } + + /** + * Returns the blocker object used by tests in this file. + * Any old object will do; we'll return a convenient one. + */ + static Object theBlocker() { + return LockSupportTest.class; + } + + enum ParkMethod { + park() { + void park() { + LockSupport.park(); + } + void park(long millis) { + throw new UnsupportedOperationException(); + } + }, + parkUntil() { + void park(long millis) { + LockSupport.parkUntil(deadline(millis)); + } + }, + parkNanos() { + void park(long millis) { + LockSupport.parkNanos(MILLISECONDS.toNanos(millis)); + } + }, + parkBlocker() { + void park() { + LockSupport.park(theBlocker()); + } + void park(long millis) { + throw new UnsupportedOperationException(); + } + }, + parkUntilBlocker() { + void park(long millis) { + LockSupport.parkUntil(theBlocker(), deadline(millis)); + } + }, + parkNanosBlocker() { + void park(long millis) { + LockSupport.parkNanos(theBlocker(), + MILLISECONDS.toNanos(millis)); + } + }; + + void park() { park(2 * LONG_DELAY_MS); } + abstract void park(long millis); + + /** Returns a deadline to use with parkUntil. */ + long deadline(long millis) { + // beware of rounding + return System.currentTimeMillis() + millis + 1; + } + } + + /** + * park is released by subsequent unpark + */ + public void testParkBeforeUnpark_park() { + testParkBeforeUnpark(ParkMethod.park); + } + public void testParkBeforeUnpark_parkNanos() { + testParkBeforeUnpark(ParkMethod.parkNanos); + } + public void testParkBeforeUnpark_parkUntil() { + testParkBeforeUnpark(ParkMethod.parkUntil); + } + public void testParkBeforeUnpark_parkBlocker() { + testParkBeforeUnpark(ParkMethod.parkBlocker); + } + public void testParkBeforeUnpark_parkNanosBlocker() { + testParkBeforeUnpark(ParkMethod.parkNanosBlocker); + } + public void testParkBeforeUnpark_parkUntilBlocker() { + testParkBeforeUnpark(ParkMethod.parkUntilBlocker); + } + public void testParkBeforeUnpark(final ParkMethod parkMethod) { + final CountDownLatch pleaseUnpark = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + pleaseUnpark.countDown(); + parkMethod.park(); + }}); + + await(pleaseUnpark); + LockSupport.unpark(t); + awaitTermination(t); + } + + /** + * park is released by preceding unpark + */ + public void testParkAfterUnpark_park() { + testParkAfterUnpark(ParkMethod.park); + } + public void testParkAfterUnpark_parkNanos() { + testParkAfterUnpark(ParkMethod.parkNanos); + } + public void testParkAfterUnpark_parkUntil() { + testParkAfterUnpark(ParkMethod.parkUntil); + } + public void testParkAfterUnpark_parkBlocker() { + testParkAfterUnpark(ParkMethod.parkBlocker); + } + public void testParkAfterUnpark_parkNanosBlocker() { + testParkAfterUnpark(ParkMethod.parkNanosBlocker); + } + public void testParkAfterUnpark_parkUntilBlocker() { + testParkAfterUnpark(ParkMethod.parkUntilBlocker); + } + public void testParkAfterUnpark(final ParkMethod parkMethod) { + final CountDownLatch pleaseUnpark = new CountDownLatch(1); + final AtomicBoolean pleasePark = new AtomicBoolean(false); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + pleaseUnpark.countDown(); + while (!pleasePark.get()) + Thread.yield(); + parkMethod.park(); + }}); + + await(pleaseUnpark); + LockSupport.unpark(t); + pleasePark.set(true); + awaitTermination(t); + } + + /** + * park is released by subsequent interrupt + */ + public void testParkBeforeInterrupt_park() { + testParkBeforeInterrupt(ParkMethod.park); + } + public void testParkBeforeInterrupt_parkNanos() { + testParkBeforeInterrupt(ParkMethod.parkNanos); + } + public void testParkBeforeInterrupt_parkUntil() { + testParkBeforeInterrupt(ParkMethod.parkUntil); + } + public void testParkBeforeInterrupt_parkBlocker() { + testParkBeforeInterrupt(ParkMethod.parkBlocker); + } + public void testParkBeforeInterrupt_parkNanosBlocker() { + testParkBeforeInterrupt(ParkMethod.parkNanosBlocker); + } + public void testParkBeforeInterrupt_parkUntilBlocker() { + testParkBeforeInterrupt(ParkMethod.parkUntilBlocker); + } + public void testParkBeforeInterrupt(final ParkMethod parkMethod) { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + pleaseInterrupt.countDown(); + do { + parkMethod.park(); + // park may return spuriously + } while (! Thread.currentThread().isInterrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * park is released by preceding interrupt + */ + public void testParkAfterInterrupt_park() { + testParkAfterInterrupt(ParkMethod.park); + } + public void testParkAfterInterrupt_parkNanos() { + testParkAfterInterrupt(ParkMethod.parkNanos); + } + public void testParkAfterInterrupt_parkUntil() { + testParkAfterInterrupt(ParkMethod.parkUntil); + } + public void testParkAfterInterrupt_parkBlocker() { + testParkAfterInterrupt(ParkMethod.parkBlocker); + } + public void testParkAfterInterrupt_parkNanosBlocker() { + testParkAfterInterrupt(ParkMethod.parkNanosBlocker); + } + public void testParkAfterInterrupt_parkUntilBlocker() { + testParkAfterInterrupt(ParkMethod.parkUntilBlocker); + } + public void testParkAfterInterrupt(final ParkMethod parkMethod) { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + final AtomicBoolean pleasePark = new AtomicBoolean(false); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + pleaseInterrupt.countDown(); + while (!pleasePark.get()) + Thread.yield(); + assertTrue(Thread.currentThread().isInterrupted()); + parkMethod.park(); + assertTrue(Thread.currentThread().isInterrupted()); + }}); + + await(pleaseInterrupt); + t.interrupt(); + pleasePark.set(true); + awaitTermination(t); + } + + /** + * timed park times out if not unparked + */ + public void testParkTimesOut_parkNanos() { + testParkTimesOut(ParkMethod.parkNanos); + } + public void testParkTimesOut_parkUntil() { + testParkTimesOut(ParkMethod.parkUntil); + } + public void testParkTimesOut_parkNanosBlocker() { + testParkTimesOut(ParkMethod.parkNanosBlocker); + } + public void testParkTimesOut_parkUntilBlocker() { + testParkTimesOut(ParkMethod.parkUntilBlocker); + } + public void testParkTimesOut(final ParkMethod parkMethod) { + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + for (;;) { + long startTime = System.nanoTime(); + parkMethod.park(timeoutMillis()); + // park may return spuriously + if (millisElapsedSince(startTime) >= timeoutMillis()) + return; + } + }}); + + awaitTermination(t); + } + + /** + * getBlocker(null) throws NullPointerException + */ + public void testGetBlockerNull() { + try { + LockSupport.getBlocker(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getBlocker returns the blocker object passed to park + */ + public void testGetBlocker_parkBlocker() { + testGetBlocker(ParkMethod.parkBlocker); + } + public void testGetBlocker_parkNanosBlocker() { + testGetBlocker(ParkMethod.parkNanosBlocker); + } + public void testGetBlocker_parkUntilBlocker() { + testGetBlocker(ParkMethod.parkUntilBlocker); + } + public void testGetBlocker(final ParkMethod parkMethod) { + final CountDownLatch started = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + Thread t = Thread.currentThread(); + started.countDown(); + do { + assertNull(LockSupport.getBlocker(t)); + parkMethod.park(); + assertNull(LockSupport.getBlocker(t)); + // park may return spuriously + } while (! Thread.currentThread().isInterrupted()); + }}); + + long startTime = System.nanoTime(); + await(started); + for (;;) { + Object x = LockSupport.getBlocker(t); + if (x == theBlocker()) { // success + t.interrupt(); + awaitTermination(t); + assertNull(LockSupport.getBlocker(t)); + return; + } else { + assertNull(x); // ok + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + } + } + + /** + * timed park(0) returns immediately. + * + * Requires hotspot fix for: + * 6763959 java.util.concurrent.locks.LockSupport.parkUntil(0) blocks forever + * which is in jdk7-b118 and 6u25. + */ + public void testPark0_parkNanos() { + testPark0(ParkMethod.parkNanos); + } + public void testPark0_parkUntil() { + testPark0(ParkMethod.parkUntil); + } + public void testPark0_parkNanosBlocker() { + testPark0(ParkMethod.parkNanosBlocker); + } + public void testPark0_parkUntilBlocker() { + testPark0(ParkMethod.parkUntilBlocker); + } + public void testPark0(final ParkMethod parkMethod) { + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + parkMethod.park(0L); + }}); + + awaitTermination(t); + } + + /** + * timed park(Long.MIN_VALUE) returns immediately. + */ + public void testParkNeg_parkNanos() { + testParkNeg(ParkMethod.parkNanos); + } + public void testParkNeg_parkUntil() { + testParkNeg(ParkMethod.parkUntil); + } + public void testParkNeg_parkNanosBlocker() { + testParkNeg(ParkMethod.parkNanosBlocker); + } + public void testParkNeg_parkUntilBlocker() { + testParkNeg(ParkMethod.parkUntilBlocker); + } + public void testParkNeg(final ParkMethod parkMethod) { + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + parkMethod.park(Long.MIN_VALUE); + }}); + + awaitTermination(t); + } +} diff --git a/jdk/test/java/util/concurrent/tck/LongAccumulatorTest.java b/jdk/test/java/util/concurrent/tck/LongAccumulatorTest.java new file mode 100644 index 00000000000..6acfd27efc7 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/LongAccumulatorTest.java @@ -0,0 +1,183 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Phaser; +import java.util.concurrent.atomic.LongAccumulator; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class LongAccumulatorTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(LongAccumulatorTest.class); + } + + /** + * default constructed initializes to zero + */ + public void testConstructor() { + LongAccumulator ai = new LongAccumulator(Long::max, 0L); + assertEquals(0, ai.get()); + } + + /** + * accumulate accumulates given value to current, and get returns current value + */ + public void testAccumulateAndGet() { + LongAccumulator ai = new LongAccumulator(Long::max, 0L); + ai.accumulate(2); + assertEquals(2, ai.get()); + ai.accumulate(-4); + assertEquals(2, ai.get()); + ai.accumulate(4); + assertEquals(4, ai.get()); + } + + /** + * reset() causes subsequent get() to return zero + */ + public void testReset() { + LongAccumulator ai = new LongAccumulator(Long::max, 0L); + ai.accumulate(2); + assertEquals(2, ai.get()); + ai.reset(); + assertEquals(0, ai.get()); + } + + /** + * getThenReset() returns current value; subsequent get() returns zero + */ + public void testGetThenReset() { + LongAccumulator ai = new LongAccumulator(Long::max, 0L); + ai.accumulate(2); + assertEquals(2, ai.get()); + assertEquals(2, ai.getThenReset()); + assertEquals(0, ai.get()); + } + + /** + * toString returns current value. + */ + public void testToString() { + LongAccumulator ai = new LongAccumulator(Long::max, 0L); + assertEquals("0", ai.toString()); + ai.accumulate(1); + assertEquals(Long.toString(1), ai.toString()); + } + + /** + * intValue returns current value. + */ + public void testIntValue() { + LongAccumulator ai = new LongAccumulator(Long::max, 0L); + assertEquals(0, ai.intValue()); + ai.accumulate(1); + assertEquals(1, ai.intValue()); + } + + /** + * longValue returns current value. + */ + public void testLongValue() { + LongAccumulator ai = new LongAccumulator(Long::max, 0L); + assertEquals(0, ai.longValue()); + ai.accumulate(1); + assertEquals(1, ai.longValue()); + } + + /** + * floatValue returns current value. + */ + public void testFloatValue() { + LongAccumulator ai = new LongAccumulator(Long::max, 0L); + assertEquals(0.0f, ai.floatValue()); + ai.accumulate(1); + assertEquals(1.0f, ai.floatValue()); + } + + /** + * doubleValue returns current value. + */ + public void testDoubleValue() { + LongAccumulator ai = new LongAccumulator(Long::max, 0L); + assertEquals(0.0, ai.doubleValue()); + ai.accumulate(1); + assertEquals(1.0, ai.doubleValue()); + } + + /** + * accumulates by multiple threads produce correct result + */ + public void testAccumulateAndGetMT() { + final int incs = 1000000; + final int nthreads = 4; + final ExecutorService pool = Executors.newCachedThreadPool(); + LongAccumulator a = new LongAccumulator(Long::max, 0L); + Phaser phaser = new Phaser(nthreads + 1); + for (int i = 0; i < nthreads; ++i) + pool.execute(new AccTask(a, phaser, incs)); + phaser.arriveAndAwaitAdvance(); + phaser.arriveAndAwaitAdvance(); + long expected = incs - 1; + long result = a.get(); + assertEquals(expected, result); + pool.shutdown(); + } + + static final class AccTask implements Runnable { + final LongAccumulator acc; + final Phaser phaser; + final int incs; + volatile long result; + AccTask(LongAccumulator acc, Phaser phaser, int incs) { + this.acc = acc; + this.phaser = phaser; + this.incs = incs; + } + + public void run() { + phaser.arriveAndAwaitAdvance(); + LongAccumulator a = acc; + for (int i = 0; i < incs; ++i) + a.accumulate(i); + result = a.get(); + phaser.arrive(); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/LongAdderTest.java b/jdk/test/java/util/concurrent/tck/LongAdderTest.java new file mode 100644 index 00000000000..4f0d5e07f75 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/LongAdderTest.java @@ -0,0 +1,220 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.LongAdder; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class LongAdderTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(LongAdderTest.class); + } + + /** + * default constructed initializes to zero + */ + public void testConstructor() { + LongAdder ai = new LongAdder(); + assertEquals(0, ai.sum()); + } + + /** + * add adds given value to current, and sum returns current value + */ + public void testAddAndSum() { + LongAdder ai = new LongAdder(); + ai.add(2); + assertEquals(2, ai.sum()); + ai.add(-4); + assertEquals(-2, ai.sum()); + } + + /** + * decrement decrements and sum returns current value + */ + public void testDecrementAndsum() { + LongAdder ai = new LongAdder(); + ai.decrement(); + assertEquals(-1, ai.sum()); + ai.decrement(); + assertEquals(-2, ai.sum()); + } + + /** + * incrementAndGet increments and returns current value + */ + public void testIncrementAndsum() { + LongAdder ai = new LongAdder(); + ai.increment(); + assertEquals(1, ai.sum()); + ai.increment(); + assertEquals(2, ai.sum()); + } + + /** + * reset() causes subsequent sum() to return zero + */ + public void testReset() { + LongAdder ai = new LongAdder(); + ai.add(2); + assertEquals(2, ai.sum()); + ai.reset(); + assertEquals(0, ai.sum()); + } + + /** + * sumThenReset() returns sum; subsequent sum() returns zero + */ + public void testSumThenReset() { + LongAdder ai = new LongAdder(); + ai.add(2); + assertEquals(2, ai.sum()); + assertEquals(2, ai.sumThenReset()); + assertEquals(0, ai.sum()); + } + + /** + * a deserialized serialized adder holds same value + */ + public void testSerialization() throws Exception { + LongAdder x = new LongAdder(); + LongAdder y = serialClone(x); + assertNotSame(x, y); + x.add(-22); + LongAdder z = serialClone(x); + assertNotSame(y, z); + assertEquals(-22, x.sum()); + assertEquals(0, y.sum()); + assertEquals(-22, z.sum()); + } + + /** + * toString returns current value. + */ + public void testToString() { + LongAdder ai = new LongAdder(); + assertEquals("0", ai.toString()); + ai.increment(); + assertEquals(Long.toString(1), ai.toString()); + } + + /** + * intValue returns current value. + */ + public void testIntValue() { + LongAdder ai = new LongAdder(); + assertEquals(0, ai.intValue()); + ai.increment(); + assertEquals(1, ai.intValue()); + } + + /** + * longValue returns current value. + */ + public void testLongValue() { + LongAdder ai = new LongAdder(); + assertEquals(0, ai.longValue()); + ai.increment(); + assertEquals(1, ai.longValue()); + } + + /** + * floatValue returns current value. + */ + public void testFloatValue() { + LongAdder ai = new LongAdder(); + assertEquals(0.0f, ai.floatValue()); + ai.increment(); + assertEquals(1.0f, ai.floatValue()); + } + + /** + * doubleValue returns current value. + */ + public void testDoubleValue() { + LongAdder ai = new LongAdder(); + assertEquals(0.0, ai.doubleValue()); + ai.increment(); + assertEquals(1.0, ai.doubleValue()); + } + + /** + * adds by multiple threads produce correct sum + */ + public void testAddAndSumMT() throws Throwable { + final int incs = 1000000; + final int nthreads = 4; + final ExecutorService pool = Executors.newCachedThreadPool(); + LongAdder a = new LongAdder(); + CyclicBarrier barrier = new CyclicBarrier(nthreads + 1); + for (int i = 0; i < nthreads; ++i) + pool.execute(new AdderTask(a, barrier, incs)); + barrier.await(); + barrier.await(); + long total = (long)nthreads * incs; + long sum = a.sum(); + assertEquals(sum, total); + pool.shutdown(); + } + + static final class AdderTask implements Runnable { + final LongAdder adder; + final CyclicBarrier barrier; + final int incs; + volatile long result; + AdderTask(LongAdder adder, CyclicBarrier barrier, int incs) { + this.adder = adder; + this.barrier = barrier; + this.incs = incs; + } + + public void run() { + try { + barrier.await(); + LongAdder a = adder; + for (int i = 0; i < incs; ++i) + a.add(1L); + result = a.sum(); + barrier.await(); + } catch (Throwable t) { throw new Error(t); } + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/PhaserTest.java b/jdk/test/java/util/concurrent/tck/PhaserTest.java new file mode 100644 index 00000000000..69b6c808ff8 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/PhaserTest.java @@ -0,0 +1,820 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include John Vint + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Phaser; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class PhaserTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(PhaserTest.class); + } + + private static final int maxParties = 65535; + + /** Checks state of unterminated phaser. */ + protected void assertState(Phaser phaser, + int phase, int parties, int unarrived) { + assertEquals(phase, phaser.getPhase()); + assertEquals(parties, phaser.getRegisteredParties()); + assertEquals(unarrived, phaser.getUnarrivedParties()); + assertEquals(parties - unarrived, phaser.getArrivedParties()); + assertFalse(phaser.isTerminated()); + } + + /** Checks state of terminated phaser. */ + protected void assertTerminated(Phaser phaser, int maxPhase, int parties) { + assertTrue(phaser.isTerminated()); + int expectedPhase = maxPhase + Integer.MIN_VALUE; + assertEquals(expectedPhase, phaser.getPhase()); + assertEquals(parties, phaser.getRegisteredParties()); + assertEquals(expectedPhase, phaser.register()); + assertEquals(expectedPhase, phaser.arrive()); + assertEquals(expectedPhase, phaser.arriveAndDeregister()); + } + + protected void assertTerminated(Phaser phaser, int maxPhase) { + assertTerminated(phaser, maxPhase, 0); + } + + /** + * Empty constructor builds a new Phaser with no parent, no registered + * parties and initial phase number of 0 + */ + public void testConstructorDefaultValues() { + Phaser phaser = new Phaser(); + assertNull(phaser.getParent()); + assertEquals(0, phaser.getRegisteredParties()); + assertEquals(0, phaser.getArrivedParties()); + assertEquals(0, phaser.getUnarrivedParties()); + assertEquals(0, phaser.getPhase()); + } + + /** + * Constructing with a negative number of parties throws + * IllegalArgumentException + */ + public void testConstructorNegativeParties() { + try { + new Phaser(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructing with a negative number of parties throws + * IllegalArgumentException + */ + public void testConstructorNegativeParties2() { + try { + new Phaser(new Phaser(), -1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructing with a number of parties > 65535 throws + * IllegalArgumentException + */ + public void testConstructorPartiesExceedsLimit() { + new Phaser(maxParties); + try { + new Phaser(maxParties + 1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + + new Phaser(new Phaser(), maxParties); + try { + new Phaser(new Phaser(), maxParties + 1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * The parent provided to the constructor should be returned from + * a later call to getParent + */ + public void testConstructor3() { + Phaser parent = new Phaser(); + assertSame(parent, new Phaser(parent).getParent()); + assertNull(new Phaser(null).getParent()); + } + + /** + * The parent being input into the parameter should equal the original + * parent when being returned + */ + public void testConstructor5() { + Phaser parent = new Phaser(); + assertSame(parent, new Phaser(parent, 0).getParent()); + assertNull(new Phaser(null, 0).getParent()); + } + + /** + * register() will increment the number of unarrived parties by + * one and not affect its arrived parties + */ + public void testRegister1() { + Phaser phaser = new Phaser(); + assertState(phaser, 0, 0, 0); + assertEquals(0, phaser.register()); + assertState(phaser, 0, 1, 1); + } + + /** + * Registering more than 65536 parties causes IllegalStateException + */ + public void testRegister2() { + Phaser phaser = new Phaser(0); + assertState(phaser, 0, 0, 0); + assertEquals(0, phaser.bulkRegister(maxParties - 10)); + assertState(phaser, 0, maxParties - 10, maxParties - 10); + for (int i = 0; i < 10; i++) { + assertState(phaser, 0, maxParties - 10 + i, maxParties - 10 + i); + assertEquals(0, phaser.register()); + } + assertState(phaser, 0, maxParties, maxParties); + try { + phaser.register(); + shouldThrow(); + } catch (IllegalStateException success) {} + + try { + phaser.bulkRegister(Integer.MAX_VALUE); + shouldThrow(); + } catch (IllegalStateException success) {} + + assertEquals(0, phaser.bulkRegister(0)); + assertState(phaser, 0, maxParties, maxParties); + } + + /** + * register() correctly returns the current barrier phase number + * when invoked + */ + public void testRegister3() { + Phaser phaser = new Phaser(); + assertEquals(0, phaser.register()); + assertEquals(0, phaser.arrive()); + assertEquals(1, phaser.register()); + assertState(phaser, 1, 2, 2); + } + + /** + * register causes the next arrive to not increment the phase + * rather retain the phase number + */ + public void testRegister4() { + Phaser phaser = new Phaser(1); + assertEquals(0, phaser.arrive()); + assertEquals(1, phaser.register()); + assertEquals(1, phaser.arrive()); + assertState(phaser, 1, 2, 1); + } + + /** + * register on a subphaser that is currently empty succeeds, even + * in the presence of another non-empty subphaser + */ + public void testRegisterEmptySubPhaser() { + Phaser root = new Phaser(); + Phaser child1 = new Phaser(root, 1); + Phaser child2 = new Phaser(root, 0); + assertEquals(0, child2.register()); + assertState(root, 0, 2, 2); + assertState(child1, 0, 1, 1); + assertState(child2, 0, 1, 1); + assertEquals(0, child2.arriveAndDeregister()); + assertState(root, 0, 1, 1); + assertState(child1, 0, 1, 1); + assertState(child2, 0, 0, 0); + assertEquals(0, child2.register()); + assertEquals(0, child2.arriveAndDeregister()); + assertState(root, 0, 1, 1); + assertState(child1, 0, 1, 1); + assertState(child2, 0, 0, 0); + assertEquals(0, child1.arriveAndDeregister()); + assertTerminated(root, 1); + assertTerminated(child1, 1); + assertTerminated(child2, 1); + } + + /** + * Invoking bulkRegister with a negative parameter throws an + * IllegalArgumentException + */ + public void testBulkRegister1() { + try { + new Phaser().bulkRegister(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * bulkRegister should correctly record the number of unarrived + * parties with the number of parties being registered + */ + public void testBulkRegister2() { + Phaser phaser = new Phaser(); + assertEquals(0, phaser.bulkRegister(0)); + assertState(phaser, 0, 0, 0); + assertEquals(0, phaser.bulkRegister(20)); + assertState(phaser, 0, 20, 20); + } + + /** + * Registering with a number of parties greater than or equal to 1<<16 + * throws IllegalStateException. + */ + public void testBulkRegister3() { + assertEquals(0, new Phaser().bulkRegister((1 << 16) - 1)); + + try { + new Phaser().bulkRegister(1 << 16); + shouldThrow(); + } catch (IllegalStateException success) {} + + try { + new Phaser(2).bulkRegister((1 << 16) - 2); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * the phase number increments correctly when tripping the barrier + */ + public void testPhaseIncrement1() { + for (int size = 1; size < nine; size++) { + final Phaser phaser = new Phaser(size); + for (int index = 0; index <= (1 << size); index++) { + int phase = phaser.arrive(); + assertTrue(index % size == 0 ? (index / size) == phase : index - (phase * size) > 0); + } + } + } + + /** + * arrive() on a registered phaser increments phase. + */ + public void testArrive1() { + Phaser phaser = new Phaser(1); + assertState(phaser, 0, 1, 1); + assertEquals(0, phaser.arrive()); + assertState(phaser, 1, 1, 1); + } + + /** + * arriveAndDeregister does not wait for others to arrive at barrier + */ + public void testArriveAndDeregister() { + final Phaser phaser = new Phaser(1); + for (int i = 0; i < 10; i++) { + assertState(phaser, 0, 1, 1); + assertEquals(0, phaser.register()); + assertState(phaser, 0, 2, 2); + assertEquals(0, phaser.arriveAndDeregister()); + assertState(phaser, 0, 1, 1); + } + assertEquals(0, phaser.arriveAndDeregister()); + assertTerminated(phaser, 1); + } + + /** + * arriveAndDeregister does not wait for others to arrive at barrier + */ + public void testArrive2() { + final Phaser phaser = new Phaser(); + assertEquals(0, phaser.register()); + List threads = new ArrayList(); + for (int i = 0; i < 10; i++) { + assertEquals(0, phaser.register()); + threads.add(newStartedThread(new CheckedRunnable() { + public void realRun() { + assertEquals(0, phaser.arriveAndDeregister()); + }})); + } + + for (Thread thread : threads) + awaitTermination(thread); + assertState(phaser, 0, 1, 1); + assertEquals(0, phaser.arrive()); + assertState(phaser, 1, 1, 1); + } + + /** + * arrive() returns a negative number if the Phaser is terminated + */ + public void testArrive3() { + Phaser phaser = new Phaser(1); + phaser.forceTermination(); + assertTerminated(phaser, 0, 1); + assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE); + assertTrue(phaser.arrive() < 0); + assertTrue(phaser.register() < 0); + assertTrue(phaser.arriveAndDeregister() < 0); + assertTrue(phaser.awaitAdvance(1) < 0); + assertTrue(phaser.getPhase() < 0); + } + + /** + * arriveAndDeregister() throws IllegalStateException if number of + * registered or unarrived parties would become negative + */ + public void testArriveAndDeregister1() { + Phaser phaser = new Phaser(); + try { + phaser.arriveAndDeregister(); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * arriveAndDeregister reduces the number of arrived parties + */ + public void testArriveAndDeregister2() { + final Phaser phaser = new Phaser(1); + assertEquals(0, phaser.register()); + assertEquals(0, phaser.arrive()); + assertState(phaser, 0, 2, 1); + assertEquals(0, phaser.arriveAndDeregister()); + assertState(phaser, 1, 1, 1); + } + + /** + * arriveAndDeregister arrives at the barrier on a phaser with a parent and + * when a deregistration occurs and causes the phaser to have zero parties + * its parent will be deregistered as well + */ + public void testArriveAndDeregister3() { + Phaser parent = new Phaser(); + Phaser child = new Phaser(parent); + assertState(child, 0, 0, 0); + assertState(parent, 0, 0, 0); + assertEquals(0, child.register()); + assertState(child, 0, 1, 1); + assertState(parent, 0, 1, 1); + assertEquals(0, child.arriveAndDeregister()); + assertTerminated(child, 1); + assertTerminated(parent, 1); + } + + /** + * arriveAndDeregister deregisters one party from its parent when + * the number of parties of child is zero after deregistration + */ + public void testArriveAndDeregister4() { + Phaser parent = new Phaser(); + Phaser child = new Phaser(parent); + assertEquals(0, parent.register()); + assertEquals(0, child.register()); + assertState(child, 0, 1, 1); + assertState(parent, 0, 2, 2); + assertEquals(0, child.arriveAndDeregister()); + assertState(child, 0, 0, 0); + assertState(parent, 0, 1, 1); + } + + /** + * arriveAndDeregister deregisters one party from its parent when + * the number of parties of root is nonzero after deregistration. + */ + public void testArriveAndDeregister5() { + Phaser root = new Phaser(); + Phaser parent = new Phaser(root); + Phaser child = new Phaser(parent); + assertState(root, 0, 0, 0); + assertState(parent, 0, 0, 0); + assertState(child, 0, 0, 0); + assertEquals(0, child.register()); + assertState(root, 0, 1, 1); + assertState(parent, 0, 1, 1); + assertState(child, 0, 1, 1); + assertEquals(0, child.arriveAndDeregister()); + assertTerminated(child, 1); + assertTerminated(parent, 1); + assertTerminated(root, 1); + } + + /** + * arriveAndDeregister returns the phase in which it leaves the + * phaser in after deregistration + */ + public void testArriveAndDeregister6() { + final Phaser phaser = new Phaser(2); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertEquals(0, phaser.arrive()); + }}); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + assertState(phaser, 1, 2, 2); + assertEquals(1, phaser.arriveAndDeregister()); + assertState(phaser, 1, 1, 1); + assertEquals(1, phaser.arriveAndDeregister()); + assertTerminated(phaser, 2); + awaitTermination(t); + } + + /** + * awaitAdvance succeeds upon advance + */ + public void testAwaitAdvance1() { + final Phaser phaser = new Phaser(1); + assertEquals(0, phaser.arrive()); + assertEquals(1, phaser.awaitAdvance(0)); + } + + /** + * awaitAdvance with a negative parameter will return without affecting the + * phaser + */ + public void testAwaitAdvance2() { + Phaser phaser = new Phaser(); + assertTrue(phaser.awaitAdvance(-1) < 0); + assertState(phaser, 0, 0, 0); + } + + /** + * awaitAdvanceInterruptibly blocks interruptibly + */ + public void testAwaitAdvanceInterruptibly_interruptible() throws InterruptedException { + final Phaser phaser = new Phaser(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(2); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + Thread.currentThread().interrupt(); + try { + phaser.awaitAdvanceInterruptibly(0); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + phaser.awaitAdvanceInterruptibly(0); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws TimeoutException { + Thread.currentThread().interrupt(); + try { + phaser.awaitAdvanceInterruptibly(0, 2*LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + phaser.awaitAdvanceInterruptibly(0, 2*LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertState(phaser, 0, 1, 1); + assertThreadsStayAlive(t1, t2); + t1.interrupt(); + t2.interrupt(); + awaitTermination(t1); + awaitTermination(t2); + assertState(phaser, 0, 1, 1); + assertEquals(0, phaser.arrive()); + assertState(phaser, 1, 1, 1); + } + + /** + * awaitAdvance continues waiting if interrupted before waiting + */ + public void testAwaitAdvanceAfterInterrupt() { + final Phaser phaser = new Phaser(); + assertEquals(0, phaser.register()); + final CountDownLatch pleaseArrive = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + Thread.currentThread().interrupt(); + assertEquals(0, phaser.register()); + assertEquals(0, phaser.arrive()); + pleaseArrive.countDown(); + assertTrue(Thread.currentThread().isInterrupted()); + assertEquals(1, phaser.awaitAdvance(0)); + assertTrue(Thread.interrupted()); + }}); + + await(pleaseArrive); + waitForThreadToEnterWaitState(t, SHORT_DELAY_MS); + assertEquals(0, phaser.arrive()); + awaitTermination(t); + + Thread.currentThread().interrupt(); + assertEquals(1, phaser.awaitAdvance(0)); + assertTrue(Thread.interrupted()); + } + + /** + * awaitAdvance continues waiting if interrupted while waiting + */ + public void testAwaitAdvanceBeforeInterrupt() { + final Phaser phaser = new Phaser(); + assertEquals(0, phaser.register()); + final CountDownLatch pleaseArrive = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertEquals(0, phaser.register()); + assertEquals(0, phaser.arrive()); + assertFalse(Thread.currentThread().isInterrupted()); + pleaseArrive.countDown(); + assertEquals(1, phaser.awaitAdvance(0)); + assertTrue(Thread.interrupted()); + }}); + + await(pleaseArrive); + waitForThreadToEnterWaitState(t, SHORT_DELAY_MS); + t.interrupt(); + assertEquals(0, phaser.arrive()); + awaitTermination(t); + + Thread.currentThread().interrupt(); + assertEquals(1, phaser.awaitAdvance(0)); + assertTrue(Thread.interrupted()); + } + + /** + * arriveAndAwaitAdvance continues waiting if interrupted before waiting + */ + public void testArriveAndAwaitAdvanceAfterInterrupt() { + final Phaser phaser = new Phaser(); + assertEquals(0, phaser.register()); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + Thread.currentThread().interrupt(); + assertEquals(0, phaser.register()); + pleaseInterrupt.countDown(); + assertTrue(Thread.currentThread().isInterrupted()); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + assertTrue(Thread.currentThread().isInterrupted()); + }}); + + await(pleaseInterrupt); + waitForThreadToEnterWaitState(t, SHORT_DELAY_MS); + Thread.currentThread().interrupt(); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + assertTrue(Thread.interrupted()); + awaitTermination(t); + } + + /** + * arriveAndAwaitAdvance continues waiting if interrupted while waiting + */ + public void testArriveAndAwaitAdvanceBeforeInterrupt() { + final Phaser phaser = new Phaser(); + assertEquals(0, phaser.register()); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertEquals(0, phaser.register()); + assertFalse(Thread.currentThread().isInterrupted()); + pleaseInterrupt.countDown(); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + assertTrue(Thread.currentThread().isInterrupted()); + }}); + + await(pleaseInterrupt); + waitForThreadToEnterWaitState(t, SHORT_DELAY_MS); + t.interrupt(); + Thread.currentThread().interrupt(); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + assertTrue(Thread.interrupted()); + awaitTermination(t); + } + + /** + * awaitAdvance atomically waits for all parties within the same phase to + * complete before continuing + */ + public void testAwaitAdvance4() { + final Phaser phaser = new Phaser(4); + final AtomicInteger count = new AtomicInteger(0); + List threads = new ArrayList(); + for (int i = 0; i < 4; i++) + threads.add(newStartedThread(new CheckedRunnable() { + public void realRun() { + for (int k = 0; k < 3; k++) { + assertEquals(2 * k + 1, phaser.arriveAndAwaitAdvance()); + count.incrementAndGet(); + assertEquals(2 * k + 1, phaser.arrive()); + assertEquals(2 * k + 2, phaser.awaitAdvance(2 * k + 1)); + assertEquals(4 * (k + 1), count.get()); + }}})); + + for (Thread thread : threads) + awaitTermination(thread); + } + + /** + * awaitAdvance returns the current phase + */ + public void testAwaitAdvance5() { + final Phaser phaser = new Phaser(1); + assertEquals(1, phaser.awaitAdvance(phaser.arrive())); + assertEquals(1, phaser.getPhase()); + assertEquals(1, phaser.register()); + List threads = new ArrayList(); + for (int i = 0; i < 8; i++) { + final CountDownLatch latch = new CountDownLatch(1); + final boolean goesFirst = ((i & 1) == 0); + threads.add(newStartedThread(new CheckedRunnable() { + public void realRun() { + if (goesFirst) + latch.countDown(); + else + await(latch); + phaser.arrive(); + }})); + if (goesFirst) + await(latch); + else + latch.countDown(); + assertEquals(i + 2, phaser.awaitAdvance(phaser.arrive())); + assertEquals(i + 2, phaser.getPhase()); + } + for (Thread thread : threads) + awaitTermination(thread); + } + + /** + * awaitAdvance returns the current phase in child phasers + */ + public void testAwaitAdvanceTieredPhaser() throws Exception { + final Phaser parent = new Phaser(); + final List zeroPartyChildren = new ArrayList(3); + final List onePartyChildren = new ArrayList(3); + for (int i = 0; i < 3; i++) { + zeroPartyChildren.add(new Phaser(parent, 0)); + onePartyChildren.add(new Phaser(parent, 1)); + } + final List phasers = new ArrayList(); + phasers.addAll(zeroPartyChildren); + phasers.addAll(onePartyChildren); + phasers.add(parent); + for (Phaser phaser : phasers) { + assertEquals(-42, phaser.awaitAdvance(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, MEDIUM_DELAY_MS, MILLISECONDS)); + } + + for (Phaser child : onePartyChildren) + assertEquals(0, child.arrive()); + for (Phaser phaser : phasers) { + assertEquals(-42, phaser.awaitAdvance(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, MEDIUM_DELAY_MS, MILLISECONDS)); + assertEquals(1, phaser.awaitAdvance(0)); + assertEquals(1, phaser.awaitAdvanceInterruptibly(0)); + assertEquals(1, phaser.awaitAdvanceInterruptibly(0, MEDIUM_DELAY_MS, MILLISECONDS)); + } + + for (Phaser child : onePartyChildren) + assertEquals(1, child.arrive()); + for (Phaser phaser : phasers) { + assertEquals(-42, phaser.awaitAdvance(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, MEDIUM_DELAY_MS, MILLISECONDS)); + assertEquals(2, phaser.awaitAdvance(0)); + assertEquals(2, phaser.awaitAdvanceInterruptibly(0)); + assertEquals(2, phaser.awaitAdvanceInterruptibly(0, MEDIUM_DELAY_MS, MILLISECONDS)); + assertEquals(2, phaser.awaitAdvance(1)); + assertEquals(2, phaser.awaitAdvanceInterruptibly(1)); + assertEquals(2, phaser.awaitAdvanceInterruptibly(1, MEDIUM_DELAY_MS, MILLISECONDS)); + } + } + + /** + * awaitAdvance returns when the phaser is externally terminated + */ + public void testAwaitAdvance6() { + final Phaser phaser = new Phaser(3); + final CountDownLatch pleaseForceTermination = new CountDownLatch(2); + final List threads = new ArrayList(); + for (int i = 0; i < 2; i++) { + Runnable r = new CheckedRunnable() { + public void realRun() { + assertEquals(0, phaser.arrive()); + pleaseForceTermination.countDown(); + assertTrue(phaser.awaitAdvance(0) < 0); + assertTrue(phaser.isTerminated()); + assertTrue(phaser.getPhase() < 0); + assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE); + assertEquals(3, phaser.getRegisteredParties()); + }}; + threads.add(newStartedThread(r)); + } + await(pleaseForceTermination); + phaser.forceTermination(); + assertTrue(phaser.isTerminated()); + assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE); + for (Thread thread : threads) + awaitTermination(thread); + assertEquals(3, phaser.getRegisteredParties()); + } + + /** + * arriveAndAwaitAdvance throws IllegalStateException with no + * unarrived parties + */ + public void testArriveAndAwaitAdvance1() { + Phaser phaser = new Phaser(); + try { + phaser.arriveAndAwaitAdvance(); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * arriveAndAwaitAdvance waits for all threads to arrive, the + * number of arrived parties is the same number that is accounted + * for when the main thread awaitsAdvance + */ + public void testArriveAndAwaitAdvance3() { + final Phaser phaser = new Phaser(1); + final int THREADS = 3; + final CountDownLatch pleaseArrive = new CountDownLatch(THREADS); + final List threads = new ArrayList(); + for (int i = 0; i < THREADS; i++) + threads.add(newStartedThread(new CheckedRunnable() { + public void realRun() { + assertEquals(0, phaser.register()); + pleaseArrive.countDown(); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + }})); + + await(pleaseArrive); + long startTime = System.nanoTime(); + while (phaser.getArrivedParties() < THREADS) + Thread.yield(); + assertEquals(THREADS, phaser.getArrivedParties()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + for (Thread thread : threads) + waitForThreadToEnterWaitState(thread, SHORT_DELAY_MS); + for (Thread thread : threads) + assertTrue(thread.isAlive()); + assertState(phaser, 0, THREADS + 1, 1); + phaser.arriveAndAwaitAdvance(); + for (Thread thread : threads) + awaitTermination(thread); + assertState(phaser, 1, THREADS + 1, THREADS + 1); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java new file mode 100644 index 00000000000..c586837720a --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java @@ -0,0 +1,764 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.PriorityBlockingQueue; + +import junit.framework.Test; + +public class PriorityBlockingQueueTest extends JSR166TestCase { + + public static class Generic extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new PriorityBlockingQueue(); + } + } + + public static class InitialCapacity extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new PriorityBlockingQueue(SIZE); + } + } + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return newTestSuite(PriorityBlockingQueueTest.class, + new Generic().testSuite(), + new InitialCapacity().testSuite()); + } + + /** Sample Comparator */ + static class MyReverseComparator implements Comparator { + public int compare(Object x, Object y) { + return ((Comparable)y).compareTo(x); + } + } + + /** + * Returns a new queue of given size containing consecutive + * Integers 0 ... n. + */ + private PriorityBlockingQueue populatedQueue(int n) { + PriorityBlockingQueue q = + new PriorityBlockingQueue(n); + assertTrue(q.isEmpty()); + for (int i = n - 1; i >= 0; i -= 2) + assertTrue(q.offer(new Integer(i))); + for (int i = (n & 1); i < n; i += 2) + assertTrue(q.offer(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + assertEquals(n, q.size()); + return q; + } + + /** + * A new queue has unbounded capacity + */ + public void testConstructor1() { + assertEquals(Integer.MAX_VALUE, + new PriorityBlockingQueue(SIZE).remainingCapacity()); + } + + /** + * Constructor throws IAE if capacity argument nonpositive + */ + public void testConstructor2() { + try { + new PriorityBlockingQueue(0); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new PriorityBlockingQueue(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NPE + */ + public void testConstructor4() { + Collection elements = Arrays.asList(new Integer[SIZE]); + try { + new PriorityBlockingQueue(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws NPE + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = i; + Collection elements = Arrays.asList(ints); + try { + new PriorityBlockingQueue(elements); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = i; + PriorityBlockingQueue q = new PriorityBlockingQueue(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * The comparator used in constructor is used + */ + public void testConstructor7() { + MyReverseComparator cmp = new MyReverseComparator(); + PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE, cmp); + assertEquals(cmp, q.comparator()); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + q.addAll(Arrays.asList(ints)); + for (int i = SIZE - 1; i >= 0; --i) + assertEquals(ints[i], q.poll()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + PriorityBlockingQueue q = new PriorityBlockingQueue(2); + assertTrue(q.isEmpty()); + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + q.add(one); + assertFalse(q.isEmpty()); + q.add(two); + q.remove(); + q.remove(); + assertTrue(q.isEmpty()); + } + + /** + * remainingCapacity() always returns Integer.MAX_VALUE + */ + public void testRemainingCapacity() { + BlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + assertEquals(SIZE - i, q.size()); + assertEquals(i, q.remove()); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(Integer.MAX_VALUE, q.remainingCapacity()); + assertEquals(i, q.size()); + assertTrue(q.add(i)); + } + } + + /** + * Offer of comparable element succeeds + */ + public void testOffer() { + PriorityBlockingQueue q = new PriorityBlockingQueue(1); + assertTrue(q.offer(zero)); + assertTrue(q.offer(one)); + } + + /** + * Offer of non-Comparable throws CCE + */ + public void testOfferNonComparable() { + PriorityBlockingQueue q = new PriorityBlockingQueue(1); + try { + q.offer(new Object()); + q.offer(new Object()); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * add of comparable succeeds + */ + public void testAdd() { + PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + assertTrue(q.add(new Integer(i))); + } + } + + /** + * addAll(this) throws IAE + */ + public void testAddAllSelf() { + PriorityBlockingQueue q = populatedQueue(SIZE); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = SIZE - 1; i >= 0; --i) + ints[i] = new Integer(i); + PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * all elements successfully put are contained + */ + public void testPut() { + PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + Integer x = new Integer(i); + q.put(x); + assertTrue(q.contains(x)); + } + assertEquals(SIZE, q.size()); + } + + /** + * put doesn't block waiting for take + */ + public void testPutWithTake() throws InterruptedException { + final PriorityBlockingQueue q = new PriorityBlockingQueue(2); + final int size = 4; + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + for (int i = 0; i < size; i++) + q.put(new Integer(0)); + }}); + + awaitTermination(t); + assertEquals(size, q.size()); + q.take(); + } + + /** + * timed offer does not time out + */ + public void testTimedOffer() throws InterruptedException { + final PriorityBlockingQueue q = new PriorityBlockingQueue(2); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + q.put(new Integer(0)); + q.put(new Integer(0)); + assertTrue(q.offer(new Integer(0), SHORT_DELAY_MS, MILLISECONDS)); + assertTrue(q.offer(new Integer(0), LONG_DELAY_MS, MILLISECONDS)); + }}); + + awaitTermination(t); + } + + /** + * take retrieves elements in priority order + */ + public void testTake() throws InterruptedException { + PriorityBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.take()); + } + } + + /** + * Take removes existing elements until empty, then blocks interruptibly + */ + public void testBlockingTake() throws InterruptedException { + final PriorityBlockingQueue q = populatedQueue(SIZE); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.take()); + } + + Thread.currentThread().interrupt(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.take(); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + PriorityBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll()); + } + assertNull(q.poll()); + } + + /** + * timed poll with zero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll0() throws InterruptedException { + PriorityBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll(0, MILLISECONDS)); + } + assertNull(q.poll(0, MILLISECONDS)); + } + + /** + * timed poll with nonzero timeout succeeds when non-empty, else times out + */ + public void testTimedPoll() throws InterruptedException { + PriorityBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + long startTime = System.nanoTime(); + assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + long startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + checkEmpty(q); + } + + /** + * Interrupted timed poll throws InterruptedException instead of + * returning timeout status + */ + public void testInterruptedTimedPoll() throws InterruptedException { + final BlockingQueue q = populatedQueue(SIZE); + final CountDownLatch aboutToWait = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, (int) q.poll(LONG_DELAY_MS, MILLISECONDS)); + } + aboutToWait.countDown(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) { + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + }}); + + aboutToWait.await(); + waitForThreadToEnterWaitState(t, LONG_DELAY_MS); + t.interrupt(); + awaitTermination(t); + } + + /** + * peek returns next element, or null if empty + */ + public void testPeek() { + PriorityBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peek()); + assertEquals(i, q.poll()); + assertTrue(q.peek() == null || + !q.peek().equals(i)); + } + assertNull(q.peek()); + } + + /** + * element returns next element, or throws NSEE if empty + */ + public void testElement() { + PriorityBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.element()); + assertEquals(i, q.poll()); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove removes next element, or throws NSEE if empty + */ + public void testRemove() { + PriorityBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + PriorityBlockingQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.poll(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + PriorityBlockingQueue q = populatedQueue(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + q.add(one); + assertFalse(q.isEmpty()); + assertTrue(q.contains(one)); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + PriorityBlockingQueue q = populatedQueue(SIZE); + PriorityBlockingQueue p = new PriorityBlockingQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + PriorityBlockingQueue q = populatedQueue(SIZE); + PriorityBlockingQueue p = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + PriorityBlockingQueue q = populatedQueue(SIZE); + PriorityBlockingQueue p = populatedQueue(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.remove()); + assertFalse(q.contains(x)); + } + } + } + + /** + * toArray contains all elements + */ + public void testToArray() throws InterruptedException { + PriorityBlockingQueue q = populatedQueue(SIZE); + Object[] o = q.toArray(); + Arrays.sort(o); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.take()); + } + + /** + * toArray(a) contains all elements + */ + public void testToArray2() throws InterruptedException { + PriorityBlockingQueue q = populatedQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + Arrays.sort(ints); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.take()); + } + + /** + * toArray(incompatible array type) throws ArrayStoreException + */ + public void testToArray1_BadArg() { + PriorityBlockingQueue q = populatedQueue(SIZE); + try { + q.toArray(new String[10]); + shouldThrow(); + } catch (ArrayStoreException success) {} + } + + /** + * iterator iterates through all elements + */ + public void testIterator() { + PriorityBlockingQueue q = populatedQueue(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new PriorityBlockingQueue().iterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final PriorityBlockingQueue q = new PriorityBlockingQueue(3); + q.add(new Integer(2)); + q.add(new Integer(1)); + q.add(new Integer(3)); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertEquals(it.next(), new Integer(2)); + assertEquals(it.next(), new Integer(3)); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + PriorityBlockingQueue q = populatedQueue(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * timed poll transfers elements across Executor tasks + */ + public void testPollInExecutor() { + final PriorityBlockingQueue q = new PriorityBlockingQueue(2); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertNull(q.poll()); + threadsStarted.await(); + assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS)); + checkEmpty(q); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + q.put(one); + }}); + } + } + + /** + * A deserialized serialized queue has same elements + */ + public void testSerialization() throws Exception { + Queue x = populatedQueue(SIZE); + Queue y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(), y.remove()); + } + assertTrue(y.isEmpty()); + } + + /** + * drainTo(c) empties queue into another collection c + */ + public void testDrainTo() { + PriorityBlockingQueue q = populatedQueue(SIZE); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(SIZE, l.size()); + for (int i = 0; i < SIZE; ++i) + assertEquals(l.get(i), new Integer(i)); + q.add(zero); + q.add(one); + assertFalse(q.isEmpty()); + assertTrue(q.contains(zero)); + assertTrue(q.contains(one)); + l.clear(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(2, l.size()); + for (int i = 0; i < 2; ++i) + assertEquals(l.get(i), new Integer(i)); + } + + /** + * drainTo empties queue + */ + public void testDrainToWithActivePut() throws InterruptedException { + final PriorityBlockingQueue q = populatedQueue(SIZE); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() { + q.put(new Integer(SIZE + 1)); + }}); + + t.start(); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertTrue(l.size() >= SIZE); + for (int i = 0; i < SIZE; ++i) + assertEquals(l.get(i), new Integer(i)); + t.join(); + assertTrue(q.size() + l.size() >= SIZE); + } + + /** + * drainTo(c, n) empties first min(n, size) elements of queue into c + */ + public void testDrainToN() { + PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE * 2); + for (int i = 0; i < SIZE + 2; ++i) { + for (int j = 0; j < SIZE; j++) + assertTrue(q.offer(new Integer(j))); + ArrayList l = new ArrayList(); + q.drainTo(l, i); + int k = (i < SIZE) ? i : SIZE; + assertEquals(k, l.size()); + assertEquals(SIZE - k, q.size()); + for (int j = 0; j < k; ++j) + assertEquals(l.get(j), new Integer(j)); + do {} while (q.poll() != null); + } + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Collection[] qs = { + new PriorityBlockingQueue(), + populatedQueue(2), + }; + + for (Collection q : qs) { + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java b/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java new file mode 100644 index 00000000000..edb2379e2ec --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java @@ -0,0 +1,528 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.PriorityQueue; +import java.util.Queue; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class PriorityQueueTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(PriorityQueueTest.class); + } + + static class MyReverseComparator implements Comparator { + public int compare(Object x, Object y) { + return ((Comparable)y).compareTo(x); + } + } + + /** + * Returns a new queue of given size containing consecutive + * Integers 0 ... n. + */ + private PriorityQueue populatedQueue(int n) { + PriorityQueue q = new PriorityQueue(n); + assertTrue(q.isEmpty()); + for (int i = n - 1; i >= 0; i -= 2) + assertTrue(q.offer(new Integer(i))); + for (int i = (n & 1); i < n; i += 2) + assertTrue(q.offer(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(n, q.size()); + return q; + } + + /** + * A new queue has unbounded capacity + */ + public void testConstructor1() { + assertEquals(0, new PriorityQueue(SIZE).size()); + } + + /** + * Constructor throws IAE if capacity argument nonpositive + */ + public void testConstructor2() { + try { + new PriorityQueue(0); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new PriorityQueue((Collection)null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NPE + */ + public void testConstructor4() { + try { + new PriorityQueue(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws NPE + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + new PriorityQueue(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + PriorityQueue q = new PriorityQueue(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.poll()); + } + + /** + * The comparator used in constructor is used + */ + public void testConstructor7() { + MyReverseComparator cmp = new MyReverseComparator(); + PriorityQueue q = new PriorityQueue(SIZE, cmp); + assertEquals(cmp, q.comparator()); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + q.addAll(Arrays.asList(ints)); + for (int i = SIZE - 1; i >= 0; --i) + assertEquals(ints[i], q.poll()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + PriorityQueue q = new PriorityQueue(2); + assertTrue(q.isEmpty()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.add(new Integer(2)); + q.remove(); + q.remove(); + assertTrue(q.isEmpty()); + } + + /** + * size changes when elements added and removed + */ + public void testSize() { + PriorityQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.remove(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * offer(null) throws NPE + */ + public void testOfferNull() { + PriorityQueue q = new PriorityQueue(1); + try { + q.offer(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * add(null) throws NPE + */ + public void testAddNull() { + PriorityQueue q = new PriorityQueue(1); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Offer of comparable element succeeds + */ + public void testOffer() { + PriorityQueue q = new PriorityQueue(1); + assertTrue(q.offer(zero)); + assertTrue(q.offer(one)); + } + + /** + * Offer of non-Comparable throws CCE + */ + public void testOfferNonComparable() { + PriorityQueue q = new PriorityQueue(1); + try { + q.offer(new Object()); + q.offer(new Object()); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * add of comparable succeeds + */ + public void testAdd() { + PriorityQueue q = new PriorityQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + assertTrue(q.add(new Integer(i))); + } + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + PriorityQueue q = new PriorityQueue(1); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testAddAll2() { + PriorityQueue q = new PriorityQueue(SIZE); + try { + q.addAll(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + PriorityQueue q = new PriorityQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Queue contains all elements of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(SIZE - 1 - i); + PriorityQueue q = new PriorityQueue(SIZE); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(new Integer(i), q.poll()); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + PriorityQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.poll()); + } + assertNull(q.poll()); + } + + /** + * peek returns next element, or null if empty + */ + public void testPeek() { + PriorityQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.peek()); + assertEquals(i, q.poll()); + assertTrue(q.peek() == null || + !q.peek().equals(i)); + } + assertNull(q.peek()); + } + + /** + * element returns next element, or throws NSEE if empty + */ + public void testElement() { + PriorityQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.element()); + assertEquals(i, q.poll()); + } + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove removes next element, or throws NSEE if empty + */ + public void testRemove() { + PriorityQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.remove()); + } + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove(x) removes x and returns true if present + */ + public void testRemoveElement() { + PriorityQueue q = populatedQueue(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertTrue(q.contains(i - 1)); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertFalse(q.remove(i + 1)); + assertFalse(q.contains(i + 1)); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + PriorityQueue q = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.poll(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + PriorityQueue q = populatedQueue(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + PriorityQueue q = populatedQueue(SIZE); + PriorityQueue p = new PriorityQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + PriorityQueue q = populatedQueue(SIZE); + PriorityQueue p = populatedQueue(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.remove(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + PriorityQueue q = populatedQueue(SIZE); + PriorityQueue p = populatedQueue(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.remove()); + assertFalse(q.contains(x)); + } + } + } + + /** + * toArray contains all elements + */ + public void testToArray() { + PriorityQueue q = populatedQueue(SIZE); + Object[] o = q.toArray(); + Arrays.sort(o); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.poll()); + } + + /** + * toArray(a) contains all elements + */ + public void testToArray2() { + PriorityQueue q = populatedQueue(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + Arrays.sort(ints); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.poll()); + } + + /** + * iterator iterates through all elements + */ + public void testIterator() { + PriorityQueue q = populatedQueue(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty collection has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new PriorityQueue().iterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final PriorityQueue q = new PriorityQueue(3); + q.add(new Integer(2)); + q.add(new Integer(1)); + q.add(new Integer(3)); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertEquals(it.next(), new Integer(2)); + assertEquals(it.next(), new Integer(3)); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + PriorityQueue q = populatedQueue(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized queue has same elements + */ + public void testSerialization() throws Exception { + Queue x = populatedQueue(SIZE); + Queue y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.remove(), y.remove()); + } + assertTrue(y.isEmpty()); + } +} diff --git a/jdk/test/java/util/concurrent/tck/RecursiveActionTest.java b/jdk/test/java/util/concurrent/tck/RecursiveActionTest.java new file mode 100644 index 00000000000..9ce68c34166 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/RecursiveActionTest.java @@ -0,0 +1,1272 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.RecursiveAction; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeoutException; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class RecursiveActionTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(RecursiveActionTest.class); + } + + private static ForkJoinPool mainPool() { + return new ForkJoinPool(); + } + + private static ForkJoinPool singletonPool() { + return new ForkJoinPool(1); + } + + private static ForkJoinPool asyncSingletonPool() { + return new ForkJoinPool(1, + ForkJoinPool.defaultForkJoinWorkerThreadFactory, + null, true); + } + + private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) { + try (PoolCleaner cleaner = cleaner(pool)) { + checkNotDone(a); + + assertNull(pool.invoke(a)); + + checkCompletedNormally(a); + } + } + + void checkNotDone(RecursiveAction a) { + assertFalse(a.isDone()); + assertFalse(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + + if (! ForkJoinTask.inForkJoinPool()) { + Thread.currentThread().interrupt(); + try { + a.get(); + shouldThrow(); + } catch (InterruptedException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + Thread.currentThread().interrupt(); + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (InterruptedException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + try { + a.get(0L, SECONDS); + shouldThrow(); + } catch (TimeoutException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedNormally(RecursiveAction a) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertTrue(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + assertNull(a.join()); + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + try { + assertNull(a.get()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertNull(a.get(5L, SECONDS)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCancelled(RecursiveAction a) { + assertTrue(a.isDone()); + assertTrue(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertTrue(a.getException() instanceof CancellationException); + assertNull(a.getRawResult()); + + try { + a.join(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedAbnormally(RecursiveAction a, Throwable t) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertSame(t.getClass(), a.getException().getClass()); + assertNull(a.getRawResult()); + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + + try { + a.join(); + shouldThrow(); + } catch (Throwable expected) { + assertSame(expected.getClass(), t.getClass()); + } + + try { + a.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + public static final class FJException extends RuntimeException { + public FJException() { super(); } + public FJException(Throwable cause) { super(cause); } + } + + // A simple recursive action for testing + final class FibAction extends CheckedRecursiveAction { + final int number; + int result; + FibAction(int n) { number = n; } + protected void realCompute() { + int n = number; + if (n <= 1) + result = n; + else { + FibAction f1 = new FibAction(n - 1); + FibAction f2 = new FibAction(n - 2); + invokeAll(f1, f2); + result = f1.result + f2.result; + } + } + } + + // A recursive action failing in base case + static final class FailingFibAction extends RecursiveAction { + final int number; + int result; + FailingFibAction(int n) { number = n; } + public void compute() { + int n = number; + if (n <= 1) + throw new FJException(); + else { + FailingFibAction f1 = new FailingFibAction(n - 1); + FailingFibAction f2 = new FailingFibAction(n - 2); + invokeAll(f1, f2); + result = f1.result + f2.result; + } + } + } + + /** + * invoke returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks. getRawResult of a RecursiveAction returns null; + */ + public void testInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertNull(f.invoke()); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyInvoke task returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks + */ + public void testQuietlyInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + f.quietlyInvoke(); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join of a forked task returns when task completes + */ + public void testForkJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertNull(f.join()); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join/quietlyJoin of a forked task succeeds in the presence of interrupts + */ + public void testJoinIgnoresInterrupts() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + final Thread myself = Thread.currentThread(); + + // test join() + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + assertNull(f.join()); + Thread.interrupted(); + assertEquals(21, f.result); + checkCompletedNormally(f); + + f = new FibAction(8); + f.cancel(true); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + Thread.interrupted(); + checkCancelled(f); + } + + f = new FibAction(8); + f.completeExceptionally(new FJException()); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + Thread.interrupted(); + checkCompletedAbnormally(f, success); + } + + // test quietlyJoin() + f = new FibAction(8); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + Thread.interrupted(); + assertEquals(21, f.result); + checkCompletedNormally(f); + + f = new FibAction(8); + f.cancel(true); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + Thread.interrupted(); + checkCancelled(f); + + f = new FibAction(8); + f.completeExceptionally(new FJException()); + assertSame(f, f.fork()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + Thread.interrupted(); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(mainPool(), a); + a.reinitialize(); + testInvokeOnPool(singletonPool(), a); + } + + /** + * join/quietlyJoin of a forked task when not in ForkJoinPool + * succeeds in the presence of interrupts + */ + public void testJoinIgnoresInterruptsOutsideForkJoinPool() { + final SynchronousQueue sq = + new SynchronousQueue(); + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws InterruptedException { + FibAction[] fibActions = new FibAction[6]; + for (int i = 0; i < fibActions.length; i++) + fibActions[i] = new FibAction(8); + + fibActions[1].cancel(false); + fibActions[2].completeExceptionally(new FJException()); + fibActions[4].cancel(true); + fibActions[5].completeExceptionally(new FJException()); + + for (int i = 0; i < fibActions.length; i++) + fibActions[i].fork(); + + sq.put(fibActions); + + helpQuiesce(); + }}; + + Runnable r = new CheckedRunnable() { + public void realRun() throws InterruptedException { + FibAction[] fibActions = sq.take(); + FibAction f; + final Thread myself = Thread.currentThread(); + + // test join() ------------ + + f = fibActions[0]; + assertFalse(ForkJoinTask.inForkJoinPool()); + myself.interrupt(); + assertTrue(myself.isInterrupted()); + assertNull(f.join()); + assertTrue(Thread.interrupted()); + assertEquals(21, f.result); + checkCompletedNormally(f); + + f = fibActions[1]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + assertTrue(Thread.interrupted()); + checkCancelled(f); + } + + f = fibActions[2]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + assertTrue(Thread.interrupted()); + checkCompletedAbnormally(f, success); + } + + // test quietlyJoin() --------- + + f = fibActions[3]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + assertTrue(Thread.interrupted()); + assertEquals(21, f.result); + checkCompletedNormally(f); + + f = fibActions[4]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + assertTrue(Thread.interrupted()); + checkCancelled(f); + + f = fibActions[5]; + myself.interrupt(); + assertTrue(myself.isInterrupted()); + f.quietlyJoin(); + assertTrue(Thread.interrupted()); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + + Thread t; + + t = newStartedThread(r); + testInvokeOnPool(mainPool(), a); + awaitTermination(t); + + a.reinitialize(); + t = newStartedThread(r); + testInvokeOnPool(singletonPool(), a); + awaitTermination(t); + } + + /** + * get of a forked task returns when task completes + */ + public void testForkGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertNull(f.get()); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get of a forked task returns when task completes + */ + public void testForkTimedGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertNull(f.get(5L, SECONDS)); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get with null time unit throws NPE + */ + public void testForkTimedGetNPE() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + try { + f.get(5L, null); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes + */ + public void testForkQuietlyJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertEquals(21, f.result); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * helpQuiesce returns when tasks are complete. + * getQueuedTaskCount returns 0 when quiescent + */ + public void testForkHelpQuiesce() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + helpQuiesce(); + while (!f.isDone()) // wait out race + ; + assertEquals(21, f.result); + assertEquals(0, getQueuedTaskCount()); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invoke task throws exception when task completes abnormally + */ + public void testAbnormalInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyInvoke task returns when task completes abnormally + */ + public void testAbnormalQuietlyInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + f.quietlyInvoke(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingFibAction f = new FailingFibAction(8); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkTimedGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FailingFibAction f = new FailingFibAction(8); + assertSame(f, f.fork()); + try { + f.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task completes abnormally + */ + public void testAbnormalForkQuietlyJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invoke task throws exception when task cancelled + */ + public void testCancelledInvoke() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + try { + f.invoke(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * join of a forked task throws exception when task cancelled + */ + public void testCancelledForkJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.join(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * get of a forked task throws exception when task cancelled + */ + public void testCancelledForkGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * timed get of a forked task throws exception when task cancelled + */ + public void testCancelledForkTimedGet() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() throws Exception { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + f.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * quietlyJoin of a forked task returns when task cancelled + */ + public void testCancelledForkQuietlyJoin() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + f.quietlyJoin(); + checkCancelled(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * getPool of executing task returns its pool + */ + public void testGetPool() { + final ForkJoinPool mainPool = mainPool(); + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertSame(mainPool, getPool()); + }}; + testInvokeOnPool(mainPool, a); + } + + /** + * getPool of non-FJ task returns null + */ + public void testGetPool2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertNull(getPool()); + }}; + assertNull(a.invoke()); + } + + /** + * inForkJoinPool of executing task returns true + */ + public void testInForkJoinPool() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertTrue(inForkJoinPool()); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * inForkJoinPool of non-FJ task returns false + */ + public void testInForkJoinPool2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + assertFalse(inForkJoinPool()); + }}; + assertNull(a.invoke()); + } + + /** + * getPool of current thread in pool returns its pool + */ + public void testWorkerGetPool() { + final ForkJoinPool mainPool = mainPool(); + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + ForkJoinWorkerThread w = + (ForkJoinWorkerThread) Thread.currentThread(); + assertSame(mainPool, w.getPool()); + }}; + testInvokeOnPool(mainPool, a); + } + + /** + * getPoolIndex of current thread in pool returns 0 <= value < poolSize + */ + public void testWorkerGetPoolIndex() { + final ForkJoinPool mainPool = mainPool(); + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + ForkJoinWorkerThread w = + (ForkJoinWorkerThread) Thread.currentThread(); + assertTrue(w.getPoolIndex() >= 0); + // pool size can shrink after assigning index, so cannot check + // assertTrue(w.getPoolIndex() < mainPool.getPoolSize()); + }}; + testInvokeOnPool(mainPool, a); + } + + /** + * setRawResult(null) succeeds + */ + public void testSetRawResult() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + setRawResult(null); + assertNull(getRawResult()); + }}; + assertNull(a.invoke()); + } + + /** + * A reinitialized normally completed task may be re-invoked + */ + public void testReinitialize() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + checkNotDone(f); + + for (int i = 0; i < 3; i++) { + assertNull(f.invoke()); + assertEquals(21, f.result); + checkCompletedNormally(f); + f.reinitialize(); + checkNotDone(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * A reinitialized abnormally completed task may be re-invoked + */ + public void testReinitializeAbnormal() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + checkNotDone(f); + + for (int i = 0; i < 3; i++) { + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + f.reinitialize(); + checkNotDone(f); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invoke task throws exception after invoking completeExceptionally + */ + public void testCompleteExceptionally() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + f.completeExceptionally(new FJException()); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invoke task suppresses execution invoking complete + */ + public void testComplete() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + f.complete(null); + assertNull(f.invoke()); + assertEquals(0, f.result); + checkCompletedNormally(f); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(t1, t2) invokes all task arguments + */ + public void testInvokeAll2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FibAction g = new FibAction(9); + invokeAll(f, g); + checkCompletedNormally(f); + assertEquals(21, f.result); + checkCompletedNormally(g); + assertEquals(34, g.result); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument invokes task + */ + public void testInvokeAll1() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + invokeAll(f); + checkCompletedNormally(f); + assertEquals(21, f.result); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument invokes tasks + */ + public void testInvokeAll3() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FibAction g = new FibAction(9); + FibAction h = new FibAction(7); + invokeAll(f, g, h); + assertTrue(f.isDone()); + assertTrue(g.isDone()); + assertTrue(h.isDone()); + checkCompletedNormally(f); + assertEquals(21, f.result); + checkCompletedNormally(g); + assertEquals(34, g.result); + checkCompletedNormally(g); + assertEquals(13, h.result); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(collection) invokes all tasks in the collection + */ + public void testInvokeAllCollection() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FibAction g = new FibAction(9); + FibAction h = new FibAction(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + invokeAll(set); + assertTrue(f.isDone()); + assertTrue(g.isDone()); + assertTrue(h.isDone()); + checkCompletedNormally(f); + assertEquals(21, f.result); + checkCompletedNormally(g); + assertEquals(34, g.result); + checkCompletedNormally(g); + assertEquals(13, h.result); + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with any null task throws NPE + */ + public void testInvokeAllNPE() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FibAction g = new FibAction(9); + FibAction h = null; + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (NullPointerException success) {} + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(t1, t2) throw exception if any task does + */ + public void testAbnormalInvokeAll2() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FailingFibAction g = new FailingFibAction(9); + try { + invokeAll(f, g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with 1 argument throws exception if task does + */ + public void testAbnormalInvokeAll1() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction g = new FailingFibAction(9); + try { + invokeAll(g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(tasks) with > 2 argument throws exception if any task does + */ + public void testAbnormalInvokeAll3() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction f = new FibAction(8); + FailingFibAction g = new FailingFibAction(9); + FibAction h = new FibAction(7); + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * invokeAll(collection) throws exception if any task does + */ + public void testAbnormalInvokeAllCollection() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FailingFibAction f = new FailingFibAction(8); + FibAction g = new FibAction(9); + FibAction h = new FibAction(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + try { + invokeAll(set); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + }}; + testInvokeOnPool(mainPool(), a); + } + + /** + * tryUnfork returns true for most recent unexecuted task, + * and suppresses execution + */ + public void testTryUnfork() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction g = new FibAction(9); + assertSame(g, g.fork()); + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertTrue(f.tryUnfork()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * getSurplusQueuedTaskCount returns > 0 when + * there are more tasks than threads + */ + public void testGetSurplusQueuedTaskCount() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction h = new FibAction(7); + assertSame(h, h.fork()); + FibAction g = new FibAction(9); + assertSame(g, g.fork()); + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertTrue(getSurplusQueuedTaskCount() > 0); + helpQuiesce(); + assertEquals(0, getSurplusQueuedTaskCount()); + checkCompletedNormally(f); + checkCompletedNormally(g); + checkCompletedNormally(h); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * peekNextLocalTask returns most recent unexecuted task. + */ + public void testPeekNextLocalTask() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction g = new FibAction(9); + assertSame(g, g.fork()); + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertSame(f, peekNextLocalTask()); + assertNull(f.join()); + checkCompletedNormally(f); + helpQuiesce(); + checkCompletedNormally(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * pollNextLocalTask returns most recent unexecuted task + * without executing it + */ + public void testPollNextLocalTask() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction g = new FibAction(9); + assertSame(g, g.fork()); + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertSame(f, pollNextLocalTask()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * pollTask returns an unexecuted task without executing it + */ + public void testPollTask() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction g = new FibAction(9); + assertSame(g, g.fork()); + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertSame(f, pollTask()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(singletonPool(), a); + } + + /** + * peekNextLocalTask returns least recent unexecuted task in async mode + */ + public void testPeekNextLocalTaskAsync() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction g = new FibAction(9); + assertSame(g, g.fork()); + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertSame(g, peekNextLocalTask()); + assertNull(f.join()); + helpQuiesce(); + checkCompletedNormally(f); + checkCompletedNormally(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** + * pollNextLocalTask returns least recent unexecuted task without + * executing it, in async mode + */ + public void testPollNextLocalTaskAsync() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction g = new FibAction(9); + assertSame(g, g.fork()); + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertSame(g, pollNextLocalTask()); + helpQuiesce(); + checkCompletedNormally(f); + checkNotDone(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** + * pollTask returns an unexecuted task without executing it, in + * async mode + */ + public void testPollTaskAsync() { + RecursiveAction a = new CheckedRecursiveAction() { + protected void realCompute() { + FibAction g = new FibAction(9); + assertSame(g, g.fork()); + FibAction f = new FibAction(8); + assertSame(f, f.fork()); + assertSame(g, pollTask()); + helpQuiesce(); + checkCompletedNormally(f); + checkNotDone(g); + }}; + testInvokeOnPool(asyncSingletonPool(), a); + } + + /** Demo from RecursiveAction javadoc */ + static class SortTask extends RecursiveAction { + final long[] array; final int lo, hi; + SortTask(long[] array, int lo, int hi) { + this.array = array; this.lo = lo; this.hi = hi; + } + SortTask(long[] array) { this(array, 0, array.length); } + protected void compute() { + if (hi - lo < THRESHOLD) + sortSequentially(lo, hi); + else { + int mid = (lo + hi) >>> 1; + invokeAll(new SortTask(array, lo, mid), + new SortTask(array, mid, hi)); + merge(lo, mid, hi); + } + } + // implementation details follow: + static final int THRESHOLD = 100; + void sortSequentially(int lo, int hi) { + Arrays.sort(array, lo, hi); + } + void merge(int lo, int mid, int hi) { + long[] buf = Arrays.copyOfRange(array, lo, mid); + for (int i = 0, j = lo, k = mid; i < buf.length; j++) + array[j] = (k == hi || buf[i] < array[k]) ? + buf[i++] : array[k++]; + } + } + + /** + * SortTask demo works as advertised + */ + public void testSortTaskDemo() { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + long[] array = new long[1007]; + for (int i = 0; i < array.length; i++) + array[i] = rnd.nextLong(); + long[] arrayClone = array.clone(); + testInvokeOnPool(mainPool(), new SortTask(array)); + Arrays.sort(arrayClone); + assertTrue(Arrays.equals(array, arrayClone)); + } +} diff --git a/jdk/test/java/util/concurrent/tck/RecursiveTaskTest.java b/jdk/test/java/util/concurrent/tck/RecursiveTaskTest.java new file mode 100644 index 00000000000..ce13daa8e7b --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/RecursiveTaskTest.java @@ -0,0 +1,1053 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.HashSet; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.TimeoutException; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class RecursiveTaskTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(RecursiveTaskTest.class); + } + + private static ForkJoinPool mainPool() { + return new ForkJoinPool(); + } + + private static ForkJoinPool singletonPool() { + return new ForkJoinPool(1); + } + + private static ForkJoinPool asyncSingletonPool() { + return new ForkJoinPool(1, + ForkJoinPool.defaultForkJoinWorkerThreadFactory, + null, true); + } + + private T testInvokeOnPool(ForkJoinPool pool, RecursiveTask a) { + try (PoolCleaner cleaner = cleaner(pool)) { + checkNotDone(a); + + T result = pool.invoke(a); + + checkCompletedNormally(a, result); + return result; + } + } + + void checkNotDone(RecursiveTask a) { + assertFalse(a.isDone()); + assertFalse(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertFalse(a.isCancelled()); + assertNull(a.getException()); + assertNull(a.getRawResult()); + + if (! ForkJoinTask.inForkJoinPool()) { + Thread.currentThread().interrupt(); + try { + a.get(); + shouldThrow(); + } catch (InterruptedException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + Thread.currentThread().interrupt(); + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (InterruptedException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + try { + a.get(0L, SECONDS); + shouldThrow(); + } catch (TimeoutException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedNormally(RecursiveTask a, T expected) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertTrue(a.isCompletedNormally()); + assertFalse(a.isCompletedAbnormally()); + assertNull(a.getException()); + assertSame(expected, a.getRawResult()); + assertSame(expected, a.join()); + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + try { + assertSame(expected, a.get()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + assertSame(expected, a.get(5L, SECONDS)); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + /** + * Waits for the task to complete, and checks that when it does, + * it will have an Integer result equals to the given int. + */ + void checkCompletesNormally(RecursiveTask a, int expected) { + Integer r = a.join(); + assertEquals(expected, (int) r); + checkCompletedNormally(a, r); + } + + /** + * Like checkCompletesNormally, but verifies that the task has + * already completed. + */ + void checkCompletedNormally(RecursiveTask a, int expected) { + Integer r = a.getRawResult(); + assertEquals(expected, (int) r); + checkCompletedNormally(a, r); + } + + void checkCancelled(RecursiveTask a) { + assertTrue(a.isDone()); + assertTrue(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertTrue(a.getException() instanceof CancellationException); + assertNull(a.getRawResult()); + + try { + a.join(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + void checkCompletedAbnormally(RecursiveTask a, Throwable t) { + assertTrue(a.isDone()); + assertFalse(a.isCancelled()); + assertFalse(a.isCompletedNormally()); + assertTrue(a.isCompletedAbnormally()); + assertSame(t.getClass(), a.getException().getClass()); + assertNull(a.getRawResult()); + assertFalse(a.cancel(false)); + assertFalse(a.cancel(true)); + + try { + a.join(); + shouldThrow(); + } catch (Throwable expected) { + assertSame(t.getClass(), expected.getClass()); + } + + try { + a.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + + try { + a.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(t.getClass(), success.getCause().getClass()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + } + + public static final class FJException extends RuntimeException { + public FJException() { super(); } + } + + // An invalid return value for Fib + static final Integer NoResult = Integer.valueOf(-17); + + // A simple recursive task for testing + final class FibTask extends CheckedRecursiveTask { + final int number; + FibTask(int n) { number = n; } + public Integer realCompute() { + int n = number; + if (n <= 1) + return n; + FibTask f1 = new FibTask(n - 1); + f1.fork(); + return (new FibTask(n - 2)).compute() + f1.join(); + } + + public void publicSetRawResult(Integer result) { + setRawResult(result); + } + } + + // A recursive action failing in base case + final class FailingFibTask extends RecursiveTask { + final int number; + int result; + FailingFibTask(int n) { number = n; } + public Integer compute() { + int n = number; + if (n <= 1) + throw new FJException(); + FailingFibTask f1 = new FailingFibTask(n - 1); + f1.fork(); + return (new FibTask(n - 2)).compute() + f1.join(); + } + } + + /** + * invoke returns value when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks. getRawResult of a completed non-null task + * returns value; + */ + public void testInvoke() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + Integer r = f.invoke(); + assertEquals(21, (int) r); + checkCompletedNormally(f, r); + return r; + }}; + assertEquals(21, (int) testInvokeOnPool(mainPool(), a)); + } + + /** + * quietlyInvoke task returns when task completes normally. + * isCompletedAbnormally and isCancelled return false for normally + * completed tasks + */ + public void testQuietlyInvoke() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + f.quietlyInvoke(); + checkCompletedNormally(f, 21); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * join of a forked task returns when task completes + */ + public void testForkJoin() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + Integer r = f.join(); + assertEquals(21, (int) r); + checkCompletedNormally(f, r); + return r; + }}; + assertEquals(21, (int) testInvokeOnPool(mainPool(), a)); + } + + /** + * get of a forked task returns when task completes + */ + public void testForkGet() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() throws Exception { + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + Integer r = f.get(); + assertEquals(21, (int) r); + checkCompletedNormally(f, r); + return r; + }}; + assertEquals(21, (int) testInvokeOnPool(mainPool(), a)); + } + + /** + * timed get of a forked task returns when task completes + */ + public void testForkTimedGet() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() throws Exception { + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + Integer r = f.get(5L, SECONDS); + assertEquals(21, (int) r); + checkCompletedNormally(f, r); + return r; + }}; + assertEquals(21, (int) testInvokeOnPool(mainPool(), a)); + } + + /** + * quietlyJoin of a forked task returns when task completes + */ + public void testForkQuietlyJoin() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + Integer r = f.getRawResult(); + assertEquals(21, (int) r); + checkCompletedNormally(f, r); + return r; + }}; + assertEquals(21, (int) testInvokeOnPool(mainPool(), a)); + } + + /** + * helpQuiesce returns when tasks are complete. + * getQueuedTaskCount returns 0 when quiescent + */ + public void testForkHelpQuiesce() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + helpQuiesce(); + while (!f.isDone()) // wait out race + ; + assertEquals(0, getQueuedTaskCount()); + checkCompletedNormally(f, 21); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invoke task throws exception when task completes abnormally + */ + public void testAbnormalInvoke() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FailingFibTask f = new FailingFibTask(8); + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * quietlyInvoke task returns when task completes abnormally + */ + public void testAbnormalQuietlyInvoke() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FailingFibTask f = new FailingFibTask(8); + f.quietlyInvoke(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * join of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkJoin() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FailingFibTask f = new FailingFibTask(8); + assertSame(f, f.fork()); + try { + Integer r = f.join(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkGet() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() throws Exception { + FailingFibTask f = new FailingFibTask(8); + assertSame(f, f.fork()); + try { + Integer r = f.get(); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * timed get of a forked task throws exception when task completes abnormally + */ + public void testAbnormalForkTimedGet() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() throws Exception { + FailingFibTask f = new FailingFibTask(8); + assertSame(f, f.fork()); + try { + Integer r = f.get(5L, SECONDS); + shouldThrow(); + } catch (ExecutionException success) { + Throwable cause = success.getCause(); + assertTrue(cause instanceof FJException); + checkCompletedAbnormally(f, cause); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * quietlyJoin of a forked task returns when task completes abnormally + */ + public void testAbnormalForkQuietlyJoin() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FailingFibTask f = new FailingFibTask(8); + assertSame(f, f.fork()); + f.quietlyJoin(); + assertTrue(f.getException() instanceof FJException); + checkCompletedAbnormally(f, f.getException()); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invoke task throws exception when task cancelled + */ + public void testCancelledInvoke() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + assertTrue(f.cancel(true)); + try { + Integer r = f.invoke(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * join of a forked task throws exception when task cancelled + */ + public void testCancelledForkJoin() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + Integer r = f.join(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * get of a forked task throws exception when task cancelled + */ + public void testCancelledForkGet() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() throws Exception { + FibTask f = new FibTask(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + Integer r = f.get(); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * timed get of a forked task throws exception when task cancelled + */ + public void testCancelledForkTimedGet() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() throws Exception { + FibTask f = new FibTask(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + try { + Integer r = f.get(5L, SECONDS); + shouldThrow(); + } catch (CancellationException success) { + checkCancelled(f); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * quietlyJoin of a forked task returns when task cancelled + */ + public void testCancelledForkQuietlyJoin() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + assertTrue(f.cancel(true)); + assertSame(f, f.fork()); + f.quietlyJoin(); + checkCancelled(f); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * getPool of executing task returns its pool + */ + public void testGetPool() { + final ForkJoinPool mainPool = mainPool(); + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + assertSame(mainPool, getPool()); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool, a)); + } + + /** + * getPool of non-FJ task returns null + */ + public void testGetPool2() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + assertNull(getPool()); + return NoResult; + }}; + assertSame(NoResult, a.invoke()); + } + + /** + * inForkJoinPool of executing task returns true + */ + public void testInForkJoinPool() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + assertTrue(inForkJoinPool()); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * inForkJoinPool of non-FJ task returns false + */ + public void testInForkJoinPool2() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + assertFalse(inForkJoinPool()); + return NoResult; + }}; + assertSame(NoResult, a.invoke()); + } + + /** + * The value set by setRawResult is returned by getRawResult + */ + public void testSetRawResult() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + setRawResult(NoResult); + assertSame(NoResult, getRawResult()); + return NoResult; + } + }; + assertSame(NoResult, a.invoke()); + } + + /** + * A reinitialized normally completed task may be re-invoked + */ + public void testReinitialize() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + checkNotDone(f); + + for (int i = 0; i < 3; i++) { + Integer r = f.invoke(); + assertEquals(21, (int) r); + checkCompletedNormally(f, r); + f.reinitialize(); + f.publicSetRawResult(null); + checkNotDone(f); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * A reinitialized abnormally completed task may be re-invoked + */ + public void testReinitializeAbnormal() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FailingFibTask f = new FailingFibTask(8); + checkNotDone(f); + + for (int i = 0; i < 3; i++) { + try { + f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + f.reinitialize(); + checkNotDone(f); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invoke task throws exception after invoking completeExceptionally + */ + public void testCompleteExceptionally() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + f.completeExceptionally(new FJException()); + try { + Integer r = f.invoke(); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invoke task suppresses execution invoking complete + */ + public void testComplete() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + f.complete(NoResult); + Integer r = f.invoke(); + assertSame(NoResult, r); + checkCompletedNormally(f, NoResult); + return r; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invokeAll(t1, t2) invokes all task arguments + */ + public void testInvokeAll2() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + FibTask g = new FibTask(9); + invokeAll(f, g); + checkCompletedNormally(f, 21); + checkCompletedNormally(g, 34); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invokeAll(tasks) with 1 argument invokes task + */ + public void testInvokeAll1() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + invokeAll(f); + checkCompletedNormally(f, 21); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invokeAll(tasks) with > 2 argument invokes tasks + */ + public void testInvokeAll3() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + FibTask g = new FibTask(9); + FibTask h = new FibTask(7); + invokeAll(f, g, h); + assertTrue(f.isDone()); + assertTrue(g.isDone()); + assertTrue(h.isDone()); + checkCompletedNormally(f, 21); + checkCompletedNormally(g, 34); + checkCompletedNormally(h, 13); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invokeAll(collection) invokes all tasks in the collection + */ + public void testInvokeAllCollection() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + FibTask g = new FibTask(9); + FibTask h = new FibTask(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + invokeAll(set); + assertTrue(f.isDone()); + assertTrue(g.isDone()); + assertTrue(h.isDone()); + checkCompletedNormally(f, 21); + checkCompletedNormally(g, 34); + checkCompletedNormally(h, 13); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invokeAll(tasks) with any null task throws NPE + */ + public void testInvokeAllNPE() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + FibTask g = new FibTask(9); + FibTask h = null; + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (NullPointerException success) {} + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invokeAll(t1, t2) throw exception if any task does + */ + public void testAbnormalInvokeAll2() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + FailingFibTask g = new FailingFibTask(9); + try { + invokeAll(f, g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invokeAll(tasks) with 1 argument throws exception if task does + */ + public void testAbnormalInvokeAll1() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FailingFibTask g = new FailingFibTask(9); + try { + invokeAll(g); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invokeAll(tasks) with > 2 argument throws exception if any task does + */ + public void testAbnormalInvokeAll3() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask f = new FibTask(8); + FailingFibTask g = new FailingFibTask(9); + FibTask h = new FibTask(7); + try { + invokeAll(f, g, h); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(g, success); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * invokeAll(collection) throws exception if any task does + */ + public void testAbnormalInvokeAllCollection() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FailingFibTask f = new FailingFibTask(8); + FibTask g = new FibTask(9); + FibTask h = new FibTask(7); + HashSet set = new HashSet(); + set.add(f); + set.add(g); + set.add(h); + try { + invokeAll(set); + shouldThrow(); + } catch (FJException success) { + checkCompletedAbnormally(f, success); + } + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(mainPool(), a)); + } + + /** + * tryUnfork returns true for most recent unexecuted task, + * and suppresses execution + */ + public void testTryUnfork() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask g = new FibTask(9); + assertSame(g, g.fork()); + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + assertTrue(f.tryUnfork()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g, 34); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(singletonPool(), a)); + } + + /** + * getSurplusQueuedTaskCount returns > 0 when + * there are more tasks than threads + */ + public void testGetSurplusQueuedTaskCount() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask h = new FibTask(7); + assertSame(h, h.fork()); + FibTask g = new FibTask(9); + assertSame(g, g.fork()); + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + assertTrue(getSurplusQueuedTaskCount() > 0); + helpQuiesce(); + assertEquals(0, getSurplusQueuedTaskCount()); + checkCompletedNormally(f, 21); + checkCompletedNormally(g, 34); + checkCompletedNormally(h, 13); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(singletonPool(), a)); + } + + /** + * peekNextLocalTask returns most recent unexecuted task. + */ + public void testPeekNextLocalTask() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask g = new FibTask(9); + assertSame(g, g.fork()); + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + assertSame(f, peekNextLocalTask()); + checkCompletesNormally(f, 21); + helpQuiesce(); + checkCompletedNormally(g, 34); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(singletonPool(), a)); + } + + /** + * pollNextLocalTask returns most recent unexecuted task + * without executing it + */ + public void testPollNextLocalTask() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask g = new FibTask(9); + assertSame(g, g.fork()); + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + assertSame(f, pollNextLocalTask()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g, 34); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(singletonPool(), a)); + } + + /** + * pollTask returns an unexecuted task without executing it + */ + public void testPollTask() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask g = new FibTask(9); + assertSame(g, g.fork()); + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + assertSame(f, pollTask()); + helpQuiesce(); + checkNotDone(f); + checkCompletedNormally(g, 34); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(singletonPool(), a)); + } + + /** + * peekNextLocalTask returns least recent unexecuted task in async mode + */ + public void testPeekNextLocalTaskAsync() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask g = new FibTask(9); + assertSame(g, g.fork()); + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + assertSame(g, peekNextLocalTask()); + assertEquals(21, (int) f.join()); + helpQuiesce(); + checkCompletedNormally(f, 21); + checkCompletedNormally(g, 34); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a)); + } + + /** + * pollNextLocalTask returns least recent unexecuted task without + * executing it, in async mode + */ + public void testPollNextLocalTaskAsync() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask g = new FibTask(9); + assertSame(g, g.fork()); + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + assertSame(g, pollNextLocalTask()); + helpQuiesce(); + checkCompletedNormally(f, 21); + checkNotDone(g); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a)); + } + + /** + * pollTask returns an unexecuted task without executing it, in + * async mode + */ + public void testPollTaskAsync() { + RecursiveTask a = new CheckedRecursiveTask() { + public Integer realCompute() { + FibTask g = new FibTask(9); + assertSame(g, g.fork()); + FibTask f = new FibTask(8); + assertSame(f, f.fork()); + assertSame(g, pollTask()); + helpQuiesce(); + checkCompletedNormally(f, 21); + checkNotDone(g); + return NoResult; + }}; + assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a)); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ReentrantLockTest.java b/jdk/test/java/util/concurrent/tck/ReentrantLockTest.java new file mode 100644 index 00000000000..8088498562a --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ReentrantLockTest.java @@ -0,0 +1,1163 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ReentrantLockTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ReentrantLockTest.class); + } + + /** + * A checked runnable calling lockInterruptibly + */ + class InterruptibleLockRunnable extends CheckedRunnable { + final ReentrantLock lock; + InterruptibleLockRunnable(ReentrantLock lock) { this.lock = lock; } + public void realRun() throws InterruptedException { + lock.lockInterruptibly(); + } + } + + /** + * A checked runnable calling lockInterruptibly that expects to be + * interrupted + */ + class InterruptedLockRunnable extends CheckedInterruptedRunnable { + final ReentrantLock lock; + InterruptedLockRunnable(ReentrantLock lock) { this.lock = lock; } + public void realRun() throws InterruptedException { + lock.lockInterruptibly(); + } + } + + /** + * Subclass to expose protected methods + */ + static class PublicReentrantLock extends ReentrantLock { + PublicReentrantLock() { super(); } + PublicReentrantLock(boolean fair) { super(fair); } + public Thread getOwner() { + return super.getOwner(); + } + public Collection getQueuedThreads() { + return super.getQueuedThreads(); + } + public Collection getWaitingThreads(Condition c) { + return super.getWaitingThreads(c); + } + } + + /** + * Releases write lock, checking that it had a hold count of 1. + */ + void releaseLock(PublicReentrantLock lock) { + assertLockedByMoi(lock); + lock.unlock(); + assertFalse(lock.isHeldByCurrentThread()); + assertNotLocked(lock); + } + + /** + * Spin-waits until lock.hasQueuedThread(t) becomes true. + */ + void waitForQueuedThread(PublicReentrantLock lock, Thread t) { + long startTime = System.nanoTime(); + while (!lock.hasQueuedThread(t)) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + throw new AssertionFailedError("timed out"); + Thread.yield(); + } + assertTrue(t.isAlive()); + assertNotSame(t, lock.getOwner()); + } + + /** + * Checks that lock is not locked. + */ + void assertNotLocked(PublicReentrantLock lock) { + assertFalse(lock.isLocked()); + assertFalse(lock.isHeldByCurrentThread()); + assertNull(lock.getOwner()); + assertEquals(0, lock.getHoldCount()); + } + + /** + * Checks that lock is locked by the given thread. + */ + void assertLockedBy(PublicReentrantLock lock, Thread t) { + assertTrue(lock.isLocked()); + assertSame(t, lock.getOwner()); + assertEquals(t == Thread.currentThread(), + lock.isHeldByCurrentThread()); + assertEquals(t == Thread.currentThread(), + lock.getHoldCount() > 0); + } + + /** + * Checks that lock is locked by the current thread. + */ + void assertLockedByMoi(PublicReentrantLock lock) { + assertLockedBy(lock, Thread.currentThread()); + } + + /** + * Checks that condition c has no waiters. + */ + void assertHasNoWaiters(PublicReentrantLock lock, Condition c) { + assertHasWaiters(lock, c, new Thread[] {}); + } + + /** + * Checks that condition c has exactly the given waiter threads. + */ + void assertHasWaiters(PublicReentrantLock lock, Condition c, + Thread... threads) { + lock.lock(); + assertEquals(threads.length > 0, lock.hasWaiters(c)); + assertEquals(threads.length, lock.getWaitQueueLength(c)); + assertEquals(threads.length == 0, lock.getWaitingThreads(c).isEmpty()); + assertEquals(threads.length, lock.getWaitingThreads(c).size()); + assertEquals(new HashSet(lock.getWaitingThreads(c)), + new HashSet(Arrays.asList(threads))); + lock.unlock(); + } + + enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil } + + /** + * Awaits condition "indefinitely" using the specified AwaitMethod. + */ + void await(Condition c, AwaitMethod awaitMethod) + throws InterruptedException { + long timeoutMillis = 2 * LONG_DELAY_MS; + switch (awaitMethod) { + case await: + c.await(); + break; + case awaitTimed: + assertTrue(c.await(timeoutMillis, MILLISECONDS)); + break; + case awaitNanos: + long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis); + long nanosRemaining = c.awaitNanos(timeoutNanos); + assertTrue(nanosRemaining > timeoutNanos / 2); + assertTrue(nanosRemaining <= timeoutNanos); + break; + case awaitUntil: + assertTrue(c.awaitUntil(delayedDate(timeoutMillis))); + break; + default: + throw new AssertionError(); + } + } + + /** + * Constructor sets given fairness, and is in unlocked state + */ + public void testConstructor() { + PublicReentrantLock lock; + + lock = new PublicReentrantLock(); + assertFalse(lock.isFair()); + assertNotLocked(lock); + + lock = new PublicReentrantLock(true); + assertTrue(lock.isFair()); + assertNotLocked(lock); + + lock = new PublicReentrantLock(false); + assertFalse(lock.isFair()); + assertNotLocked(lock); + } + + /** + * locking an unlocked lock succeeds + */ + public void testLock() { testLock(false); } + public void testLock_fair() { testLock(true); } + public void testLock(boolean fair) { + PublicReentrantLock lock = new PublicReentrantLock(fair); + lock.lock(); + assertLockedByMoi(lock); + releaseLock(lock); + } + + /** + * Unlocking an unlocked lock throws IllegalMonitorStateException + */ + public void testUnlock_IMSE() { testUnlock_IMSE(false); } + public void testUnlock_IMSE_fair() { testUnlock_IMSE(true); } + public void testUnlock_IMSE(boolean fair) { + ReentrantLock lock = new ReentrantLock(fair); + try { + lock.unlock(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * tryLock on an unlocked lock succeeds + */ + public void testTryLock() { testTryLock(false); } + public void testTryLock_fair() { testTryLock(true); } + public void testTryLock(boolean fair) { + PublicReentrantLock lock = new PublicReentrantLock(fair); + assertTrue(lock.tryLock()); + assertLockedByMoi(lock); + assertTrue(lock.tryLock()); + assertLockedByMoi(lock); + lock.unlock(); + releaseLock(lock); + } + + /** + * hasQueuedThreads reports whether there are waiting threads + */ + public void testHasQueuedThreads() { testHasQueuedThreads(false); } + public void testHasQueuedThreads_fair() { testHasQueuedThreads(true); } + public void testHasQueuedThreads(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertFalse(lock.hasQueuedThreads()); + lock.lock(); + assertFalse(lock.hasQueuedThreads()); + t1.start(); + waitForQueuedThread(lock, t1); + assertTrue(lock.hasQueuedThreads()); + t2.start(); + waitForQueuedThread(lock, t2); + assertTrue(lock.hasQueuedThreads()); + t1.interrupt(); + awaitTermination(t1); + assertTrue(lock.hasQueuedThreads()); + lock.unlock(); + awaitTermination(t2); + assertFalse(lock.hasQueuedThreads()); + } + + /** + * getQueueLength reports number of waiting threads + */ + public void testGetQueueLength() { testGetQueueLength(false); } + public void testGetQueueLength_fair() { testGetQueueLength(true); } + public void testGetQueueLength(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertEquals(0, lock.getQueueLength()); + lock.lock(); + t1.start(); + waitForQueuedThread(lock, t1); + assertEquals(1, lock.getQueueLength()); + t2.start(); + waitForQueuedThread(lock, t2); + assertEquals(2, lock.getQueueLength()); + t1.interrupt(); + awaitTermination(t1); + assertEquals(1, lock.getQueueLength()); + lock.unlock(); + awaitTermination(t2); + assertEquals(0, lock.getQueueLength()); + } + + /** + * hasQueuedThread(null) throws NPE + */ + public void testHasQueuedThreadNPE() { testHasQueuedThreadNPE(false); } + public void testHasQueuedThreadNPE_fair() { testHasQueuedThreadNPE(true); } + public void testHasQueuedThreadNPE(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + try { + lock.hasQueuedThread(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * hasQueuedThread reports whether a thread is queued + */ + public void testHasQueuedThread() { testHasQueuedThread(false); } + public void testHasQueuedThread_fair() { testHasQueuedThread(true); } + public void testHasQueuedThread(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertFalse(lock.hasQueuedThread(t1)); + assertFalse(lock.hasQueuedThread(t2)); + lock.lock(); + t1.start(); + waitForQueuedThread(lock, t1); + assertTrue(lock.hasQueuedThread(t1)); + assertFalse(lock.hasQueuedThread(t2)); + t2.start(); + waitForQueuedThread(lock, t2); + assertTrue(lock.hasQueuedThread(t1)); + assertTrue(lock.hasQueuedThread(t2)); + t1.interrupt(); + awaitTermination(t1); + assertFalse(lock.hasQueuedThread(t1)); + assertTrue(lock.hasQueuedThread(t2)); + lock.unlock(); + awaitTermination(t2); + assertFalse(lock.hasQueuedThread(t1)); + assertFalse(lock.hasQueuedThread(t2)); + } + + /** + * getQueuedThreads includes waiting threads + */ + public void testGetQueuedThreads() { testGetQueuedThreads(false); } + public void testGetQueuedThreads_fair() { testGetQueuedThreads(true); } + public void testGetQueuedThreads(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertTrue(lock.getQueuedThreads().isEmpty()); + lock.lock(); + assertTrue(lock.getQueuedThreads().isEmpty()); + t1.start(); + waitForQueuedThread(lock, t1); + assertEquals(1, lock.getQueuedThreads().size()); + assertTrue(lock.getQueuedThreads().contains(t1)); + t2.start(); + waitForQueuedThread(lock, t2); + assertEquals(2, lock.getQueuedThreads().size()); + assertTrue(lock.getQueuedThreads().contains(t1)); + assertTrue(lock.getQueuedThreads().contains(t2)); + t1.interrupt(); + awaitTermination(t1); + assertFalse(lock.getQueuedThreads().contains(t1)); + assertTrue(lock.getQueuedThreads().contains(t2)); + assertEquals(1, lock.getQueuedThreads().size()); + lock.unlock(); + awaitTermination(t2); + assertTrue(lock.getQueuedThreads().isEmpty()); + } + + /** + * timed tryLock is interruptible + */ + public void testTryLock_Interruptible() { testTryLock_Interruptible(false); } + public void testTryLock_Interruptible_fair() { testTryLock_Interruptible(true); } + public void testTryLock_Interruptible(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + lock.lock(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.tryLock(2 * LONG_DELAY_MS, MILLISECONDS); + }}); + + waitForQueuedThread(lock, t); + t.interrupt(); + awaitTermination(t); + releaseLock(lock); + } + + /** + * tryLock on a locked lock fails + */ + public void testTryLockWhenLocked() { testTryLockWhenLocked(false); } + public void testTryLockWhenLocked_fair() { testTryLockWhenLocked(true); } + public void testTryLockWhenLocked(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + lock.lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertFalse(lock.tryLock()); + }}); + + awaitTermination(t); + releaseLock(lock); + } + + /** + * Timed tryLock on a locked lock times out + */ + public void testTryLock_Timeout() { testTryLock_Timeout(false); } + public void testTryLock_Timeout_fair() { testTryLock_Timeout(true); } + public void testTryLock_Timeout(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + lock.lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + long timeoutMillis = 10; + assertFalse(lock.tryLock(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + }}); + + awaitTermination(t); + releaseLock(lock); + } + + /** + * getHoldCount returns number of recursive holds + */ + public void testGetHoldCount() { testGetHoldCount(false); } + public void testGetHoldCount_fair() { testGetHoldCount(true); } + public void testGetHoldCount(boolean fair) { + ReentrantLock lock = new ReentrantLock(fair); + for (int i = 1; i <= SIZE; i++) { + lock.lock(); + assertEquals(i, lock.getHoldCount()); + } + for (int i = SIZE; i > 0; i--) { + lock.unlock(); + assertEquals(i - 1, lock.getHoldCount()); + } + } + + /** + * isLocked is true when locked and false when not + */ + public void testIsLocked() { testIsLocked(false); } + public void testIsLocked_fair() { testIsLocked(true); } + public void testIsLocked(boolean fair) { + try { + final ReentrantLock lock = new ReentrantLock(fair); + assertFalse(lock.isLocked()); + lock.lock(); + assertTrue(lock.isLocked()); + lock.lock(); + assertTrue(lock.isLocked()); + lock.unlock(); + assertTrue(lock.isLocked()); + lock.unlock(); + assertFalse(lock.isLocked()); + final CyclicBarrier barrier = new CyclicBarrier(2); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws Exception { + lock.lock(); + assertTrue(lock.isLocked()); + barrier.await(); + barrier.await(); + lock.unlock(); + }}); + + barrier.await(); + assertTrue(lock.isLocked()); + barrier.await(); + awaitTermination(t); + assertFalse(lock.isLocked()); + } catch (Exception fail) { threadUnexpectedException(fail); } + } + + /** + * lockInterruptibly succeeds when unlocked, else is interruptible + */ + public void testLockInterruptibly() { testLockInterruptibly(false); } + public void testLockInterruptibly_fair() { testLockInterruptibly(true); } + public void testLockInterruptibly(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + try { + lock.lockInterruptibly(); + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + assertLockedByMoi(lock); + Thread t = newStartedThread(new InterruptedLockRunnable(lock)); + waitForQueuedThread(lock, t); + t.interrupt(); + assertTrue(lock.isLocked()); + assertTrue(lock.isHeldByCurrentThread()); + awaitTermination(t); + releaseLock(lock); + } + + /** + * Calling await without holding lock throws IllegalMonitorStateException + */ + public void testAwait_IMSE() { testAwait_IMSE(false); } + public void testAwait_IMSE_fair() { testAwait_IMSE(true); } + public void testAwait_IMSE(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + for (AwaitMethod awaitMethod : AwaitMethod.values()) { + long startTime = System.nanoTime(); + try { + await(c, awaitMethod); + shouldThrow(); + } catch (IllegalMonitorStateException success) { + } catch (InterruptedException e) { threadUnexpectedException(e); } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * Calling signal without holding lock throws IllegalMonitorStateException + */ + public void testSignal_IMSE() { testSignal_IMSE(false); } + public void testSignal_IMSE_fair() { testSignal_IMSE(true); } + public void testSignal_IMSE(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + try { + c.signal(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * awaitNanos without a signal times out + */ + public void testAwaitNanos_Timeout() { testAwaitNanos_Timeout(false); } + public void testAwaitNanos_Timeout_fair() { testAwaitNanos_Timeout(true); } + public void testAwaitNanos_Timeout(boolean fair) { + try { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + lock.lock(); + long startTime = System.nanoTime(); + long timeoutMillis = 10; + long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis); + long nanosRemaining = c.awaitNanos(timeoutNanos); + assertTrue(nanosRemaining <= 0); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + lock.unlock(); + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + } + + /** + * timed await without a signal times out + */ + public void testAwait_Timeout() { testAwait_Timeout(false); } + public void testAwait_Timeout_fair() { testAwait_Timeout(true); } + public void testAwait_Timeout(boolean fair) { + try { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + lock.lock(); + long startTime = System.nanoTime(); + long timeoutMillis = 10; + assertFalse(c.await(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + lock.unlock(); + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + } + + /** + * awaitUntil without a signal times out + */ + public void testAwaitUntil_Timeout() { testAwaitUntil_Timeout(false); } + public void testAwaitUntil_Timeout_fair() { testAwaitUntil_Timeout(true); } + public void testAwaitUntil_Timeout(boolean fair) { + try { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + lock.lock(); + // We shouldn't assume that nanoTime and currentTimeMillis + // use the same time source, so don't use nanoTime here. + java.util.Date delayedDate = delayedDate(timeoutMillis()); + assertFalse(c.awaitUntil(delayedDate)); + assertTrue(new java.util.Date().getTime() >= delayedDate.getTime()); + lock.unlock(); + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + } + + /** + * await returns when signalled + */ + public void testAwait() { testAwait(false); } + public void testAwait_fair() { testAwait(true); } + public void testAwait(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + final CountDownLatch locked = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + locked.countDown(); + c.await(); + lock.unlock(); + }}); + + await(locked); + lock.lock(); + assertHasWaiters(lock, c, t); + c.signal(); + assertHasNoWaiters(lock, c); + assertTrue(t.isAlive()); + lock.unlock(); + awaitTermination(t); + } + + /** + * hasWaiters throws NPE if null + */ + public void testHasWaitersNPE() { testHasWaitersNPE(false); } + public void testHasWaitersNPE_fair() { testHasWaitersNPE(true); } + public void testHasWaitersNPE(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + try { + lock.hasWaiters(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getWaitQueueLength throws NPE if null + */ + public void testGetWaitQueueLengthNPE() { testGetWaitQueueLengthNPE(false); } + public void testGetWaitQueueLengthNPE_fair() { testGetWaitQueueLengthNPE(true); } + public void testGetWaitQueueLengthNPE(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + try { + lock.getWaitQueueLength(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getWaitingThreads throws NPE if null + */ + public void testGetWaitingThreadsNPE() { testGetWaitingThreadsNPE(false); } + public void testGetWaitingThreadsNPE_fair() { testGetWaitingThreadsNPE(true); } + public void testGetWaitingThreadsNPE(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + try { + lock.getWaitingThreads(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * hasWaiters throws IllegalArgumentException if not owned + */ + public void testHasWaitersIAE() { testHasWaitersIAE(false); } + public void testHasWaitersIAE_fair() { testHasWaitersIAE(true); } + public void testHasWaitersIAE(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + final ReentrantLock lock2 = new ReentrantLock(fair); + try { + lock2.hasWaiters(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * hasWaiters throws IllegalMonitorStateException if not locked + */ + public void testHasWaitersIMSE() { testHasWaitersIMSE(false); } + public void testHasWaitersIMSE_fair() { testHasWaitersIMSE(true); } + public void testHasWaitersIMSE(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + try { + lock.hasWaiters(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * getWaitQueueLength throws IllegalArgumentException if not owned + */ + public void testGetWaitQueueLengthIAE() { testGetWaitQueueLengthIAE(false); } + public void testGetWaitQueueLengthIAE_fair() { testGetWaitQueueLengthIAE(true); } + public void testGetWaitQueueLengthIAE(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + final ReentrantLock lock2 = new ReentrantLock(fair); + try { + lock2.getWaitQueueLength(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * getWaitQueueLength throws IllegalMonitorStateException if not locked + */ + public void testGetWaitQueueLengthIMSE() { testGetWaitQueueLengthIMSE(false); } + public void testGetWaitQueueLengthIMSE_fair() { testGetWaitQueueLengthIMSE(true); } + public void testGetWaitQueueLengthIMSE(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + try { + lock.getWaitQueueLength(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * getWaitingThreads throws IllegalArgumentException if not owned + */ + public void testGetWaitingThreadsIAE() { testGetWaitingThreadsIAE(false); } + public void testGetWaitingThreadsIAE_fair() { testGetWaitingThreadsIAE(true); } + public void testGetWaitingThreadsIAE(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + final PublicReentrantLock lock2 = new PublicReentrantLock(fair); + try { + lock2.getWaitingThreads(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * getWaitingThreads throws IllegalMonitorStateException if not locked + */ + public void testGetWaitingThreadsIMSE() { testGetWaitingThreadsIMSE(false); } + public void testGetWaitingThreadsIMSE_fair() { testGetWaitingThreadsIMSE(true); } + public void testGetWaitingThreadsIMSE(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + try { + lock.getWaitingThreads(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * hasWaiters returns true when a thread is waiting, else false + */ + public void testHasWaiters() { testHasWaiters(false); } + public void testHasWaiters_fair() { testHasWaiters(true); } + public void testHasWaiters(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + final CountDownLatch pleaseSignal = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + assertHasNoWaiters(lock, c); + assertFalse(lock.hasWaiters(c)); + pleaseSignal.countDown(); + c.await(); + assertHasNoWaiters(lock, c); + assertFalse(lock.hasWaiters(c)); + lock.unlock(); + }}); + + await(pleaseSignal); + lock.lock(); + assertHasWaiters(lock, c, t); + assertTrue(lock.hasWaiters(c)); + c.signal(); + assertHasNoWaiters(lock, c); + assertFalse(lock.hasWaiters(c)); + lock.unlock(); + awaitTermination(t); + assertHasNoWaiters(lock, c); + } + + /** + * getWaitQueueLength returns number of waiting threads + */ + public void testGetWaitQueueLength() { testGetWaitQueueLength(false); } + public void testGetWaitQueueLength_fair() { testGetWaitQueueLength(true); } + public void testGetWaitQueueLength(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + final CountDownLatch locked1 = new CountDownLatch(1); + final CountDownLatch locked2 = new CountDownLatch(1); + Thread t1 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + assertFalse(lock.hasWaiters(c)); + assertEquals(0, lock.getWaitQueueLength(c)); + locked1.countDown(); + c.await(); + lock.unlock(); + }}); + + Thread t2 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + assertTrue(lock.hasWaiters(c)); + assertEquals(1, lock.getWaitQueueLength(c)); + locked2.countDown(); + c.await(); + lock.unlock(); + }}); + + lock.lock(); + assertEquals(0, lock.getWaitQueueLength(c)); + lock.unlock(); + + t1.start(); + await(locked1); + + lock.lock(); + assertHasWaiters(lock, c, t1); + assertEquals(1, lock.getWaitQueueLength(c)); + lock.unlock(); + + t2.start(); + await(locked2); + + lock.lock(); + assertHasWaiters(lock, c, t1, t2); + assertEquals(2, lock.getWaitQueueLength(c)); + c.signalAll(); + assertHasNoWaiters(lock, c); + lock.unlock(); + + awaitTermination(t1); + awaitTermination(t2); + + assertHasNoWaiters(lock, c); + } + + /** + * getWaitingThreads returns only and all waiting threads + */ + public void testGetWaitingThreads() { testGetWaitingThreads(false); } + public void testGetWaitingThreads_fair() { testGetWaitingThreads(true); } + public void testGetWaitingThreads(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + final CountDownLatch locked1 = new CountDownLatch(1); + final CountDownLatch locked2 = new CountDownLatch(1); + Thread t1 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + assertTrue(lock.getWaitingThreads(c).isEmpty()); + locked1.countDown(); + c.await(); + lock.unlock(); + }}); + + Thread t2 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + assertFalse(lock.getWaitingThreads(c).isEmpty()); + locked2.countDown(); + c.await(); + lock.unlock(); + }}); + + lock.lock(); + assertTrue(lock.getWaitingThreads(c).isEmpty()); + lock.unlock(); + + t1.start(); + await(locked1); + + lock.lock(); + assertHasWaiters(lock, c, t1); + assertTrue(lock.getWaitingThreads(c).contains(t1)); + assertFalse(lock.getWaitingThreads(c).contains(t2)); + assertEquals(1, lock.getWaitingThreads(c).size()); + lock.unlock(); + + t2.start(); + await(locked2); + + lock.lock(); + assertHasWaiters(lock, c, t1, t2); + assertTrue(lock.getWaitingThreads(c).contains(t1)); + assertTrue(lock.getWaitingThreads(c).contains(t2)); + assertEquals(2, lock.getWaitingThreads(c).size()); + c.signalAll(); + assertHasNoWaiters(lock, c); + lock.unlock(); + + awaitTermination(t1); + awaitTermination(t2); + + assertHasNoWaiters(lock, c); + } + + /** + * awaitUninterruptibly is uninterruptible + */ + public void testAwaitUninterruptibly() { testAwaitUninterruptibly(false); } + public void testAwaitUninterruptibly_fair() { testAwaitUninterruptibly(true); } + public void testAwaitUninterruptibly(boolean fair) { + final ReentrantLock lock = new ReentrantLock(fair); + final Condition c = lock.newCondition(); + final CountDownLatch pleaseInterrupt = new CountDownLatch(2); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + // Interrupt before awaitUninterruptibly + lock.lock(); + pleaseInterrupt.countDown(); + Thread.currentThread().interrupt(); + c.awaitUninterruptibly(); + assertTrue(Thread.interrupted()); + lock.unlock(); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + // Interrupt during awaitUninterruptibly + lock.lock(); + pleaseInterrupt.countDown(); + c.awaitUninterruptibly(); + assertTrue(Thread.interrupted()); + lock.unlock(); + }}); + + await(pleaseInterrupt); + lock.lock(); + lock.unlock(); + t2.interrupt(); + + assertThreadStaysAlive(t1); + assertTrue(t2.isAlive()); + + lock.lock(); + c.signalAll(); + lock.unlock(); + + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * await/awaitNanos/awaitUntil is interruptible + */ + public void testInterruptible_await() { testInterruptible(false, AwaitMethod.await); } + public void testInterruptible_await_fair() { testInterruptible(true, AwaitMethod.await); } + public void testInterruptible_awaitTimed() { testInterruptible(false, AwaitMethod.awaitTimed); } + public void testInterruptible_awaitTimed_fair() { testInterruptible(true, AwaitMethod.awaitTimed); } + public void testInterruptible_awaitNanos() { testInterruptible(false, AwaitMethod.awaitNanos); } + public void testInterruptible_awaitNanos_fair() { testInterruptible(true, AwaitMethod.awaitNanos); } + public void testInterruptible_awaitUntil() { testInterruptible(false, AwaitMethod.awaitUntil); } + public void testInterruptible_awaitUntil_fair() { testInterruptible(true, AwaitMethod.awaitUntil); } + public void testInterruptible(boolean fair, final AwaitMethod awaitMethod) { + final PublicReentrantLock lock = + new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + assertLockedByMoi(lock); + assertHasNoWaiters(lock, c); + pleaseInterrupt.countDown(); + try { + await(c, awaitMethod); + } finally { + assertLockedByMoi(lock); + assertHasNoWaiters(lock, c); + lock.unlock(); + assertFalse(Thread.interrupted()); + } + }}); + + await(pleaseInterrupt); + assertHasWaiters(lock, c, t); + t.interrupt(); + awaitTermination(t); + assertNotLocked(lock); + } + + /** + * signalAll wakes up all threads + */ + public void testSignalAll_await() { testSignalAll(false, AwaitMethod.await); } + public void testSignalAll_await_fair() { testSignalAll(true, AwaitMethod.await); } + public void testSignalAll_awaitTimed() { testSignalAll(false, AwaitMethod.awaitTimed); } + public void testSignalAll_awaitTimed_fair() { testSignalAll(true, AwaitMethod.awaitTimed); } + public void testSignalAll_awaitNanos() { testSignalAll(false, AwaitMethod.awaitNanos); } + public void testSignalAll_awaitNanos_fair() { testSignalAll(true, AwaitMethod.awaitNanos); } + public void testSignalAll_awaitUntil() { testSignalAll(false, AwaitMethod.awaitUntil); } + public void testSignalAll_awaitUntil_fair() { testSignalAll(true, AwaitMethod.awaitUntil); } + public void testSignalAll(boolean fair, final AwaitMethod awaitMethod) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + final CountDownLatch pleaseSignal = new CountDownLatch(2); + class Awaiter extends CheckedRunnable { + public void realRun() throws InterruptedException { + lock.lock(); + pleaseSignal.countDown(); + await(c, awaitMethod); + lock.unlock(); + } + } + + Thread t1 = newStartedThread(new Awaiter()); + Thread t2 = newStartedThread(new Awaiter()); + + await(pleaseSignal); + lock.lock(); + assertHasWaiters(lock, c, t1, t2); + c.signalAll(); + assertHasNoWaiters(lock, c); + lock.unlock(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * signal wakes up waiting threads in FIFO order + */ + public void testSignalWakesFifo() { testSignalWakesFifo(false); } + public void testSignalWakesFifo_fair() { testSignalWakesFifo(true); } + public void testSignalWakesFifo(boolean fair) { + final PublicReentrantLock lock = + new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + final CountDownLatch locked1 = new CountDownLatch(1); + final CountDownLatch locked2 = new CountDownLatch(1); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + locked1.countDown(); + c.await(); + lock.unlock(); + }}); + + await(locked1); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + locked2.countDown(); + c.await(); + lock.unlock(); + }}); + + await(locked2); + + lock.lock(); + assertHasWaiters(lock, c, t1, t2); + assertFalse(lock.hasQueuedThreads()); + c.signal(); + assertHasWaiters(lock, c, t2); + assertTrue(lock.hasQueuedThread(t1)); + assertFalse(lock.hasQueuedThread(t2)); + c.signal(); + assertHasNoWaiters(lock, c); + assertTrue(lock.hasQueuedThread(t1)); + assertTrue(lock.hasQueuedThread(t2)); + lock.unlock(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * await after multiple reentrant locking preserves lock count + */ + public void testAwaitLockCount() { testAwaitLockCount(false); } + public void testAwaitLockCount_fair() { testAwaitLockCount(true); } + public void testAwaitLockCount(boolean fair) { + final PublicReentrantLock lock = new PublicReentrantLock(fair); + final Condition c = lock.newCondition(); + final CountDownLatch pleaseSignal = new CountDownLatch(2); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + assertLockedByMoi(lock); + assertEquals(1, lock.getHoldCount()); + pleaseSignal.countDown(); + c.await(); + assertLockedByMoi(lock); + assertEquals(1, lock.getHoldCount()); + lock.unlock(); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.lock(); + lock.lock(); + assertLockedByMoi(lock); + assertEquals(2, lock.getHoldCount()); + pleaseSignal.countDown(); + c.await(); + assertLockedByMoi(lock); + assertEquals(2, lock.getHoldCount()); + lock.unlock(); + lock.unlock(); + }}); + + await(pleaseSignal); + lock.lock(); + assertHasWaiters(lock, c, t1, t2); + assertEquals(1, lock.getHoldCount()); + c.signalAll(); + assertHasNoWaiters(lock, c); + lock.unlock(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * A serialized lock deserializes as unlocked + */ + public void testSerialization() { testSerialization(false); } + public void testSerialization_fair() { testSerialization(true); } + public void testSerialization(boolean fair) { + ReentrantLock lock = new ReentrantLock(fair); + lock.lock(); + + ReentrantLock clone = serialClone(lock); + assertEquals(lock.isFair(), clone.isFair()); + assertTrue(lock.isLocked()); + assertFalse(clone.isLocked()); + assertEquals(1, lock.getHoldCount()); + assertEquals(0, clone.getHoldCount()); + clone.lock(); + clone.lock(); + assertTrue(clone.isLocked()); + assertEquals(2, clone.getHoldCount()); + assertEquals(1, lock.getHoldCount()); + clone.unlock(); + clone.unlock(); + assertTrue(lock.isLocked()); + assertFalse(clone.isLocked()); + } + + /** + * toString indicates current lock state + */ + public void testToString() { testToString(false); } + public void testToString_fair() { testToString(true); } + public void testToString(boolean fair) { + ReentrantLock lock = new ReentrantLock(fair); + assertTrue(lock.toString().contains("Unlocked")); + lock.lock(); + assertTrue(lock.toString().contains("Locked")); + lock.unlock(); + assertTrue(lock.toString().contains("Unlocked")); + } +} diff --git a/jdk/test/java/util/concurrent/tck/ReentrantReadWriteLockTest.java b/jdk/test/java/util/concurrent/tck/ReentrantReadWriteLockTest.java new file mode 100644 index 00000000000..a2e597e5eb7 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ReentrantReadWriteLockTest.java @@ -0,0 +1,1703 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ReentrantReadWriteLockTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ReentrantReadWriteLockTest.class); + } + + /** + * A runnable calling lockInterruptibly + */ + class InterruptibleLockRunnable extends CheckedRunnable { + final ReentrantReadWriteLock lock; + InterruptibleLockRunnable(ReentrantReadWriteLock l) { lock = l; } + public void realRun() throws InterruptedException { + lock.writeLock().lockInterruptibly(); + } + } + + /** + * A runnable calling lockInterruptibly that expects to be + * interrupted + */ + class InterruptedLockRunnable extends CheckedInterruptedRunnable { + final ReentrantReadWriteLock lock; + InterruptedLockRunnable(ReentrantReadWriteLock l) { lock = l; } + public void realRun() throws InterruptedException { + lock.writeLock().lockInterruptibly(); + } + } + + /** + * Subclass to expose protected methods + */ + static class PublicReentrantReadWriteLock extends ReentrantReadWriteLock { + PublicReentrantReadWriteLock() { super(); } + PublicReentrantReadWriteLock(boolean fair) { super(fair); } + public Thread getOwner() { + return super.getOwner(); + } + public Collection getQueuedThreads() { + return super.getQueuedThreads(); + } + public Collection getWaitingThreads(Condition c) { + return super.getWaitingThreads(c); + } + } + + /** + * Releases write lock, checking that it had a hold count of 1. + */ + void releaseWriteLock(PublicReentrantReadWriteLock lock) { + ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock(); + assertWriteLockedByMoi(lock); + assertEquals(1, lock.getWriteHoldCount()); + writeLock.unlock(); + assertNotWriteLocked(lock); + } + + /** + * Spin-waits until lock.hasQueuedThread(t) becomes true. + */ + void waitForQueuedThread(PublicReentrantReadWriteLock lock, Thread t) { + long startTime = System.nanoTime(); + while (!lock.hasQueuedThread(t)) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + throw new AssertionFailedError("timed out"); + Thread.yield(); + } + assertTrue(t.isAlive()); + assertNotSame(t, lock.getOwner()); + } + + /** + * Checks that lock is not write-locked. + */ + void assertNotWriteLocked(PublicReentrantReadWriteLock lock) { + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isWriteLockedByCurrentThread()); + assertFalse(lock.writeLock().isHeldByCurrentThread()); + assertEquals(0, lock.getWriteHoldCount()); + assertEquals(0, lock.writeLock().getHoldCount()); + assertNull(lock.getOwner()); + } + + /** + * Checks that lock is write-locked by the given thread. + */ + void assertWriteLockedBy(PublicReentrantReadWriteLock lock, Thread t) { + assertTrue(lock.isWriteLocked()); + assertSame(t, lock.getOwner()); + assertEquals(t == Thread.currentThread(), + lock.isWriteLockedByCurrentThread()); + assertEquals(t == Thread.currentThread(), + lock.writeLock().isHeldByCurrentThread()); + assertEquals(t == Thread.currentThread(), + lock.getWriteHoldCount() > 0); + assertEquals(t == Thread.currentThread(), + lock.writeLock().getHoldCount() > 0); + assertEquals(0, lock.getReadLockCount()); + } + + /** + * Checks that lock is write-locked by the current thread. + */ + void assertWriteLockedByMoi(PublicReentrantReadWriteLock lock) { + assertWriteLockedBy(lock, Thread.currentThread()); + } + + /** + * Checks that condition c has no waiters. + */ + void assertHasNoWaiters(PublicReentrantReadWriteLock lock, Condition c) { + assertHasWaiters(lock, c, new Thread[] {}); + } + + /** + * Checks that condition c has exactly the given waiter threads. + */ + void assertHasWaiters(PublicReentrantReadWriteLock lock, Condition c, + Thread... threads) { + lock.writeLock().lock(); + assertEquals(threads.length > 0, lock.hasWaiters(c)); + assertEquals(threads.length, lock.getWaitQueueLength(c)); + assertEquals(threads.length == 0, lock.getWaitingThreads(c).isEmpty()); + assertEquals(threads.length, lock.getWaitingThreads(c).size()); + assertEquals(new HashSet(lock.getWaitingThreads(c)), + new HashSet(Arrays.asList(threads))); + lock.writeLock().unlock(); + } + + enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil } + + /** + * Awaits condition "indefinitely" using the specified AwaitMethod. + */ + void await(Condition c, AwaitMethod awaitMethod) + throws InterruptedException { + long timeoutMillis = 2 * LONG_DELAY_MS; + switch (awaitMethod) { + case await: + c.await(); + break; + case awaitTimed: + assertTrue(c.await(timeoutMillis, MILLISECONDS)); + break; + case awaitNanos: + long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis); + long nanosRemaining = c.awaitNanos(timeoutNanos); + assertTrue(nanosRemaining > timeoutNanos / 2); + assertTrue(nanosRemaining <= timeoutNanos); + break; + case awaitUntil: + assertTrue(c.awaitUntil(delayedDate(timeoutMillis))); + break; + default: + throw new AssertionError(); + } + } + + /** + * Constructor sets given fairness, and is in unlocked state + */ + public void testConstructor() { + PublicReentrantReadWriteLock lock; + + lock = new PublicReentrantReadWriteLock(); + assertFalse(lock.isFair()); + assertNotWriteLocked(lock); + assertEquals(0, lock.getReadLockCount()); + + lock = new PublicReentrantReadWriteLock(true); + assertTrue(lock.isFair()); + assertNotWriteLocked(lock); + assertEquals(0, lock.getReadLockCount()); + + lock = new PublicReentrantReadWriteLock(false); + assertFalse(lock.isFair()); + assertNotWriteLocked(lock); + assertEquals(0, lock.getReadLockCount()); + } + + /** + * write-locking and read-locking an unlocked lock succeed + */ + public void testLock() { testLock(false); } + public void testLock_fair() { testLock(true); } + public void testLock(boolean fair) { + PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + assertNotWriteLocked(lock); + lock.writeLock().lock(); + assertWriteLockedByMoi(lock); + lock.writeLock().unlock(); + assertNotWriteLocked(lock); + assertEquals(0, lock.getReadLockCount()); + lock.readLock().lock(); + assertNotWriteLocked(lock); + assertEquals(1, lock.getReadLockCount()); + lock.readLock().unlock(); + assertNotWriteLocked(lock); + assertEquals(0, lock.getReadLockCount()); + } + + /** + * getWriteHoldCount returns number of recursive holds + */ + public void testGetWriteHoldCount() { testGetWriteHoldCount(false); } + public void testGetWriteHoldCount_fair() { testGetWriteHoldCount(true); } + public void testGetWriteHoldCount(boolean fair) { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + for (int i = 1; i <= SIZE; i++) { + lock.writeLock().lock(); + assertEquals(i,lock.getWriteHoldCount()); + } + for (int i = SIZE; i > 0; i--) { + lock.writeLock().unlock(); + assertEquals(i - 1,lock.getWriteHoldCount()); + } + } + + /** + * writelock.getHoldCount returns number of recursive holds + */ + public void testGetHoldCount() { testGetHoldCount(false); } + public void testGetHoldCount_fair() { testGetHoldCount(true); } + public void testGetHoldCount(boolean fair) { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + for (int i = 1; i <= SIZE; i++) { + lock.writeLock().lock(); + assertEquals(i,lock.writeLock().getHoldCount()); + } + for (int i = SIZE; i > 0; i--) { + lock.writeLock().unlock(); + assertEquals(i - 1,lock.writeLock().getHoldCount()); + } + } + + /** + * getReadHoldCount returns number of recursive holds + */ + public void testGetReadHoldCount() { testGetReadHoldCount(false); } + public void testGetReadHoldCount_fair() { testGetReadHoldCount(true); } + public void testGetReadHoldCount(boolean fair) { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + for (int i = 1; i <= SIZE; i++) { + lock.readLock().lock(); + assertEquals(i,lock.getReadHoldCount()); + } + for (int i = SIZE; i > 0; i--) { + lock.readLock().unlock(); + assertEquals(i - 1,lock.getReadHoldCount()); + } + } + + /** + * write-unlocking an unlocked lock throws IllegalMonitorStateException + */ + public void testWriteUnlock_IMSE() { testWriteUnlock_IMSE(false); } + public void testWriteUnlock_IMSE_fair() { testWriteUnlock_IMSE(true); } + public void testWriteUnlock_IMSE(boolean fair) { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + try { + lock.writeLock().unlock(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * read-unlocking an unlocked lock throws IllegalMonitorStateException + */ + public void testReadUnlock_IMSE() { testReadUnlock_IMSE(false); } + public void testReadUnlock_IMSE_fair() { testReadUnlock_IMSE(true); } + public void testReadUnlock_IMSE(boolean fair) { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + try { + lock.readLock().unlock(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * write-lockInterruptibly is interruptible + */ + public void testWriteLockInterruptibly_Interruptible() { testWriteLockInterruptibly_Interruptible(false); } + public void testWriteLockInterruptibly_Interruptible_fair() { testWriteLockInterruptibly_Interruptible(true); } + public void testWriteLockInterruptibly_Interruptible(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lockInterruptibly(); + }}); + + waitForQueuedThread(lock, t); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock); + } + + /** + * timed write-tryLock is interruptible + */ + public void testWriteTryLock_Interruptible() { testWriteTryLock_Interruptible(false); } + public void testWriteTryLock_Interruptible_fair() { testWriteTryLock_Interruptible(true); } + public void testWriteTryLock_Interruptible(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().tryLock(2 * LONG_DELAY_MS, MILLISECONDS); + }}); + + waitForQueuedThread(lock, t); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock); + } + + /** + * read-lockInterruptibly is interruptible + */ + public void testReadLockInterruptibly_Interruptible() { testReadLockInterruptibly_Interruptible(false); } + public void testReadLockInterruptibly_Interruptible_fair() { testReadLockInterruptibly_Interruptible(true); } + public void testReadLockInterruptibly_Interruptible(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.readLock().lockInterruptibly(); + }}); + + waitForQueuedThread(lock, t); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock); + } + + /** + * timed read-tryLock is interruptible + */ + public void testReadTryLock_Interruptible() { testReadTryLock_Interruptible(false); } + public void testReadTryLock_Interruptible_fair() { testReadTryLock_Interruptible(true); } + public void testReadTryLock_Interruptible(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.readLock().tryLock(2 * LONG_DELAY_MS, MILLISECONDS); + }}); + + waitForQueuedThread(lock, t); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock); + } + + /** + * write-tryLock on an unlocked lock succeeds + */ + public void testWriteTryLock() { testWriteTryLock(false); } + public void testWriteTryLock_fair() { testWriteTryLock(true); } + public void testWriteTryLock(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + assertTrue(lock.writeLock().tryLock()); + assertWriteLockedByMoi(lock); + assertTrue(lock.writeLock().tryLock()); + assertWriteLockedByMoi(lock); + lock.writeLock().unlock(); + releaseWriteLock(lock); + } + + /** + * write-tryLock fails if locked + */ + public void testWriteTryLockWhenLocked() { testWriteTryLockWhenLocked(false); } + public void testWriteTryLockWhenLocked_fair() { testWriteTryLockWhenLocked(true); } + public void testWriteTryLockWhenLocked(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertFalse(lock.writeLock().tryLock()); + }}); + + awaitTermination(t); + releaseWriteLock(lock); + } + + /** + * read-tryLock fails if locked + */ + public void testReadTryLockWhenLocked() { testReadTryLockWhenLocked(false); } + public void testReadTryLockWhenLocked_fair() { testReadTryLockWhenLocked(true); } + public void testReadTryLockWhenLocked(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertFalse(lock.readLock().tryLock()); + }}); + + awaitTermination(t); + releaseWriteLock(lock); + } + + /** + * Multiple threads can hold a read lock when not write-locked + */ + public void testMultipleReadLocks() { testMultipleReadLocks(false); } + public void testMultipleReadLocks_fair() { testMultipleReadLocks(true); } + public void testMultipleReadLocks(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + lock.readLock().lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertTrue(lock.readLock().tryLock()); + lock.readLock().unlock(); + assertTrue(lock.readLock().tryLock(LONG_DELAY_MS, MILLISECONDS)); + lock.readLock().unlock(); + lock.readLock().lock(); + lock.readLock().unlock(); + }}); + + awaitTermination(t); + lock.readLock().unlock(); + } + + /** + * A writelock succeeds only after a reading thread unlocks + */ + public void testWriteAfterReadLock() { testWriteAfterReadLock(false); } + public void testWriteAfterReadLock_fair() { testWriteAfterReadLock(true); } + public void testWriteAfterReadLock(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.readLock().lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertEquals(1, lock.getReadLockCount()); + lock.writeLock().lock(); + assertEquals(0, lock.getReadLockCount()); + lock.writeLock().unlock(); + }}); + waitForQueuedThread(lock, t); + assertNotWriteLocked(lock); + assertEquals(1, lock.getReadLockCount()); + lock.readLock().unlock(); + assertEquals(0, lock.getReadLockCount()); + awaitTermination(t); + assertNotWriteLocked(lock); + } + + /** + * A writelock succeeds only after reading threads unlock + */ + public void testWriteAfterMultipleReadLocks() { testWriteAfterMultipleReadLocks(false); } + public void testWriteAfterMultipleReadLocks_fair() { testWriteAfterMultipleReadLocks(true); } + public void testWriteAfterMultipleReadLocks(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.readLock().lock(); + lock.readLock().lock(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.readLock().lock(); + assertEquals(3, lock.getReadLockCount()); + lock.readLock().unlock(); + }}); + awaitTermination(t1); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertEquals(2, lock.getReadLockCount()); + lock.writeLock().lock(); + assertEquals(0, lock.getReadLockCount()); + lock.writeLock().unlock(); + }}); + waitForQueuedThread(lock, t2); + assertNotWriteLocked(lock); + assertEquals(2, lock.getReadLockCount()); + lock.readLock().unlock(); + lock.readLock().unlock(); + assertEquals(0, lock.getReadLockCount()); + awaitTermination(t2); + assertNotWriteLocked(lock); + } + + /** + * A thread that tries to acquire a fair read lock (non-reentrantly) + * will block if there is a waiting writer thread + */ + public void testReaderWriterReaderFairFifo() { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(true); + final AtomicBoolean t1GotLock = new AtomicBoolean(false); + + lock.readLock().lock(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertEquals(1, lock.getReadLockCount()); + lock.writeLock().lock(); + assertEquals(0, lock.getReadLockCount()); + t1GotLock.set(true); + lock.writeLock().unlock(); + }}); + waitForQueuedThread(lock, t1); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertEquals(1, lock.getReadLockCount()); + lock.readLock().lock(); + assertEquals(1, lock.getReadLockCount()); + assertTrue(t1GotLock.get()); + lock.readLock().unlock(); + }}); + waitForQueuedThread(lock, t2); + assertTrue(t1.isAlive()); + assertNotWriteLocked(lock); + assertEquals(1, lock.getReadLockCount()); + lock.readLock().unlock(); + awaitTermination(t1); + awaitTermination(t2); + assertNotWriteLocked(lock); + } + + /** + * Readlocks succeed only after a writing thread unlocks + */ + public void testReadAfterWriteLock() { testReadAfterWriteLock(false); } + public void testReadAfterWriteLock_fair() { testReadAfterWriteLock(true); } + public void testReadAfterWriteLock(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.readLock().lock(); + lock.readLock().unlock(); + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.readLock().lock(); + lock.readLock().unlock(); + }}); + + waitForQueuedThread(lock, t1); + waitForQueuedThread(lock, t2); + releaseWriteLock(lock); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * Read trylock succeeds if write locked by current thread + */ + public void testReadHoldingWriteLock() { testReadHoldingWriteLock(false); } + public void testReadHoldingWriteLock_fair() { testReadHoldingWriteLock(true); } + public void testReadHoldingWriteLock(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + lock.writeLock().lock(); + assertTrue(lock.readLock().tryLock()); + lock.readLock().unlock(); + lock.writeLock().unlock(); + } + + /** + * Read trylock succeeds (barging) even in the presence of waiting + * readers and/or writers + */ + public void testReadTryLockBarging() { testReadTryLockBarging(false); } + public void testReadTryLockBarging_fair() { testReadTryLockBarging(true); } + public void testReadTryLockBarging(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.readLock().lock(); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + }}); + + waitForQueuedThread(lock, t1); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.readLock().lock(); + lock.readLock().unlock(); + }}); + + if (fair) + waitForQueuedThread(lock, t2); + + Thread t3 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.readLock().tryLock(); + lock.readLock().unlock(); + }}); + + assertTrue(lock.getReadLockCount() > 0); + awaitTermination(t3); + assertTrue(t1.isAlive()); + if (fair) assertTrue(t2.isAlive()); + lock.readLock().unlock(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * Read lock succeeds if write locked by current thread even if + * other threads are waiting for readlock + */ + public void testReadHoldingWriteLock2() { testReadHoldingWriteLock2(false); } + public void testReadHoldingWriteLock2_fair() { testReadHoldingWriteLock2(true); } + public void testReadHoldingWriteLock2(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + lock.readLock().lock(); + lock.readLock().unlock(); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.readLock().lock(); + lock.readLock().unlock(); + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.readLock().lock(); + lock.readLock().unlock(); + }}); + + waitForQueuedThread(lock, t1); + waitForQueuedThread(lock, t2); + assertWriteLockedByMoi(lock); + lock.readLock().lock(); + lock.readLock().unlock(); + releaseWriteLock(lock); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * Read lock succeeds if write locked by current thread even if + * other threads are waiting for writelock + */ + public void testReadHoldingWriteLock3() { testReadHoldingWriteLock3(false); } + public void testReadHoldingWriteLock3_fair() { testReadHoldingWriteLock3(true); } + public void testReadHoldingWriteLock3(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + lock.readLock().lock(); + lock.readLock().unlock(); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + }}); + + waitForQueuedThread(lock, t1); + waitForQueuedThread(lock, t2); + assertWriteLockedByMoi(lock); + lock.readLock().lock(); + lock.readLock().unlock(); + assertWriteLockedByMoi(lock); + lock.writeLock().unlock(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * Write lock succeeds if write locked by current thread even if + * other threads are waiting for writelock + */ + public void testWriteHoldingWriteLock4() { testWriteHoldingWriteLock4(false); } + public void testWriteHoldingWriteLock4_fair() { testWriteHoldingWriteLock4(true); } + public void testWriteHoldingWriteLock4(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + lock.writeLock().lock(); + lock.writeLock().unlock(); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + lock.writeLock().lock(); + lock.writeLock().unlock(); + }}); + + waitForQueuedThread(lock, t1); + waitForQueuedThread(lock, t2); + assertWriteLockedByMoi(lock); + assertEquals(1, lock.getWriteHoldCount()); + lock.writeLock().lock(); + assertWriteLockedByMoi(lock); + assertEquals(2, lock.getWriteHoldCount()); + lock.writeLock().unlock(); + assertWriteLockedByMoi(lock); + assertEquals(1, lock.getWriteHoldCount()); + lock.writeLock().unlock(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * Read tryLock succeeds if readlocked but not writelocked + */ + public void testTryLockWhenReadLocked() { testTryLockWhenReadLocked(false); } + public void testTryLockWhenReadLocked_fair() { testTryLockWhenReadLocked(true); } + public void testTryLockWhenReadLocked(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + lock.readLock().lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertTrue(lock.readLock().tryLock()); + lock.readLock().unlock(); + }}); + + awaitTermination(t); + lock.readLock().unlock(); + } + + /** + * write tryLock fails when readlocked + */ + public void testWriteTryLockWhenReadLocked() { testWriteTryLockWhenReadLocked(false); } + public void testWriteTryLockWhenReadLocked_fair() { testWriteTryLockWhenReadLocked(true); } + public void testWriteTryLockWhenReadLocked(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + lock.readLock().lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + assertFalse(lock.writeLock().tryLock()); + }}); + + awaitTermination(t); + lock.readLock().unlock(); + } + + /** + * write timed tryLock times out if locked + */ + public void testWriteTryLock_Timeout() { testWriteTryLock_Timeout(false); } + public void testWriteTryLock_Timeout_fair() { testWriteTryLock_Timeout(true); } + public void testWriteTryLock_Timeout(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + lock.writeLock().lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + long timeoutMillis = 10; + assertFalse(lock.writeLock().tryLock(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + }}); + + awaitTermination(t); + releaseWriteLock(lock); + } + + /** + * read timed tryLock times out if write-locked + */ + public void testReadTryLock_Timeout() { testReadTryLock_Timeout(false); } + public void testReadTryLock_Timeout_fair() { testReadTryLock_Timeout(true); } + public void testReadTryLock_Timeout(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + lock.writeLock().lock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + long timeoutMillis = 10; + assertFalse(lock.readLock().tryLock(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + }}); + + awaitTermination(t); + assertTrue(lock.writeLock().isHeldByCurrentThread()); + lock.writeLock().unlock(); + } + + /** + * write lockInterruptibly succeeds if unlocked, else is interruptible + */ + public void testWriteLockInterruptibly() { testWriteLockInterruptibly(false); } + public void testWriteLockInterruptibly_fair() { testWriteLockInterruptibly(true); } + public void testWriteLockInterruptibly(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + try { + lock.writeLock().lockInterruptibly(); + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lockInterruptibly(); + }}); + + waitForQueuedThread(lock, t); + t.interrupt(); + assertTrue(lock.writeLock().isHeldByCurrentThread()); + awaitTermination(t); + releaseWriteLock(lock); + } + + /** + * read lockInterruptibly succeeds if lock free else is interruptible + */ + public void testReadLockInterruptibly() { testReadLockInterruptibly(false); } + public void testReadLockInterruptibly_fair() { testReadLockInterruptibly(true); } + public void testReadLockInterruptibly(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + try { + lock.readLock().lockInterruptibly(); + lock.readLock().unlock(); + lock.writeLock().lockInterruptibly(); + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.readLock().lockInterruptibly(); + }}); + + waitForQueuedThread(lock, t); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock); + } + + /** + * Calling await without holding lock throws IllegalMonitorStateException + */ + public void testAwait_IMSE() { testAwait_IMSE(false); } + public void testAwait_IMSE_fair() { testAwait_IMSE(true); } + public void testAwait_IMSE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + for (AwaitMethod awaitMethod : AwaitMethod.values()) { + long startTime = System.nanoTime(); + try { + await(c, awaitMethod); + shouldThrow(); + } catch (IllegalMonitorStateException success) { + } catch (InterruptedException fail) { + threadUnexpectedException(fail); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * Calling signal without holding lock throws IllegalMonitorStateException + */ + public void testSignal_IMSE() { testSignal_IMSE(false); } + public void testSignal_IMSE_fair() { testSignal_IMSE(true); } + public void testSignal_IMSE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + try { + c.signal(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * Calling signalAll without holding lock throws IllegalMonitorStateException + */ + public void testSignalAll_IMSE() { testSignalAll_IMSE(false); } + public void testSignalAll_IMSE_fair() { testSignalAll_IMSE(true); } + public void testSignalAll_IMSE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + try { + c.signalAll(); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * awaitNanos without a signal times out + */ + public void testAwaitNanos_Timeout() { testAwaitNanos_Timeout(false); } + public void testAwaitNanos_Timeout_fair() { testAwaitNanos_Timeout(true); } + public void testAwaitNanos_Timeout(boolean fair) { + try { + final ReentrantReadWriteLock lock = + new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + lock.writeLock().lock(); + long startTime = System.nanoTime(); + long timeoutMillis = 10; + long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis); + long nanosRemaining = c.awaitNanos(timeoutNanos); + assertTrue(nanosRemaining <= 0); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + lock.writeLock().unlock(); + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + } + + /** + * timed await without a signal times out + */ + public void testAwait_Timeout() { testAwait_Timeout(false); } + public void testAwait_Timeout_fair() { testAwait_Timeout(true); } + public void testAwait_Timeout(boolean fair) { + try { + final ReentrantReadWriteLock lock = + new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + lock.writeLock().lock(); + long startTime = System.nanoTime(); + long timeoutMillis = 10; + assertFalse(c.await(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + lock.writeLock().unlock(); + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + } + + /** + * awaitUntil without a signal times out + */ + public void testAwaitUntil_Timeout() { testAwaitUntil_Timeout(false); } + public void testAwaitUntil_Timeout_fair() { testAwaitUntil_Timeout(true); } + public void testAwaitUntil_Timeout(boolean fair) { + try { + final ReentrantReadWriteLock lock = + new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + lock.writeLock().lock(); + // We shouldn't assume that nanoTime and currentTimeMillis + // use the same time source, so don't use nanoTime here. + java.util.Date delayedDate = delayedDate(timeoutMillis()); + assertFalse(c.awaitUntil(delayedDate)); + assertTrue(new java.util.Date().getTime() >= delayedDate.getTime()); + lock.writeLock().unlock(); + } catch (InterruptedException fail) { threadUnexpectedException(fail); } + } + + /** + * await returns when signalled + */ + public void testAwait() { testAwait(false); } + public void testAwait_fair() { testAwait(true); } + public void testAwait(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final CountDownLatch locked = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lock(); + locked.countDown(); + c.await(); + lock.writeLock().unlock(); + }}); + + await(locked); + lock.writeLock().lock(); + assertHasWaiters(lock, c, t); + c.signal(); + assertHasNoWaiters(lock, c); + assertTrue(t.isAlive()); + lock.writeLock().unlock(); + awaitTermination(t); + } + + /** + * awaitUninterruptibly is uninterruptible + */ + public void testAwaitUninterruptibly() { testAwaitUninterruptibly(false); } + public void testAwaitUninterruptibly_fair() { testAwaitUninterruptibly(true); } + public void testAwaitUninterruptibly(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final CountDownLatch pleaseInterrupt = new CountDownLatch(2); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + // Interrupt before awaitUninterruptibly + lock.writeLock().lock(); + pleaseInterrupt.countDown(); + Thread.currentThread().interrupt(); + c.awaitUninterruptibly(); + assertTrue(Thread.interrupted()); + lock.writeLock().unlock(); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + // Interrupt during awaitUninterruptibly + lock.writeLock().lock(); + pleaseInterrupt.countDown(); + c.awaitUninterruptibly(); + assertTrue(Thread.interrupted()); + lock.writeLock().unlock(); + }}); + + await(pleaseInterrupt); + lock.writeLock().lock(); + lock.writeLock().unlock(); + t2.interrupt(); + + assertThreadStaysAlive(t1); + assertTrue(t2.isAlive()); + + lock.writeLock().lock(); + c.signalAll(); + lock.writeLock().unlock(); + + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * await/awaitNanos/awaitUntil is interruptible + */ + public void testInterruptible_await() { testInterruptible(false, AwaitMethod.await); } + public void testInterruptible_await_fair() { testInterruptible(true, AwaitMethod.await); } + public void testInterruptible_awaitTimed() { testInterruptible(false, AwaitMethod.awaitTimed); } + public void testInterruptible_awaitTimed_fair() { testInterruptible(true, AwaitMethod.awaitTimed); } + public void testInterruptible_awaitNanos() { testInterruptible(false, AwaitMethod.awaitNanos); } + public void testInterruptible_awaitNanos_fair() { testInterruptible(true, AwaitMethod.awaitNanos); } + public void testInterruptible_awaitUntil() { testInterruptible(false, AwaitMethod.awaitUntil); } + public void testInterruptible_awaitUntil_fair() { testInterruptible(true, AwaitMethod.awaitUntil); } + public void testInterruptible(boolean fair, final AwaitMethod awaitMethod) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final CountDownLatch locked = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lock(); + assertWriteLockedByMoi(lock); + assertHasNoWaiters(lock, c); + locked.countDown(); + try { + await(c, awaitMethod); + } finally { + assertWriteLockedByMoi(lock); + assertHasNoWaiters(lock, c); + lock.writeLock().unlock(); + assertFalse(Thread.interrupted()); + } + }}); + + await(locked); + assertHasWaiters(lock, c, t); + t.interrupt(); + awaitTermination(t); + assertNotWriteLocked(lock); + } + + /** + * signalAll wakes up all threads + */ + public void testSignalAll_await() { testSignalAll(false, AwaitMethod.await); } + public void testSignalAll_await_fair() { testSignalAll(true, AwaitMethod.await); } + public void testSignalAll_awaitTimed() { testSignalAll(false, AwaitMethod.awaitTimed); } + public void testSignalAll_awaitTimed_fair() { testSignalAll(true, AwaitMethod.awaitTimed); } + public void testSignalAll_awaitNanos() { testSignalAll(false, AwaitMethod.awaitNanos); } + public void testSignalAll_awaitNanos_fair() { testSignalAll(true, AwaitMethod.awaitNanos); } + public void testSignalAll_awaitUntil() { testSignalAll(false, AwaitMethod.awaitUntil); } + public void testSignalAll_awaitUntil_fair() { testSignalAll(true, AwaitMethod.awaitUntil); } + public void testSignalAll(boolean fair, final AwaitMethod awaitMethod) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final CountDownLatch locked = new CountDownLatch(2); + final Lock writeLock = lock.writeLock(); + class Awaiter extends CheckedRunnable { + public void realRun() throws InterruptedException { + writeLock.lock(); + locked.countDown(); + await(c, awaitMethod); + writeLock.unlock(); + } + } + + Thread t1 = newStartedThread(new Awaiter()); + Thread t2 = newStartedThread(new Awaiter()); + + await(locked); + writeLock.lock(); + assertHasWaiters(lock, c, t1, t2); + c.signalAll(); + assertHasNoWaiters(lock, c); + writeLock.unlock(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * signal wakes up waiting threads in FIFO order + */ + public void testSignalWakesFifo() { testSignalWakesFifo(false); } + public void testSignalWakesFifo_fair() { testSignalWakesFifo(true); } + public void testSignalWakesFifo(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final CountDownLatch locked1 = new CountDownLatch(1); + final CountDownLatch locked2 = new CountDownLatch(1); + final Lock writeLock = lock.writeLock(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + writeLock.lock(); + locked1.countDown(); + c.await(); + writeLock.unlock(); + }}); + + await(locked1); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + writeLock.lock(); + locked2.countDown(); + c.await(); + writeLock.unlock(); + }}); + + await(locked2); + + writeLock.lock(); + assertHasWaiters(lock, c, t1, t2); + assertFalse(lock.hasQueuedThreads()); + c.signal(); + assertHasWaiters(lock, c, t2); + assertTrue(lock.hasQueuedThread(t1)); + assertFalse(lock.hasQueuedThread(t2)); + c.signal(); + assertHasNoWaiters(lock, c); + assertTrue(lock.hasQueuedThread(t1)); + assertTrue(lock.hasQueuedThread(t2)); + writeLock.unlock(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * await after multiple reentrant locking preserves lock count + */ + public void testAwaitLockCount() { testAwaitLockCount(false); } + public void testAwaitLockCount_fair() { testAwaitLockCount(true); } + public void testAwaitLockCount(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final CountDownLatch locked = new CountDownLatch(2); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lock(); + assertWriteLockedByMoi(lock); + assertEquals(1, lock.writeLock().getHoldCount()); + locked.countDown(); + c.await(); + assertWriteLockedByMoi(lock); + assertEquals(1, lock.writeLock().getHoldCount()); + lock.writeLock().unlock(); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lock(); + lock.writeLock().lock(); + assertWriteLockedByMoi(lock); + assertEquals(2, lock.writeLock().getHoldCount()); + locked.countDown(); + c.await(); + assertWriteLockedByMoi(lock); + assertEquals(2, lock.writeLock().getHoldCount()); + lock.writeLock().unlock(); + lock.writeLock().unlock(); + }}); + + await(locked); + lock.writeLock().lock(); + assertHasWaiters(lock, c, t1, t2); + c.signalAll(); + assertHasNoWaiters(lock, c); + lock.writeLock().unlock(); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * A serialized lock deserializes as unlocked + */ + public void testSerialization() { testSerialization(false); } + public void testSerialization_fair() { testSerialization(true); } + public void testSerialization(boolean fair) { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + lock.writeLock().lock(); + lock.readLock().lock(); + + ReentrantReadWriteLock clone = serialClone(lock); + assertEquals(lock.isFair(), clone.isFair()); + assertTrue(lock.isWriteLocked()); + assertFalse(clone.isWriteLocked()); + assertEquals(1, lock.getReadLockCount()); + assertEquals(0, clone.getReadLockCount()); + clone.writeLock().lock(); + clone.readLock().lock(); + assertTrue(clone.isWriteLocked()); + assertEquals(1, clone.getReadLockCount()); + clone.readLock().unlock(); + clone.writeLock().unlock(); + assertFalse(clone.isWriteLocked()); + assertEquals(1, lock.getReadLockCount()); + assertEquals(0, clone.getReadLockCount()); + } + + /** + * hasQueuedThreads reports whether there are waiting threads + */ + public void testHasQueuedThreads() { testHasQueuedThreads(false); } + public void testHasQueuedThreads_fair() { testHasQueuedThreads(true); } + public void testHasQueuedThreads(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertFalse(lock.hasQueuedThreads()); + lock.writeLock().lock(); + assertFalse(lock.hasQueuedThreads()); + t1.start(); + waitForQueuedThread(lock, t1); + assertTrue(lock.hasQueuedThreads()); + t2.start(); + waitForQueuedThread(lock, t2); + assertTrue(lock.hasQueuedThreads()); + t1.interrupt(); + awaitTermination(t1); + assertTrue(lock.hasQueuedThreads()); + lock.writeLock().unlock(); + awaitTermination(t2); + assertFalse(lock.hasQueuedThreads()); + } + + /** + * hasQueuedThread(null) throws NPE + */ + public void testHasQueuedThreadNPE() { testHasQueuedThreadNPE(false); } + public void testHasQueuedThreadNPE_fair() { testHasQueuedThreadNPE(true); } + public void testHasQueuedThreadNPE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + try { + lock.hasQueuedThread(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * hasQueuedThread reports whether a thread is queued + */ + public void testHasQueuedThread() { testHasQueuedThread(false); } + public void testHasQueuedThread_fair() { testHasQueuedThread(true); } + public void testHasQueuedThread(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertFalse(lock.hasQueuedThread(t1)); + assertFalse(lock.hasQueuedThread(t2)); + lock.writeLock().lock(); + t1.start(); + waitForQueuedThread(lock, t1); + assertTrue(lock.hasQueuedThread(t1)); + assertFalse(lock.hasQueuedThread(t2)); + t2.start(); + waitForQueuedThread(lock, t2); + assertTrue(lock.hasQueuedThread(t1)); + assertTrue(lock.hasQueuedThread(t2)); + t1.interrupt(); + awaitTermination(t1); + assertFalse(lock.hasQueuedThread(t1)); + assertTrue(lock.hasQueuedThread(t2)); + lock.writeLock().unlock(); + awaitTermination(t2); + assertFalse(lock.hasQueuedThread(t1)); + assertFalse(lock.hasQueuedThread(t2)); + } + + /** + * getQueueLength reports number of waiting threads + */ + public void testGetQueueLength() { testGetQueueLength(false); } + public void testGetQueueLength_fair() { testGetQueueLength(true); } + public void testGetQueueLength(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertEquals(0, lock.getQueueLength()); + lock.writeLock().lock(); + t1.start(); + waitForQueuedThread(lock, t1); + assertEquals(1, lock.getQueueLength()); + t2.start(); + waitForQueuedThread(lock, t2); + assertEquals(2, lock.getQueueLength()); + t1.interrupt(); + awaitTermination(t1); + assertEquals(1, lock.getQueueLength()); + lock.writeLock().unlock(); + awaitTermination(t2); + assertEquals(0, lock.getQueueLength()); + } + + /** + * getQueuedThreads includes waiting threads + */ + public void testGetQueuedThreads() { testGetQueuedThreads(false); } + public void testGetQueuedThreads_fair() { testGetQueuedThreads(true); } + public void testGetQueuedThreads(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertTrue(lock.getQueuedThreads().isEmpty()); + lock.writeLock().lock(); + assertTrue(lock.getQueuedThreads().isEmpty()); + t1.start(); + waitForQueuedThread(lock, t1); + assertEquals(1, lock.getQueuedThreads().size()); + assertTrue(lock.getQueuedThreads().contains(t1)); + t2.start(); + waitForQueuedThread(lock, t2); + assertEquals(2, lock.getQueuedThreads().size()); + assertTrue(lock.getQueuedThreads().contains(t1)); + assertTrue(lock.getQueuedThreads().contains(t2)); + t1.interrupt(); + awaitTermination(t1); + assertFalse(lock.getQueuedThreads().contains(t1)); + assertTrue(lock.getQueuedThreads().contains(t2)); + assertEquals(1, lock.getQueuedThreads().size()); + lock.writeLock().unlock(); + awaitTermination(t2); + assertTrue(lock.getQueuedThreads().isEmpty()); + } + + /** + * hasWaiters throws NPE if null + */ + public void testHasWaitersNPE() { testHasWaitersNPE(false); } + public void testHasWaitersNPE_fair() { testHasWaitersNPE(true); } + public void testHasWaitersNPE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + try { + lock.hasWaiters(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getWaitQueueLength throws NPE if null + */ + public void testGetWaitQueueLengthNPE() { testGetWaitQueueLengthNPE(false); } + public void testGetWaitQueueLengthNPE_fair() { testGetWaitQueueLengthNPE(true); } + public void testGetWaitQueueLengthNPE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + try { + lock.getWaitQueueLength(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * getWaitingThreads throws NPE if null + */ + public void testGetWaitingThreadsNPE() { testGetWaitingThreadsNPE(false); } + public void testGetWaitingThreadsNPE_fair() { testGetWaitingThreadsNPE(true); } + public void testGetWaitingThreadsNPE(boolean fair) { + final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock(fair); + try { + lock.getWaitingThreads(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * hasWaiters throws IllegalArgumentException if not owned + */ + public void testHasWaitersIAE() { testHasWaitersIAE(false); } + public void testHasWaitersIAE_fair() { testHasWaitersIAE(true); } + public void testHasWaitersIAE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock(fair); + try { + lock2.hasWaiters(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * hasWaiters throws IllegalMonitorStateException if not locked + */ + public void testHasWaitersIMSE() { testHasWaitersIMSE(false); } + public void testHasWaitersIMSE_fair() { testHasWaitersIMSE(true); } + public void testHasWaitersIMSE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + try { + lock.hasWaiters(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * getWaitQueueLength throws IllegalArgumentException if not owned + */ + public void testGetWaitQueueLengthIAE() { testGetWaitQueueLengthIAE(false); } + public void testGetWaitQueueLengthIAE_fair() { testGetWaitQueueLengthIAE(true); } + public void testGetWaitQueueLengthIAE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock(fair); + try { + lock2.getWaitQueueLength(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * getWaitQueueLength throws IllegalMonitorStateException if not locked + */ + public void testGetWaitQueueLengthIMSE() { testGetWaitQueueLengthIMSE(false); } + public void testGetWaitQueueLengthIMSE_fair() { testGetWaitQueueLengthIMSE(true); } + public void testGetWaitQueueLengthIMSE(boolean fair) { + final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + try { + lock.getWaitQueueLength(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * getWaitingThreads throws IllegalArgumentException if not owned + */ + public void testGetWaitingThreadsIAE() { testGetWaitingThreadsIAE(false); } + public void testGetWaitingThreadsIAE_fair() { testGetWaitingThreadsIAE(true); } + public void testGetWaitingThreadsIAE(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final PublicReentrantReadWriteLock lock2 = + new PublicReentrantReadWriteLock(fair); + try { + lock2.getWaitingThreads(c); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * getWaitingThreads throws IllegalMonitorStateException if not locked + */ + public void testGetWaitingThreadsIMSE() { testGetWaitingThreadsIMSE(false); } + public void testGetWaitingThreadsIMSE_fair() { testGetWaitingThreadsIMSE(true); } + public void testGetWaitingThreadsIMSE(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + try { + lock.getWaitingThreads(c); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * hasWaiters returns true when a thread is waiting, else false + */ + public void testHasWaiters() { testHasWaiters(false); } + public void testHasWaiters_fair() { testHasWaiters(true); } + public void testHasWaiters(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final CountDownLatch locked = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lock(); + assertHasNoWaiters(lock, c); + assertFalse(lock.hasWaiters(c)); + locked.countDown(); + c.await(); + assertHasNoWaiters(lock, c); + assertFalse(lock.hasWaiters(c)); + lock.writeLock().unlock(); + }}); + + await(locked); + lock.writeLock().lock(); + assertHasWaiters(lock, c, t); + assertTrue(lock.hasWaiters(c)); + c.signal(); + assertHasNoWaiters(lock, c); + assertFalse(lock.hasWaiters(c)); + lock.writeLock().unlock(); + awaitTermination(t); + assertHasNoWaiters(lock, c); + } + + /** + * getWaitQueueLength returns number of waiting threads + */ + public void testGetWaitQueueLength() { testGetWaitQueueLength(false); } + public void testGetWaitQueueLength_fair() { testGetWaitQueueLength(true); } + public void testGetWaitQueueLength(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final CountDownLatch locked = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lock(); + assertEquals(0, lock.getWaitQueueLength(c)); + locked.countDown(); + c.await(); + lock.writeLock().unlock(); + }}); + + await(locked); + lock.writeLock().lock(); + assertHasWaiters(lock, c, t); + assertEquals(1, lock.getWaitQueueLength(c)); + c.signal(); + assertHasNoWaiters(lock, c); + assertEquals(0, lock.getWaitQueueLength(c)); + lock.writeLock().unlock(); + awaitTermination(t); + } + + /** + * getWaitingThreads returns only and all waiting threads + */ + public void testGetWaitingThreads() { testGetWaitingThreads(false); } + public void testGetWaitingThreads_fair() { testGetWaitingThreads(true); } + public void testGetWaitingThreads(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + final Condition c = lock.writeLock().newCondition(); + final CountDownLatch locked1 = new CountDownLatch(1); + final CountDownLatch locked2 = new CountDownLatch(1); + Thread t1 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lock(); + assertTrue(lock.getWaitingThreads(c).isEmpty()); + locked1.countDown(); + c.await(); + lock.writeLock().unlock(); + }}); + + Thread t2 = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLock().lock(); + assertFalse(lock.getWaitingThreads(c).isEmpty()); + locked2.countDown(); + c.await(); + lock.writeLock().unlock(); + }}); + + lock.writeLock().lock(); + assertTrue(lock.getWaitingThreads(c).isEmpty()); + lock.writeLock().unlock(); + + t1.start(); + await(locked1); + t2.start(); + await(locked2); + + lock.writeLock().lock(); + assertTrue(lock.hasWaiters(c)); + assertTrue(lock.getWaitingThreads(c).contains(t1)); + assertTrue(lock.getWaitingThreads(c).contains(t2)); + assertEquals(2, lock.getWaitingThreads(c).size()); + c.signalAll(); + assertHasNoWaiters(lock, c); + lock.writeLock().unlock(); + + awaitTermination(t1); + awaitTermination(t2); + + assertHasNoWaiters(lock, c); + } + + /** + * toString indicates current lock state + */ + public void testToString() { testToString(false); } + public void testToString_fair() { testToString(true); } + public void testToString(boolean fair) { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + assertTrue(lock.toString().contains("Write locks = 0")); + assertTrue(lock.toString().contains("Read locks = 0")); + lock.writeLock().lock(); + assertTrue(lock.toString().contains("Write locks = 1")); + assertTrue(lock.toString().contains("Read locks = 0")); + lock.writeLock().unlock(); + lock.readLock().lock(); + lock.readLock().lock(); + assertTrue(lock.toString().contains("Write locks = 0")); + assertTrue(lock.toString().contains("Read locks = 2")); + } + + /** + * readLock.toString indicates current lock state + */ + public void testReadLockToString() { testReadLockToString(false); } + public void testReadLockToString_fair() { testReadLockToString(true); } + public void testReadLockToString(boolean fair) { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + assertTrue(lock.readLock().toString().contains("Read locks = 0")); + lock.readLock().lock(); + lock.readLock().lock(); + assertTrue(lock.readLock().toString().contains("Read locks = 2")); + } + + /** + * writeLock.toString indicates current lock state + */ + public void testWriteLockToString() { testWriteLockToString(false); } + public void testWriteLockToString_fair() { testWriteLockToString(true); } + public void testWriteLockToString(boolean fair) { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + assertTrue(lock.writeLock().toString().contains("Unlocked")); + lock.writeLock().lock(); + assertTrue(lock.writeLock().toString().contains("Locked")); + lock.writeLock().unlock(); + assertTrue(lock.writeLock().toString().contains("Unlocked")); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java new file mode 100644 index 00000000000..50b7b171140 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java @@ -0,0 +1,1286 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Delayed; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.RunnableScheduledFuture; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ScheduledExecutorSubclassTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ScheduledExecutorSubclassTest.class); + } + + static class CustomTask implements RunnableScheduledFuture { + RunnableScheduledFuture task; + volatile boolean ran; + CustomTask(RunnableScheduledFuture t) { task = t; } + public boolean isPeriodic() { return task.isPeriodic(); } + public void run() { + ran = true; + task.run(); + } + public long getDelay(TimeUnit unit) { return task.getDelay(unit); } + public int compareTo(Delayed t) { + return task.compareTo(((CustomTask)t).task); + } + public boolean cancel(boolean mayInterruptIfRunning) { + return task.cancel(mayInterruptIfRunning); + } + public boolean isCancelled() { return task.isCancelled(); } + public boolean isDone() { return task.isDone(); } + public V get() throws InterruptedException, ExecutionException { + V v = task.get(); + assertTrue(ran); + return v; + } + public V get(long time, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + V v = task.get(time, unit); + assertTrue(ran); + return v; + } + } + + public class CustomExecutor extends ScheduledThreadPoolExecutor { + + protected RunnableScheduledFuture decorateTask(Runnable r, RunnableScheduledFuture task) { + return new CustomTask(task); + } + + protected RunnableScheduledFuture decorateTask(Callable c, RunnableScheduledFuture task) { + return new CustomTask(task); + } + CustomExecutor(int corePoolSize) { super(corePoolSize); } + CustomExecutor(int corePoolSize, RejectedExecutionHandler handler) { + super(corePoolSize, handler); + } + + CustomExecutor(int corePoolSize, ThreadFactory threadFactory) { + super(corePoolSize, threadFactory); + } + CustomExecutor(int corePoolSize, ThreadFactory threadFactory, + RejectedExecutionHandler handler) { + super(corePoolSize, threadFactory, handler); + } + + } + + /** + * execute successfully executes a runnable + */ + public void testExecute() throws InterruptedException { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch done = new CountDownLatch(1); + final Runnable task = new CheckedRunnable() { + public void realRun() { done.countDown(); }}; + p.execute(task); + await(done); + } + } + + /** + * delayed schedule of callable successfully executes after delay + */ + public void testSchedule1() throws Exception { + final CountDownLatch done = new CountDownLatch(1); + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + final long startTime = System.nanoTime(); + Callable task = new CheckedCallable() { + public Boolean realCall() { + done.countDown(); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + return Boolean.TRUE; + }}; + Future f = p.schedule(task, timeoutMillis(), MILLISECONDS); + assertSame(Boolean.TRUE, f.get()); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + } + + /** + * delayed schedule of runnable successfully executes after delay + */ + public void testSchedule3() throws Exception { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final long startTime = System.nanoTime(); + final CountDownLatch done = new CountDownLatch(1); + Runnable task = new CheckedRunnable() { + public void realRun() { + done.countDown(); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}; + Future f = p.schedule(task, timeoutMillis(), MILLISECONDS); + await(done); + assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + } + + /** + * scheduleAtFixedRate executes runnable after given initial delay + */ + public void testSchedule4() throws InterruptedException { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final long startTime = System.nanoTime(); + final CountDownLatch done = new CountDownLatch(1); + Runnable task = new CheckedRunnable() { + public void realRun() { + done.countDown(); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}; + ScheduledFuture f = + p.scheduleAtFixedRate(task, timeoutMillis(), + LONG_DELAY_MS, MILLISECONDS); + await(done); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + f.cancel(true); + } + } + + /** + * scheduleWithFixedDelay executes runnable after given initial delay + */ + public void testSchedule5() throws InterruptedException { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final long startTime = System.nanoTime(); + final CountDownLatch done = new CountDownLatch(1); + Runnable task = new CheckedRunnable() { + public void realRun() { + done.countDown(); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}; + ScheduledFuture f = + p.scheduleWithFixedDelay(task, timeoutMillis(), + LONG_DELAY_MS, MILLISECONDS); + await(done); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + f.cancel(true); + } + } + + static class RunnableCounter implements Runnable { + AtomicInteger count = new AtomicInteger(0); + public void run() { count.getAndIncrement(); } + } + + /** + * scheduleAtFixedRate executes series of tasks at given rate + */ + public void testFixedRateSequence() throws InterruptedException { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { + long startTime = System.nanoTime(); + int cycles = 10; + final CountDownLatch done = new CountDownLatch(cycles); + Runnable task = new CheckedRunnable() { + public void realRun() { done.countDown(); }}; + ScheduledFuture h = + p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS); + await(done); + h.cancel(true); + double normalizedTime = + (double) millisElapsedSince(startTime) / delay; + if (normalizedTime >= cycles - 1 && + normalizedTime <= cycles) + return; + } + fail("unexpected execution rate"); + } + } + + /** + * scheduleWithFixedDelay executes series of tasks with given period + */ + public void testFixedDelaySequence() throws InterruptedException { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { + long startTime = System.nanoTime(); + int cycles = 10; + final CountDownLatch done = new CountDownLatch(cycles); + Runnable task = new CheckedRunnable() { + public void realRun() { done.countDown(); }}; + ScheduledFuture h = + p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS); + await(done); + h.cancel(true); + double normalizedTime = + (double) millisElapsedSince(startTime) / delay; + if (normalizedTime >= cycles - 1 && + normalizedTime <= cycles) + return; + } + fail("unexpected execution rate"); + } + } + + /** + * execute(null) throws NPE + */ + public void testExecuteNull() throws InterruptedException { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.execute(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * schedule(null) throws NPE + */ + public void testScheduleNull() throws InterruptedException { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + TrackedCallable callable = null; + Future f = p.schedule(callable, SHORT_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * execute throws RejectedExecutionException if shutdown + */ + public void testSchedule1_RejectedExecutionException() { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.schedule(new NoOpRunnable(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * schedule throws RejectedExecutionException if shutdown + */ + public void testSchedule2_RejectedExecutionException() { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.schedule(new NoOpCallable(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * schedule callable throws RejectedExecutionException if shutdown + */ + public void testSchedule3_RejectedExecutionException() { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.schedule(new NoOpCallable(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * scheduleAtFixedRate throws RejectedExecutionException if shutdown + */ + public void testScheduleAtFixedRate1_RejectedExecutionException() { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.scheduleAtFixedRate(new NoOpRunnable(), + MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * scheduleWithFixedDelay throws RejectedExecutionException if shutdown + */ + public void testScheduleWithFixedDelay1_RejectedExecutionException() { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.scheduleWithFixedDelay(new NoOpRunnable(), + MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * getActiveCount increases but doesn't overestimate, when a + * thread becomes active + */ + public void testGetActiveCount() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertEquals(0, p.getActiveCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1, p.getActiveCount()); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getActiveCount()); + } + } + + /** + * getCompletedTaskCount increases, but doesn't overestimate, + * when tasks complete + */ + public void testGetCompletedTaskCount() throws InterruptedException { + final ThreadPoolExecutor p = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch threadProceed = new CountDownLatch(1); + final CountDownLatch threadDone = new CountDownLatch(1); + assertEquals(0, p.getCompletedTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(0, p.getCompletedTaskCount()); + threadProceed.await(); + threadDone.countDown(); + }}); + await(threadStarted); + assertEquals(0, p.getCompletedTaskCount()); + threadProceed.countDown(); + threadDone.await(); + long startTime = System.nanoTime(); + while (p.getCompletedTaskCount() != 1) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + } + } + + /** + * getCorePoolSize returns size given in constructor if not otherwise set + */ + public void testGetCorePoolSize() { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(1, p.getCorePoolSize()); + } + } + + /** + * getLargestPoolSize increases, but doesn't overestimate, when + * multiple threads active + */ + public void testGetLargestPoolSize() throws InterruptedException { + final int THREADS = 3; + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = new CustomExecutor(THREADS); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadsStarted = new CountDownLatch(THREADS); + assertEquals(0, p.getLargestPoolSize()); + for (int i = 0; i < THREADS; i++) + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.countDown(); + await(done); + assertEquals(THREADS, p.getLargestPoolSize()); + }}); + await(threadsStarted); + assertEquals(THREADS, p.getLargestPoolSize()); + } + assertEquals(THREADS, p.getLargestPoolSize()); + } + + /** + * getPoolSize increases, but doesn't overestimate, when threads + * become active + */ + public void testGetPoolSize() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertEquals(0, p.getPoolSize()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1, p.getPoolSize()); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getPoolSize()); + } + } + + /** + * getTaskCount increases, but doesn't overestimate, when tasks + * submitted + */ + public void testGetTaskCount() throws InterruptedException { + final int TASKS = 3; + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertEquals(0, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + for (int i = 0; i < TASKS; i++) { + assertEquals(1 + i, p.getTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1 + TASKS, p.getTaskCount()); + await(done); + }}); + } + assertEquals(1 + TASKS, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + } + assertEquals(1 + TASKS, p.getTaskCount()); + assertEquals(1 + TASKS, p.getCompletedTaskCount()); + } + + /** + * getThreadFactory returns factory in constructor if not set + */ + public void testGetThreadFactory() { + final ThreadFactory threadFactory = new SimpleThreadFactory(); + final CustomExecutor p = new CustomExecutor(1, threadFactory); + try (PoolCleaner cleaner = cleaner(p)) { + assertSame(threadFactory, p.getThreadFactory()); + } + } + + /** + * setThreadFactory sets the thread factory returned by getThreadFactory + */ + public void testSetThreadFactory() { + final ThreadFactory threadFactory = new SimpleThreadFactory(); + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + p.setThreadFactory(threadFactory); + assertSame(threadFactory, p.getThreadFactory()); + } + } + + /** + * setThreadFactory(null) throws NPE + */ + public void testSetThreadFactoryNull() { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setThreadFactory(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * isShutdown is false before shutdown, true after + */ + public void testIsShutdown() { + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + assertFalse(p.isShutdown()); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.isShutdown()); + } + } + + /** + * isTerminated is false before termination, true after + */ + public void testIsTerminated() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(p.isTerminated()); + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertFalse(p.isTerminated()); + assertFalse(p.isTerminating()); + done.countDown(); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + } + } + + /** + * isTerminating is not true when running or when terminated + */ + public void testIsTerminating() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertFalse(p.isTerminating()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(p.isTerminating()); + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertFalse(p.isTerminating()); + done.countDown(); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertFalse(p.isTerminating()); + } + } + + /** + * getQueue returns the work queue, which contains queued tasks + */ + public void testGetQueue() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ScheduledThreadPoolExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + ScheduledFuture[] tasks = new ScheduledFuture[5]; + for (int i = 0; i < tasks.length; i++) { + Runnable r = new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}; + tasks[i] = p.schedule(r, 1, MILLISECONDS); + } + await(threadStarted); + BlockingQueue q = p.getQueue(); + assertTrue(q.contains(tasks[tasks.length - 1])); + assertFalse(q.contains(tasks[0])); + } + } + + /** + * remove(task) removes queued task, and fails to remove active task + */ + public void testRemove() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ScheduledThreadPoolExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + ScheduledFuture[] tasks = new ScheduledFuture[5]; + final CountDownLatch threadStarted = new CountDownLatch(1); + for (int i = 0; i < tasks.length; i++) { + Runnable r = new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}; + tasks[i] = p.schedule(r, 1, MILLISECONDS); + } + await(threadStarted); + BlockingQueue q = p.getQueue(); + assertFalse(p.remove((Runnable)tasks[0])); + assertTrue(q.contains((Runnable)tasks[4])); + assertTrue(q.contains((Runnable)tasks[3])); + assertTrue(p.remove((Runnable)tasks[4])); + assertFalse(p.remove((Runnable)tasks[4])); + assertFalse(q.contains((Runnable)tasks[4])); + assertTrue(q.contains((Runnable)tasks[3])); + assertTrue(p.remove((Runnable)tasks[3])); + assertFalse(q.contains((Runnable)tasks[3])); + } + } + + /** + * purge removes cancelled tasks from the queue + */ + public void testPurge() throws InterruptedException { + final ScheduledFuture[] tasks = new ScheduledFuture[5]; + final Runnable releaser = new Runnable() { public void run() { + for (ScheduledFuture task : tasks) + if (task != null) task.cancel(true); }}; + final CustomExecutor p = new CustomExecutor(1); + try (PoolCleaner cleaner = cleaner(p, releaser)) { + for (int i = 0; i < tasks.length; i++) + tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(), + LONG_DELAY_MS, MILLISECONDS); + int max = tasks.length; + if (tasks[4].cancel(true)) --max; + if (tasks[3].cancel(true)) --max; + // There must eventually be an interference-free point at + // which purge will not fail. (At worst, when queue is empty.) + long startTime = System.nanoTime(); + do { + p.purge(); + long count = p.getTaskCount(); + if (count == max) + return; + } while (millisElapsedSince(startTime) < LONG_DELAY_MS); + fail("Purge failed to remove cancelled tasks"); + } + } + + /** + * shutdownNow returns a list containing tasks that were not run, + * and those tasks are drained from the queue + */ + public void testShutdownNow() throws InterruptedException { + final int poolSize = 2; + final int count = 5; + final AtomicInteger ran = new AtomicInteger(0); + final CustomExecutor p = new CustomExecutor(poolSize); + final CountDownLatch threadsStarted = new CountDownLatch(poolSize); + Runnable waiter = new CheckedRunnable() { public void realRun() { + threadsStarted.countDown(); + try { + MILLISECONDS.sleep(2 * LONG_DELAY_MS); + } catch (InterruptedException success) {} + ran.getAndIncrement(); + }}; + for (int i = 0; i < count; i++) + p.execute(waiter); + await(threadsStarted); + assertEquals(poolSize, p.getActiveCount()); + assertEquals(0, p.getCompletedTaskCount()); + final List queuedTasks; + try { + queuedTasks = p.shutdownNow(); + } catch (SecurityException ok) { + return; // Allowed in case test doesn't have privs + } + assertTrue(p.isShutdown()); + assertTrue(p.getQueue().isEmpty()); + assertEquals(count - poolSize, queuedTasks.size()); + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertEquals(poolSize, ran.get()); + assertEquals(poolSize, p.getCompletedTaskCount()); + } + + /** + * shutdownNow returns a list containing tasks that were not run, + * and those tasks are drained from the queue + */ + public void testShutdownNow_delayedTasks() throws InterruptedException { + final CustomExecutor p = new CustomExecutor(1); + List tasks = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + Runnable r = new NoOpRunnable(); + tasks.add(p.schedule(r, 9, SECONDS)); + tasks.add(p.scheduleAtFixedRate(r, 9, 9, SECONDS)); + tasks.add(p.scheduleWithFixedDelay(r, 9, 9, SECONDS)); + } + if (testImplementationDetails) + assertEquals(new HashSet(tasks), new HashSet(p.getQueue())); + final List queuedTasks; + try { + queuedTasks = p.shutdownNow(); + } catch (SecurityException ok) { + return; // Allowed in case test doesn't have privs + } + assertTrue(p.isShutdown()); + assertTrue(p.getQueue().isEmpty()); + if (testImplementationDetails) + assertEquals(new HashSet(tasks), new HashSet(queuedTasks)); + assertEquals(tasks.size(), queuedTasks.size()); + for (ScheduledFuture task : tasks) { + assertFalse(((CustomTask)task).ran); + assertFalse(task.isDone()); + assertFalse(task.isCancelled()); + } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + } + + /** + * By default, periodic tasks are cancelled at shutdown. + * By default, delayed tasks keep running after shutdown. + * Check that changing the default values work: + * - setExecuteExistingDelayedTasksAfterShutdownPolicy + * - setContinueExistingPeriodicTasksAfterShutdownPolicy + */ + public void testShutdown_cancellation() throws Exception { + Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE }; + for (Boolean policy : allBooleans) + { + final int poolSize = 2; + final CustomExecutor p = new CustomExecutor(poolSize); + final boolean effectiveDelayedPolicy = (policy != Boolean.FALSE); + final boolean effectivePeriodicPolicy = (policy == Boolean.TRUE); + final boolean effectiveRemovePolicy = (policy == Boolean.TRUE); + if (policy != null) { + p.setExecuteExistingDelayedTasksAfterShutdownPolicy(policy); + p.setContinueExistingPeriodicTasksAfterShutdownPolicy(policy); + p.setRemoveOnCancelPolicy(policy); + } + assertEquals(effectiveDelayedPolicy, + p.getExecuteExistingDelayedTasksAfterShutdownPolicy()); + assertEquals(effectivePeriodicPolicy, + p.getContinueExistingPeriodicTasksAfterShutdownPolicy()); + assertEquals(effectiveRemovePolicy, + p.getRemoveOnCancelPolicy()); + // Strategy: Wedge the pool with poolSize "blocker" threads + final AtomicInteger ran = new AtomicInteger(0); + final CountDownLatch poolBlocked = new CountDownLatch(poolSize); + final CountDownLatch unblock = new CountDownLatch(1); + final CountDownLatch periodicLatch1 = new CountDownLatch(2); + final CountDownLatch periodicLatch2 = new CountDownLatch(2); + Runnable task = new CheckedRunnable() { public void realRun() + throws InterruptedException { + poolBlocked.countDown(); + assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS)); + ran.getAndIncrement(); + }}; + List> blockers = new ArrayList<>(); + List> periodics = new ArrayList<>(); + List> delayeds = new ArrayList<>(); + for (int i = 0; i < poolSize; i++) + blockers.add(p.submit(task)); + assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS)); + + periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1), + 1, 1, MILLISECONDS)); + periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2), + 1, 1, MILLISECONDS)); + delayeds.add(p.schedule(task, 1, MILLISECONDS)); + + assertTrue(p.getQueue().containsAll(periodics)); + assertTrue(p.getQueue().containsAll(delayeds)); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.isShutdown()); + assertFalse(p.isTerminated()); + for (Future periodic : periodics) { + assertTrue(effectivePeriodicPolicy ^ periodic.isCancelled()); + assertTrue(effectivePeriodicPolicy ^ periodic.isDone()); + } + for (Future delayed : delayeds) { + assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled()); + assertTrue(effectiveDelayedPolicy ^ delayed.isDone()); + } + if (testImplementationDetails) { + assertEquals(effectivePeriodicPolicy, + p.getQueue().containsAll(periodics)); + assertEquals(effectiveDelayedPolicy, + p.getQueue().containsAll(delayeds)); + } + // Release all pool threads + unblock.countDown(); + + for (Future delayed : delayeds) { + if (effectiveDelayedPolicy) { + assertNull(delayed.get()); + } + } + if (effectivePeriodicPolicy) { + assertTrue(periodicLatch1.await(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(periodicLatch2.await(LONG_DELAY_MS, MILLISECONDS)); + for (Future periodic : periodics) { + assertTrue(periodic.cancel(false)); + assertTrue(periodic.isCancelled()); + assertTrue(periodic.isDone()); + } + } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertEquals(2 + (effectiveDelayedPolicy ? 1 : 0), ran.get()); + }} + + /** + * completed submit of callable returns result + */ + public void testSubmitCallable() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new StringTask()); + String result = future.get(); + assertSame(TEST_STRING, result); + } + } + + /** + * completed submit of runnable returns successfully + */ + public void testSubmitRunnable() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable()); + future.get(); + assertTrue(future.isDone()); + } + } + + /** + * completed submit of (runnable, result) returns result + */ + public void testSubmitRunnable2() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable(), TEST_STRING); + String result = future.get(); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAny(null) throws NPE + */ + public void testInvokeAny1() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAny(empty collection) throws IAE + */ + public void testInvokeAny2() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * invokeAny(c) throws NPE if c has null elements + */ + public void testInvokeAny3() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * invokeAny(c) throws ExecutionException if no task completes + */ + public void testInvokeAny4() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAny(c) returns result of some task + */ + public void testInvokeAny5() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAll(null) throws NPE + */ + public void testInvokeAll1() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAll(empty collection) returns empty collection + */ + public void testInvokeAll2() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>()); + assertTrue(r.isEmpty()); + } + } + + /** + * invokeAll(c) throws NPE if c has null elements + */ + public void testInvokeAll3() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of invokeAll(c) throws exception on failed task + */ + public void testInvokeAll4() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = e.invokeAll(l); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAll(c) returns results of all completed tasks + */ + public void testInvokeAll5() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = e.invokeAll(l); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAny(null) throws NPE + */ + public void testTimedInvokeAny1() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(,,null) throws NPE + */ + public void testTimedInvokeAnyNullTimeUnit() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(empty collection) throws IAE + */ + public void testTimedInvokeAny2() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>(), MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * timed invokeAny(c) throws NPE if c has null elements + */ + public void testTimedInvokeAny3() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * timed invokeAny(c) throws ExecutionException if no task completes + */ + public void testTimedInvokeAny4() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAny(c) returns result of some task + */ + public void testTimedInvokeAny5() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + assertSame(TEST_STRING, result); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAll(null) throws NPE + */ + public void testTimedInvokeAll1() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(,,null) throws NPE + */ + public void testTimedInvokeAllNullTimeUnit() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(empty collection) returns empty collection + */ + public void testTimedInvokeAll2() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>(), MEDIUM_DELAY_MS, MILLISECONDS); + assertTrue(r.isEmpty()); + } + } + + /** + * timed invokeAll(c) throws NPE if c has null elements + */ + public void testTimedInvokeAll3() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of element of invokeAll(c) throws exception on failed task + */ + public void testTimedInvokeAll4() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * timed invokeAll(c) returns results of all completed tasks + */ + public void testTimedInvokeAll5() throws Exception { + final ExecutorService e = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = + e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAll(c) cancels tasks not completed by timeout + */ + public void testTimedInvokeAll6() throws Exception { + for (long timeout = timeoutMillis();;) { + final CountDownLatch done = new CountDownLatch(1); + final Callable waiter = new CheckedCallable() { + public String realCall() { + try { done.await(LONG_DELAY_MS, MILLISECONDS); } + catch (InterruptedException ok) {} + return "1"; }}; + final ExecutorService p = new CustomExecutor(2); + try (PoolCleaner cleaner = cleaner(p, done)) { + List> tasks = new ArrayList<>(); + tasks.add(new StringTask("0")); + tasks.add(waiter); + tasks.add(new StringTask("2")); + long startTime = System.nanoTime(); + List> futures = + p.invokeAll(tasks, timeout, MILLISECONDS); + assertEquals(tasks.size(), futures.size()); + assertTrue(millisElapsedSince(startTime) >= timeout); + for (Future future : futures) + assertTrue(future.isDone()); + assertTrue(futures.get(1).isCancelled()); + try { + assertEquals("0", futures.get(0).get()); + assertEquals("2", futures.get(2).get()); + break; + } catch (CancellationException retryWithLongerTimeout) { + timeout *= 2; + if (timeout >= LONG_DELAY_MS / 2) + fail("expected exactly one task to be cancelled"); + } + } + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java new file mode 100644 index 00000000000..797dee3a845 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java @@ -0,0 +1,1259 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicInteger; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ScheduledExecutorTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ScheduledExecutorTest.class); + } + + /** + * execute successfully executes a runnable + */ + public void testExecute() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch done = new CountDownLatch(1); + final Runnable task = new CheckedRunnable() { + public void realRun() { done.countDown(); }}; + p.execute(task); + assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS)); + } + } + + /** + * delayed schedule of callable successfully executes after delay + */ + public void testSchedule1() throws Exception { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final long startTime = System.nanoTime(); + final CountDownLatch done = new CountDownLatch(1); + Callable task = new CheckedCallable() { + public Boolean realCall() { + done.countDown(); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + return Boolean.TRUE; + }}; + Future f = p.schedule(task, timeoutMillis(), MILLISECONDS); + assertSame(Boolean.TRUE, f.get()); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + assertTrue(done.await(0L, MILLISECONDS)); + } + } + + /** + * delayed schedule of runnable successfully executes after delay + */ + public void testSchedule3() throws Exception { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final long startTime = System.nanoTime(); + final CountDownLatch done = new CountDownLatch(1); + Runnable task = new CheckedRunnable() { + public void realRun() { + done.countDown(); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}; + Future f = p.schedule(task, timeoutMillis(), MILLISECONDS); + await(done); + assertNull(f.get(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + } + + /** + * scheduleAtFixedRate executes runnable after given initial delay + */ + public void testSchedule4() throws Exception { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final long startTime = System.nanoTime(); + final CountDownLatch done = new CountDownLatch(1); + Runnable task = new CheckedRunnable() { + public void realRun() { + done.countDown(); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}; + ScheduledFuture f = + p.scheduleAtFixedRate(task, timeoutMillis(), + LONG_DELAY_MS, MILLISECONDS); + await(done); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + f.cancel(true); + } + } + + /** + * scheduleWithFixedDelay executes runnable after given initial delay + */ + public void testSchedule5() throws Exception { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final long startTime = System.nanoTime(); + final CountDownLatch done = new CountDownLatch(1); + Runnable task = new CheckedRunnable() { + public void realRun() { + done.countDown(); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + }}; + ScheduledFuture f = + p.scheduleWithFixedDelay(task, timeoutMillis(), + LONG_DELAY_MS, MILLISECONDS); + await(done); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + f.cancel(true); + } + } + + static class RunnableCounter implements Runnable { + AtomicInteger count = new AtomicInteger(0); + public void run() { count.getAndIncrement(); } + } + + /** + * scheduleAtFixedRate executes series of tasks at given rate + */ + public void testFixedRateSequence() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { + long startTime = System.nanoTime(); + int cycles = 10; + final CountDownLatch done = new CountDownLatch(cycles); + Runnable task = new CheckedRunnable() { + public void realRun() { done.countDown(); }}; + ScheduledFuture h = + p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS); + await(done); + h.cancel(true); + double normalizedTime = + (double) millisElapsedSince(startTime) / delay; + if (normalizedTime >= cycles - 1 && + normalizedTime <= cycles) + return; + } + fail("unexpected execution rate"); + } + } + + /** + * scheduleWithFixedDelay executes series of tasks with given period + */ + public void testFixedDelaySequence() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { + long startTime = System.nanoTime(); + int cycles = 10; + final CountDownLatch done = new CountDownLatch(cycles); + Runnable task = new CheckedRunnable() { + public void realRun() { done.countDown(); }}; + ScheduledFuture h = + p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS); + await(done); + h.cancel(true); + double normalizedTime = + (double) millisElapsedSince(startTime) / delay; + if (normalizedTime >= cycles - 1 && + normalizedTime <= cycles) + return; + } + fail("unexpected execution rate"); + } + } + + /** + * execute(null) throws NPE + */ + public void testExecuteNull() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.execute(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * schedule(null) throws NPE + */ + public void testScheduleNull() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + TrackedCallable callable = null; + Future f = p.schedule(callable, SHORT_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * execute throws RejectedExecutionException if shutdown + */ + public void testSchedule1_RejectedExecutionException() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.schedule(new NoOpRunnable(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * schedule throws RejectedExecutionException if shutdown + */ + public void testSchedule2_RejectedExecutionException() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.schedule(new NoOpCallable(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * schedule callable throws RejectedExecutionException if shutdown + */ + public void testSchedule3_RejectedExecutionException() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.schedule(new NoOpCallable(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * scheduleAtFixedRate throws RejectedExecutionException if shutdown + */ + public void testScheduleAtFixedRate1_RejectedExecutionException() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.scheduleAtFixedRate(new NoOpRunnable(), + MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * scheduleWithFixedDelay throws RejectedExecutionException if shutdown + */ + public void testScheduleWithFixedDelay1_RejectedExecutionException() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.shutdown(); + p.scheduleWithFixedDelay(new NoOpRunnable(), + MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (RejectedExecutionException success) { + } catch (SecurityException ok) {} + } + } + + /** + * getActiveCount increases but doesn't overestimate, when a + * thread becomes active + */ + public void testGetActiveCount() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertEquals(0, p.getActiveCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1, p.getActiveCount()); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getActiveCount()); + } + } + + /** + * getCompletedTaskCount increases, but doesn't overestimate, + * when tasks complete + */ + public void testGetCompletedTaskCount() throws InterruptedException { + final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch threadProceed = new CountDownLatch(1); + final CountDownLatch threadDone = new CountDownLatch(1); + assertEquals(0, p.getCompletedTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(0, p.getCompletedTaskCount()); + threadProceed.await(); + threadDone.countDown(); + }}); + await(threadStarted); + assertEquals(0, p.getCompletedTaskCount()); + threadProceed.countDown(); + threadDone.await(); + long startTime = System.nanoTime(); + while (p.getCompletedTaskCount() != 1) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + } + } + + /** + * getCorePoolSize returns size given in constructor if not otherwise set + */ + public void testGetCorePoolSize() throws InterruptedException { + ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(1, p.getCorePoolSize()); + } + } + + /** + * getLargestPoolSize increases, but doesn't overestimate, when + * multiple threads active + */ + public void testGetLargestPoolSize() throws InterruptedException { + final int THREADS = 3; + final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(THREADS); + final CountDownLatch threadsStarted = new CountDownLatch(THREADS); + final CountDownLatch done = new CountDownLatch(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + assertEquals(0, p.getLargestPoolSize()); + for (int i = 0; i < THREADS; i++) + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.countDown(); + await(done); + assertEquals(THREADS, p.getLargestPoolSize()); + }}); + await(threadsStarted); + assertEquals(THREADS, p.getLargestPoolSize()); + } + assertEquals(THREADS, p.getLargestPoolSize()); + } + + /** + * getPoolSize increases, but doesn't overestimate, when threads + * become active + */ + public void testGetPoolSize() throws InterruptedException { + final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + assertEquals(0, p.getPoolSize()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1, p.getPoolSize()); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getPoolSize()); + } + } + + /** + * getTaskCount increases, but doesn't overestimate, when tasks + * submitted + */ + public void testGetTaskCount() throws InterruptedException { + final int TASKS = 3; + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertEquals(0, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + for (int i = 0; i < TASKS; i++) { + assertEquals(1 + i, p.getTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1 + TASKS, p.getTaskCount()); + await(done); + }}); + } + assertEquals(1 + TASKS, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + } + assertEquals(1 + TASKS, p.getTaskCount()); + assertEquals(1 + TASKS, p.getCompletedTaskCount()); + } + + /** + * getThreadFactory returns factory in constructor if not set + */ + public void testGetThreadFactory() throws InterruptedException { + final ThreadFactory threadFactory = new SimpleThreadFactory(); + final ScheduledThreadPoolExecutor p = + new ScheduledThreadPoolExecutor(1, threadFactory); + try (PoolCleaner cleaner = cleaner(p)) { + assertSame(threadFactory, p.getThreadFactory()); + } + } + + /** + * setThreadFactory sets the thread factory returned by getThreadFactory + */ + public void testSetThreadFactory() throws InterruptedException { + ThreadFactory threadFactory = new SimpleThreadFactory(); + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + p.setThreadFactory(threadFactory); + assertSame(threadFactory, p.getThreadFactory()); + } + } + + /** + * setThreadFactory(null) throws NPE + */ + public void testSetThreadFactoryNull() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setThreadFactory(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * isShutdown is false before shutdown, true after + */ + public void testIsShutdown() { + + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try { + assertFalse(p.isShutdown()); + } + finally { + try { p.shutdown(); } catch (SecurityException ok) { return; } + } + assertTrue(p.isShutdown()); + } + + /** + * isTerminated is false before termination, true after + */ + public void testIsTerminated() throws InterruptedException { + final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + assertFalse(p.isTerminated()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(p.isTerminated()); + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertFalse(p.isTerminating()); + done.countDown(); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + } + } + + /** + * isTerminating is not true when running or when terminated + */ + public void testIsTerminating() throws InterruptedException { + final ThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + try (PoolCleaner cleaner = cleaner(p)) { + assertFalse(p.isTerminating()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(p.isTerminating()); + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertFalse(p.isTerminating()); + done.countDown(); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertFalse(p.isTerminating()); + } + } + + /** + * getQueue returns the work queue, which contains queued tasks + */ + public void testGetQueue() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + ScheduledFuture[] tasks = new ScheduledFuture[5]; + for (int i = 0; i < tasks.length; i++) { + Runnable r = new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}; + tasks[i] = p.schedule(r, 1, MILLISECONDS); + } + await(threadStarted); + BlockingQueue q = p.getQueue(); + assertTrue(q.contains(tasks[tasks.length - 1])); + assertFalse(q.contains(tasks[0])); + } + } + + /** + * remove(task) removes queued task, and fails to remove active task + */ + public void testRemove() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p, done)) { + ScheduledFuture[] tasks = new ScheduledFuture[5]; + final CountDownLatch threadStarted = new CountDownLatch(1); + for (int i = 0; i < tasks.length; i++) { + Runnable r = new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}; + tasks[i] = p.schedule(r, 1, MILLISECONDS); + } + await(threadStarted); + BlockingQueue q = p.getQueue(); + assertFalse(p.remove((Runnable)tasks[0])); + assertTrue(q.contains((Runnable)tasks[4])); + assertTrue(q.contains((Runnable)tasks[3])); + assertTrue(p.remove((Runnable)tasks[4])); + assertFalse(p.remove((Runnable)tasks[4])); + assertFalse(q.contains((Runnable)tasks[4])); + assertTrue(q.contains((Runnable)tasks[3])); + assertTrue(p.remove((Runnable)tasks[3])); + assertFalse(q.contains((Runnable)tasks[3])); + } + } + + /** + * purge eventually removes cancelled tasks from the queue + */ + public void testPurge() throws InterruptedException { + final ScheduledFuture[] tasks = new ScheduledFuture[5]; + final Runnable releaser = new Runnable() { public void run() { + for (ScheduledFuture task : tasks) + if (task != null) task.cancel(true); }}; + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p, releaser)) { + for (int i = 0; i < tasks.length; i++) + tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(), + LONG_DELAY_MS, MILLISECONDS); + int max = tasks.length; + if (tasks[4].cancel(true)) --max; + if (tasks[3].cancel(true)) --max; + // There must eventually be an interference-free point at + // which purge will not fail. (At worst, when queue is empty.) + long startTime = System.nanoTime(); + do { + p.purge(); + long count = p.getTaskCount(); + if (count == max) + return; + } while (millisElapsedSince(startTime) < LONG_DELAY_MS); + fail("Purge failed to remove cancelled tasks"); + } + } + + /** + * shutdownNow returns a list containing tasks that were not run, + * and those tasks are drained from the queue + */ + public void testShutdownNow() throws InterruptedException { + final int poolSize = 2; + final int count = 5; + final AtomicInteger ran = new AtomicInteger(0); + final ScheduledThreadPoolExecutor p = + new ScheduledThreadPoolExecutor(poolSize); + final CountDownLatch threadsStarted = new CountDownLatch(poolSize); + Runnable waiter = new CheckedRunnable() { public void realRun() { + threadsStarted.countDown(); + try { + MILLISECONDS.sleep(2 * LONG_DELAY_MS); + } catch (InterruptedException success) {} + ran.getAndIncrement(); + }}; + for (int i = 0; i < count; i++) + p.execute(waiter); + await(threadsStarted); + assertEquals(poolSize, p.getActiveCount()); + assertEquals(0, p.getCompletedTaskCount()); + final List queuedTasks; + try { + queuedTasks = p.shutdownNow(); + } catch (SecurityException ok) { + return; // Allowed in case test doesn't have privs + } + assertTrue(p.isShutdown()); + assertTrue(p.getQueue().isEmpty()); + assertEquals(count - poolSize, queuedTasks.size()); + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertEquals(poolSize, ran.get()); + assertEquals(poolSize, p.getCompletedTaskCount()); + } + + /** + * shutdownNow returns a list containing tasks that were not run, + * and those tasks are drained from the queue + */ + public void testShutdownNow_delayedTasks() throws InterruptedException { + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + List tasks = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + Runnable r = new NoOpRunnable(); + tasks.add(p.schedule(r, 9, SECONDS)); + tasks.add(p.scheduleAtFixedRate(r, 9, 9, SECONDS)); + tasks.add(p.scheduleWithFixedDelay(r, 9, 9, SECONDS)); + } + if (testImplementationDetails) + assertEquals(new HashSet(tasks), new HashSet(p.getQueue())); + final List queuedTasks; + try { + queuedTasks = p.shutdownNow(); + } catch (SecurityException ok) { + return; // Allowed in case test doesn't have privs + } + assertTrue(p.isShutdown()); + assertTrue(p.getQueue().isEmpty()); + if (testImplementationDetails) + assertEquals(new HashSet(tasks), new HashSet(queuedTasks)); + assertEquals(tasks.size(), queuedTasks.size()); + for (ScheduledFuture task : tasks) { + assertFalse(task.isDone()); + assertFalse(task.isCancelled()); + } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + } + + /** + * By default, periodic tasks are cancelled at shutdown. + * By default, delayed tasks keep running after shutdown. + * Check that changing the default values work: + * - setExecuteExistingDelayedTasksAfterShutdownPolicy + * - setContinueExistingPeriodicTasksAfterShutdownPolicy + */ + public void testShutdown_cancellation() throws Exception { + Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE }; + for (Boolean policy : allBooleans) + { + final int poolSize = 2; + final ScheduledThreadPoolExecutor p + = new ScheduledThreadPoolExecutor(poolSize); + final boolean effectiveDelayedPolicy = (policy != Boolean.FALSE); + final boolean effectivePeriodicPolicy = (policy == Boolean.TRUE); + final boolean effectiveRemovePolicy = (policy == Boolean.TRUE); + if (policy != null) { + p.setExecuteExistingDelayedTasksAfterShutdownPolicy(policy); + p.setContinueExistingPeriodicTasksAfterShutdownPolicy(policy); + p.setRemoveOnCancelPolicy(policy); + } + assertEquals(effectiveDelayedPolicy, + p.getExecuteExistingDelayedTasksAfterShutdownPolicy()); + assertEquals(effectivePeriodicPolicy, + p.getContinueExistingPeriodicTasksAfterShutdownPolicy()); + assertEquals(effectiveRemovePolicy, + p.getRemoveOnCancelPolicy()); + // Strategy: Wedge the pool with poolSize "blocker" threads + final AtomicInteger ran = new AtomicInteger(0); + final CountDownLatch poolBlocked = new CountDownLatch(poolSize); + final CountDownLatch unblock = new CountDownLatch(1); + final CountDownLatch periodicLatch1 = new CountDownLatch(2); + final CountDownLatch periodicLatch2 = new CountDownLatch(2); + Runnable task = new CheckedRunnable() { public void realRun() + throws InterruptedException { + poolBlocked.countDown(); + assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS)); + ran.getAndIncrement(); + }}; + List> blockers = new ArrayList<>(); + List> periodics = new ArrayList<>(); + List> delayeds = new ArrayList<>(); + for (int i = 0; i < poolSize; i++) + blockers.add(p.submit(task)); + assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS)); + + periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1), + 1, 1, MILLISECONDS)); + periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2), + 1, 1, MILLISECONDS)); + delayeds.add(p.schedule(task, 1, MILLISECONDS)); + + assertTrue(p.getQueue().containsAll(periodics)); + assertTrue(p.getQueue().containsAll(delayeds)); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.isShutdown()); + assertFalse(p.isTerminated()); + for (Future periodic : periodics) { + assertTrue(effectivePeriodicPolicy ^ periodic.isCancelled()); + assertTrue(effectivePeriodicPolicy ^ periodic.isDone()); + } + for (Future delayed : delayeds) { + assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled()); + assertTrue(effectiveDelayedPolicy ^ delayed.isDone()); + } + if (testImplementationDetails) { + assertEquals(effectivePeriodicPolicy, + p.getQueue().containsAll(periodics)); + assertEquals(effectiveDelayedPolicy, + p.getQueue().containsAll(delayeds)); + } + // Release all pool threads + unblock.countDown(); + + for (Future delayed : delayeds) { + if (effectiveDelayedPolicy) { + assertNull(delayed.get()); + } + } + if (effectivePeriodicPolicy) { + assertTrue(periodicLatch1.await(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(periodicLatch2.await(LONG_DELAY_MS, MILLISECONDS)); + for (Future periodic : periodics) { + assertTrue(periodic.cancel(false)); + assertTrue(periodic.isCancelled()); + assertTrue(periodic.isDone()); + } + } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertEquals(2 + (effectiveDelayedPolicy ? 1 : 0), ran.get()); + }} + + /** + * completed submit of callable returns result + */ + public void testSubmitCallable() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new StringTask()); + String result = future.get(); + assertSame(TEST_STRING, result); + } + } + + /** + * completed submit of runnable returns successfully + */ + public void testSubmitRunnable() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable()); + future.get(); + assertTrue(future.isDone()); + } + } + + /** + * completed submit of (runnable, result) returns result + */ + public void testSubmitRunnable2() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable(), TEST_STRING); + String result = future.get(); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAny(null) throws NPE + */ + public void testInvokeAny1() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAny(empty collection) throws IAE + */ + public void testInvokeAny2() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * invokeAny(c) throws NPE if c has null elements + */ + public void testInvokeAny3() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * invokeAny(c) throws ExecutionException if no task completes + */ + public void testInvokeAny4() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAny(c) returns result of some task + */ + public void testInvokeAny5() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAll(null) throws NPE + */ + public void testInvokeAll1() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAll(empty collection) returns empty collection + */ + public void testInvokeAll2() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>()); + assertTrue(r.isEmpty()); + } + } + + /** + * invokeAll(c) throws NPE if c has null elements + */ + public void testInvokeAll3() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of invokeAll(c) throws exception on failed task + */ + public void testInvokeAll4() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = e.invokeAll(l); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAll(c) returns results of all completed tasks + */ + public void testInvokeAll5() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = e.invokeAll(l); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAny(null) throws NPE + */ + public void testTimedInvokeAny1() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(,,null) throws NPE + */ + public void testTimedInvokeAnyNullTimeUnit() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(empty collection) throws IAE + */ + public void testTimedInvokeAny2() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>(), MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * timed invokeAny(c) throws NPE if c has null elements + */ + public void testTimedInvokeAny3() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * timed invokeAny(c) throws ExecutionException if no task completes + */ + public void testTimedInvokeAny4() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAny(c) returns result of some task + */ + public void testTimedInvokeAny5() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + assertSame(TEST_STRING, result); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAll(null) throws NPE + */ + public void testTimedInvokeAll1() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(,,null) throws NPE + */ + public void testTimedInvokeAllNullTimeUnit() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(empty collection) returns empty collection + */ + public void testTimedInvokeAll2() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>(), + MEDIUM_DELAY_MS, MILLISECONDS); + assertTrue(r.isEmpty()); + } + } + + /** + * timed invokeAll(c) throws NPE if c has null elements + */ + public void testTimedInvokeAll3() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of element of invokeAll(c) throws exception on failed task + */ + public void testTimedInvokeAll4() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = + e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * timed invokeAll(c) returns results of all completed tasks + */ + public void testTimedInvokeAll5() throws Exception { + final ExecutorService e = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = + e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAll(c) cancels tasks not completed by timeout + */ + public void testTimedInvokeAll6() throws Exception { + for (long timeout = timeoutMillis();;) { + final CountDownLatch done = new CountDownLatch(1); + final Callable waiter = new CheckedCallable() { + public String realCall() { + try { done.await(LONG_DELAY_MS, MILLISECONDS); } + catch (InterruptedException ok) {} + return "1"; }}; + final ExecutorService p = new ScheduledThreadPoolExecutor(2); + try (PoolCleaner cleaner = cleaner(p, done)) { + List> tasks = new ArrayList<>(); + tasks.add(new StringTask("0")); + tasks.add(waiter); + tasks.add(new StringTask("2")); + long startTime = System.nanoTime(); + List> futures = + p.invokeAll(tasks, timeout, MILLISECONDS); + assertEquals(tasks.size(), futures.size()); + assertTrue(millisElapsedSince(startTime) >= timeout); + for (Future future : futures) + assertTrue(future.isDone()); + assertTrue(futures.get(1).isCancelled()); + try { + assertEquals("0", futures.get(0).get()); + assertEquals("2", futures.get(2).get()); + break; + } catch (CancellationException retryWithLongerTimeout) { + timeout *= 2; + if (timeout >= LONG_DELAY_MS / 2) + fail("expected exactly one task to be cancelled"); + } + } + } + } + + /** + * A fixed delay task with overflowing period should not prevent a + * one-shot task from executing. + * https://bugs.openjdk.java.net/browse/JDK-8051859 + */ + public void testScheduleWithFixedDelay_overflow() throws Exception { + final CountDownLatch delayedDone = new CountDownLatch(1); + final CountDownLatch immediateDone = new CountDownLatch(1); + final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); + try (PoolCleaner cleaner = cleaner(p)) { + final Runnable immediate = new Runnable() { public void run() { + immediateDone.countDown(); + }}; + final Runnable delayed = new Runnable() { public void run() { + delayedDone.countDown(); + p.submit(immediate); + }}; + p.scheduleWithFixedDelay(delayed, 0L, Long.MAX_VALUE, SECONDS); + await(delayedDone); + await(immediateDone); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/SemaphoreTest.java b/jdk/test/java/util/concurrent/tck/SemaphoreTest.java new file mode 100644 index 00000000000..0e85d7c73fc --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/SemaphoreTest.java @@ -0,0 +1,669 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.Collection; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Semaphore; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +public class SemaphoreTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(SemaphoreTest.class); + } + + /** + * Subclass to expose protected methods + */ + static class PublicSemaphore extends Semaphore { + PublicSemaphore(int permits) { super(permits); } + PublicSemaphore(int permits, boolean fair) { super(permits, fair); } + public Collection getQueuedThreads() { + return super.getQueuedThreads(); + } + public boolean hasQueuedThread(Thread t) { + return super.getQueuedThreads().contains(t); + } + public void reducePermits(int reduction) { + super.reducePermits(reduction); + } + } + + /** + * A runnable calling acquire + */ + class InterruptibleLockRunnable extends CheckedRunnable { + final Semaphore lock; + InterruptibleLockRunnable(Semaphore s) { lock = s; } + public void realRun() { + try { + lock.acquire(); + } + catch (InterruptedException ignored) {} + } + } + + /** + * A runnable calling acquire that expects to be interrupted + */ + class InterruptedLockRunnable extends CheckedInterruptedRunnable { + final Semaphore lock; + InterruptedLockRunnable(Semaphore s) { lock = s; } + public void realRun() throws InterruptedException { + lock.acquire(); + } + } + + /** + * Spin-waits until s.hasQueuedThread(t) becomes true. + */ + void waitForQueuedThread(PublicSemaphore s, Thread t) { + long startTime = System.nanoTime(); + while (!s.hasQueuedThread(t)) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + throw new AssertionFailedError("timed out"); + Thread.yield(); + } + assertTrue(s.hasQueuedThreads()); + assertTrue(t.isAlive()); + } + + /** + * Spin-waits until s.hasQueuedThreads() becomes true. + */ + void waitForQueuedThreads(Semaphore s) { + long startTime = System.nanoTime(); + while (!s.hasQueuedThreads()) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + throw new AssertionFailedError("timed out"); + Thread.yield(); + } + } + + enum AcquireMethod { + acquire() { + void acquire(Semaphore s) throws InterruptedException { + s.acquire(); + } + }, + acquireN() { + void acquire(Semaphore s, int permits) throws InterruptedException { + s.acquire(permits); + } + }, + acquireUninterruptibly() { + void acquire(Semaphore s) { + s.acquireUninterruptibly(); + } + }, + acquireUninterruptiblyN() { + void acquire(Semaphore s, int permits) { + s.acquireUninterruptibly(permits); + } + }, + tryAcquire() { + void acquire(Semaphore s) { + assertTrue(s.tryAcquire()); + } + }, + tryAcquireN() { + void acquire(Semaphore s, int permits) { + assertTrue(s.tryAcquire(permits)); + } + }, + tryAcquireTimed() { + void acquire(Semaphore s) throws InterruptedException { + assertTrue(s.tryAcquire(2 * LONG_DELAY_MS, MILLISECONDS)); + } + }, + tryAcquireTimedN { + void acquire(Semaphore s, int permits) throws InterruptedException { + assertTrue(s.tryAcquire(permits, 2 * LONG_DELAY_MS, MILLISECONDS)); + } + }; + + // Intentionally meta-circular + + /** Acquires 1 permit. */ + void acquire(Semaphore s) throws InterruptedException { + acquire(s, 1); + } + /** Acquires the given number of permits. */ + void acquire(Semaphore s, int permits) throws InterruptedException { + for (int i = 0; i < permits; i++) + acquire(s); + } + } + + /** + * Zero, negative, and positive initial values are allowed in constructor + */ + public void testConstructor() { testConstructor(false); } + public void testConstructor_fair() { testConstructor(true); } + public void testConstructor(boolean fair) { + for (int permits : new int[] { -42, -1, 0, 1, 42 }) { + Semaphore s = new Semaphore(permits, fair); + assertEquals(permits, s.availablePermits()); + assertEquals(fair, s.isFair()); + } + } + + /** + * Constructor without fairness argument behaves as nonfair + */ + public void testConstructorDefaultsToNonFair() { + for (int permits : new int[] { -42, -1, 0, 1, 42 }) { + Semaphore s = new Semaphore(permits); + assertEquals(permits, s.availablePermits()); + assertFalse(s.isFair()); + } + } + + /** + * tryAcquire succeeds when sufficient permits, else fails + */ + public void testTryAcquireInSameThread() { testTryAcquireInSameThread(false); } + public void testTryAcquireInSameThread_fair() { testTryAcquireInSameThread(true); } + public void testTryAcquireInSameThread(boolean fair) { + Semaphore s = new Semaphore(2, fair); + assertEquals(2, s.availablePermits()); + assertTrue(s.tryAcquire()); + assertTrue(s.tryAcquire()); + assertEquals(0, s.availablePermits()); + assertFalse(s.tryAcquire()); + assertFalse(s.tryAcquire()); + assertEquals(0, s.availablePermits()); + } + + /** + * timed tryAcquire times out + */ + public void testTryAcquire_timeout() { testTryAcquire_timeout(false); } + public void testTryAcquire_timeout_fair() { testTryAcquire_timeout(true); } + public void testTryAcquire_timeout(boolean fair) { + Semaphore s = new Semaphore(0, fair); + long startTime = System.nanoTime(); + try { assertFalse(s.tryAcquire(timeoutMillis(), MILLISECONDS)); } + catch (InterruptedException e) { threadUnexpectedException(e); } + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + + /** + * timed tryAcquire(N) times out + */ + public void testTryAcquireN_timeout() { testTryAcquireN_timeout(false); } + public void testTryAcquireN_timeout_fair() { testTryAcquireN_timeout(true); } + public void testTryAcquireN_timeout(boolean fair) { + Semaphore s = new Semaphore(2, fair); + long startTime = System.nanoTime(); + try { assertFalse(s.tryAcquire(3, timeoutMillis(), MILLISECONDS)); } + catch (InterruptedException e) { threadUnexpectedException(e); } + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + + /** + * acquire(), acquire(N), timed tryAcquired, timed tryAcquire(N) + * are interruptible + */ + public void testInterruptible_acquire() { testInterruptible(false, AcquireMethod.acquire); } + public void testInterruptible_acquire_fair() { testInterruptible(true, AcquireMethod.acquire); } + public void testInterruptible_acquireN() { testInterruptible(false, AcquireMethod.acquireN); } + public void testInterruptible_acquireN_fair() { testInterruptible(true, AcquireMethod.acquireN); } + public void testInterruptible_tryAcquireTimed() { testInterruptible(false, AcquireMethod.tryAcquireTimed); } + public void testInterruptible_tryAcquireTimed_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimed); } + public void testInterruptible_tryAcquireTimedN() { testInterruptible(false, AcquireMethod.tryAcquireTimedN); } + public void testInterruptible_tryAcquireTimedN_fair() { testInterruptible(true, AcquireMethod.tryAcquireTimedN); } + public void testInterruptible(boolean fair, final AcquireMethod acquirer) { + final PublicSemaphore s = new PublicSemaphore(0, fair); + final Semaphore pleaseInterrupt = new Semaphore(0, fair); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + // Interrupt before acquire + Thread.currentThread().interrupt(); + try { + acquirer.acquire(s); + shouldThrow(); + } catch (InterruptedException success) {} + + // Interrupt during acquire + try { + acquirer.acquire(s); + shouldThrow(); + } catch (InterruptedException success) {} + + // Interrupt before acquire(N) + Thread.currentThread().interrupt(); + try { + acquirer.acquire(s, 3); + shouldThrow(); + } catch (InterruptedException success) {} + + pleaseInterrupt.release(); + + // Interrupt during acquire(N) + try { + acquirer.acquire(s, 3); + shouldThrow(); + } catch (InterruptedException success) {} + }}); + + waitForQueuedThread(s, t); + t.interrupt(); + await(pleaseInterrupt); + waitForQueuedThread(s, t); + t.interrupt(); + awaitTermination(t); + } + + /** + * acquireUninterruptibly(), acquireUninterruptibly(N) are + * uninterruptible + */ + public void testUninterruptible_acquireUninterruptibly() { testUninterruptible(false, AcquireMethod.acquireUninterruptibly); } + public void testUninterruptible_acquireUninterruptibly_fair() { testUninterruptible(true, AcquireMethod.acquireUninterruptibly); } + public void testUninterruptible_acquireUninterruptiblyN() { testUninterruptible(false, AcquireMethod.acquireUninterruptiblyN); } + public void testUninterruptible_acquireUninterruptiblyN_fair() { testUninterruptible(true, AcquireMethod.acquireUninterruptiblyN); } + public void testUninterruptible(boolean fair, final AcquireMethod acquirer) { + final PublicSemaphore s = new PublicSemaphore(0, fair); + final Semaphore pleaseInterrupt = new Semaphore(-1, fair); + + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + // Interrupt before acquire + pleaseInterrupt.release(); + Thread.currentThread().interrupt(); + acquirer.acquire(s); + assertTrue(Thread.interrupted()); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + // Interrupt during acquire + pleaseInterrupt.release(); + acquirer.acquire(s); + assertTrue(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + waitForQueuedThread(s, t1); + waitForQueuedThread(s, t2); + t2.interrupt(); + + assertThreadStaysAlive(t1); + assertTrue(t2.isAlive()); + + s.release(2); + + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * hasQueuedThreads reports whether there are waiting threads + */ + public void testHasQueuedThreads() { testHasQueuedThreads(false); } + public void testHasQueuedThreads_fair() { testHasQueuedThreads(true); } + public void testHasQueuedThreads(boolean fair) { + final PublicSemaphore lock = new PublicSemaphore(1, fair); + assertFalse(lock.hasQueuedThreads()); + lock.acquireUninterruptibly(); + Thread t1 = newStartedThread(new InterruptedLockRunnable(lock)); + waitForQueuedThread(lock, t1); + assertTrue(lock.hasQueuedThreads()); + Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock)); + waitForQueuedThread(lock, t2); + assertTrue(lock.hasQueuedThreads()); + t1.interrupt(); + awaitTermination(t1); + assertTrue(lock.hasQueuedThreads()); + lock.release(); + awaitTermination(t2); + assertFalse(lock.hasQueuedThreads()); + } + + /** + * getQueueLength reports number of waiting threads + */ + public void testGetQueueLength() { testGetQueueLength(false); } + public void testGetQueueLength_fair() { testGetQueueLength(true); } + public void testGetQueueLength(boolean fair) { + final PublicSemaphore lock = new PublicSemaphore(1, fair); + assertEquals(0, lock.getQueueLength()); + lock.acquireUninterruptibly(); + Thread t1 = newStartedThread(new InterruptedLockRunnable(lock)); + waitForQueuedThread(lock, t1); + assertEquals(1, lock.getQueueLength()); + Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock)); + waitForQueuedThread(lock, t2); + assertEquals(2, lock.getQueueLength()); + t1.interrupt(); + awaitTermination(t1); + assertEquals(1, lock.getQueueLength()); + lock.release(); + awaitTermination(t2); + assertEquals(0, lock.getQueueLength()); + } + + /** + * getQueuedThreads includes waiting threads + */ + public void testGetQueuedThreads() { testGetQueuedThreads(false); } + public void testGetQueuedThreads_fair() { testGetQueuedThreads(true); } + public void testGetQueuedThreads(boolean fair) { + final PublicSemaphore lock = new PublicSemaphore(1, fair); + assertTrue(lock.getQueuedThreads().isEmpty()); + lock.acquireUninterruptibly(); + assertTrue(lock.getQueuedThreads().isEmpty()); + Thread t1 = newStartedThread(new InterruptedLockRunnable(lock)); + waitForQueuedThread(lock, t1); + assertTrue(lock.getQueuedThreads().contains(t1)); + Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock)); + waitForQueuedThread(lock, t2); + assertTrue(lock.getQueuedThreads().contains(t1)); + assertTrue(lock.getQueuedThreads().contains(t2)); + t1.interrupt(); + awaitTermination(t1); + assertFalse(lock.getQueuedThreads().contains(t1)); + assertTrue(lock.getQueuedThreads().contains(t2)); + lock.release(); + awaitTermination(t2); + assertTrue(lock.getQueuedThreads().isEmpty()); + } + + /** + * drainPermits reports and removes given number of permits + */ + public void testDrainPermits() { testDrainPermits(false); } + public void testDrainPermits_fair() { testDrainPermits(true); } + public void testDrainPermits(boolean fair) { + Semaphore s = new Semaphore(0, fair); + assertEquals(0, s.availablePermits()); + assertEquals(0, s.drainPermits()); + s.release(10); + assertEquals(10, s.availablePermits()); + assertEquals(10, s.drainPermits()); + assertEquals(0, s.availablePermits()); + assertEquals(0, s.drainPermits()); + } + + /** + * release(-N) throws IllegalArgumentException + */ + public void testReleaseIAE() { testReleaseIAE(false); } + public void testReleaseIAE_fair() { testReleaseIAE(true); } + public void testReleaseIAE(boolean fair) { + Semaphore s = new Semaphore(10, fair); + try { + s.release(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * reducePermits(-N) throws IllegalArgumentException + */ + public void testReducePermitsIAE() { testReducePermitsIAE(false); } + public void testReducePermitsIAE_fair() { testReducePermitsIAE(true); } + public void testReducePermitsIAE(boolean fair) { + PublicSemaphore s = new PublicSemaphore(10, fair); + try { + s.reducePermits(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * reducePermits reduces number of permits + */ + public void testReducePermits() { testReducePermits(false); } + public void testReducePermits_fair() { testReducePermits(true); } + public void testReducePermits(boolean fair) { + PublicSemaphore s = new PublicSemaphore(10, fair); + assertEquals(10, s.availablePermits()); + s.reducePermits(0); + assertEquals(10, s.availablePermits()); + s.reducePermits(1); + assertEquals(9, s.availablePermits()); + s.reducePermits(10); + assertEquals(-1, s.availablePermits()); + s.reducePermits(10); + assertEquals(-11, s.availablePermits()); + s.reducePermits(0); + assertEquals(-11, s.availablePermits()); + } + + /** + * a reserialized semaphore has same number of permits and + * fairness, but no queued threads + */ + public void testSerialization() { testSerialization(false); } + public void testSerialization_fair() { testSerialization(true); } + public void testSerialization(boolean fair) { + try { + Semaphore s = new Semaphore(3, fair); + s.acquire(); + s.acquire(); + s.release(); + + Semaphore clone = serialClone(s); + assertEquals(fair, s.isFair()); + assertEquals(fair, clone.isFair()); + assertEquals(2, s.availablePermits()); + assertEquals(2, clone.availablePermits()); + clone.acquire(); + clone.acquire(); + clone.release(); + assertEquals(2, s.availablePermits()); + assertEquals(1, clone.availablePermits()); + assertFalse(s.hasQueuedThreads()); + assertFalse(clone.hasQueuedThreads()); + } catch (InterruptedException e) { threadUnexpectedException(e); } + + { + PublicSemaphore s = new PublicSemaphore(0, fair); + Thread t = newStartedThread(new InterruptibleLockRunnable(s)); + // waitForQueuedThreads(s); // suffers from "flicker", so ... + waitForQueuedThread(s, t); // ... we use this instead + PublicSemaphore clone = serialClone(s); + assertEquals(fair, s.isFair()); + assertEquals(fair, clone.isFair()); + assertEquals(0, s.availablePermits()); + assertEquals(0, clone.availablePermits()); + assertTrue(s.hasQueuedThreads()); + assertFalse(clone.hasQueuedThreads()); + s.release(); + awaitTermination(t); + assertFalse(s.hasQueuedThreads()); + assertFalse(clone.hasQueuedThreads()); + } + } + + /** + * tryAcquire(n) succeeds when sufficient permits, else fails + */ + public void testTryAcquireNInSameThread() { testTryAcquireNInSameThread(false); } + public void testTryAcquireNInSameThread_fair() { testTryAcquireNInSameThread(true); } + public void testTryAcquireNInSameThread(boolean fair) { + Semaphore s = new Semaphore(2, fair); + assertEquals(2, s.availablePermits()); + assertFalse(s.tryAcquire(3)); + assertEquals(2, s.availablePermits()); + assertTrue(s.tryAcquire(2)); + assertEquals(0, s.availablePermits()); + assertFalse(s.tryAcquire(1)); + assertFalse(s.tryAcquire(2)); + assertEquals(0, s.availablePermits()); + } + + /** + * acquire succeeds if permits available + */ + public void testReleaseAcquireSameThread_acquire() { testReleaseAcquireSameThread(false, AcquireMethod.acquire); } + public void testReleaseAcquireSameThread_acquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquire); } + public void testReleaseAcquireSameThread_acquireN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireN); } + public void testReleaseAcquireSameThread_acquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireN); } + public void testReleaseAcquireSameThread_acquireUninterruptibly() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); } + public void testReleaseAcquireSameThread_acquireUninterruptibly_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); } + public void testReleaseAcquireSameThread_acquireUninterruptiblyN() { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); } + public void testReleaseAcquireSameThread_acquireUninterruptiblyN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); } + public void testReleaseAcquireSameThread_tryAcquire() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquire); } + public void testReleaseAcquireSameThread_tryAcquire_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquire); } + public void testReleaseAcquireSameThread_tryAcquireN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireN); } + public void testReleaseAcquireSameThread_tryAcquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireN); } + public void testReleaseAcquireSameThread_tryAcquireTimed() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimed); } + public void testReleaseAcquireSameThread_tryAcquireTimed_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimed); } + public void testReleaseAcquireSameThread_tryAcquireTimedN() { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimedN); } + public void testReleaseAcquireSameThread_tryAcquireTimedN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimedN); } + public void testReleaseAcquireSameThread(boolean fair, + final AcquireMethod acquirer) { + Semaphore s = new Semaphore(1, fair); + for (int i = 1; i < 6; i++) { + s.release(i); + assertEquals(1 + i, s.availablePermits()); + try { + acquirer.acquire(s, i); + } catch (InterruptedException e) { threadUnexpectedException(e); } + assertEquals(1, s.availablePermits()); + } + } + + /** + * release in one thread enables acquire in another thread + */ + public void testReleaseAcquireDifferentThreads_acquire() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquire); } + public void testReleaseAcquireDifferentThreads_acquire_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquire); } + public void testReleaseAcquireDifferentThreads_acquireN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireN); } + public void testReleaseAcquireDifferentThreads_acquireN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireN); } + public void testReleaseAcquireDifferentThreads_acquireUninterruptibly() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); } + public void testReleaseAcquireDifferentThreads_acquireUninterruptibly_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); } + public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); } + public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); } + public void testReleaseAcquireDifferentThreads_tryAcquireTimed() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimed); } + public void testReleaseAcquireDifferentThreads_tryAcquireTimed_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimed); } + public void testReleaseAcquireDifferentThreads_tryAcquireTimedN() { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimedN); } + public void testReleaseAcquireDifferentThreads_tryAcquireTimedN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimedN); } + public void testReleaseAcquireDifferentThreads(boolean fair, + final AcquireMethod acquirer) { + final Semaphore s = new Semaphore(0, fair); + final int rounds = 4; + long startTime = System.nanoTime(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + for (int i = 0; i < rounds; i++) { + assertFalse(s.hasQueuedThreads()); + if (i % 2 == 0) + acquirer.acquire(s); + else + acquirer.acquire(s, 3); + }}}); + + for (int i = 0; i < rounds; i++) { + while (! (s.availablePermits() == 0 && s.hasQueuedThreads())) + Thread.yield(); + assertTrue(t.isAlive()); + if (i % 2 == 0) + s.release(); + else + s.release(3); + } + awaitTermination(t); + assertEquals(0, s.availablePermits()); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + + /** + * fair locks are strictly FIFO + */ + public void testFairLocksFifo() { + final PublicSemaphore s = new PublicSemaphore(1, true); + final CountDownLatch pleaseRelease = new CountDownLatch(1); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + // Will block; permits are available, but not three + s.acquire(3); + }}); + + waitForQueuedThread(s, t1); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + // Will fail, even though 1 permit is available + assertFalse(s.tryAcquire(0L, MILLISECONDS)); + assertFalse(s.tryAcquire(1, 0L, MILLISECONDS)); + + // untimed tryAcquire will barge and succeed + assertTrue(s.tryAcquire()); + s.release(2); + assertTrue(s.tryAcquire(2)); + s.release(); + + pleaseRelease.countDown(); + // Will queue up behind t1, even though 1 permit is available + s.acquire(); + }}); + + await(pleaseRelease); + waitForQueuedThread(s, t2); + s.release(2); + awaitTermination(t1); + assertTrue(t2.isAlive()); + s.release(); + awaitTermination(t2); + } + + /** + * toString indicates current number of permits + */ + public void testToString() { testToString(false); } + public void testToString_fair() { testToString(true); } + public void testToString(boolean fair) { + PublicSemaphore s = new PublicSemaphore(0, fair); + assertTrue(s.toString().contains("Permits = 0")); + s.release(); + assertTrue(s.toString().contains("Permits = 1")); + s.release(2); + assertTrue(s.toString().contains("Permits = 3")); + s.reducePermits(5); + assertTrue(s.toString().contains("Permits = -2")); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/SplittableRandomTest.java b/jdk/test/java/util/concurrent/tck/SplittableRandomTest.java new file mode 100644 index 00000000000..74baf387653 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/SplittableRandomTest.java @@ -0,0 +1,555 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.SplittableRandom; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.LongAdder; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class SplittableRandomTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(SplittableRandomTest.class); + } + + /* + * Testing coverage notes: + * + * 1. Many of the test methods are adapted from ThreadLocalRandomTest. + * + * 2. These tests do not check for random number generator quality. + * But we check for minimal API compliance by requiring that + * repeated calls to nextX methods, up to NCALLS tries, produce at + * least two distinct results. (In some possible universe, a + * "correct" implementation might fail, but the odds are vastly + * less than that of encountering a hardware failure while running + * the test.) For bounded nextX methods, we sample various + * intervals across multiples of primes. In other tests, we repeat + * under REPS different values. + */ + + // max numbers of calls to detect getting stuck on one value + static final int NCALLS = 10000; + + // max sampled int bound + static final int MAX_INT_BOUND = (1 << 26); + + // max sampled long bound + static final long MAX_LONG_BOUND = (1L << 40); + + // Number of replications for other checks + static final int REPS = + Integer.getInteger("SplittableRandomTest.reps", 4); + + /** + * Repeated calls to nextInt produce at least two distinct results + */ + public void testNextInt() { + SplittableRandom sr = new SplittableRandom(); + int f = sr.nextInt(); + int i = 0; + while (i < NCALLS && sr.nextInt() == f) + ++i; + assertTrue(i < NCALLS); + } + + /** + * Repeated calls to nextLong produce at least two distinct results + */ + public void testNextLong() { + SplittableRandom sr = new SplittableRandom(); + long f = sr.nextLong(); + int i = 0; + while (i < NCALLS && sr.nextLong() == f) + ++i; + assertTrue(i < NCALLS); + } + + /** + * Repeated calls to nextDouble produce at least two distinct results + */ + public void testNextDouble() { + SplittableRandom sr = new SplittableRandom(); + double f = sr.nextDouble(); + int i = 0; + while (i < NCALLS && sr.nextDouble() == f) + ++i; + assertTrue(i < NCALLS); + } + + /** + * Two SplittableRandoms created with the same seed produce the + * same values for nextLong. + */ + public void testSeedConstructor() { + for (long seed = 2; seed < MAX_LONG_BOUND; seed += 15485863) { + SplittableRandom sr1 = new SplittableRandom(seed); + SplittableRandom sr2 = new SplittableRandom(seed); + for (int i = 0; i < REPS; ++i) + assertEquals(sr1.nextLong(), sr2.nextLong()); + } + } + + /** + * A SplittableRandom produced by split() of a default-constructed + * SplittableRandom generates a different sequence + */ + public void testSplit1() { + SplittableRandom sr = new SplittableRandom(); + for (int reps = 0; reps < REPS; ++reps) { + SplittableRandom sc = sr.split(); + int i = 0; + while (i < NCALLS && sr.nextLong() == sc.nextLong()) + ++i; + assertTrue(i < NCALLS); + } + } + + /** + * A SplittableRandom produced by split() of a seeded-constructed + * SplittableRandom generates a different sequence + */ + public void testSplit2() { + SplittableRandom sr = new SplittableRandom(12345); + for (int reps = 0; reps < REPS; ++reps) { + SplittableRandom sc = sr.split(); + int i = 0; + while (i < NCALLS && sr.nextLong() == sc.nextLong()) + ++i; + assertTrue(i < NCALLS); + } + } + + /** + * nextInt(non-positive) throws IllegalArgumentException + */ + public void testNextIntBoundNonPositive() { + SplittableRandom sr = new SplittableRandom(); + Runnable[] throwingActions = { + () -> sr.nextInt(-17), + () -> sr.nextInt(0), + () -> sr.nextInt(Integer.MIN_VALUE), + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + /** + * nextInt(least >= bound) throws IllegalArgumentException + */ + public void testNextIntBadBounds() { + SplittableRandom sr = new SplittableRandom(); + Runnable[] throwingActions = { + () -> sr.nextInt(17, 2), + () -> sr.nextInt(-42, -42), + () -> sr.nextInt(Integer.MAX_VALUE, Integer.MIN_VALUE), + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + /** + * nextInt(bound) returns 0 <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextIntBounded() { + SplittableRandom sr = new SplittableRandom(); + for (int i = 0; i < 2; i++) assertEquals(0, sr.nextInt(1)); + // sample bound space across prime number increments + for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) { + int f = sr.nextInt(bound); + assertTrue(0 <= f && f < bound); + int i = 0; + int j; + while (i < NCALLS && + (j = sr.nextInt(bound)) == f) { + assertTrue(0 <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + + /** + * nextInt(least, bound) returns least <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextIntBounded2() { + SplittableRandom sr = new SplittableRandom(); + for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) { + for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) { + int f = sr.nextInt(least, bound); + assertTrue(least <= f && f < bound); + int i = 0; + int j; + while (i < NCALLS && + (j = sr.nextInt(least, bound)) == f) { + assertTrue(least <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + } + + /** + * nextLong(non-positive) throws IllegalArgumentException + */ + public void testNextLongBoundNonPositive() { + SplittableRandom sr = new SplittableRandom(); + Runnable[] throwingActions = { + () -> sr.nextLong(-17L), + () -> sr.nextLong(0L), + () -> sr.nextLong(Long.MIN_VALUE), + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + /** + * nextLong(least >= bound) throws IllegalArgumentException + */ + public void testNextLongBadBounds() { + SplittableRandom sr = new SplittableRandom(); + Runnable[] throwingActions = { + () -> sr.nextLong(17L, 2L), + () -> sr.nextLong(-42L, -42L), + () -> sr.nextLong(Long.MAX_VALUE, Long.MIN_VALUE), + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + /** + * nextLong(bound) returns 0 <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextLongBounded() { + SplittableRandom sr = new SplittableRandom(); + for (int i = 0; i < 2; i++) assertEquals(0L, sr.nextLong(1L)); + for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) { + long f = sr.nextLong(bound); + assertTrue(0 <= f && f < bound); + int i = 0; + long j; + while (i < NCALLS && + (j = sr.nextLong(bound)) == f) { + assertTrue(0 <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + + /** + * nextLong(least, bound) returns least <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextLongBounded2() { + SplittableRandom sr = new SplittableRandom(); + for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) { + for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) { + long f = sr.nextLong(least, bound); + assertTrue(least <= f && f < bound); + int i = 0; + long j; + while (i < NCALLS && + (j = sr.nextLong(least, bound)) == f) { + assertTrue(least <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + } + + /** + * nextDouble(non-positive) throws IllegalArgumentException + */ + public void testNextDoubleBoundNonPositive() { + SplittableRandom sr = new SplittableRandom(); + Runnable[] throwingActions = { + () -> sr.nextDouble(-17.0d), + () -> sr.nextDouble(0.0d), + () -> sr.nextDouble(-Double.MIN_VALUE), + () -> sr.nextDouble(Double.NEGATIVE_INFINITY), + () -> sr.nextDouble(Double.NaN), + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + /** + * nextDouble(! (least < bound)) throws IllegalArgumentException + */ + public void testNextDoubleBadBounds() { + SplittableRandom sr = new SplittableRandom(); + Runnable[] throwingActions = { + () -> sr.nextDouble(17.0d, 2.0d), + () -> sr.nextDouble(-42.0d, -42.0d), + () -> sr.nextDouble(Double.MAX_VALUE, Double.MIN_VALUE), + () -> sr.nextDouble(Double.NaN, 0.0d), + () -> sr.nextDouble(0.0d, Double.NaN), + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + // TODO: Test infinite bounds! + //() -> sr.nextDouble(Double.NEGATIVE_INFINITY, 0.0d), + //() -> sr.nextDouble(0.0d, Double.POSITIVE_INFINITY), + + /** + * nextDouble(least, bound) returns least <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextDoubleBounded2() { + SplittableRandom sr = new SplittableRandom(); + for (double least = 0.0001; least < 1.0e20; least *= 8) { + for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) { + double f = sr.nextDouble(least, bound); + assertTrue(least <= f && f < bound); + int i = 0; + double j; + while (i < NCALLS && + (j = sr.nextDouble(least, bound)) == f) { + assertTrue(least <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + } + + /** + * Invoking sized ints, long, doubles, with negative sizes throws + * IllegalArgumentException + */ + public void testBadStreamSize() { + SplittableRandom r = new SplittableRandom(); + Runnable[] throwingActions = { + () -> { java.util.stream.IntStream x = r.ints(-1L); }, + () -> { java.util.stream.IntStream x = r.ints(-1L, 2, 3); }, + () -> { java.util.stream.LongStream x = r.longs(-1L); }, + () -> { java.util.stream.LongStream x = r.longs(-1L, -1L, 1L); }, + () -> { java.util.stream.DoubleStream x = r.doubles(-1L); }, + () -> { java.util.stream.DoubleStream x = r.doubles(-1L, .5, .6); }, + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + /** + * Invoking bounded ints, long, doubles, with illegal bounds throws + * IllegalArgumentException + */ + public void testBadStreamBounds() { + SplittableRandom r = new SplittableRandom(); + Runnable[] throwingActions = { + () -> { java.util.stream.IntStream x = r.ints(2, 1); }, + () -> { java.util.stream.IntStream x = r.ints(10, 42, 42); }, + () -> { java.util.stream.LongStream x = r.longs(-1L, -1L); }, + () -> { java.util.stream.LongStream x = r.longs(10, 1L, -2L); }, + () -> { java.util.stream.DoubleStream x = r.doubles(0.0, 0.0); }, + () -> { java.util.stream.DoubleStream x = r.doubles(10, .5, .4); }, + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + /** + * A parallel sized stream of ints generates the given number of values + */ + public void testIntsCount() { + LongAdder counter = new LongAdder(); + SplittableRandom r = new SplittableRandom(); + long size = 0; + for (int reps = 0; reps < REPS; ++reps) { + counter.reset(); + r.ints(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + size += 524959; + } + } + + /** + * A parallel sized stream of longs generates the given number of values + */ + public void testLongsCount() { + LongAdder counter = new LongAdder(); + SplittableRandom r = new SplittableRandom(); + long size = 0; + for (int reps = 0; reps < REPS; ++reps) { + counter.reset(); + r.longs(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + size += 524959; + } + } + + /** + * A parallel sized stream of doubles generates the given number of values + */ + public void testDoublesCount() { + LongAdder counter = new LongAdder(); + SplittableRandom r = new SplittableRandom(); + long size = 0; + for (int reps = 0; reps < REPS; ++reps) { + counter.reset(); + r.doubles(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + size += 524959; + } + } + + /** + * Each of a parallel sized stream of bounded ints is within bounds + */ + public void testBoundedInts() { + AtomicInteger fails = new AtomicInteger(0); + SplittableRandom r = new SplittableRandom(); + long size = 12345L; + for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) { + for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) { + final int lo = least, hi = bound; + r.ints(size, lo, hi).parallel().forEach( + x -> { + if (x < lo || x >= hi) + fails.getAndIncrement(); }); + } + } + assertEquals(0, fails.get()); + } + + /** + * Each of a parallel sized stream of bounded longs is within bounds + */ + public void testBoundedLongs() { + AtomicInteger fails = new AtomicInteger(0); + SplittableRandom r = new SplittableRandom(); + long size = 123L; + for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) { + for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) { + final long lo = least, hi = bound; + r.longs(size, lo, hi).parallel().forEach( + x -> { + if (x < lo || x >= hi) + fails.getAndIncrement(); }); + } + } + assertEquals(0, fails.get()); + } + + /** + * Each of a parallel sized stream of bounded doubles is within bounds + */ + public void testBoundedDoubles() { + AtomicInteger fails = new AtomicInteger(0); + SplittableRandom r = new SplittableRandom(); + long size = 456; + for (double least = 0.00011; least < 1.0e20; least *= 9) { + for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) { + final double lo = least, hi = bound; + r.doubles(size, lo, hi).parallel().forEach( + x -> { + if (x < lo || x >= hi) + fails.getAndIncrement(); }); + } + } + assertEquals(0, fails.get()); + } + + /** + * A parallel unsized stream of ints generates at least 100 values + */ + public void testUnsizedIntsCount() { + LongAdder counter = new LongAdder(); + SplittableRandom r = new SplittableRandom(); + long size = 100; + r.ints().limit(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A parallel unsized stream of longs generates at least 100 values + */ + public void testUnsizedLongsCount() { + LongAdder counter = new LongAdder(); + SplittableRandom r = new SplittableRandom(); + long size = 100; + r.longs().limit(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A parallel unsized stream of doubles generates at least 100 values + */ + public void testUnsizedDoublesCount() { + LongAdder counter = new LongAdder(); + SplittableRandom r = new SplittableRandom(); + long size = 100; + r.doubles().limit(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A sequential unsized stream of ints generates at least 100 values + */ + public void testUnsizedIntsCountSeq() { + LongAdder counter = new LongAdder(); + SplittableRandom r = new SplittableRandom(); + long size = 100; + r.ints().limit(size).forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A sequential unsized stream of longs generates at least 100 values + */ + public void testUnsizedLongsCountSeq() { + LongAdder counter = new LongAdder(); + SplittableRandom r = new SplittableRandom(); + long size = 100; + r.longs().limit(size).forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A sequential unsized stream of doubles generates at least 100 values + */ + public void testUnsizedDoublesCountSeq() { + LongAdder counter = new LongAdder(); + SplittableRandom r = new SplittableRandom(); + long size = 100; + r.doubles().limit(size).forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/StampedLockTest.java b/jdk/test/java/util/concurrent/tck/StampedLockTest.java new file mode 100644 index 00000000000..84026409d7b --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/StampedLockTest.java @@ -0,0 +1,906 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz + * with assistance from members of JCP JSR-166 Expert Group and + * released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.StampedLock; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class StampedLockTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(StampedLockTest.class); + } + + /** + * A runnable calling writeLockInterruptibly + */ + class InterruptibleLockRunnable extends CheckedRunnable { + final StampedLock lock; + InterruptibleLockRunnable(StampedLock l) { lock = l; } + public void realRun() throws InterruptedException { + lock.writeLockInterruptibly(); + } + } + + /** + * A runnable calling writeLockInterruptibly that expects to be + * interrupted + */ + class InterruptedLockRunnable extends CheckedInterruptedRunnable { + final StampedLock lock; + InterruptedLockRunnable(StampedLock l) { lock = l; } + public void realRun() throws InterruptedException { + lock.writeLockInterruptibly(); + } + } + + /** + * Releases write lock, checking isWriteLocked before and after + */ + void releaseWriteLock(StampedLock lock, long s) { + assertTrue(lock.isWriteLocked()); + lock.unlockWrite(s); + assertFalse(lock.isWriteLocked()); + } + + /** + * Constructed StampedLock is in unlocked state + */ + public void testConstructor() { + StampedLock lock; + lock = new StampedLock(); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + } + + /** + * write-locking and read-locking an unlocked lock succeed + */ + public void testLock() { + StampedLock lock = new StampedLock(); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + long s = lock.writeLock(); + assertTrue(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + lock.unlockWrite(s); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + long rs = lock.readLock(); + assertFalse(lock.isWriteLocked()); + assertTrue(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 1); + lock.unlockRead(rs); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + } + + /** + * unlock releases either a read or write lock + */ + public void testUnlock() { + StampedLock lock = new StampedLock(); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + long s = lock.writeLock(); + assertTrue(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + lock.unlock(s); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + long rs = lock.readLock(); + assertFalse(lock.isWriteLocked()); + assertTrue(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 1); + lock.unlock(rs); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + } + + /** + * tryUnlockRead/Write succeeds if locked in associated mode else + * returns false + */ + public void testTryUnlock() { + StampedLock lock = new StampedLock(); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + long s = lock.writeLock(); + assertTrue(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + assertFalse(lock.tryUnlockRead()); + assertTrue(lock.tryUnlockWrite()); + assertFalse(lock.tryUnlockWrite()); + assertFalse(lock.tryUnlockRead()); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + long rs = lock.readLock(); + assertFalse(lock.isWriteLocked()); + assertTrue(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 1); + assertFalse(lock.tryUnlockWrite()); + assertTrue(lock.tryUnlockRead()); + assertFalse(lock.tryUnlockRead()); + assertFalse(lock.tryUnlockWrite()); + assertFalse(lock.isWriteLocked()); + assertFalse(lock.isReadLocked()); + assertEquals(lock.getReadLockCount(), 0); + } + + /** + * write-unlocking an unlocked lock throws IllegalMonitorStateException + */ + public void testWriteUnlock_IMSE() { + StampedLock lock = new StampedLock(); + try { + lock.unlockWrite(0L); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * write-unlocking an unlocked lock throws IllegalMonitorStateException + */ + public void testWriteUnlock_IMSE2() { + StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + lock.unlockWrite(s); + try { + lock.unlockWrite(s); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * write-unlocking after readlock throws IllegalMonitorStateException + */ + public void testWriteUnlock_IMSE3() { + StampedLock lock = new StampedLock(); + long s = lock.readLock(); + try { + lock.unlockWrite(s); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * read-unlocking an unlocked lock throws IllegalMonitorStateException + */ + public void testReadUnlock_IMSE() { + StampedLock lock = new StampedLock(); + long s = lock.readLock(); + lock.unlockRead(s); + try { + lock.unlockRead(s); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * read-unlocking an unlocked lock throws IllegalMonitorStateException + */ + public void testReadUnlock_IMSE2() { + StampedLock lock = new StampedLock(); + try { + lock.unlockRead(0L); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * read-unlocking after writeLock throws IllegalMonitorStateException + */ + public void testReadUnlock_IMSE3() { + StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + try { + lock.unlockRead(s); + shouldThrow(); + } catch (IllegalMonitorStateException success) {} + } + + /** + * validate(0) fails + */ + public void testValidate0() { + StampedLock lock = new StampedLock(); + assertFalse(lock.validate(0L)); + } + + /** + * A stamp obtained from a successful lock operation validates + */ + public void testValidate() throws InterruptedException { + StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + assertTrue(lock.validate(s)); + lock.unlockWrite(s); + s = lock.readLock(); + assertTrue(lock.validate(s)); + lock.unlockRead(s); + assertTrue((s = lock.tryWriteLock()) != 0L); + assertTrue(lock.validate(s)); + lock.unlockWrite(s); + assertTrue((s = lock.tryReadLock()) != 0L); + assertTrue(lock.validate(s)); + lock.unlockRead(s); + assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); + assertTrue(lock.validate(s)); + lock.unlockWrite(s); + assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); + assertTrue(lock.validate(s)); + lock.unlockRead(s); + assertTrue((s = lock.tryOptimisticRead()) != 0L); + } + + /** + * A stamp obtained from an unsuccessful lock operation does not validate + */ + public void testValidate2() throws InterruptedException { + StampedLock lock = new StampedLock(); + long s; + assertTrue((s = lock.writeLock()) != 0L); + assertTrue(lock.validate(s)); + assertFalse(lock.validate(lock.tryWriteLock())); + assertFalse(lock.validate(lock.tryWriteLock(10L, MILLISECONDS))); + assertFalse(lock.validate(lock.tryReadLock())); + assertFalse(lock.validate(lock.tryReadLock(10L, MILLISECONDS))); + assertFalse(lock.validate(lock.tryOptimisticRead())); + lock.unlockWrite(s); + } + + /** + * writeLockInterruptibly is interruptible + */ + public void testWriteLockInterruptibly_Interruptible() + throws InterruptedException { + final CountDownLatch running = new CountDownLatch(1); + final StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + running.countDown(); + lock.writeLockInterruptibly(); + }}); + + running.await(); + waitForThreadToEnterWaitState(t, 100); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock, s); + } + + /** + * timed tryWriteLock is interruptible + */ + public void testWriteTryLock_Interruptible() throws InterruptedException { + final CountDownLatch running = new CountDownLatch(1); + final StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + running.countDown(); + lock.tryWriteLock(2 * LONG_DELAY_MS, MILLISECONDS); + }}); + + running.await(); + waitForThreadToEnterWaitState(t, 100); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock, s); + } + + /** + * readLockInterruptibly is interruptible + */ + public void testReadLockInterruptibly_Interruptible() + throws InterruptedException { + final CountDownLatch running = new CountDownLatch(1); + final StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + running.countDown(); + lock.readLockInterruptibly(); + }}); + + running.await(); + waitForThreadToEnterWaitState(t, 100); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock, s); + } + + /** + * timed tryReadLock is interruptible + */ + public void testReadTryLock_Interruptible() throws InterruptedException { + final CountDownLatch running = new CountDownLatch(1); + final StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + running.countDown(); + lock.tryReadLock(2 * LONG_DELAY_MS, MILLISECONDS); + }}); + + running.await(); + waitForThreadToEnterWaitState(t, 100); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock, s); + } + + /** + * tryWriteLock on an unlocked lock succeeds + */ + public void testWriteTryLock() { + final StampedLock lock = new StampedLock(); + long s = lock.tryWriteLock(); + assertTrue(s != 0L); + assertTrue(lock.isWriteLocked()); + long s2 = lock.tryWriteLock(); + assertEquals(s2, 0L); + releaseWriteLock(lock, s); + } + + /** + * tryWriteLock fails if locked + */ + public void testWriteTryLockWhenLocked() { + final StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + long ws = lock.tryWriteLock(); + assertTrue(ws == 0L); + }}); + + awaitTermination(t); + releaseWriteLock(lock, s); + } + + /** + * tryReadLock fails if write-locked + */ + public void testReadTryLockWhenLocked() { + final StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + long rs = lock.tryReadLock(); + assertEquals(rs, 0L); + }}); + + awaitTermination(t); + releaseWriteLock(lock, s); + } + + /** + * Multiple threads can hold a read lock when not write-locked + */ + public void testMultipleReadLocks() { + final StampedLock lock = new StampedLock(); + final long s = lock.readLock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long s2 = lock.tryReadLock(); + assertTrue(s2 != 0L); + lock.unlockRead(s2); + long s3 = lock.tryReadLock(LONG_DELAY_MS, MILLISECONDS); + assertTrue(s3 != 0L); + lock.unlockRead(s3); + long s4 = lock.readLock(); + lock.unlockRead(s4); + }}); + + awaitTermination(t); + lock.unlockRead(s); + } + + /** + * A writelock succeeds only after a reading thread unlocks + */ + public void testWriteAfterReadLock() throws InterruptedException { + final CountDownLatch running = new CountDownLatch(1); + final StampedLock lock = new StampedLock(); + long rs = lock.readLock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + running.countDown(); + long s = lock.writeLock(); + lock.unlockWrite(s); + }}); + + running.await(); + waitForThreadToEnterWaitState(t, 100); + assertFalse(lock.isWriteLocked()); + lock.unlockRead(rs); + awaitTermination(t); + assertFalse(lock.isWriteLocked()); + } + + /** + * A writelock succeeds only after reading threads unlock + */ + public void testWriteAfterMultipleReadLocks() { + final StampedLock lock = new StampedLock(); + long s = lock.readLock(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + long rs = lock.readLock(); + lock.unlockRead(rs); + }}); + + awaitTermination(t1); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + long ws = lock.writeLock(); + lock.unlockWrite(ws); + }}); + + assertFalse(lock.isWriteLocked()); + lock.unlockRead(s); + awaitTermination(t2); + assertFalse(lock.isWriteLocked()); + } + + /** + * Readlocks succeed only after a writing thread unlocks + */ + public void testReadAfterWriteLock() { + final StampedLock lock = new StampedLock(); + final long s = lock.writeLock(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() { + long rs = lock.readLock(); + lock.unlockRead(rs); + }}); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + long rs = lock.readLock(); + lock.unlockRead(rs); + }}); + + releaseWriteLock(lock, s); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * tryReadLock succeeds if readlocked but not writelocked + */ + public void testTryLockWhenReadLocked() { + final StampedLock lock = new StampedLock(); + long s = lock.readLock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + long rs = lock.tryReadLock(); + threadAssertTrue(rs != 0L); + lock.unlockRead(rs); + }}); + + awaitTermination(t); + lock.unlockRead(s); + } + + /** + * tryWriteLock fails when readlocked + */ + public void testWriteTryLockWhenReadLocked() { + final StampedLock lock = new StampedLock(); + long s = lock.readLock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() { + long ws = lock.tryWriteLock(); + threadAssertEquals(ws, 0L); + }}); + + awaitTermination(t); + lock.unlockRead(s); + } + + /** + * timed tryWriteLock times out if locked + */ + public void testWriteTryLock_Timeout() { + final StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + long timeoutMillis = 10; + long ws = lock.tryWriteLock(timeoutMillis, MILLISECONDS); + assertEquals(ws, 0L); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + }}); + + awaitTermination(t); + releaseWriteLock(lock, s); + } + + /** + * timed tryReadLock times out if write-locked + */ + public void testReadTryLock_Timeout() { + final StampedLock lock = new StampedLock(); + long s = lock.writeLock(); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + long timeoutMillis = 10; + long rs = lock.tryReadLock(timeoutMillis, MILLISECONDS); + assertEquals(rs, 0L); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + }}); + + awaitTermination(t); + assertTrue(lock.isWriteLocked()); + lock.unlockWrite(s); + } + + /** + * writeLockInterruptibly succeeds if unlocked, else is interruptible + */ + public void testWriteLockInterruptibly() throws InterruptedException { + final CountDownLatch running = new CountDownLatch(1); + final StampedLock lock = new StampedLock(); + long s = lock.writeLockInterruptibly(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + running.countDown(); + lock.writeLockInterruptibly(); + }}); + + running.await(); + waitForThreadToEnterWaitState(t, 100); + t.interrupt(); + assertTrue(lock.isWriteLocked()); + awaitTermination(t); + releaseWriteLock(lock, s); + } + + /** + * readLockInterruptibly succeeds if lock free else is interruptible + */ + public void testReadLockInterruptibly() throws InterruptedException { + final CountDownLatch running = new CountDownLatch(1); + final StampedLock lock = new StampedLock(); + long s; + s = lock.readLockInterruptibly(); + lock.unlockRead(s); + s = lock.writeLockInterruptibly(); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + running.countDown(); + lock.readLockInterruptibly(); + }}); + + running.await(); + waitForThreadToEnterWaitState(t, 100); + t.interrupt(); + awaitTermination(t); + releaseWriteLock(lock, s); + } + + /** + * A serialized lock deserializes as unlocked + */ + public void testSerialization() { + StampedLock lock = new StampedLock(); + lock.writeLock(); + StampedLock clone = serialClone(lock); + assertTrue(lock.isWriteLocked()); + assertFalse(clone.isWriteLocked()); + long s = clone.writeLock(); + assertTrue(clone.isWriteLocked()); + clone.unlockWrite(s); + assertFalse(clone.isWriteLocked()); + } + + /** + * toString indicates current lock state + */ + public void testToString() { + StampedLock lock = new StampedLock(); + assertTrue(lock.toString().contains("Unlocked")); + long s = lock.writeLock(); + assertTrue(lock.toString().contains("Write-locked")); + lock.unlockWrite(s); + s = lock.readLock(); + assertTrue(lock.toString().contains("Read-locks")); + } + + /** + * tryOptimisticRead succeeds and validates if unlocked, fails if locked + */ + public void testValidateOptimistic() throws InterruptedException { + StampedLock lock = new StampedLock(); + long s, p; + assertTrue((p = lock.tryOptimisticRead()) != 0L); + assertTrue(lock.validate(p)); + assertTrue((s = lock.writeLock()) != 0L); + assertFalse((p = lock.tryOptimisticRead()) != 0L); + assertTrue(lock.validate(s)); + lock.unlockWrite(s); + assertTrue((p = lock.tryOptimisticRead()) != 0L); + assertTrue(lock.validate(p)); + assertTrue((s = lock.readLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryOptimisticRead()) != 0L); + assertTrue(lock.validate(p)); + lock.unlockRead(s); + assertTrue((s = lock.tryWriteLock()) != 0L); + assertTrue(lock.validate(s)); + assertFalse((p = lock.tryOptimisticRead()) != 0L); + lock.unlockWrite(s); + assertTrue((s = lock.tryReadLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryOptimisticRead()) != 0L); + lock.unlockRead(s); + assertTrue(lock.validate(p)); + assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); + assertFalse((p = lock.tryOptimisticRead()) != 0L); + assertTrue(lock.validate(s)); + lock.unlockWrite(s); + assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryOptimisticRead()) != 0L); + lock.unlockRead(s); + assertTrue((p = lock.tryOptimisticRead()) != 0L); + } + + /** + * tryOptimisticRead stamp does not validate if a write lock intervenes + */ + public void testValidateOptimisticWriteLocked() { + StampedLock lock = new StampedLock(); + long s, p; + assertTrue((p = lock.tryOptimisticRead()) != 0L); + assertTrue((s = lock.writeLock()) != 0L); + assertFalse(lock.validate(p)); + assertFalse((p = lock.tryOptimisticRead()) != 0L); + assertTrue(lock.validate(s)); + lock.unlockWrite(s); + } + + /** + * tryOptimisticRead stamp does not validate if a write lock + * intervenes in another thread + */ + public void testValidateOptimisticWriteLocked2() + throws InterruptedException { + final CountDownLatch running = new CountDownLatch(1); + final StampedLock lock = new StampedLock(); + long s, p; + assertTrue((p = lock.tryOptimisticRead()) != 0L); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + lock.writeLockInterruptibly(); + running.countDown(); + lock.writeLockInterruptibly(); + }}); + + running.await(); + assertFalse(lock.validate(p)); + assertFalse((p = lock.tryOptimisticRead()) != 0L); + t.interrupt(); + awaitTermination(t); + } + + /** + * tryConvertToOptimisticRead succeeds and validates if successfully locked, + */ + public void testTryConvertToOptimisticRead() throws InterruptedException { + StampedLock lock = new StampedLock(); + long s, p; + s = 0L; + assertFalse((p = lock.tryConvertToOptimisticRead(s)) != 0L); + assertTrue((s = lock.tryOptimisticRead()) != 0L); + assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); + assertTrue((s = lock.writeLock()) != 0L); + assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); + assertTrue(lock.validate(p)); + assertTrue((s = lock.readLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); + assertTrue(lock.validate(p)); + assertTrue((s = lock.tryWriteLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); + assertTrue(lock.validate(p)); + assertTrue((s = lock.tryReadLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); + assertTrue(lock.validate(p)); + assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); + assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); + assertTrue(lock.validate(p)); + assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L); + assertTrue(lock.validate(p)); + } + + /** + * tryConvertToReadLock succeeds and validates if successfully locked + * or lock free; + */ + public void testTryConvertToReadLock() throws InterruptedException { + StampedLock lock = new StampedLock(); + long s, p; + s = 0L; + assertFalse((p = lock.tryConvertToReadLock(s)) != 0L); + assertTrue((s = lock.tryOptimisticRead()) != 0L); + assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); + lock.unlockRead(p); + assertTrue((s = lock.writeLock()) != 0L); + assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockRead(p); + assertTrue((s = lock.readLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockRead(p); + assertTrue((s = lock.tryWriteLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockRead(p); + assertTrue((s = lock.tryReadLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockRead(p); + assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); + assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockRead(p); + assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToReadLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockRead(p); + } + + /** + * tryConvertToWriteLock succeeds and validates if successfully locked + * or lock free; + */ + public void testTryConvertToWriteLock() throws InterruptedException { + StampedLock lock = new StampedLock(); + long s, p; + s = 0L; + assertFalse((p = lock.tryConvertToWriteLock(s)) != 0L); + assertTrue((s = lock.tryOptimisticRead()) != 0L); + assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); + lock.unlockWrite(p); + assertTrue((s = lock.writeLock()) != 0L); + assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockWrite(p); + assertTrue((s = lock.readLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockWrite(p); + assertTrue((s = lock.tryWriteLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockWrite(p); + assertTrue((s = lock.tryReadLock()) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockWrite(p); + assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L); + assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockWrite(p); + assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L); + assertTrue(lock.validate(s)); + assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L); + assertTrue(lock.validate(p)); + lock.unlockWrite(p); + } + + /** + * asWriteLock can be locked and unlocked + */ + public void testAsWriteLock() { + StampedLock sl = new StampedLock(); + Lock lock = sl.asWriteLock(); + lock.lock(); + assertFalse(lock.tryLock()); + lock.unlock(); + assertTrue(lock.tryLock()); + } + + /** + * asReadLock can be locked and unlocked + */ + public void testAsReadLock() { + StampedLock sl = new StampedLock(); + Lock lock = sl.asReadLock(); + lock.lock(); + lock.unlock(); + assertTrue(lock.tryLock()); + } + + /** + * asReadWriteLock.writeLock can be locked and unlocked + */ + public void testAsReadWriteLockWriteLock() { + StampedLock sl = new StampedLock(); + Lock lock = sl.asReadWriteLock().writeLock(); + lock.lock(); + assertFalse(lock.tryLock()); + lock.unlock(); + assertTrue(lock.tryLock()); + } + + /** + * asReadWriteLock.readLock can be locked and unlocked + */ + public void testAsReadWriteLockReadLock() { + StampedLock sl = new StampedLock(); + Lock lock = sl.asReadWriteLock().readLock(); + lock.lock(); + lock.unlock(); + assertTrue(lock.tryLock()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java b/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java new file mode 100644 index 00000000000..ab4c9e90438 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java @@ -0,0 +1,1010 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea and Martin Buchholz with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.Flow; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.SubmissionPublisher; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.BiPredicate; +import java.util.stream.Stream; +import junit.framework.Test; +import junit.framework.TestSuite; + +import static java.util.concurrent.Flow.Publisher; +import static java.util.concurrent.Flow.Subscriber; +import static java.util.concurrent.Flow.Subscription; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +public class SubmissionPublisherTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(SubmissionPublisherTest.class); + } + + final Executor basicExecutor = basicPublisher().getExecutor(); + + static SubmissionPublisher basicPublisher() { + return new SubmissionPublisher(); + } + + static class SPException extends RuntimeException {} + + class TestSubscriber implements Subscriber { + volatile Subscription sn; + int last; // Requires that onNexts are in numeric order + volatile int nexts; + volatile int errors; + volatile int completes; + volatile boolean throwOnCall = false; + volatile boolean request = true; + volatile Throwable lastError; + + public synchronized void onSubscribe(Subscription s) { + threadAssertTrue(sn == null); + sn = s; + notifyAll(); + if (throwOnCall) + throw new SPException(); + if (request) + sn.request(1L); + } + public synchronized void onNext(Integer t) { + ++nexts; + notifyAll(); + int current = t.intValue(); + threadAssertTrue(current >= last); + last = current; + if (request) + sn.request(1L); + if (throwOnCall) + throw new SPException(); + } + public synchronized void onError(Throwable t) { + threadAssertTrue(completes == 0); + threadAssertTrue(errors == 0); + lastError = t; + ++errors; + notifyAll(); + } + public synchronized void onComplete() { + threadAssertTrue(completes == 0); + ++completes; + notifyAll(); + } + + synchronized void awaitSubscribe() { + while (sn == null) { + try { + wait(); + } catch (Exception ex) { + threadUnexpectedException(ex); + break; + } + } + } + synchronized void awaitNext(int n) { + while (nexts < n) { + try { + wait(); + } catch (Exception ex) { + threadUnexpectedException(ex); + break; + } + } + } + synchronized void awaitComplete() { + while (completes == 0 && errors == 0) { + try { + wait(); + } catch (Exception ex) { + threadUnexpectedException(ex); + break; + } + } + } + synchronized void awaitError() { + while (errors == 0) { + try { + wait(); + } catch (Exception ex) { + threadUnexpectedException(ex); + break; + } + } + } + + } + + /** + * A new SubmissionPublisher has no subscribers, a non-null + * executor, a power-of-two capacity, is not closed, and reports + * zero demand and lag + */ + void checkInitialState(SubmissionPublisher p) { + assertFalse(p.hasSubscribers()); + assertEquals(0, p.getNumberOfSubscribers()); + assertTrue(p.getSubscribers().isEmpty()); + assertFalse(p.isClosed()); + assertNull(p.getClosedException()); + int n = p.getMaxBufferCapacity(); + assertTrue((n & (n - 1)) == 0); // power of two + assertNotNull(p.getExecutor()); + assertEquals(0, p.estimateMinimumDemand()); + assertEquals(0, p.estimateMaximumLag()); + } + + /** + * A default-constructed SubmissionPublisher has no subscribers, + * is not closed, has default buffer size, and uses the + * defaultExecutor + */ + public void testConstructor1() { + SubmissionPublisher p = new SubmissionPublisher(); + checkInitialState(p); + assertEquals(p.getMaxBufferCapacity(), Flow.defaultBufferSize()); + Executor e = p.getExecutor(), c = ForkJoinPool.commonPool(); + if (ForkJoinPool.getCommonPoolParallelism() > 1) + assertSame(e, c); + else + assertNotSame(e, c); + } + + /** + * A new SubmissionPublisher has no subscribers, is not closed, + * has the given buffer size, and uses the given executor + */ + public void testConstructor2() { + Executor e = Executors.newFixedThreadPool(1); + SubmissionPublisher p = new SubmissionPublisher(e, 8); + checkInitialState(p); + assertSame(p.getExecutor(), e); + assertEquals(8, p.getMaxBufferCapacity()); + } + + /** + * A null Executor argument to SubmissionPublisher constructor throws NPE + */ + public void testConstructor3() { + try { + new SubmissionPublisher(null, 8); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * A negative capacity argument to SubmissionPublisher constructor + * throws IAE + */ + public void testConstructor4() { + Executor e = Executors.newFixedThreadPool(1); + try { + new SubmissionPublisher(e, -1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * A closed publisher reports isClosed with no closedException and + * throws ISE upon attempted submission; a subsequent close or + * closeExceptionally has no additional effect. + */ + public void testClose() { + SubmissionPublisher p = basicPublisher(); + checkInitialState(p); + p.close(); + assertTrue(p.isClosed()); + assertNull(p.getClosedException()); + try { + p.submit(1); + shouldThrow(); + } catch (IllegalStateException success) {} + Throwable ex = new SPException(); + p.closeExceptionally(ex); + assertTrue(p.isClosed()); + assertNull(p.getClosedException()); + } + + /** + * A publisher closedExceptionally reports isClosed with the + * closedException and throws ISE upon attempted submission; a + * subsequent close or closeExceptionally has no additional + * effect. + */ + public void testCloseExceptionally() { + SubmissionPublisher p = basicPublisher(); + checkInitialState(p); + Throwable ex = new SPException(); + p.closeExceptionally(ex); + assertTrue(p.isClosed()); + assertSame(p.getClosedException(), ex); + try { + p.submit(1); + shouldThrow(); + } catch (IllegalStateException success) {} + p.close(); + assertTrue(p.isClosed()); + assertSame(p.getClosedException(), ex); + } + + /** + * Upon subscription, the subscriber's onSubscribe is called, no + * other Subscriber methods are invoked, the publisher + * hasSubscribers, isSubscribed is true, and existing + * subscriptions are unaffected. + */ + public void testSubscribe1() { + TestSubscriber s = new TestSubscriber(); + SubmissionPublisher p = basicPublisher(); + p.subscribe(s); + assertTrue(p.hasSubscribers()); + assertEquals(1, p.getNumberOfSubscribers()); + assertTrue(p.getSubscribers().contains(s)); + assertTrue(p.isSubscribed(s)); + s.awaitSubscribe(); + assertNotNull(s.sn); + assertEquals(0, s.nexts); + assertEquals(0, s.errors); + assertEquals(0, s.completes); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s2); + assertTrue(p.hasSubscribers()); + assertEquals(2, p.getNumberOfSubscribers()); + assertTrue(p.getSubscribers().contains(s)); + assertTrue(p.getSubscribers().contains(s2)); + assertTrue(p.isSubscribed(s)); + assertTrue(p.isSubscribed(s2)); + s2.awaitSubscribe(); + assertNotNull(s2.sn); + assertEquals(0, s2.nexts); + assertEquals(0, s2.errors); + assertEquals(0, s2.completes); + p.close(); + } + + /** + * If closed, upon subscription, the subscriber's onComplete + * method is invoked + */ + public void testSubscribe2() { + TestSubscriber s = new TestSubscriber(); + SubmissionPublisher p = basicPublisher(); + p.close(); + p.subscribe(s); + s.awaitComplete(); + assertEquals(0, s.nexts); + assertEquals(0, s.errors); + assertEquals(1, s.completes, 1); + } + + /** + * If closedExceptionally, upon subscription, the subscriber's + * onError method is invoked + */ + public void testSubscribe3() { + TestSubscriber s = new TestSubscriber(); + SubmissionPublisher p = basicPublisher(); + Throwable ex = new SPException(); + p.closeExceptionally(ex); + assertTrue(p.isClosed()); + assertSame(p.getClosedException(), ex); + p.subscribe(s); + s.awaitError(); + assertEquals(0, s.nexts); + assertEquals(1, s.errors); + } + + /** + * Upon attempted resubscription, the subscriber's onError is + * called and the subscription is cancelled. + */ + public void testSubscribe4() { + TestSubscriber s = new TestSubscriber(); + SubmissionPublisher p = basicPublisher(); + p.subscribe(s); + assertTrue(p.hasSubscribers()); + assertEquals(1, p.getNumberOfSubscribers()); + assertTrue(p.getSubscribers().contains(s)); + assertTrue(p.isSubscribed(s)); + s.awaitSubscribe(); + assertNotNull(s.sn); + assertEquals(0, s.nexts); + assertEquals(0, s.errors); + assertEquals(0, s.completes); + p.subscribe(s); + s.awaitError(); + assertEquals(0, s.nexts); + assertEquals(1, s.errors); + assertFalse(p.isSubscribed(s)); + } + + /** + * An exception thrown in onSubscribe causes onError + */ + public void testSubscribe5() { + TestSubscriber s = new TestSubscriber(); + SubmissionPublisher p = basicPublisher(); + s.throwOnCall = true; + try { + p.subscribe(s); + } catch (Exception ok) {} + s.awaitError(); + assertEquals(0, s.nexts); + assertEquals(1, s.errors); + assertEquals(0, s.completes); + } + + /** + * subscribe(null) throws NPE + */ + public void testSubscribe6() { + SubmissionPublisher p = basicPublisher(); + try { + p.subscribe(null); + shouldThrow(); + } catch (NullPointerException success) {} + checkInitialState(p); + } + + /** + * Closing a publisher causes onComplete to subscribers + */ + public void testCloseCompletes() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s1); + p.subscribe(s2); + p.submit(1); + p.close(); + assertTrue(p.isClosed()); + assertNull(p.getClosedException()); + s1.awaitComplete(); + assertEquals(1, s1.nexts); + assertEquals(1, s1.completes); + s2.awaitComplete(); + assertEquals(1, s2.nexts); + assertEquals(1, s2.completes); + } + + /** + * Closing a publisher exceptionally causes onError to subscribers + */ + public void testCloseExceptionallyError() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s1); + p.subscribe(s2); + p.submit(1); + p.closeExceptionally(new SPException()); + assertTrue(p.isClosed()); + s1.awaitError(); + assertTrue(s1.nexts <= 1); + assertEquals(1, s1.errors); + s2.awaitError(); + assertTrue(s2.nexts <= 1); + assertEquals(1, s2.errors); + } + + /** + * Cancelling a subscription eventually causes no more onNexts to be issued + */ + public void testCancel() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s1); + p.subscribe(s2); + s1.awaitSubscribe(); + p.submit(1); + s1.sn.cancel(); + for (int i = 2; i <= 20; ++i) + p.submit(i); + p.close(); + s2.awaitComplete(); + assertEquals(20, s2.nexts); + assertEquals(1, s2.completes); + assertTrue(s1.nexts < 20); + assertFalse(p.isSubscribed(s1)); + } + + /** + * Throwing an exception in onNext causes onError + */ + public void testThrowOnNext() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s1); + p.subscribe(s2); + s1.awaitSubscribe(); + p.submit(1); + s1.throwOnCall = true; + p.submit(2); + p.close(); + s2.awaitComplete(); + assertEquals(2, s2.nexts); + s1.awaitComplete(); + assertEquals(1, s1.errors); + } + + /** + * If a handler is supplied in constructor, it is invoked when + * subscriber throws an exception in onNext + */ + public void testThrowOnNextHandler() { + AtomicInteger calls = new AtomicInteger(); + SubmissionPublisher p = new SubmissionPublisher + (basicExecutor, 8, + (s, e) -> calls.getAndIncrement()); + TestSubscriber s1 = new TestSubscriber(); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s1); + p.subscribe(s2); + s1.awaitSubscribe(); + p.submit(1); + s1.throwOnCall = true; + p.submit(2); + p.close(); + s2.awaitComplete(); + assertEquals(2, s2.nexts); + assertEquals(1, s2.completes); + s1.awaitError(); + assertEquals(1, s1.errors); + assertEquals(1, calls.get()); + } + + /** + * onNext items are issued in the same order to each subscriber + */ + public void testOrder() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s1); + p.subscribe(s2); + for (int i = 1; i <= 20; ++i) + p.submit(i); + p.close(); + s2.awaitComplete(); + s1.awaitComplete(); + assertEquals(20, s2.nexts); + assertEquals(1, s2.completes); + assertEquals(20, s1.nexts); + assertEquals(1, s1.completes); + } + + /** + * onNext is issued only if requested + */ + public void testRequest1() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + p.subscribe(s1); + s1.awaitSubscribe(); + assertTrue(p.estimateMinimumDemand() == 0); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s2); + p.submit(1); + p.submit(2); + s2.awaitNext(1); + assertEquals(0, s1.nexts); + s1.sn.request(3); + p.submit(3); + p.close(); + s2.awaitComplete(); + assertEquals(3, s2.nexts); + assertEquals(1, s2.completes); + s1.awaitComplete(); + assertTrue(s1.nexts > 0); + assertEquals(1, s1.completes); + } + + /** + * onNext is not issued when requests become zero + */ + public void testRequest2() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + s1.request = false; + p.submit(1); + p.submit(2); + p.close(); + s2.awaitComplete(); + assertEquals(2, s2.nexts); + assertEquals(1, s2.completes); + s1.awaitNext(1); + assertEquals(1, s1.nexts); + } + + /** + * Negative request causes error + */ + public void testRequest3() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + s1.sn.request(-1L); + p.submit(1); + p.submit(2); + p.close(); + s2.awaitComplete(); + assertEquals(2, s2.nexts); + assertEquals(1, s2.completes); + s1.awaitError(); + assertEquals(1, s1.errors); + assertTrue(s1.lastError instanceof IllegalArgumentException); + } + + /** + * estimateMinimumDemand reports 0 until request, nonzero after + * request, and zero again after delivery + */ + public void testEstimateMinimumDemand() { + TestSubscriber s = new TestSubscriber(); + SubmissionPublisher p = basicPublisher(); + s.request = false; + p.subscribe(s); + s.awaitSubscribe(); + assertEquals(0, p.estimateMinimumDemand()); + s.sn.request(1); + assertEquals(1, p.estimateMinimumDemand()); + p.submit(1); + s.awaitNext(1); + assertEquals(0, p.estimateMinimumDemand()); + } + + /** + * submit to a publisher with no subscribers returns lag 0 + */ + public void testEmptySubmit() { + SubmissionPublisher p = basicPublisher(); + assertEquals(0, p.submit(1)); + } + + /** + * submit(null) throws NPE + */ + public void testNullSubmit() { + SubmissionPublisher p = basicPublisher(); + try { + p.submit(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * submit returns number of lagged items, compatible with result + * of estimateMaximumLag. + */ + public void testLaggedSubmit() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + TestSubscriber s2 = new TestSubscriber(); + s2.request = false; + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + assertEquals(1, p.submit(1)); + assertTrue(p.estimateMaximumLag() >= 1); + assertTrue(p.submit(2) >= 2); + assertTrue(p.estimateMaximumLag() >= 2); + s1.sn.request(4); + assertTrue(p.submit(3) >= 3); + assertTrue(p.estimateMaximumLag() >= 3); + s2.sn.request(4); + p.submit(4); + p.close(); + s2.awaitComplete(); + assertEquals(4, s2.nexts); + s1.awaitComplete(); + assertEquals(4, s2.nexts); + } + + /** + * submit eventually issues requested items when buffer capacity is 1 + */ + public void testCap1Submit() { + SubmissionPublisher p = new SubmissionPublisher( + basicExecutor, 1); + TestSubscriber s1 = new TestSubscriber(); + TestSubscriber s2 = new TestSubscriber(); + p.subscribe(s1); + p.subscribe(s2); + for (int i = 1; i <= 20; ++i) { + assertTrue(p.estimateMinimumDemand() <= 1); + assertTrue(p.submit(i) >= 0); + } + p.close(); + s2.awaitComplete(); + s1.awaitComplete(); + assertEquals(20, s2.nexts); + assertEquals(1, s2.completes); + assertEquals(20, s1.nexts); + assertEquals(1, s1.completes); + } + + static boolean noopHandle(AtomicInteger count) { + count.getAndIncrement(); + return false; + } + + static boolean reqHandle(AtomicInteger count, Subscriber s) { + count.getAndIncrement(); + ((TestSubscriber)s).sn.request(Long.MAX_VALUE); + return true; + } + + /** + * offer to a publisher with no subscribers returns lag 0 + */ + public void testEmptyOffer() { + SubmissionPublisher p = basicPublisher(); + assertEquals(0, p.offer(1, null)); + } + + /** + * offer(null) throws NPE + */ + public void testNullOffer() { + SubmissionPublisher p = basicPublisher(); + try { + p.offer(null, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * offer returns number of lagged items if not saturated + */ + public void testLaggedOffer() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + TestSubscriber s2 = new TestSubscriber(); + s2.request = false; + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + assertTrue(p.offer(1, null) >= 1); + assertTrue(p.offer(2, null) >= 2); + s1.sn.request(4); + assertTrue(p.offer(3, null) >= 3); + s2.sn.request(4); + p.offer(4, null); + p.close(); + s2.awaitComplete(); + assertEquals(4, s2.nexts); + s1.awaitComplete(); + assertEquals(4, s2.nexts); + } + + /** + * offer reports drops if saturated + */ + public void testDroppedOffer() { + SubmissionPublisher p = new SubmissionPublisher( + basicExecutor, 4); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + TestSubscriber s2 = new TestSubscriber(); + s2.request = false; + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + for (int i = 1; i <= 4; ++i) + assertTrue(p.offer(i, null) >= 0); + p.offer(5, null); + assertTrue(p.offer(6, null) < 0); + s1.sn.request(64); + assertTrue(p.offer(7, null) < 0); + s2.sn.request(64); + p.close(); + s2.awaitComplete(); + assertTrue(s2.nexts >= 4); + s1.awaitComplete(); + assertTrue(s1.nexts >= 4); + } + + /** + * offer invokes drop handler if saturated + */ + public void testHandledDroppedOffer() { + AtomicInteger calls = new AtomicInteger(); + SubmissionPublisher p = new SubmissionPublisher( + basicExecutor, 4); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + TestSubscriber s2 = new TestSubscriber(); + s2.request = false; + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + for (int i = 1; i <= 4; ++i) + assertTrue(p.offer(i, (s, x) -> noopHandle(calls)) >= 0); + p.offer(4, (s, x) -> noopHandle(calls)); + assertTrue(p.offer(6, (s, x) -> noopHandle(calls)) < 0); + s1.sn.request(64); + assertTrue(p.offer(7, (s, x) -> noopHandle(calls)) < 0); + s2.sn.request(64); + p.close(); + s2.awaitComplete(); + s1.awaitComplete(); + assertTrue(calls.get() >= 4); + } + + /** + * offer succeeds if drop handler forces request + */ + public void testRecoveredHandledDroppedOffer() { + AtomicInteger calls = new AtomicInteger(); + SubmissionPublisher p = new SubmissionPublisher( + basicExecutor, 4); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + TestSubscriber s2 = new TestSubscriber(); + s2.request = false; + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + int n = 0; + for (int i = 1; i <= 8; ++i) { + int d = p.offer(i, (s, x) -> reqHandle(calls, s)); + n = n + 2 + (d < 0 ? d : 0); + } + p.close(); + s2.awaitComplete(); + s1.awaitComplete(); + assertEquals(n, s1.nexts + s2.nexts); + assertTrue(calls.get() >= 2); + } + + /** + * Timed offer to a publisher with no subscribers returns lag 0 + */ + public void testEmptyTimedOffer() { + SubmissionPublisher p = basicPublisher(); + long startTime = System.nanoTime(); + assertEquals(0, p.offer(1, LONG_DELAY_MS, MILLISECONDS, null)); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2); + } + + /** + * Timed offer with null item or TimeUnit throws NPE + */ + public void testNullTimedOffer() { + SubmissionPublisher p = basicPublisher(); + long startTime = System.nanoTime(); + try { + p.offer(null, LONG_DELAY_MS, MILLISECONDS, null); + shouldThrow(); + } catch (NullPointerException success) {} + try { + p.offer(1, LONG_DELAY_MS, null, null); + shouldThrow(); + } catch (NullPointerException success) {} + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2); + } + + /** + * Timed offer returns number of lagged items if not saturated + */ + public void testLaggedTimedOffer() { + SubmissionPublisher p = basicPublisher(); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + TestSubscriber s2 = new TestSubscriber(); + s2.request = false; + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + long startTime = System.nanoTime(); + assertTrue(p.offer(1, LONG_DELAY_MS, MILLISECONDS, null) >= 1); + assertTrue(p.offer(2, LONG_DELAY_MS, MILLISECONDS, null) >= 2); + s1.sn.request(4); + assertTrue(p.offer(3, LONG_DELAY_MS, MILLISECONDS, null) >= 3); + s2.sn.request(4); + p.offer(4, LONG_DELAY_MS, MILLISECONDS, null); + p.close(); + s2.awaitComplete(); + assertEquals(4, s2.nexts); + s1.awaitComplete(); + assertEquals(4, s2.nexts); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2); + } + + /** + * Timed offer reports drops if saturated + */ + public void testDroppedTimedOffer() { + SubmissionPublisher p = new SubmissionPublisher( + basicExecutor, 4); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + TestSubscriber s2 = new TestSubscriber(); + s2.request = false; + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + long delay = timeoutMillis(); + for (int i = 1; i <= 4; ++i) + assertTrue(p.offer(i, delay, MILLISECONDS, null) >= 0); + long startTime = System.nanoTime(); + assertTrue(p.offer(5, delay, MILLISECONDS, null) < 0); + s1.sn.request(64); + assertTrue(p.offer(6, delay, MILLISECONDS, null) < 0); + // 2 * delay should elapse but check only 1 * delay to allow timer slop + assertTrue(millisElapsedSince(startTime) >= delay); + s2.sn.request(64); + p.close(); + s2.awaitComplete(); + assertTrue(s2.nexts >= 2); + s1.awaitComplete(); + assertTrue(s1.nexts >= 2); + } + + /** + * Timed offer invokes drop handler if saturated + */ + public void testHandledDroppedTimedOffer() { + AtomicInteger calls = new AtomicInteger(); + SubmissionPublisher p = new SubmissionPublisher( + basicExecutor, 4); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + TestSubscriber s2 = new TestSubscriber(); + s2.request = false; + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + long delay = timeoutMillis(); + for (int i = 1; i <= 4; ++i) + assertTrue(p.offer(i, delay, MILLISECONDS, (s, x) -> noopHandle(calls)) >= 0); + long startTime = System.nanoTime(); + assertTrue(p.offer(5, delay, MILLISECONDS, (s, x) -> noopHandle(calls)) < 0); + s1.sn.request(64); + assertTrue(p.offer(6, delay, MILLISECONDS, (s, x) -> noopHandle(calls)) < 0); + assertTrue(millisElapsedSince(startTime) >= delay); + s2.sn.request(64); + p.close(); + s2.awaitComplete(); + s1.awaitComplete(); + assertTrue(calls.get() >= 2); + } + + /** + * Timed offer succeeds if drop handler forces request + */ + public void testRecoveredHandledDroppedTimedOffer() { + AtomicInteger calls = new AtomicInteger(); + SubmissionPublisher p = new SubmissionPublisher( + basicExecutor, 4); + TestSubscriber s1 = new TestSubscriber(); + s1.request = false; + TestSubscriber s2 = new TestSubscriber(); + s2.request = false; + p.subscribe(s1); + p.subscribe(s2); + s2.awaitSubscribe(); + s1.awaitSubscribe(); + int n = 0; + long delay = timeoutMillis(); + long startTime = System.nanoTime(); + for (int i = 1; i <= 6; ++i) { + int d = p.offer(i, delay, MILLISECONDS, (s, x) -> reqHandle(calls, s)); + n = n + 2 + (d < 0 ? d : 0); + } + assertTrue(millisElapsedSince(startTime) >= delay); + p.close(); + s2.awaitComplete(); + s1.awaitComplete(); + assertEquals(n, s1.nexts + s2.nexts); + assertTrue(calls.get() >= 2); + } + + /** + * consume returns a CompletableFuture that is done when + * publisher completes + */ + public void testConsume() { + AtomicInteger sum = new AtomicInteger(); + SubmissionPublisher p = basicPublisher(); + CompletableFuture f = + p.consume((Integer x) -> { sum.getAndAdd(x.intValue()); }); + int n = 20; + for (int i = 1; i <= n; ++i) + p.submit(i); + p.close(); + f.join(); + assertEquals((n * (n + 1)) / 2, sum.get()); + } + + /** + * consume(null) throws NPE + */ + public void testConsumeNPE() { + SubmissionPublisher p = basicPublisher(); + try { + CompletableFuture f = p.consume(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * consume eventually stops processing published items if cancelled + */ + public void testCancelledConsume() { + AtomicInteger count = new AtomicInteger(); + SubmissionPublisher p = basicPublisher(); + CompletableFuture f = p.consume(x -> count.getAndIncrement()); + f.cancel(true); + int n = 1000000; // arbitrary limit + for (int i = 1; i <= n; ++i) + p.submit(i); + assertTrue(count.get() < n); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java b/jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java new file mode 100644 index 00000000000..b4529801928 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java @@ -0,0 +1,643 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.SynchronousQueue; + +import junit.framework.Test; + +public class SynchronousQueueTest extends JSR166TestCase { + + public static class Fair extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new SynchronousQueue(true); + } + } + + public static class NonFair extends BlockingQueueTest { + protected BlockingQueue emptyCollection() { + return new SynchronousQueue(false); + } + } + + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return newTestSuite(SynchronousQueueTest.class, + new Fair().testSuite(), + new NonFair().testSuite()); + } + + /** + * Any SynchronousQueue is both empty and full + */ + public void testEmptyFull() { testEmptyFull(false); } + public void testEmptyFull_fair() { testEmptyFull(true); } + public void testEmptyFull(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertEquals(0, q.remainingCapacity()); + assertFalse(q.offer(zero)); + } + + /** + * offer fails if no active taker + */ + public void testOffer() { testOffer(false); } + public void testOffer_fair() { testOffer(true); } + public void testOffer(boolean fair) { + SynchronousQueue q = new SynchronousQueue(fair); + assertFalse(q.offer(one)); + } + + /** + * add throws IllegalStateException if no active taker + */ + public void testAdd() { testAdd(false); } + public void testAdd_fair() { testAdd(true); } + public void testAdd(boolean fair) { + SynchronousQueue q = new SynchronousQueue(fair); + assertEquals(0, q.remainingCapacity()); + try { + q.add(one); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * addAll(this) throws IllegalArgumentException + */ + public void testAddAll_self() { testAddAll_self(false); } + public void testAddAll_self_fair() { testAddAll_self(true); } + public void testAddAll_self(boolean fair) { + SynchronousQueue q = new SynchronousQueue(fair); + try { + q.addAll(q); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * addAll throws ISE if no active taker + */ + public void testAddAll_ISE() { testAddAll_ISE(false); } + public void testAddAll_ISE_fair() { testAddAll_ISE(true); } + public void testAddAll_ISE(boolean fair) { + SynchronousQueue q = new SynchronousQueue(fair); + Integer[] ints = new Integer[1]; + for (int i = 0; i < ints.length; i++) + ints[i] = i; + Collection coll = Arrays.asList(ints); + try { + q.addAll(coll); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * put blocks interruptibly if no active taker + */ + public void testBlockingPut() { testBlockingPut(false); } + public void testBlockingPut_fair() { testBlockingPut(true); } + public void testBlockingPut(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + Thread.currentThread().interrupt(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(0, q.remainingCapacity()); + } + + /** + * put blocks interruptibly waiting for take + */ + public void testPutWithTake() { testPutWithTake(false); } + public void testPutWithTake_fair() { testPutWithTake(true); } + public void testPutWithTake(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CountDownLatch pleaseTake = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + pleaseTake.countDown(); + q.put(one); + + pleaseInterrupt.countDown(); + try { + q.put(99); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseTake); + assertEquals(0, q.remainingCapacity()); + try { assertSame(one, q.take()); } + catch (InterruptedException e) { threadUnexpectedException(e); } + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + assertEquals(0, q.remainingCapacity()); + } + + /** + * timed offer times out if elements not taken + */ + public void testTimedOffer() { testTimedOffer(false); } + public void testTimedOffer_fair() { testTimedOffer(true); } + public void testTimedOffer(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertFalse(q.offer(new Object(), timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + pleaseInterrupt.countDown(); + try { + q.offer(new Object(), 2 * LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * poll return null if no active putter + */ + public void testPoll() { testPoll(false); } + public void testPoll_fair() { testPoll(true); } + public void testPoll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + assertNull(q.poll()); + } + + /** + * timed poll with zero timeout times out if no active putter + */ + public void testTimedPoll0() { testTimedPoll0(false); } + public void testTimedPoll0_fair() { testTimedPoll0(true); } + public void testTimedPoll0(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + try { assertNull(q.poll(0, MILLISECONDS)); } + catch (InterruptedException e) { threadUnexpectedException(e); } + } + + /** + * timed poll with nonzero timeout times out if no active putter + */ + public void testTimedPoll() { testTimedPoll(false); } + public void testTimedPoll_fair() { testTimedPoll(true); } + public void testTimedPoll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + long startTime = System.nanoTime(); + try { assertNull(q.poll(timeoutMillis(), MILLISECONDS)); } + catch (InterruptedException e) { threadUnexpectedException(e); } + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + } + + /** + * timed poll before a delayed offer times out, returning null; + * after offer succeeds; on interruption throws + */ + public void testTimedPollWithOffer() { testTimedPollWithOffer(false); } + public void testTimedPollWithOffer_fair() { testTimedPollWithOffer(true); } + public void testTimedPollWithOffer(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CountDownLatch pleaseOffer = new CountDownLatch(1); + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + long startTime = System.nanoTime(); + assertNull(q.poll(timeoutMillis(), MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + + pleaseOffer.countDown(); + startTime = System.nanoTime(); + assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS)); + + Thread.currentThread().interrupt(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + q.poll(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + }}); + + await(pleaseOffer); + long startTime = System.nanoTime(); + try { assertTrue(q.offer(zero, LONG_DELAY_MS, MILLISECONDS)); } + catch (InterruptedException e) { threadUnexpectedException(e); } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * peek() returns null if no active putter + */ + public void testPeek() { testPeek(false); } + public void testPeek_fair() { testPeek(true); } + public void testPeek(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + assertNull(q.peek()); + } + + /** + * element() throws NoSuchElementException if no active putter + */ + public void testElement() { testElement(false); } + public void testElement_fair() { testElement(true); } + public void testElement(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + try { + q.element(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * remove() throws NoSuchElementException if no active putter + */ + public void testRemove() { testRemove(false); } + public void testRemove_fair() { testRemove(true); } + public void testRemove(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + try { + q.remove(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + + /** + * contains returns false + */ + public void testContains() { testContains(false); } + public void testContains_fair() { testContains(true); } + public void testContains(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + assertFalse(q.contains(zero)); + } + + /** + * clear ensures isEmpty + */ + public void testClear() { testClear(false); } + public void testClear_fair() { testClear(true); } + public void testClear(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll returns false unless empty + */ + public void testContainsAll() { testContainsAll(false); } + public void testContainsAll_fair() { testContainsAll(true); } + public void testContainsAll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + Integer[] empty = new Integer[0]; + assertTrue(q.containsAll(Arrays.asList(empty))); + Integer[] ints = new Integer[1]; ints[0] = zero; + assertFalse(q.containsAll(Arrays.asList(ints))); + } + + /** + * retainAll returns false + */ + public void testRetainAll() { testRetainAll(false); } + public void testRetainAll_fair() { testRetainAll(true); } + public void testRetainAll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + Integer[] empty = new Integer[0]; + assertFalse(q.retainAll(Arrays.asList(empty))); + Integer[] ints = new Integer[1]; ints[0] = zero; + assertFalse(q.retainAll(Arrays.asList(ints))); + } + + /** + * removeAll returns false + */ + public void testRemoveAll() { testRemoveAll(false); } + public void testRemoveAll_fair() { testRemoveAll(true); } + public void testRemoveAll(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + Integer[] empty = new Integer[0]; + assertFalse(q.removeAll(Arrays.asList(empty))); + Integer[] ints = new Integer[1]; ints[0] = zero; + assertFalse(q.containsAll(Arrays.asList(ints))); + } + + /** + * toArray is empty + */ + public void testToArray() { testToArray(false); } + public void testToArray_fair() { testToArray(true); } + public void testToArray(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + Object[] o = q.toArray(); + assertEquals(0, o.length); + } + + /** + * toArray(Integer array) returns its argument with the first + * element (if present) nulled out + */ + public void testToArray2() { testToArray2(false); } + public void testToArray2_fair() { testToArray2(true); } + public void testToArray2(boolean fair) { + final SynchronousQueue q + = new SynchronousQueue(fair); + Integer[] a; + + a = new Integer[0]; + assertSame(a, q.toArray(a)); + + a = new Integer[3]; + Arrays.fill(a, 42); + assertSame(a, q.toArray(a)); + assertNull(a[0]); + for (int i = 1; i < a.length; i++) + assertEquals(42, (int) a[i]); + } + + /** + * toArray(null) throws NPE + */ + public void testToArray_null() { testToArray_null(false); } + public void testToArray_null_fair() { testToArray_null(true); } + public void testToArray_null(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + try { + Object[] o = q.toArray(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * iterator does not traverse any elements + */ + public void testIterator() { testIterator(false); } + public void testIterator_fair() { testIterator(true); } + public void testIterator(boolean fair) { + assertIteratorExhausted(new SynchronousQueue(fair).iterator()); + } + + /** + * iterator remove throws ISE + */ + public void testIteratorRemove() { testIteratorRemove(false); } + public void testIteratorRemove_fair() { testIteratorRemove(true); } + public void testIteratorRemove(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + Iterator it = q.iterator(); + try { + it.remove(); + shouldThrow(); + } catch (IllegalStateException success) {} + } + + /** + * toString returns a non-null string + */ + public void testToString() { testToString(false); } + public void testToString_fair() { testToString(true); } + public void testToString(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + String s = q.toString(); + assertNotNull(s); + } + + /** + * offer transfers elements across Executor tasks + */ + public void testOfferInExecutor() { testOfferInExecutor(false); } + public void testOfferInExecutor_fair() { testOfferInExecutor(true); } + public void testOfferInExecutor(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(q.offer(one)); + threadsStarted.await(); + assertTrue(q.offer(one, LONG_DELAY_MS, MILLISECONDS)); + assertEquals(0, q.remainingCapacity()); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + assertSame(one, q.take()); + }}); + } + } + + /** + * timed poll retrieves elements across Executor threads + */ + public void testPollInExecutor() { testPollInExecutor(false); } + public void testPollInExecutor_fair() { testPollInExecutor(true); } + public void testPollInExecutor(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + final CheckedBarrier threadsStarted = new CheckedBarrier(2); + final ExecutorService executor = Executors.newFixedThreadPool(2); + try (PoolCleaner cleaner = cleaner(executor)) { + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertNull(q.poll()); + threadsStarted.await(); + assertSame(one, q.poll(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(q.isEmpty()); + }}); + + executor.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.await(); + q.put(one); + }}); + } + } + + /** + * a deserialized serialized queue is usable + */ + public void testSerialization() { + final SynchronousQueue x = new SynchronousQueue(); + final SynchronousQueue y = new SynchronousQueue(false); + final SynchronousQueue z = new SynchronousQueue(true); + assertSerialEquals(x, y); + assertNotSerialEquals(x, z); + SynchronousQueue[] qs = { x, y, z }; + for (SynchronousQueue q : qs) { + SynchronousQueue clone = serialClone(q); + assertNotSame(q, clone); + assertSerialEquals(q, clone); + assertTrue(clone.isEmpty()); + assertEquals(0, clone.size()); + assertEquals(0, clone.remainingCapacity()); + assertFalse(clone.offer(zero)); + } + } + + /** + * drainTo(c) of empty queue doesn't transfer elements + */ + public void testDrainTo() { testDrainTo(false); } + public void testDrainTo_fair() { testDrainTo(true); } + public void testDrainTo(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + ArrayList l = new ArrayList(); + q.drainTo(l); + assertEquals(0, q.size()); + assertEquals(0, l.size()); + } + + /** + * drainTo empties queue, unblocking a waiting put. + */ + public void testDrainToWithActivePut() { testDrainToWithActivePut(false); } + public void testDrainToWithActivePut_fair() { testDrainToWithActivePut(true); } + public void testDrainToWithActivePut(boolean fair) { + final SynchronousQueue q = new SynchronousQueue(fair); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(one); + }}); + + ArrayList l = new ArrayList(); + long startTime = System.nanoTime(); + while (l.isEmpty()) { + q.drainTo(l); + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + assertTrue(l.size() == 1); + assertSame(one, l.get(0)); + awaitTermination(t); + } + + /** + * drainTo(c, n) empties up to n elements of queue into c + */ + public void testDrainToN() throws InterruptedException { + final SynchronousQueue q = new SynchronousQueue(); + Thread t1 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(one); + }}); + + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + q.put(two); + }}); + + ArrayList l = new ArrayList(); + int drained; + while ((drained = q.drainTo(l, 1)) == 0) Thread.yield(); + assertEquals(1, drained); + assertEquals(1, l.size()); + while ((drained = q.drainTo(l, 1)) == 0) Thread.yield(); + assertEquals(1, drained); + assertEquals(2, l.size()); + assertTrue(l.contains(one)); + assertTrue(l.contains(two)); + awaitTermination(t1); + awaitTermination(t2); + } + + /** + * remove(null), contains(null) always return false + */ + public void testNeverContainsNull() { + Collection q = new SynchronousQueue(); + assertFalse(q.contains(null)); + assertFalse(q.remove(null)); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/SystemTest.java b/jdk/test/java/util/concurrent/tck/SystemTest.java new file mode 100644 index 00000000000..abf3b49cdd5 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/SystemTest.java @@ -0,0 +1,96 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class SystemTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(SystemTest.class); + } + + /** + * Worst case rounding for millisecs; set for 60 cycle millis clock. + * This value might need to be changed on JVMs with coarser + * System.currentTimeMillis clocks. + */ + static final long MILLIS_ROUND = 17; + + /** + * Nanos between readings of millis is no longer than millis (plus + * possible rounding). + * This shows only that nano timing not (much) worse than milli. + */ + public void testNanoTime1() throws InterruptedException { + long m1 = System.currentTimeMillis(); + Thread.sleep(1); + long n1 = System.nanoTime(); + Thread.sleep(SHORT_DELAY_MS); + long n2 = System.nanoTime(); + Thread.sleep(1); + long m2 = System.currentTimeMillis(); + long millis = m2 - m1; + long nanos = n2 - n1; + assertTrue(nanos >= 0); + long nanosAsMillis = nanos / 1000000; + assertTrue(nanosAsMillis <= millis + MILLIS_ROUND); + } + + /** + * Millis between readings of nanos is less than nanos, adjusting + * for rounding. + * This shows only that nano timing not (much) worse than milli. + */ + public void testNanoTime2() throws InterruptedException { + long n1 = System.nanoTime(); + Thread.sleep(1); + long m1 = System.currentTimeMillis(); + Thread.sleep(SHORT_DELAY_MS); + long m2 = System.currentTimeMillis(); + Thread.sleep(1); + long n2 = System.nanoTime(); + long millis = m2 - m1; + long nanos = n2 - n1; + + assertTrue(nanos >= 0); + long nanosAsMillis = nanos / 1000000; + assertTrue(millis <= nanosAsMillis + MILLIS_ROUND); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java b/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java new file mode 100644 index 00000000000..c80af6290ec --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java @@ -0,0 +1,262 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.LongAdder; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ThreadLocalRandom8Test extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ThreadLocalRandom8Test.class); + } + + // max sampled int bound + static final int MAX_INT_BOUND = (1 << 26); + + // max sampled long bound + static final long MAX_LONG_BOUND = (1L << 42); + + // Number of replications for other checks + static final int REPS = + Integer.getInteger("ThreadLocalRandom8Test.reps", 4); + + /** + * Invoking sized ints, long, doubles, with negative sizes throws + * IllegalArgumentException + */ + public void testBadStreamSize() { + ThreadLocalRandom r = ThreadLocalRandom.current(); + Runnable[] throwingActions = { + () -> r.ints(-1L), + () -> r.ints(-1L, 2, 3), + () -> r.longs(-1L), + () -> r.longs(-1L, -1L, 1L), + () -> r.doubles(-1L), + () -> r.doubles(-1L, .5, .6), + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + /** + * Invoking bounded ints, long, doubles, with illegal bounds throws + * IllegalArgumentException + */ + public void testBadStreamBounds() { + ThreadLocalRandom r = ThreadLocalRandom.current(); + Runnable[] throwingActions = { + () -> r.ints(2, 1), + () -> r.ints(10, 42, 42), + () -> r.longs(-1L, -1L), + () -> r.longs(10, 1L, -2L), + () -> r.doubles(0.0, 0.0), + () -> r.doubles(10, .5, .4), + }; + assertThrows(IllegalArgumentException.class, throwingActions); + } + + /** + * A parallel sized stream of ints generates the given number of values + */ + public void testIntsCount() { + LongAdder counter = new LongAdder(); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 0; + for (int reps = 0; reps < REPS; ++reps) { + counter.reset(); + r.ints(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + size += 524959; + } + } + + /** + * A parallel sized stream of longs generates the given number of values + */ + public void testLongsCount() { + LongAdder counter = new LongAdder(); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 0; + for (int reps = 0; reps < REPS; ++reps) { + counter.reset(); + r.longs(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + size += 524959; + } + } + + /** + * A parallel sized stream of doubles generates the given number of values + */ + public void testDoublesCount() { + LongAdder counter = new LongAdder(); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 0; + for (int reps = 0; reps < REPS; ++reps) { + counter.reset(); + r.doubles(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + size += 524959; + } + } + + /** + * Each of a parallel sized stream of bounded ints is within bounds + */ + public void testBoundedInts() { + AtomicInteger fails = new AtomicInteger(0); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 12345L; + for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) { + for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) { + final int lo = least, hi = bound; + r.ints(size, lo, hi).parallel().forEach( + x -> { + if (x < lo || x >= hi) + fails.getAndIncrement(); }); + } + } + assertEquals(0, fails.get()); + } + + /** + * Each of a parallel sized stream of bounded longs is within bounds + */ + public void testBoundedLongs() { + AtomicInteger fails = new AtomicInteger(0); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 123L; + for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) { + for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) { + final long lo = least, hi = bound; + r.longs(size, lo, hi).parallel().forEach( + x -> { + if (x < lo || x >= hi) + fails.getAndIncrement(); }); + } + } + assertEquals(0, fails.get()); + } + + /** + * Each of a parallel sized stream of bounded doubles is within bounds + */ + public void testBoundedDoubles() { + AtomicInteger fails = new AtomicInteger(0); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 456; + for (double least = 0.00011; least < 1.0e20; least *= 9) { + for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) { + final double lo = least, hi = bound; + r.doubles(size, lo, hi).parallel().forEach( + x -> { + if (x < lo || x >= hi) + fails.getAndIncrement(); }); + } + } + assertEquals(0, fails.get()); + } + + /** + * A parallel unsized stream of ints generates at least 100 values + */ + public void testUnsizedIntsCount() { + LongAdder counter = new LongAdder(); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 100; + r.ints().limit(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A parallel unsized stream of longs generates at least 100 values + */ + public void testUnsizedLongsCount() { + LongAdder counter = new LongAdder(); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 100; + r.longs().limit(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A parallel unsized stream of doubles generates at least 100 values + */ + public void testUnsizedDoublesCount() { + LongAdder counter = new LongAdder(); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 100; + r.doubles().limit(size).parallel().forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A sequential unsized stream of ints generates at least 100 values + */ + public void testUnsizedIntsCountSeq() { + LongAdder counter = new LongAdder(); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 100; + r.ints().limit(size).forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A sequential unsized stream of longs generates at least 100 values + */ + public void testUnsizedLongsCountSeq() { + LongAdder counter = new LongAdder(); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 100; + r.longs().limit(size).forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + + /** + * A sequential unsized stream of doubles generates at least 100 values + */ + public void testUnsizedDoublesCountSeq() { + LongAdder counter = new LongAdder(); + ThreadLocalRandom r = ThreadLocalRandom.current(); + long size = 100; + r.doubles().limit(size).forEach(x -> counter.increment()); + assertEquals(size, counter.sum()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java b/jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java new file mode 100644 index 00000000000..da50bbe2495 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java @@ -0,0 +1,368 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ThreadLocalRandomTest extends JSR166TestCase { + + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ThreadLocalRandomTest.class); + } + + /* + * Testing coverage notes: + * + * We don't test randomness properties, but only that repeated + * calls, up to NCALLS tries, produce at least one different + * result. For bounded versions, we sample various intervals + * across multiples of primes. + */ + + // max numbers of calls to detect getting stuck on one value + static final int NCALLS = 10000; + + // max sampled int bound + static final int MAX_INT_BOUND = (1 << 28); + + // max sampled long bound + static final long MAX_LONG_BOUND = (1L << 42); + + // Number of replications for other checks + static final int REPS = 20; + + /** + * setSeed throws UnsupportedOperationException + */ + public void testSetSeed() { + try { + ThreadLocalRandom.current().setSeed(17); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + } + + /** + * Repeated calls to nextInt produce at least two distinct results + */ + public void testNextInt() { + int f = ThreadLocalRandom.current().nextInt(); + int i = 0; + while (i < NCALLS && ThreadLocalRandom.current().nextInt() == f) + ++i; + assertTrue(i < NCALLS); + } + + /** + * Repeated calls to nextLong produce at least two distinct results + */ + public void testNextLong() { + long f = ThreadLocalRandom.current().nextLong(); + int i = 0; + while (i < NCALLS && ThreadLocalRandom.current().nextLong() == f) + ++i; + assertTrue(i < NCALLS); + } + + /** + * Repeated calls to nextBoolean produce at least two distinct results + */ + public void testNextBoolean() { + boolean f = ThreadLocalRandom.current().nextBoolean(); + int i = 0; + while (i < NCALLS && ThreadLocalRandom.current().nextBoolean() == f) + ++i; + assertTrue(i < NCALLS); + } + + /** + * Repeated calls to nextFloat produce at least two distinct results + */ + public void testNextFloat() { + float f = ThreadLocalRandom.current().nextFloat(); + int i = 0; + while (i < NCALLS && ThreadLocalRandom.current().nextFloat() == f) + ++i; + assertTrue(i < NCALLS); + } + + /** + * Repeated calls to nextDouble produce at least two distinct results + */ + public void testNextDouble() { + double f = ThreadLocalRandom.current().nextDouble(); + int i = 0; + while (i < NCALLS && ThreadLocalRandom.current().nextDouble() == f) + ++i; + assertTrue(i < NCALLS); + } + + /** + * Repeated calls to nextGaussian produce at least two distinct results + */ + public void testNextGaussian() { + double f = ThreadLocalRandom.current().nextGaussian(); + int i = 0; + while (i < NCALLS && ThreadLocalRandom.current().nextGaussian() == f) + ++i; + assertTrue(i < NCALLS); + } + + /** + * nextInt(non-positive) throws IllegalArgumentException + */ + public void testNextIntBoundNonPositive() { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + for (int bound : new int[] { 0, -17, Integer.MIN_VALUE }) { + try { + rnd.nextInt(bound); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * nextInt(least >= bound) throws IllegalArgumentException + */ + public void testNextIntBadBounds() { + int[][] badBoundss = { + { 17, 2 }, + { -42, -42 }, + { Integer.MAX_VALUE, Integer.MIN_VALUE }, + }; + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + for (int[] badBounds : badBoundss) { + try { + rnd.nextInt(badBounds[0], badBounds[1]); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * nextInt(bound) returns 0 <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextIntBounded() { + // sample bound space across prime number increments + for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) { + int f = ThreadLocalRandom.current().nextInt(bound); + assertTrue(0 <= f && f < bound); + int i = 0; + int j; + while (i < NCALLS && + (j = ThreadLocalRandom.current().nextInt(bound)) == f) { + assertTrue(0 <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + + /** + * nextInt(least, bound) returns least <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextIntBounded2() { + for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) { + for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) { + int f = ThreadLocalRandom.current().nextInt(least, bound); + assertTrue(least <= f && f < bound); + int i = 0; + int j; + while (i < NCALLS && + (j = ThreadLocalRandom.current().nextInt(least, bound)) == f) { + assertTrue(least <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + } + + /** + * nextLong(non-positive) throws IllegalArgumentException + */ + public void testNextLongBoundNonPositive() { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + for (long bound : new long[] { 0L, -17L, Long.MIN_VALUE }) { + try { + rnd.nextLong(bound); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * nextLong(least >= bound) throws IllegalArgumentException + */ + public void testNextLongBadBounds() { + long[][] badBoundss = { + { 17L, 2L }, + { -42L, -42L }, + { Long.MAX_VALUE, Long.MIN_VALUE }, + }; + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + for (long[] badBounds : badBoundss) { + try { + rnd.nextLong(badBounds[0], badBounds[1]); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * nextLong(bound) returns 0 <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextLongBounded() { + for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) { + long f = ThreadLocalRandom.current().nextLong(bound); + assertTrue(0 <= f && f < bound); + int i = 0; + long j; + while (i < NCALLS && + (j = ThreadLocalRandom.current().nextLong(bound)) == f) { + assertTrue(0 <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + + /** + * nextLong(least, bound) returns least <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextLongBounded2() { + for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) { + for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) { + long f = ThreadLocalRandom.current().nextLong(least, bound); + assertTrue(least <= f && f < bound); + int i = 0; + long j; + while (i < NCALLS && + (j = ThreadLocalRandom.current().nextLong(least, bound)) == f) { + assertTrue(least <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + } + + /** + * nextDouble(non-positive) throws IllegalArgumentException + */ + public void testNextDoubleBoundNonPositive() { + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + double[] badBounds = { + 0.0d, + -17.0d, + -Double.MIN_VALUE, + Double.NEGATIVE_INFINITY, + Double.NaN, + }; + for (double bound : badBounds) { + try { + rnd.nextDouble(bound); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * nextDouble(least, bound) returns least <= value < bound; + * repeated calls produce at least two distinct results + */ + public void testNextDoubleBounded2() { + for (double least = 0.0001; least < 1.0e20; least *= 8) { + for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) { + double f = ThreadLocalRandom.current().nextDouble(least, bound); + assertTrue(least <= f && f < bound); + int i = 0; + double j; + while (i < NCALLS && + (j = ThreadLocalRandom.current().nextDouble(least, bound)) == f) { + assertTrue(least <= j && j < bound); + ++i; + } + assertTrue(i < NCALLS); + } + } + } + + /** + * Different threads produce different pseudo-random sequences + */ + public void testDifferentSequences() { + // Don't use main thread's ThreadLocalRandom - it is likely to + // be polluted by previous tests. + final AtomicReference threadLocalRandom = + new AtomicReference(); + final AtomicLong rand = new AtomicLong(); + + long firstRand = 0; + ThreadLocalRandom firstThreadLocalRandom = null; + + Runnable getRandomState = new CheckedRunnable() { + public void realRun() { + ThreadLocalRandom current = ThreadLocalRandom.current(); + assertSame(current, ThreadLocalRandom.current()); + // test bug: the following is not guaranteed and not true in JDK8 + // assertNotSame(current, threadLocalRandom.get()); + rand.set(current.nextLong()); + threadLocalRandom.set(current); + }}; + + Thread first = newStartedThread(getRandomState); + awaitTermination(first); + firstRand = rand.get(); + firstThreadLocalRandom = threadLocalRandom.get(); + + for (int i = 0; i < NCALLS; i++) { + Thread t = newStartedThread(getRandomState); + awaitTermination(t); + if (firstRand != rand.get()) + return; + } + fail("all threads generate the same pseudo-random sequence"); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ThreadLocalTest.java b/jdk/test/java/util/concurrent/tck/ThreadLocalTest.java new file mode 100644 index 00000000000..51d2197f4d7 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ThreadLocalTest.java @@ -0,0 +1,128 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ThreadLocalTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ThreadLocalTest.class); + } + + static ThreadLocal tl = new ThreadLocal() { + public Integer initialValue() { + return one; + } + }; + + static InheritableThreadLocal itl = + new InheritableThreadLocal() { + protected Integer initialValue() { + return zero; + } + + protected Integer childValue(Integer parentValue) { + return new Integer(parentValue.intValue() + 1); + } + }; + + /** + * remove causes next access to return initial value + */ + public void testRemove() { + assertSame(tl.get(), one); + tl.set(two); + assertSame(tl.get(), two); + tl.remove(); + assertSame(tl.get(), one); + } + + /** + * remove in InheritableThreadLocal causes next access to return + * initial value + */ + public void testRemoveITL() { + assertSame(itl.get(), zero); + itl.set(two); + assertSame(itl.get(), two); + itl.remove(); + assertSame(itl.get(), zero); + } + + private class ITLThread extends Thread { + final int[] x; + ITLThread(int[] array) { x = array; } + public void run() { + Thread child = null; + if (itl.get().intValue() < x.length - 1) { + child = new ITLThread(x); + child.start(); + } + Thread.yield(); + + int threadId = itl.get().intValue(); + for (int j = 0; j < threadId; j++) { + x[threadId]++; + Thread.yield(); + } + + if (child != null) { // Wait for child (if any) + try { + child.join(); + } catch (InterruptedException e) { + threadUnexpectedException(e); + } + } + } + } + + /** + * InheritableThreadLocal propagates generic values. + */ + public void testGenericITL() throws InterruptedException { + final int threadCount = 10; + final int[] x = new int[threadCount]; + Thread progenitor = new ITLThread(x); + progenitor.start(); + progenitor.join(); + for (int i = 0; i < threadCount; i++) { + assertEquals(i, x[i]); + } + } +} diff --git a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java new file mode 100644 index 00000000000..3959527af70 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java @@ -0,0 +1,2062 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.RunnableFuture; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ThreadPoolExecutorSubclassTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ThreadPoolExecutorSubclassTest.class); + } + + static class CustomTask implements RunnableFuture { + final Callable callable; + final ReentrantLock lock = new ReentrantLock(); + final Condition cond = lock.newCondition(); + boolean done; + boolean cancelled; + V result; + Thread thread; + Exception exception; + CustomTask(Callable c) { + if (c == null) throw new NullPointerException(); + callable = c; + } + CustomTask(final Runnable r, final V res) { + if (r == null) throw new NullPointerException(); + callable = new Callable() { + public V call() throws Exception { r.run(); return res; }}; + } + public boolean isDone() { + lock.lock(); try { return done; } finally { lock.unlock() ; } + } + public boolean isCancelled() { + lock.lock(); try { return cancelled; } finally { lock.unlock() ; } + } + public boolean cancel(boolean mayInterrupt) { + lock.lock(); + try { + if (!done) { + cancelled = true; + done = true; + if (mayInterrupt && thread != null) + thread.interrupt(); + return true; + } + return false; + } + finally { lock.unlock() ; } + } + public void run() { + lock.lock(); + try { + if (done) + return; + thread = Thread.currentThread(); + } + finally { lock.unlock() ; } + V v = null; + Exception e = null; + try { + v = callable.call(); + } + catch (Exception ex) { + e = ex; + } + lock.lock(); + try { + if (!done) { + result = v; + exception = e; + done = true; + thread = null; + cond.signalAll(); + } + } + finally { lock.unlock(); } + } + public V get() throws InterruptedException, ExecutionException { + lock.lock(); + try { + while (!done) + cond.await(); + if (cancelled) + throw new CancellationException(); + if (exception != null) + throw new ExecutionException(exception); + return result; + } + finally { lock.unlock(); } + } + public V get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + long nanos = unit.toNanos(timeout); + lock.lock(); + try { + while (!done) { + if (nanos <= 0L) + throw new TimeoutException(); + nanos = cond.awaitNanos(nanos); + } + if (cancelled) + throw new CancellationException(); + if (exception != null) + throw new ExecutionException(exception); + return result; + } + finally { lock.unlock(); } + } + } + + static class CustomTPE extends ThreadPoolExecutor { + protected RunnableFuture newTaskFor(Callable c) { + return new CustomTask(c); + } + protected RunnableFuture newTaskFor(Runnable r, V v) { + return new CustomTask(r, v); + } + + CustomTPE(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, + workQueue); + } + CustomTPE(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + threadFactory); + } + + CustomTPE(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + RejectedExecutionHandler handler) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, + handler); + } + CustomTPE(int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory, + RejectedExecutionHandler handler) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, + workQueue, threadFactory, handler); + } + + final CountDownLatch beforeCalled = new CountDownLatch(1); + final CountDownLatch afterCalled = new CountDownLatch(1); + final CountDownLatch terminatedCalled = new CountDownLatch(1); + + public CustomTPE() { + super(1, 1, LONG_DELAY_MS, MILLISECONDS, new SynchronousQueue()); + } + protected void beforeExecute(Thread t, Runnable r) { + beforeCalled.countDown(); + } + protected void afterExecute(Runnable r, Throwable t) { + afterCalled.countDown(); + } + protected void terminated() { + terminatedCalled.countDown(); + } + + public boolean beforeCalled() { + return beforeCalled.getCount() == 0; + } + public boolean afterCalled() { + return afterCalled.getCount() == 0; + } + public boolean terminatedCalled() { + return terminatedCalled.getCount() == 0; + } + } + + static class FailingThreadFactory implements ThreadFactory { + int calls = 0; + public Thread newThread(Runnable r) { + if (++calls > 1) return null; + return new Thread(r); + } + } + + /** + * execute successfully executes a runnable + */ + public void testExecute() throws InterruptedException { + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + 2 * LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch done = new CountDownLatch(1); + final Runnable task = new CheckedRunnable() { + public void realRun() { done.countDown(); }}; + p.execute(task); + assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS)); + } + } + + /** + * getActiveCount increases but doesn't overestimate, when a + * thread becomes active + */ + public void testGetActiveCount() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertEquals(0, p.getActiveCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1, p.getActiveCount()); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getActiveCount()); + } + } + + /** + * prestartCoreThread starts a thread if under corePoolSize, else doesn't + */ + public void testPrestartCoreThread() { + final ThreadPoolExecutor p = + new CustomTPE(2, 6, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(0, p.getPoolSize()); + assertTrue(p.prestartCoreThread()); + assertEquals(1, p.getPoolSize()); + assertTrue(p.prestartCoreThread()); + assertEquals(2, p.getPoolSize()); + assertFalse(p.prestartCoreThread()); + assertEquals(2, p.getPoolSize()); + p.setCorePoolSize(4); + assertTrue(p.prestartCoreThread()); + assertEquals(3, p.getPoolSize()); + assertTrue(p.prestartCoreThread()); + assertEquals(4, p.getPoolSize()); + assertFalse(p.prestartCoreThread()); + assertEquals(4, p.getPoolSize()); + } + } + + /** + * prestartAllCoreThreads starts all corePoolSize threads + */ + public void testPrestartAllCoreThreads() { + final ThreadPoolExecutor p = + new CustomTPE(2, 6, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(0, p.getPoolSize()); + p.prestartAllCoreThreads(); + assertEquals(2, p.getPoolSize()); + p.prestartAllCoreThreads(); + assertEquals(2, p.getPoolSize()); + p.setCorePoolSize(4); + p.prestartAllCoreThreads(); + assertEquals(4, p.getPoolSize()); + p.prestartAllCoreThreads(); + assertEquals(4, p.getPoolSize()); + } + } + + /** + * getCompletedTaskCount increases, but doesn't overestimate, + * when tasks complete + */ + public void testGetCompletedTaskCount() throws InterruptedException { + final ThreadPoolExecutor p = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch threadProceed = new CountDownLatch(1); + final CountDownLatch threadDone = new CountDownLatch(1); + assertEquals(0, p.getCompletedTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(0, p.getCompletedTaskCount()); + threadProceed.await(); + threadDone.countDown(); + }}); + await(threadStarted); + assertEquals(0, p.getCompletedTaskCount()); + threadProceed.countDown(); + threadDone.await(); + long startTime = System.nanoTime(); + while (p.getCompletedTaskCount() != 1) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + } + } + + /** + * getCorePoolSize returns size given in constructor if not otherwise set + */ + public void testGetCorePoolSize() { + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(1, p.getCorePoolSize()); + } + } + + /** + * getKeepAliveTime returns value given in constructor if not otherwise set + */ + public void testGetKeepAliveTime() { + final ThreadPoolExecutor p = + new CustomTPE(2, 2, + 1000, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(1, p.getKeepAliveTime(SECONDS)); + } + } + + /** + * getThreadFactory returns factory in constructor if not set + */ + public void testGetThreadFactory() { + final ThreadFactory threadFactory = new SimpleThreadFactory(); + final ThreadPoolExecutor p = + new CustomTPE(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10), + threadFactory, + new NoOpREHandler()); + try (PoolCleaner cleaner = cleaner(p)) { + assertSame(threadFactory, p.getThreadFactory()); + } + } + + /** + * setThreadFactory sets the thread factory returned by getThreadFactory + */ + public void testSetThreadFactory() { + final ThreadPoolExecutor p = + new CustomTPE(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + ThreadFactory threadFactory = new SimpleThreadFactory(); + p.setThreadFactory(threadFactory); + assertSame(threadFactory, p.getThreadFactory()); + } + } + + /** + * setThreadFactory(null) throws NPE + */ + public void testSetThreadFactoryNull() { + final ThreadPoolExecutor p = + new CustomTPE(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setThreadFactory(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * getRejectedExecutionHandler returns handler in constructor if not set + */ + public void testGetRejectedExecutionHandler() { + final RejectedExecutionHandler handler = new NoOpREHandler(); + final ThreadPoolExecutor p = + new CustomTPE(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10), + handler); + try (PoolCleaner cleaner = cleaner(p)) { + assertSame(handler, p.getRejectedExecutionHandler()); + } + } + + /** + * setRejectedExecutionHandler sets the handler returned by + * getRejectedExecutionHandler + */ + public void testSetRejectedExecutionHandler() { + final ThreadPoolExecutor p = + new CustomTPE(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + RejectedExecutionHandler handler = new NoOpREHandler(); + p.setRejectedExecutionHandler(handler); + assertSame(handler, p.getRejectedExecutionHandler()); + } + } + + /** + * setRejectedExecutionHandler(null) throws NPE + */ + public void testSetRejectedExecutionHandlerNull() { + final ThreadPoolExecutor p = + new CustomTPE(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setRejectedExecutionHandler(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * getLargestPoolSize increases, but doesn't overestimate, when + * multiple threads active + */ + public void testGetLargestPoolSize() throws InterruptedException { + final int THREADS = 3; + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new CustomTPE(THREADS, THREADS, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + assertEquals(0, p.getLargestPoolSize()); + final CountDownLatch threadsStarted = new CountDownLatch(THREADS); + for (int i = 0; i < THREADS; i++) + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.countDown(); + await(done); + assertEquals(THREADS, p.getLargestPoolSize()); + }}); + await(threadsStarted); + assertEquals(THREADS, p.getLargestPoolSize()); + } + assertEquals(THREADS, p.getLargestPoolSize()); + } + + /** + * getMaximumPoolSize returns value given in constructor if not + * otherwise set + */ + public void testGetMaximumPoolSize() { + final ThreadPoolExecutor p = + new CustomTPE(2, 3, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(3, p.getMaximumPoolSize()); + p.setMaximumPoolSize(5); + assertEquals(5, p.getMaximumPoolSize()); + p.setMaximumPoolSize(4); + assertEquals(4, p.getMaximumPoolSize()); + } + } + + /** + * getPoolSize increases, but doesn't overestimate, when threads + * become active + */ + public void testGetPoolSize() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + assertEquals(0, p.getPoolSize()); + final CountDownLatch threadStarted = new CountDownLatch(1); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1, p.getPoolSize()); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getPoolSize()); + } + } + + /** + * getTaskCount increases, but doesn't overestimate, when tasks submitted + */ + public void testGetTaskCount() throws InterruptedException { + final int TASKS = 3; + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertEquals(0, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + for (int i = 0; i < TASKS; i++) { + assertEquals(1 + i, p.getTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1 + TASKS, p.getTaskCount()); + await(done); + }}); + } + assertEquals(1 + TASKS, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + } + assertEquals(1 + TASKS, p.getTaskCount()); + assertEquals(1 + TASKS, p.getCompletedTaskCount()); + } + + /** + * isShutdown is false before shutdown, true after + */ + public void testIsShutdown() { + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertFalse(p.isShutdown()); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.isShutdown()); + } + } + + /** + * isTerminated is false before termination, true after + */ + public void testIsTerminated() throws InterruptedException { + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + assertFalse(p.isTerminating()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(p.isTerminating()); + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertFalse(p.isTerminating()); + done.countDown(); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertFalse(p.isTerminating()); + } + } + + /** + * isTerminating is not true when running or when terminated + */ + public void testIsTerminating() throws InterruptedException { + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + assertFalse(p.isTerminating()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(p.isTerminating()); + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertFalse(p.isTerminating()); + done.countDown(); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertFalse(p.isTerminating()); + } + } + + /** + * getQueue returns the work queue, which contains queued tasks + */ + public void testGetQueue() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final BlockingQueue q = new ArrayBlockingQueue(10); + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + q); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + FutureTask[] tasks = new FutureTask[5]; + for (int i = 0; i < tasks.length; i++) { + Callable task = new CheckedCallable() { + public Boolean realCall() throws InterruptedException { + threadStarted.countDown(); + assertSame(q, p.getQueue()); + await(done); + return Boolean.TRUE; + }}; + tasks[i] = new FutureTask(task); + p.execute(tasks[i]); + } + await(threadStarted); + assertSame(q, p.getQueue()); + assertFalse(q.contains(tasks[0])); + assertTrue(q.contains(tasks[tasks.length - 1])); + assertEquals(tasks.length - 1, q.size()); + } + } + + /** + * remove(task) removes queued task, and fails to remove active task + */ + public void testRemove() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + BlockingQueue q = new ArrayBlockingQueue(10); + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + q); + try (PoolCleaner cleaner = cleaner(p, done)) { + Runnable[] tasks = new Runnable[6]; + final CountDownLatch threadStarted = new CountDownLatch(1); + for (int i = 0; i < tasks.length; i++) { + tasks[i] = new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}; + p.execute(tasks[i]); + } + await(threadStarted); + assertFalse(p.remove(tasks[0])); + assertTrue(q.contains(tasks[4])); + assertTrue(q.contains(tasks[3])); + assertTrue(p.remove(tasks[4])); + assertFalse(p.remove(tasks[4])); + assertFalse(q.contains(tasks[4])); + assertTrue(q.contains(tasks[3])); + assertTrue(p.remove(tasks[3])); + assertFalse(q.contains(tasks[3])); + } + } + + /** + * purge removes cancelled tasks from the queue + */ + public void testPurge() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + final BlockingQueue q = new ArrayBlockingQueue(10); + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + q); + try (PoolCleaner cleaner = cleaner(p, done)) { + FutureTask[] tasks = new FutureTask[5]; + for (int i = 0; i < tasks.length; i++) { + Callable task = new CheckedCallable() { + public Boolean realCall() throws InterruptedException { + threadStarted.countDown(); + await(done); + return Boolean.TRUE; + }}; + tasks[i] = new FutureTask(task); + p.execute(tasks[i]); + } + await(threadStarted); + assertEquals(tasks.length, p.getTaskCount()); + assertEquals(tasks.length - 1, q.size()); + assertEquals(1L, p.getActiveCount()); + assertEquals(0L, p.getCompletedTaskCount()); + tasks[4].cancel(true); + tasks[3].cancel(false); + p.purge(); + assertEquals(tasks.length - 3, q.size()); + assertEquals(tasks.length - 2, p.getTaskCount()); + p.purge(); // Nothing to do + assertEquals(tasks.length - 3, q.size()); + assertEquals(tasks.length - 2, p.getTaskCount()); + } + } + + /** + * shutdownNow returns a list containing tasks that were not run, + * and those tasks are drained from the queue + */ + public void testShutdownNow() throws InterruptedException { + final int poolSize = 2; + final int count = 5; + final AtomicInteger ran = new AtomicInteger(0); + final ThreadPoolExecutor p = + new CustomTPE(poolSize, poolSize, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + final CountDownLatch threadsStarted = new CountDownLatch(poolSize); + Runnable waiter = new CheckedRunnable() { public void realRun() { + threadsStarted.countDown(); + try { + MILLISECONDS.sleep(2 * LONG_DELAY_MS); + } catch (InterruptedException success) {} + ran.getAndIncrement(); + }}; + for (int i = 0; i < count; i++) + p.execute(waiter); + await(threadsStarted); + assertEquals(poolSize, p.getActiveCount()); + assertEquals(0, p.getCompletedTaskCount()); + final List queuedTasks; + try { + queuedTasks = p.shutdownNow(); + } catch (SecurityException ok) { + return; // Allowed in case test doesn't have privs + } + assertTrue(p.isShutdown()); + assertTrue(p.getQueue().isEmpty()); + assertEquals(count - poolSize, queuedTasks.size()); + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertEquals(poolSize, ran.get()); + assertEquals(poolSize, p.getCompletedTaskCount()); + } + + // Exception Tests + + /** + * Constructor throws if corePoolSize argument is less than zero + */ + public void testConstructor1() { + try { + new CustomTPE(-1, 1, 1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is less than zero + */ + public void testConstructor2() { + try { + new CustomTPE(1, -1, 1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is equal to zero + */ + public void testConstructor3() { + try { + new CustomTPE(1, 0, 1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if keepAliveTime is less than zero + */ + public void testConstructor4() { + try { + new CustomTPE(1, 2, -1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if corePoolSize is greater than the maximumPoolSize + */ + public void testConstructor5() { + try { + new CustomTPE(2, 1, 1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if workQueue is set to null + */ + public void testConstructorNullPointerException() { + try { + new CustomTPE(1, 2, 1L, SECONDS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if corePoolSize argument is less than zero + */ + public void testConstructor6() { + try { + new CustomTPE(-1, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is less than zero + */ + public void testConstructor7() { + try { + new CustomTPE(1,-1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is equal to zero + */ + public void testConstructor8() { + try { + new CustomTPE(1, 0, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if keepAliveTime is less than zero + */ + public void testConstructor9() { + try { + new CustomTPE(1, 2, -1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if corePoolSize is greater than the maximumPoolSize + */ + public void testConstructor10() { + try { + new CustomTPE(2, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if workQueue is set to null + */ + public void testConstructorNullPointerException2() { + try { + new CustomTPE(1, 2, 1L, SECONDS, null, new SimpleThreadFactory()); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if threadFactory is set to null + */ + public void testConstructorNullPointerException3() { + try { + new CustomTPE(1, 2, 1L, SECONDS, + new ArrayBlockingQueue(10), + (ThreadFactory) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if corePoolSize argument is less than zero + */ + public void testConstructor11() { + try { + new CustomTPE(-1, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is less than zero + */ + public void testConstructor12() { + try { + new CustomTPE(1, -1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is equal to zero + */ + public void testConstructor13() { + try { + new CustomTPE(1, 0, 1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if keepAliveTime is less than zero + */ + public void testConstructor14() { + try { + new CustomTPE(1, 2, -1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if corePoolSize is greater than the maximumPoolSize + */ + public void testConstructor15() { + try { + new CustomTPE(2, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if workQueue is set to null + */ + public void testConstructorNullPointerException4() { + try { + new CustomTPE(1, 2, 1L, SECONDS, + null, + new NoOpREHandler()); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if handler is set to null + */ + public void testConstructorNullPointerException5() { + try { + new CustomTPE(1, 2, 1L, SECONDS, + new ArrayBlockingQueue(10), + (RejectedExecutionHandler) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if corePoolSize argument is less than zero + */ + public void testConstructor16() { + try { + new CustomTPE(-1, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is less than zero + */ + public void testConstructor17() { + try { + new CustomTPE(1, -1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is equal to zero + */ + public void testConstructor18() { + try { + new CustomTPE(1, 0, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if keepAliveTime is less than zero + */ + public void testConstructor19() { + try { + new CustomTPE(1, 2, -1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if corePoolSize is greater than the maximumPoolSize + */ + public void testConstructor20() { + try { + new CustomTPE(2, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if workQueue is null + */ + public void testConstructorNullPointerException6() { + try { + new CustomTPE(1, 2, 1L, SECONDS, + null, + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if handler is null + */ + public void testConstructorNullPointerException7() { + try { + new CustomTPE(1, 2, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + (RejectedExecutionHandler) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if ThreadFactory is null + */ + public void testConstructorNullPointerException8() { + try { + new CustomTPE(1, 2, 1L, SECONDS, + new ArrayBlockingQueue(10), + (ThreadFactory) null, + new NoOpREHandler()); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * execute throws RejectedExecutionException if saturated. + */ + public void testSaturatedExecute() { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1)); + try (PoolCleaner cleaner = cleaner(p, done)) { + Runnable task = new CheckedRunnable() { + public void realRun() throws InterruptedException { + await(done); + }}; + for (int i = 0; i < 2; ++i) + p.execute(task); + for (int i = 0; i < 2; ++i) { + try { + p.execute(task); + shouldThrow(); + } catch (RejectedExecutionException success) {} + assertTrue(p.getTaskCount() <= 2); + } + } + } + + /** + * executor using CallerRunsPolicy runs task if saturated. + */ + public void testSaturatedExecute2() { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new CustomTPE.CallerRunsPolicy()); + try (PoolCleaner cleaner = cleaner(p, done)) { + Runnable blocker = new CheckedRunnable() { + public void realRun() throws InterruptedException { + await(done); + }}; + p.execute(blocker); + TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5]; + for (int i = 0; i < tasks.length; i++) + tasks[i] = new TrackedNoOpRunnable(); + for (int i = 0; i < tasks.length; i++) + p.execute(tasks[i]); + for (int i = 1; i < tasks.length; i++) + assertTrue(tasks[i].done); + assertFalse(tasks[0].done); // waiting in queue + } + } + + /** + * executor using DiscardPolicy drops task if saturated. + */ + public void testSaturatedExecute3() { + final TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5]; + for (int i = 0; i < tasks.length; ++i) + tasks[i] = new TrackedNoOpRunnable(); + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new CustomTPE.DiscardPolicy()); + try (PoolCleaner cleaner = cleaner(p, done)) { + p.execute(awaiter(done)); + + for (TrackedNoOpRunnable task : tasks) + p.execute(task); + for (int i = 1; i < tasks.length; i++) + assertFalse(tasks[i].done); + } + for (int i = 1; i < tasks.length; i++) + assertFalse(tasks[i].done); + assertTrue(tasks[0].done); // was waiting in queue + } + + /** + * executor using DiscardOldestPolicy drops oldest task if saturated. + */ + public void testSaturatedExecute4() { + final CountDownLatch done = new CountDownLatch(1); + LatchAwaiter r1 = awaiter(done); + LatchAwaiter r2 = awaiter(done); + LatchAwaiter r3 = awaiter(done); + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new CustomTPE.DiscardOldestPolicy()); + try (PoolCleaner cleaner = cleaner(p, done)) { + assertEquals(LatchAwaiter.NEW, r1.state); + assertEquals(LatchAwaiter.NEW, r2.state); + assertEquals(LatchAwaiter.NEW, r3.state); + p.execute(r1); + p.execute(r2); + assertTrue(p.getQueue().contains(r2)); + p.execute(r3); + assertFalse(p.getQueue().contains(r2)); + assertTrue(p.getQueue().contains(r3)); + } + assertEquals(LatchAwaiter.DONE, r1.state); + assertEquals(LatchAwaiter.NEW, r2.state); + assertEquals(LatchAwaiter.DONE, r3.state); + } + + /** + * execute throws RejectedExecutionException if shutdown + */ + public void testRejectedExecutionExceptionOnShutdown() { + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1)); + try { p.shutdown(); } catch (SecurityException ok) { return; } + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.execute(new NoOpRunnable()); + shouldThrow(); + } catch (RejectedExecutionException success) {} + } + } + + /** + * execute using CallerRunsPolicy drops task on shutdown + */ + public void testCallerRunsOnShutdown() { + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new CustomTPE.CallerRunsPolicy()); + try { p.shutdown(); } catch (SecurityException ok) { return; } + try (PoolCleaner cleaner = cleaner(p)) { + TrackedNoOpRunnable r = new TrackedNoOpRunnable(); + p.execute(r); + assertFalse(r.done); + } + } + + /** + * execute using DiscardPolicy drops task on shutdown + */ + public void testDiscardOnShutdown() { + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new CustomTPE.DiscardPolicy()); + try { p.shutdown(); } catch (SecurityException ok) { return; } + try (PoolCleaner cleaner = cleaner(p)) { + TrackedNoOpRunnable r = new TrackedNoOpRunnable(); + p.execute(r); + assertFalse(r.done); + } + } + + /** + * execute using DiscardOldestPolicy drops task on shutdown + */ + public void testDiscardOldestOnShutdown() { + final ThreadPoolExecutor p = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new CustomTPE.DiscardOldestPolicy()); + + try { p.shutdown(); } catch (SecurityException ok) { return; } + try (PoolCleaner cleaner = cleaner(p)) { + TrackedNoOpRunnable r = new TrackedNoOpRunnable(); + p.execute(r); + assertFalse(r.done); + } + } + + /** + * execute(null) throws NPE + */ + public void testExecuteNull() { + final ThreadPoolExecutor p = + new CustomTPE(1, 2, + 1L, SECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.execute(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * setCorePoolSize of negative value throws IllegalArgumentException + */ + public void testCorePoolSizeIllegalArgumentException() { + final ThreadPoolExecutor p = + new CustomTPE(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setCorePoolSize(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * setMaximumPoolSize(int) throws IllegalArgumentException + * if given a value less the core pool size + */ + public void testMaximumPoolSizeIllegalArgumentException() { + final ThreadPoolExecutor p = + new CustomTPE(2, 3, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setMaximumPoolSize(1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * setMaximumPoolSize throws IllegalArgumentException + * if given a negative value + */ + public void testMaximumPoolSizeIllegalArgumentException2() { + final ThreadPoolExecutor p = + new CustomTPE(2, 3, + LONG_DELAY_MS, + MILLISECONDS,new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setMaximumPoolSize(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * setKeepAliveTime throws IllegalArgumentException + * when given a negative value + */ + public void testKeepAliveTimeIllegalArgumentException() { + final ThreadPoolExecutor p = + new CustomTPE(2, 3, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setKeepAliveTime(-1, MILLISECONDS); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * terminated() is called on termination + */ + public void testTerminated() { + CustomTPE p = new CustomTPE(); + try (PoolCleaner cleaner = cleaner(p)) { + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.terminatedCalled()); + assertTrue(p.isShutdown()); + } + } + + /** + * beforeExecute and afterExecute are called when executing task + */ + public void testBeforeAfter() throws InterruptedException { + CustomTPE p = new CustomTPE(); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch done = new CountDownLatch(1); + p.execute(new CheckedRunnable() { + public void realRun() { + done.countDown(); + }}); + await(p.afterCalled); + assertEquals(0, done.getCount()); + assertTrue(p.afterCalled()); + assertTrue(p.beforeCalled()); + } + } + + /** + * completed submit of callable returns result + */ + public void testSubmitCallable() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new StringTask()); + String result = future.get(); + assertSame(TEST_STRING, result); + } + } + + /** + * completed submit of runnable returns successfully + */ + public void testSubmitRunnable() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable()); + future.get(); + assertTrue(future.isDone()); + } + } + + /** + * completed submit of (runnable, result) returns result + */ + public void testSubmitRunnable2() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable(), TEST_STRING); + String result = future.get(); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAny(null) throws NPE + */ + public void testInvokeAny1() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAny(empty collection) throws IAE + */ + public void testInvokeAny2() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * invokeAny(c) throws NPE if c has null elements + */ + public void testInvokeAny3() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * invokeAny(c) throws ExecutionException if no task completes + */ + public void testInvokeAny4() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAny(c) returns result of some task + */ + public void testInvokeAny5() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAll(null) throws NPE + */ + public void testInvokeAll1() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAll(empty collection) returns empty collection + */ + public void testInvokeAll2() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>()); + assertTrue(r.isEmpty()); + } + } + + /** + * invokeAll(c) throws NPE if c has null elements + */ + public void testInvokeAll3() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of element of invokeAll(c) throws exception on failed task + */ + public void testInvokeAll4() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = e.invokeAll(l); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAll(c) returns results of all completed tasks + */ + public void testInvokeAll5() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = e.invokeAll(l); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAny(null) throws NPE + */ + public void testTimedInvokeAny1() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(,,null) throws NPE + */ + public void testTimedInvokeAnyNullTimeUnit() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(empty collection) throws IAE + */ + public void testTimedInvokeAny2() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * timed invokeAny(c) throws NPE if c has null elements + */ + public void testTimedInvokeAny3() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * timed invokeAny(c) throws ExecutionException if no task completes + */ + public void testTimedInvokeAny4() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAny(c) returns result of some task + */ + public void testTimedInvokeAny5() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + assertSame(TEST_STRING, result); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAll(null) throws NPE + */ + public void testTimedInvokeAll1() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(,,null) throws NPE + */ + public void testTimedInvokeAllNullTimeUnit() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(empty collection) returns empty collection + */ + public void testTimedInvokeAll2() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>(), + MEDIUM_DELAY_MS, MILLISECONDS); + assertTrue(r.isEmpty()); + } + } + + /** + * timed invokeAll(c) throws NPE if c has null elements + */ + public void testTimedInvokeAll3() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of element of invokeAll(c) throws exception on failed task + */ + public void testTimedInvokeAll4() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = + e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * timed invokeAll(c) returns results of all completed tasks + */ + public void testTimedInvokeAll5() throws Exception { + final ExecutorService e = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = + e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAll(c) cancels tasks not completed by timeout + */ + public void testTimedInvokeAll6() throws Exception { + for (long timeout = timeoutMillis();;) { + final CountDownLatch done = new CountDownLatch(1); + final Callable waiter = new CheckedCallable() { + public String realCall() { + try { done.await(LONG_DELAY_MS, MILLISECONDS); } + catch (InterruptedException ok) {} + return "1"; }}; + final ExecutorService p = + new CustomTPE(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + List> tasks = new ArrayList<>(); + tasks.add(new StringTask("0")); + tasks.add(waiter); + tasks.add(new StringTask("2")); + long startTime = System.nanoTime(); + List> futures = + p.invokeAll(tasks, timeout, MILLISECONDS); + assertEquals(tasks.size(), futures.size()); + assertTrue(millisElapsedSince(startTime) >= timeout); + for (Future future : futures) + assertTrue(future.isDone()); + assertTrue(futures.get(1).isCancelled()); + try { + assertEquals("0", futures.get(0).get()); + assertEquals("2", futures.get(2).get()); + break; + } catch (CancellationException retryWithLongerTimeout) { + timeout *= 2; + if (timeout >= LONG_DELAY_MS / 2) + fail("expected exactly one task to be cancelled"); + } + } + } + } + + /** + * Execution continues if there is at least one thread even if + * thread factory fails to create more + */ + public void testFailingThreadFactory() throws InterruptedException { + final ExecutorService e = + new CustomTPE(100, 100, + LONG_DELAY_MS, MILLISECONDS, + new LinkedBlockingQueue(), + new FailingThreadFactory()); + try (PoolCleaner cleaner = cleaner(e)) { + final int TASKS = 100; + final CountDownLatch done = new CountDownLatch(TASKS); + for (int k = 0; k < TASKS; ++k) + e.execute(new CheckedRunnable() { + public void realRun() { + done.countDown(); + }}); + assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS)); + } + } + + /** + * allowsCoreThreadTimeOut is by default false. + */ + public void testAllowsCoreThreadTimeOut() { + final ThreadPoolExecutor p = + new CustomTPE(2, 2, + 1000, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertFalse(p.allowsCoreThreadTimeOut()); + } + } + + /** + * allowCoreThreadTimeOut(true) causes idle threads to time out + */ + public void testAllowCoreThreadTimeOut_true() throws Exception { + long keepAliveTime = timeoutMillis(); + final ThreadPoolExecutor p = + new CustomTPE(2, 10, + keepAliveTime, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + p.allowCoreThreadTimeOut(true); + p.execute(new CheckedRunnable() { + public void realRun() { + threadStarted.countDown(); + assertEquals(1, p.getPoolSize()); + }}); + await(threadStarted); + delay(keepAliveTime); + long startTime = System.nanoTime(); + while (p.getPoolSize() > 0 + && millisElapsedSince(startTime) < LONG_DELAY_MS) + Thread.yield(); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + assertEquals(0, p.getPoolSize()); + } + } + + /** + * allowCoreThreadTimeOut(false) causes idle threads not to time out + */ + public void testAllowCoreThreadTimeOut_false() throws Exception { + long keepAliveTime = timeoutMillis(); + final ThreadPoolExecutor p = + new CustomTPE(2, 10, + keepAliveTime, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + p.allowCoreThreadTimeOut(false); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertTrue(p.getPoolSize() >= 1); + }}); + delay(2 * keepAliveTime); + assertTrue(p.getPoolSize() >= 1); + } + } + + /** + * get(cancelled task) throws CancellationException + * (in part, a test of CustomTPE itself) + */ + public void testGet_cancelled() throws Exception { + final CountDownLatch done = new CountDownLatch(1); + final ExecutorService e = + new CustomTPE(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new LinkedBlockingQueue()); + try (PoolCleaner cleaner = cleaner(e, done)) { + final CountDownLatch blockerStarted = new CountDownLatch(1); + final List> futures = new ArrayList<>(); + for (int i = 0; i < 2; i++) { + Runnable r = new CheckedRunnable() { public void realRun() + throws Throwable { + blockerStarted.countDown(); + assertTrue(done.await(2 * LONG_DELAY_MS, MILLISECONDS)); + }}; + futures.add(e.submit(r)); + } + await(blockerStarted); + for (Future future : futures) future.cancel(false); + for (Future future : futures) { + try { + future.get(); + shouldThrow(); + } catch (CancellationException success) {} + try { + future.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (CancellationException success) {} + assertTrue(future.isCancelled()); + assertTrue(future.isDone()); + } + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java new file mode 100644 index 00000000000..5df3c94b120 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java @@ -0,0 +1,2093 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ThreadPoolExecutorTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(ThreadPoolExecutorTest.class); + } + + static class ExtendedTPE extends ThreadPoolExecutor { + final CountDownLatch beforeCalled = new CountDownLatch(1); + final CountDownLatch afterCalled = new CountDownLatch(1); + final CountDownLatch terminatedCalled = new CountDownLatch(1); + + public ExtendedTPE() { + super(1, 1, LONG_DELAY_MS, MILLISECONDS, new SynchronousQueue()); + } + protected void beforeExecute(Thread t, Runnable r) { + beforeCalled.countDown(); + } + protected void afterExecute(Runnable r, Throwable t) { + afterCalled.countDown(); + } + protected void terminated() { + terminatedCalled.countDown(); + } + + public boolean beforeCalled() { + return beforeCalled.getCount() == 0; + } + public boolean afterCalled() { + return afterCalled.getCount() == 0; + } + public boolean terminatedCalled() { + return terminatedCalled.getCount() == 0; + } + } + + static class FailingThreadFactory implements ThreadFactory { + int calls = 0; + public Thread newThread(Runnable r) { + if (++calls > 1) return null; + return new Thread(r); + } + } + + /** + * execute successfully executes a runnable + */ + public void testExecute() throws InterruptedException { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch done = new CountDownLatch(1); + final Runnable task = new CheckedRunnable() { + public void realRun() { done.countDown(); }}; + p.execute(task); + assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS)); + } + } + + /** + * getActiveCount increases but doesn't overestimate, when a + * thread becomes active + */ + public void testGetActiveCount() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertEquals(0, p.getActiveCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1, p.getActiveCount()); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getActiveCount()); + } + } + + /** + * prestartCoreThread starts a thread if under corePoolSize, else doesn't + */ + public void testPrestartCoreThread() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 6, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(0, p.getPoolSize()); + assertTrue(p.prestartCoreThread()); + assertEquals(1, p.getPoolSize()); + assertTrue(p.prestartCoreThread()); + assertEquals(2, p.getPoolSize()); + assertFalse(p.prestartCoreThread()); + assertEquals(2, p.getPoolSize()); + p.setCorePoolSize(4); + assertTrue(p.prestartCoreThread()); + assertEquals(3, p.getPoolSize()); + assertTrue(p.prestartCoreThread()); + assertEquals(4, p.getPoolSize()); + assertFalse(p.prestartCoreThread()); + assertEquals(4, p.getPoolSize()); + } + } + + /** + * prestartAllCoreThreads starts all corePoolSize threads + */ + public void testPrestartAllCoreThreads() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 6, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(0, p.getPoolSize()); + p.prestartAllCoreThreads(); + assertEquals(2, p.getPoolSize()); + p.prestartAllCoreThreads(); + assertEquals(2, p.getPoolSize()); + p.setCorePoolSize(4); + p.prestartAllCoreThreads(); + assertEquals(4, p.getPoolSize()); + p.prestartAllCoreThreads(); + assertEquals(4, p.getPoolSize()); + } + } + + /** + * getCompletedTaskCount increases, but doesn't overestimate, + * when tasks complete + */ + public void testGetCompletedTaskCount() throws InterruptedException { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch threadProceed = new CountDownLatch(1); + final CountDownLatch threadDone = new CountDownLatch(1); + assertEquals(0, p.getCompletedTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(0, p.getCompletedTaskCount()); + threadProceed.await(); + threadDone.countDown(); + }}); + await(threadStarted); + assertEquals(0, p.getCompletedTaskCount()); + threadProceed.countDown(); + threadDone.await(); + long startTime = System.nanoTime(); + while (p.getCompletedTaskCount() != 1) { + if (millisElapsedSince(startTime) > LONG_DELAY_MS) + fail("timed out"); + Thread.yield(); + } + } + } + + /** + * getCorePoolSize returns size given in constructor if not otherwise set + */ + public void testGetCorePoolSize() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(1, p.getCorePoolSize()); + } + } + + /** + * getKeepAliveTime returns value given in constructor if not otherwise set + */ + public void testGetKeepAliveTime() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 2, + 1000, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(1, p.getKeepAliveTime(SECONDS)); + } + } + + /** + * getThreadFactory returns factory in constructor if not set + */ + public void testGetThreadFactory() { + ThreadFactory threadFactory = new SimpleThreadFactory(); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10), + threadFactory, + new NoOpREHandler()); + try (PoolCleaner cleaner = cleaner(p)) { + assertSame(threadFactory, p.getThreadFactory()); + } + } + + /** + * setThreadFactory sets the thread factory returned by getThreadFactory + */ + public void testSetThreadFactory() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + ThreadFactory threadFactory = new SimpleThreadFactory(); + p.setThreadFactory(threadFactory); + assertSame(threadFactory, p.getThreadFactory()); + } + } + + /** + * setThreadFactory(null) throws NPE + */ + public void testSetThreadFactoryNull() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setThreadFactory(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * getRejectedExecutionHandler returns handler in constructor if not set + */ + public void testGetRejectedExecutionHandler() { + final RejectedExecutionHandler handler = new NoOpREHandler(); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10), + handler); + try (PoolCleaner cleaner = cleaner(p)) { + assertSame(handler, p.getRejectedExecutionHandler()); + } + } + + /** + * setRejectedExecutionHandler sets the handler returned by + * getRejectedExecutionHandler + */ + public void testSetRejectedExecutionHandler() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + RejectedExecutionHandler handler = new NoOpREHandler(); + p.setRejectedExecutionHandler(handler); + assertSame(handler, p.getRejectedExecutionHandler()); + } + } + + /** + * setRejectedExecutionHandler(null) throws NPE + */ + public void testSetRejectedExecutionHandlerNull() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setRejectedExecutionHandler(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * getLargestPoolSize increases, but doesn't overestimate, when + * multiple threads active + */ + public void testGetLargestPoolSize() throws InterruptedException { + final int THREADS = 3; + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(THREADS, THREADS, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + assertEquals(0, p.getLargestPoolSize()); + final CountDownLatch threadsStarted = new CountDownLatch(THREADS); + for (int i = 0; i < THREADS; i++) + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadsStarted.countDown(); + await(done); + assertEquals(THREADS, p.getLargestPoolSize()); + }}); + await(threadsStarted); + assertEquals(THREADS, p.getLargestPoolSize()); + } + assertEquals(THREADS, p.getLargestPoolSize()); + } + + /** + * getMaximumPoolSize returns value given in constructor if not + * otherwise set + */ + public void testGetMaximumPoolSize() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 3, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertEquals(3, p.getMaximumPoolSize()); + p.setMaximumPoolSize(5); + assertEquals(5, p.getMaximumPoolSize()); + p.setMaximumPoolSize(4); + assertEquals(4, p.getMaximumPoolSize()); + } + } + + /** + * getPoolSize increases, but doesn't overestimate, when threads + * become active + */ + public void testGetPoolSize() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + assertEquals(0, p.getPoolSize()); + final CountDownLatch threadStarted = new CountDownLatch(1); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1, p.getPoolSize()); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getPoolSize()); + } + } + + /** + * getTaskCount increases, but doesn't overestimate, when tasks submitted + */ + public void testGetTaskCount() throws InterruptedException { + final int TASKS = 3; + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + assertEquals(0, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertEquals(1, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + for (int i = 0; i < TASKS; i++) { + assertEquals(1 + i, p.getTaskCount()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertEquals(1 + TASKS, p.getTaskCount()); + await(done); + }}); + } + assertEquals(1 + TASKS, p.getTaskCount()); + assertEquals(0, p.getCompletedTaskCount()); + } + assertEquals(1 + TASKS, p.getTaskCount()); + assertEquals(1 + TASKS, p.getCompletedTaskCount()); + } + + /** + * isShutdown is false before shutdown, true after + */ + public void testIsShutdown() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertFalse(p.isShutdown()); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.isShutdown()); + } + } + + /** + * awaitTermination on a non-shutdown pool times out + */ + public void testAwaitTermination_timesOut() throws InterruptedException { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertFalse(p.isTerminated()); + assertFalse(p.awaitTermination(Long.MIN_VALUE, NANOSECONDS)); + assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS)); + assertFalse(p.awaitTermination(-1L, NANOSECONDS)); + assertFalse(p.awaitTermination(-1L, MILLISECONDS)); + assertFalse(p.awaitTermination(0L, NANOSECONDS)); + assertFalse(p.awaitTermination(0L, MILLISECONDS)); + long timeoutNanos = 999999L; + long startTime = System.nanoTime(); + assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS)); + assertTrue(System.nanoTime() - startTime >= timeoutNanos); + assertFalse(p.isTerminated()); + startTime = System.nanoTime(); + long timeoutMillis = timeoutMillis(); + assertFalse(p.awaitTermination(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); + assertFalse(p.isTerminated()); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + } + } + + /** + * isTerminated is false before termination, true after + */ + public void testIsTerminated() throws InterruptedException { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + assertFalse(p.isTerminating()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(p.isTerminating()); + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertFalse(p.isTerminating()); + done.countDown(); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertFalse(p.isTerminating()); + } + } + + /** + * isTerminating is not true when running or when terminated + */ + public void testIsTerminating() throws InterruptedException { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + assertFalse(p.isTerminating()); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertFalse(p.isTerminating()); + threadStarted.countDown(); + await(done); + }}); + await(threadStarted); + assertFalse(p.isTerminating()); + done.countDown(); + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertFalse(p.isTerminating()); + } + } + + /** + * getQueue returns the work queue, which contains queued tasks + */ + public void testGetQueue() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final BlockingQueue q = new ArrayBlockingQueue(10); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + q); + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + FutureTask[] tasks = new FutureTask[5]; + for (int i = 0; i < tasks.length; i++) { + Callable task = new CheckedCallable() { + public Boolean realCall() throws InterruptedException { + threadStarted.countDown(); + assertSame(q, p.getQueue()); + await(done); + return Boolean.TRUE; + }}; + tasks[i] = new FutureTask(task); + p.execute(tasks[i]); + } + await(threadStarted); + assertSame(q, p.getQueue()); + assertFalse(q.contains(tasks[0])); + assertTrue(q.contains(tasks[tasks.length - 1])); + assertEquals(tasks.length - 1, q.size()); + } + } + + /** + * remove(task) removes queued task, and fails to remove active task + */ + public void testRemove() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + BlockingQueue q = new ArrayBlockingQueue(10); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + q); + try (PoolCleaner cleaner = cleaner(p, done)) { + Runnable[] tasks = new Runnable[6]; + final CountDownLatch threadStarted = new CountDownLatch(1); + for (int i = 0; i < tasks.length; i++) { + tasks[i] = new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + await(done); + }}; + p.execute(tasks[i]); + } + await(threadStarted); + assertFalse(p.remove(tasks[0])); + assertTrue(q.contains(tasks[4])); + assertTrue(q.contains(tasks[3])); + assertTrue(p.remove(tasks[4])); + assertFalse(p.remove(tasks[4])); + assertFalse(q.contains(tasks[4])); + assertTrue(q.contains(tasks[3])); + assertTrue(p.remove(tasks[3])); + assertFalse(q.contains(tasks[3])); + } + } + + /** + * purge removes cancelled tasks from the queue + */ + public void testPurge() throws InterruptedException { + final CountDownLatch threadStarted = new CountDownLatch(1); + final CountDownLatch done = new CountDownLatch(1); + final BlockingQueue q = new ArrayBlockingQueue(10); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + q); + try (PoolCleaner cleaner = cleaner(p, done)) { + FutureTask[] tasks = new FutureTask[5]; + for (int i = 0; i < tasks.length; i++) { + Callable task = new CheckedCallable() { + public Boolean realCall() throws InterruptedException { + threadStarted.countDown(); + await(done); + return Boolean.TRUE; + }}; + tasks[i] = new FutureTask(task); + p.execute(tasks[i]); + } + await(threadStarted); + assertEquals(tasks.length, p.getTaskCount()); + assertEquals(tasks.length - 1, q.size()); + assertEquals(1L, p.getActiveCount()); + assertEquals(0L, p.getCompletedTaskCount()); + tasks[4].cancel(true); + tasks[3].cancel(false); + p.purge(); + assertEquals(tasks.length - 3, q.size()); + assertEquals(tasks.length - 2, p.getTaskCount()); + p.purge(); // Nothing to do + assertEquals(tasks.length - 3, q.size()); + assertEquals(tasks.length - 2, p.getTaskCount()); + } + } + + /** + * shutdownNow returns a list containing tasks that were not run, + * and those tasks are drained from the queue + */ + public void testShutdownNow() throws InterruptedException { + final int poolSize = 2; + final int count = 5; + final AtomicInteger ran = new AtomicInteger(0); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(poolSize, poolSize, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + final CountDownLatch threadsStarted = new CountDownLatch(poolSize); + Runnable waiter = new CheckedRunnable() { public void realRun() { + threadsStarted.countDown(); + try { + MILLISECONDS.sleep(2 * LONG_DELAY_MS); + } catch (InterruptedException success) {} + ran.getAndIncrement(); + }}; + for (int i = 0; i < count; i++) + p.execute(waiter); + await(threadsStarted); + assertEquals(poolSize, p.getActiveCount()); + assertEquals(0, p.getCompletedTaskCount()); + final List queuedTasks; + try { + queuedTasks = p.shutdownNow(); + } catch (SecurityException ok) { + return; // Allowed in case test doesn't have privs + } + assertTrue(p.isShutdown()); + assertTrue(p.getQueue().isEmpty()); + assertEquals(count - poolSize, queuedTasks.size()); + assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); + assertTrue(p.isTerminated()); + assertEquals(poolSize, ran.get()); + assertEquals(poolSize, p.getCompletedTaskCount()); + } + + // Exception Tests + + /** + * Constructor throws if corePoolSize argument is less than zero + */ + public void testConstructor1() { + try { + new ThreadPoolExecutor(-1, 1, 1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is less than zero + */ + public void testConstructor2() { + try { + new ThreadPoolExecutor(1, -1, 1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is equal to zero + */ + public void testConstructor3() { + try { + new ThreadPoolExecutor(1, 0, 1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if keepAliveTime is less than zero + */ + public void testConstructor4() { + try { + new ThreadPoolExecutor(1, 2, -1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if corePoolSize is greater than the maximumPoolSize + */ + public void testConstructor5() { + try { + new ThreadPoolExecutor(2, 1, 1L, SECONDS, + new ArrayBlockingQueue(10)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if workQueue is set to null + */ + public void testConstructorNullPointerException() { + try { + new ThreadPoolExecutor(1, 2, 1L, SECONDS, + (BlockingQueue) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if corePoolSize argument is less than zero + */ + public void testConstructor6() { + try { + new ThreadPoolExecutor(-1, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is less than zero + */ + public void testConstructor7() { + try { + new ThreadPoolExecutor(1, -1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is equal to zero + */ + public void testConstructor8() { + try { + new ThreadPoolExecutor(1, 0, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if keepAliveTime is less than zero + */ + public void testConstructor9() { + try { + new ThreadPoolExecutor(1, 2, -1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if corePoolSize is greater than the maximumPoolSize + */ + public void testConstructor10() { + try { + new ThreadPoolExecutor(2, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if workQueue is set to null + */ + public void testConstructorNullPointerException2() { + try { + new ThreadPoolExecutor(1, 2, 1L, SECONDS, + (BlockingQueue) null, + new SimpleThreadFactory()); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if threadFactory is set to null + */ + public void testConstructorNullPointerException3() { + try { + new ThreadPoolExecutor(1, 2, 1L, SECONDS, + new ArrayBlockingQueue(10), + (ThreadFactory) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if corePoolSize argument is less than zero + */ + public void testConstructor11() { + try { + new ThreadPoolExecutor(-1, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is less than zero + */ + public void testConstructor12() { + try { + new ThreadPoolExecutor(1, -1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is equal to zero + */ + public void testConstructor13() { + try { + new ThreadPoolExecutor(1, 0, 1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if keepAliveTime is less than zero + */ + public void testConstructor14() { + try { + new ThreadPoolExecutor(1, 2, -1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if corePoolSize is greater than the maximumPoolSize + */ + public void testConstructor15() { + try { + new ThreadPoolExecutor(2, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if workQueue is set to null + */ + public void testConstructorNullPointerException4() { + try { + new ThreadPoolExecutor(1, 2, 1L, SECONDS, + (BlockingQueue) null, + new NoOpREHandler()); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if handler is set to null + */ + public void testConstructorNullPointerException5() { + try { + new ThreadPoolExecutor(1, 2, 1L, SECONDS, + new ArrayBlockingQueue(10), + (RejectedExecutionHandler) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if corePoolSize argument is less than zero + */ + public void testConstructor16() { + try { + new ThreadPoolExecutor(-1, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is less than zero + */ + public void testConstructor17() { + try { + new ThreadPoolExecutor(1, -1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if maximumPoolSize is equal to zero + */ + public void testConstructor18() { + try { + new ThreadPoolExecutor(1, 0, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if keepAliveTime is less than zero + */ + public void testConstructor19() { + try { + new ThreadPoolExecutor(1, 2, -1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if corePoolSize is greater than the maximumPoolSize + */ + public void testConstructor20() { + try { + new ThreadPoolExecutor(2, 1, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * Constructor throws if workQueue is null + */ + public void testConstructorNullPointerException6() { + try { + new ThreadPoolExecutor(1, 2, 1L, SECONDS, + (BlockingQueue) null, + new SimpleThreadFactory(), + new NoOpREHandler()); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if handler is null + */ + public void testConstructorNullPointerException7() { + try { + new ThreadPoolExecutor(1, 2, 1L, SECONDS, + new ArrayBlockingQueue(10), + new SimpleThreadFactory(), + (RejectedExecutionHandler) null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Constructor throws if ThreadFactory is null + */ + public void testConstructorNullPointerException8() { + try { + new ThreadPoolExecutor(1, 2, 1L, SECONDS, + new ArrayBlockingQueue(10), + (ThreadFactory) null, + new NoOpREHandler()); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * get of submitted callable throws InterruptedException if interrupted + */ + public void testInterruptedSubmit() throws InterruptedException { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + 60, SECONDS, + new ArrayBlockingQueue(10)); + + try (PoolCleaner cleaner = cleaner(p, done)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws Exception { + Callable task = new CheckedCallable() { + public Boolean realCall() throws InterruptedException { + threadStarted.countDown(); + await(done); + return Boolean.TRUE; + }}; + p.submit(task).get(); + }}); + + await(threadStarted); + t.interrupt(); + awaitTermination(t); + } + } + + /** + * execute throws RejectedExecutionException if saturated. + */ + public void testSaturatedExecute() { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1)); + try (PoolCleaner cleaner = cleaner(p, done)) { + Runnable task = new CheckedRunnable() { + public void realRun() throws InterruptedException { + await(done); + }}; + for (int i = 0; i < 2; ++i) + p.execute(task); + for (int i = 0; i < 2; ++i) { + try { + p.execute(task); + shouldThrow(); + } catch (RejectedExecutionException success) {} + assertTrue(p.getTaskCount() <= 2); + } + } + } + + /** + * submit(runnable) throws RejectedExecutionException if saturated. + */ + public void testSaturatedSubmitRunnable() { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1)); + try (PoolCleaner cleaner = cleaner(p, done)) { + Runnable task = new CheckedRunnable() { + public void realRun() throws InterruptedException { + await(done); + }}; + for (int i = 0; i < 2; ++i) + p.submit(task); + for (int i = 0; i < 2; ++i) { + try { + p.execute(task); + shouldThrow(); + } catch (RejectedExecutionException success) {} + assertTrue(p.getTaskCount() <= 2); + } + } + } + + /** + * submit(callable) throws RejectedExecutionException if saturated. + */ + public void testSaturatedSubmitCallable() { + final CountDownLatch done = new CountDownLatch(1); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1)); + try (PoolCleaner cleaner = cleaner(p, done)) { + Runnable task = new CheckedRunnable() { + public void realRun() throws InterruptedException { + await(done); + }}; + for (int i = 0; i < 2; ++i) + p.submit(Executors.callable(task)); + for (int i = 0; i < 2; ++i) { + try { + p.execute(task); + shouldThrow(); + } catch (RejectedExecutionException success) {} + assertTrue(p.getTaskCount() <= 2); + } + } + } + + /** + * executor using CallerRunsPolicy runs task if saturated. + */ + public void testSaturatedExecute2() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, + MILLISECONDS, + new ArrayBlockingQueue(1), + new ThreadPoolExecutor.CallerRunsPolicy()); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch done = new CountDownLatch(1); + Runnable blocker = new CheckedRunnable() { + public void realRun() throws InterruptedException { + await(done); + }}; + p.execute(blocker); + TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5]; + for (int i = 0; i < tasks.length; i++) + tasks[i] = new TrackedNoOpRunnable(); + for (int i = 0; i < tasks.length; i++) + p.execute(tasks[i]); + for (int i = 1; i < tasks.length; i++) + assertTrue(tasks[i].done); + assertFalse(tasks[0].done); // waiting in queue + done.countDown(); + } + } + + /** + * executor using DiscardPolicy drops task if saturated. + */ + public void testSaturatedExecute3() { + final CountDownLatch done = new CountDownLatch(1); + final TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5]; + for (int i = 0; i < tasks.length; ++i) + tasks[i] = new TrackedNoOpRunnable(); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new ThreadPoolExecutor.DiscardPolicy()); + try (PoolCleaner cleaner = cleaner(p, done)) { + p.execute(awaiter(done)); + + for (TrackedNoOpRunnable task : tasks) + p.execute(task); + for (int i = 1; i < tasks.length; i++) + assertFalse(tasks[i].done); + } + for (int i = 1; i < tasks.length; i++) + assertFalse(tasks[i].done); + assertTrue(tasks[0].done); // was waiting in queue + } + + /** + * executor using DiscardOldestPolicy drops oldest task if saturated. + */ + public void testSaturatedExecute4() { + final CountDownLatch done = new CountDownLatch(1); + LatchAwaiter r1 = awaiter(done); + LatchAwaiter r2 = awaiter(done); + LatchAwaiter r3 = awaiter(done); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new ThreadPoolExecutor.DiscardOldestPolicy()); + try (PoolCleaner cleaner = cleaner(p, done)) { + assertEquals(LatchAwaiter.NEW, r1.state); + assertEquals(LatchAwaiter.NEW, r2.state); + assertEquals(LatchAwaiter.NEW, r3.state); + p.execute(r1); + p.execute(r2); + assertTrue(p.getQueue().contains(r2)); + p.execute(r3); + assertFalse(p.getQueue().contains(r2)); + assertTrue(p.getQueue().contains(r3)); + } + assertEquals(LatchAwaiter.DONE, r1.state); + assertEquals(LatchAwaiter.NEW, r2.state); + assertEquals(LatchAwaiter.DONE, r3.state); + } + + /** + * execute throws RejectedExecutionException if shutdown + */ + public void testRejectedExecutionExceptionOnShutdown() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1)); + try { p.shutdown(); } catch (SecurityException ok) { return; } + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.execute(new NoOpRunnable()); + shouldThrow(); + } catch (RejectedExecutionException success) {} + } + } + + /** + * execute using CallerRunsPolicy drops task on shutdown + */ + public void testCallerRunsOnShutdown() { + RejectedExecutionHandler h = new ThreadPoolExecutor.CallerRunsPolicy(); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), h); + + try { p.shutdown(); } catch (SecurityException ok) { return; } + try (PoolCleaner cleaner = cleaner(p)) { + TrackedNoOpRunnable r = new TrackedNoOpRunnable(); + p.execute(r); + assertFalse(r.done); + } + } + + /** + * execute using DiscardPolicy drops task on shutdown + */ + public void testDiscardOnShutdown() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new ThreadPoolExecutor.DiscardPolicy()); + + try { p.shutdown(); } catch (SecurityException ok) { return; } + try (PoolCleaner cleaner = cleaner(p)) { + TrackedNoOpRunnable r = new TrackedNoOpRunnable(); + p.execute(r); + assertFalse(r.done); + } + } + + /** + * execute using DiscardOldestPolicy drops task on shutdown + */ + public void testDiscardOldestOnShutdown() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(1), + new ThreadPoolExecutor.DiscardOldestPolicy()); + + try { p.shutdown(); } catch (SecurityException ok) { return; } + try (PoolCleaner cleaner = cleaner(p)) { + TrackedNoOpRunnable r = new TrackedNoOpRunnable(); + p.execute(r); + assertFalse(r.done); + } + } + + /** + * execute(null) throws NPE + */ + public void testExecuteNull() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 2, + 1L, SECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.execute(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * setCorePoolSize of negative value throws IllegalArgumentException + */ + public void testCorePoolSizeIllegalArgumentException() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setCorePoolSize(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * setMaximumPoolSize(int) throws IllegalArgumentException if + * given a value less the core pool size + */ + public void testMaximumPoolSizeIllegalArgumentException() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 3, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setMaximumPoolSize(1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * setMaximumPoolSize throws IllegalArgumentException + * if given a negative value + */ + public void testMaximumPoolSizeIllegalArgumentException2() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 3, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setMaximumPoolSize(-1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * Configuration changes that allow core pool size greater than + * max pool size result in IllegalArgumentException. + */ + public void testPoolSizeInvariants() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + for (int s = 1; s < 5; s++) { + p.setMaximumPoolSize(s); + p.setCorePoolSize(s); + try { + p.setMaximumPoolSize(s - 1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + assertEquals(s, p.getCorePoolSize()); + assertEquals(s, p.getMaximumPoolSize()); + try { + p.setCorePoolSize(s + 1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + assertEquals(s, p.getCorePoolSize()); + assertEquals(s, p.getMaximumPoolSize()); + } + } + } + + /** + * setKeepAliveTime throws IllegalArgumentException + * when given a negative value + */ + public void testKeepAliveTimeIllegalArgumentException() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 3, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + try { + p.setKeepAliveTime(-1, MILLISECONDS); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * terminated() is called on termination + */ + public void testTerminated() { + ExtendedTPE p = new ExtendedTPE(); + try (PoolCleaner cleaner = cleaner(p)) { + try { p.shutdown(); } catch (SecurityException ok) { return; } + assertTrue(p.terminatedCalled()); + assertTrue(p.isShutdown()); + } + } + + /** + * beforeExecute and afterExecute are called when executing task + */ + public void testBeforeAfter() throws InterruptedException { + ExtendedTPE p = new ExtendedTPE(); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch done = new CountDownLatch(1); + p.execute(new CheckedRunnable() { + public void realRun() { + done.countDown(); + }}); + await(p.afterCalled); + assertEquals(0, done.getCount()); + assertTrue(p.afterCalled()); + assertTrue(p.beforeCalled()); + } + } + + /** + * completed submit of callable returns result + */ + public void testSubmitCallable() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new StringTask()); + String result = future.get(); + assertSame(TEST_STRING, result); + } + } + + /** + * completed submit of runnable returns successfully + */ + public void testSubmitRunnable() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable()); + future.get(); + assertTrue(future.isDone()); + } + } + + /** + * completed submit of (runnable, result) returns result + */ + public void testSubmitRunnable2() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + Future future = e.submit(new NoOpRunnable(), TEST_STRING); + String result = future.get(); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAny(null) throws NPE + */ + public void testInvokeAny1() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAny(empty collection) throws IAE + */ + public void testInvokeAny2() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>()); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * invokeAny(c) throws NPE if c has null elements + */ + public void testInvokeAny3() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * invokeAny(c) throws ExecutionException if no task completes + */ + public void testInvokeAny4() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAny(c) returns result of some task + */ + public void testInvokeAny5() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l); + assertSame(TEST_STRING, result); + } + } + + /** + * invokeAll(null) throws NPE + */ + public void testInvokeAll1() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * invokeAll(empty collection) returns empty collection + */ + public void testInvokeAll2() throws InterruptedException { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>()); + assertTrue(r.isEmpty()); + } + } + + /** + * invokeAll(c) throws NPE if c has null elements + */ + public void testInvokeAll3() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of element of invokeAll(c) throws exception on failed task + */ + public void testInvokeAll4() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = e.invokeAll(l); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * invokeAll(c) returns results of all completed tasks + */ + public void testInvokeAll5() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = e.invokeAll(l); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAny(null) throws NPE + */ + public void testTimedInvokeAny1() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(,,null) throws NPE + */ + public void testTimedInvokeAnyNullTimeUnit() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAny(empty collection) throws IAE + */ + public void testTimedInvokeAny2() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAny(new ArrayList>(), + MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + + /** + * timed invokeAny(c) throws NPE if c has null elements + */ + public void testTimedInvokeAny3() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(latchAwaitingStringTask(latch)); + l.add(null); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + latch.countDown(); + } + } + + /** + * timed invokeAny(c) throws ExecutionException if no task completes + */ + public void testTimedInvokeAny4() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAny(c) returns result of some task + */ + public void testTimedInvokeAny5() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + long startTime = System.nanoTime(); + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); + assertSame(TEST_STRING, result); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + } + } + + /** + * timed invokeAll(null) throws NPE + */ + public void testTimedInvokeAll1() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + try { + e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(,,null) throws NPE + */ + public void testTimedInvokeAllNullTimeUnit() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * timed invokeAll(empty collection) returns empty collection + */ + public void testTimedInvokeAll2() throws InterruptedException { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> r = e.invokeAll(new ArrayList>(), + MEDIUM_DELAY_MS, MILLISECONDS); + assertTrue(r.isEmpty()); + } + } + + /** + * timed invokeAll(c) throws NPE if c has null elements + */ + public void testTimedInvokeAll3() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) {} + } + } + + /** + * get of element of invokeAll(c) throws exception on failed task + */ + public void testTimedInvokeAll4() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = + e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } + } + } + + /** + * timed invokeAll(c) returns results of all completed tasks + */ + public void testTimedInvokeAll5() throws Exception { + final ExecutorService e = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(e)) { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = + e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } + } + + /** + * timed invokeAll(c) cancels tasks not completed by timeout + */ + public void testTimedInvokeAll6() throws Exception { + for (long timeout = timeoutMillis();;) { + final CountDownLatch done = new CountDownLatch(1); + final Callable waiter = new CheckedCallable() { + public String realCall() { + try { done.await(LONG_DELAY_MS, MILLISECONDS); } + catch (InterruptedException ok) {} + return "1"; }}; + final ExecutorService p = + new ThreadPoolExecutor(2, 2, + LONG_DELAY_MS, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p, done)) { + List> tasks = new ArrayList<>(); + tasks.add(new StringTask("0")); + tasks.add(waiter); + tasks.add(new StringTask("2")); + long startTime = System.nanoTime(); + List> futures = + p.invokeAll(tasks, timeout, MILLISECONDS); + assertEquals(tasks.size(), futures.size()); + assertTrue(millisElapsedSince(startTime) >= timeout); + for (Future future : futures) + assertTrue(future.isDone()); + assertTrue(futures.get(1).isCancelled()); + try { + assertEquals("0", futures.get(0).get()); + assertEquals("2", futures.get(2).get()); + break; + } catch (CancellationException retryWithLongerTimeout) { + timeout *= 2; + if (timeout >= LONG_DELAY_MS / 2) + fail("expected exactly one task to be cancelled"); + } + } + } + } + + /** + * Execution continues if there is at least one thread even if + * thread factory fails to create more + */ + public void testFailingThreadFactory() throws InterruptedException { + final ExecutorService e = + new ThreadPoolExecutor(100, 100, + LONG_DELAY_MS, MILLISECONDS, + new LinkedBlockingQueue(), + new FailingThreadFactory()); + try (PoolCleaner cleaner = cleaner(e)) { + final int TASKS = 100; + final CountDownLatch done = new CountDownLatch(TASKS); + for (int k = 0; k < TASKS; ++k) + e.execute(new CheckedRunnable() { + public void realRun() { + done.countDown(); + }}); + assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS)); + } + } + + /** + * allowsCoreThreadTimeOut is by default false. + */ + public void testAllowsCoreThreadTimeOut() { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 2, + 1000, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + assertFalse(p.allowsCoreThreadTimeOut()); + } + } + + /** + * allowCoreThreadTimeOut(true) causes idle threads to time out + */ + public void testAllowCoreThreadTimeOut_true() throws Exception { + long keepAliveTime = timeoutMillis(); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 10, + keepAliveTime, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + p.allowCoreThreadTimeOut(true); + p.execute(new CheckedRunnable() { + public void realRun() { + threadStarted.countDown(); + assertEquals(1, p.getPoolSize()); + }}); + await(threadStarted); + delay(keepAliveTime); + long startTime = System.nanoTime(); + while (p.getPoolSize() > 0 + && millisElapsedSince(startTime) < LONG_DELAY_MS) + Thread.yield(); + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); + assertEquals(0, p.getPoolSize()); + } + } + + /** + * allowCoreThreadTimeOut(false) causes idle threads not to time out + */ + public void testAllowCoreThreadTimeOut_false() throws Exception { + long keepAliveTime = timeoutMillis(); + final ThreadPoolExecutor p = + new ThreadPoolExecutor(2, 10, + keepAliveTime, MILLISECONDS, + new ArrayBlockingQueue(10)); + try (PoolCleaner cleaner = cleaner(p)) { + final CountDownLatch threadStarted = new CountDownLatch(1); + p.allowCoreThreadTimeOut(false); + p.execute(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadStarted.countDown(); + assertTrue(p.getPoolSize() >= 1); + }}); + delay(2 * keepAliveTime); + assertTrue(p.getPoolSize() >= 1); + } + } + + /** + * execute allows the same task to be submitted multiple times, even + * if rejected + */ + public void testRejectedRecycledTask() throws InterruptedException { + final int nTasks = 1000; + final CountDownLatch done = new CountDownLatch(nTasks); + final Runnable recycledTask = new Runnable() { + public void run() { + done.countDown(); + }}; + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 30, + 60, SECONDS, + new ArrayBlockingQueue(30)); + try (PoolCleaner cleaner = cleaner(p)) { + for (int i = 0; i < nTasks; ++i) { + for (;;) { + try { + p.execute(recycledTask); + break; + } + catch (RejectedExecutionException ignore) {} + } + } + // enough time to run all tasks + assertTrue(done.await(nTasks * SHORT_DELAY_MS, MILLISECONDS)); + } + } + + /** + * get(cancelled task) throws CancellationException + */ + public void testGet_cancelled() throws Exception { + final CountDownLatch done = new CountDownLatch(1); + final ExecutorService e = + new ThreadPoolExecutor(1, 1, + LONG_DELAY_MS, MILLISECONDS, + new LinkedBlockingQueue()); + try (PoolCleaner cleaner = cleaner(e, done)) { + final CountDownLatch blockerStarted = new CountDownLatch(1); + final List> futures = new ArrayList<>(); + for (int i = 0; i < 2; i++) { + Runnable r = new CheckedRunnable() { public void realRun() + throws Throwable { + blockerStarted.countDown(); + assertTrue(done.await(2 * LONG_DELAY_MS, MILLISECONDS)); + }}; + futures.add(e.submit(r)); + } + await(blockerStarted); + for (Future future : futures) future.cancel(false); + for (Future future : futures) { + try { + future.get(); + shouldThrow(); + } catch (CancellationException success) {} + try { + future.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (CancellationException success) {} + assertTrue(future.isCancelled()); + assertTrue(future.isDone()); + } + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/ThreadTest.java b/jdk/test/java/util/concurrent/tck/ThreadTest.java new file mode 100644 index 00000000000..939d590beb9 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/ThreadTest.java @@ -0,0 +1,100 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class ThreadTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ThreadTest.class); + } + + static class MyHandler implements Thread.UncaughtExceptionHandler { + public void uncaughtException(Thread t, Throwable e) { + e.printStackTrace(); + } + } + + /** + * getUncaughtExceptionHandler returns ThreadGroup unless set, + * otherwise returning value of last setUncaughtExceptionHandler. + */ + public void testGetAndSetUncaughtExceptionHandler() { + // these must be done all at once to avoid state + // dependencies across tests + Thread current = Thread.currentThread(); + ThreadGroup tg = current.getThreadGroup(); + MyHandler eh = new MyHandler(); + assertSame(tg, current.getUncaughtExceptionHandler()); + current.setUncaughtExceptionHandler(eh); + try { + assertSame(eh, current.getUncaughtExceptionHandler()); + } finally { + current.setUncaughtExceptionHandler(null); + } + assertSame(tg, current.getUncaughtExceptionHandler()); + } + + /** + * getDefaultUncaughtExceptionHandler returns value of last + * setDefaultUncaughtExceptionHandler. + */ + public void testGetAndSetDefaultUncaughtExceptionHandler() { + assertEquals(null, Thread.getDefaultUncaughtExceptionHandler()); + // failure due to securityException is OK. + // Would be nice to explicitly test both ways, but cannot yet. + Thread.UncaughtExceptionHandler defaultHandler + = Thread.getDefaultUncaughtExceptionHandler(); + MyHandler eh = new MyHandler(); + try { + Thread.setDefaultUncaughtExceptionHandler(eh); + try { + assertSame(eh, Thread.getDefaultUncaughtExceptionHandler()); + } finally { + Thread.setDefaultUncaughtExceptionHandler(defaultHandler); + } + } catch (SecurityException ok) { + assertNotNull(System.getSecurityManager()); + } + assertSame(defaultHandler, Thread.getDefaultUncaughtExceptionHandler()); + } + + // How to test actually using UEH within junit? + +} diff --git a/jdk/test/java/util/concurrent/tck/TimeUnitTest.java b/jdk/test/java/util/concurrent/tck/TimeUnitTest.java new file mode 100644 index 00000000000..30f955978d8 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/TimeUnitTest.java @@ -0,0 +1,509 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. + */ + +import static java.util.concurrent.TimeUnit.DAYS; +import static java.util.concurrent.TimeUnit.HOURS; +import static java.util.concurrent.TimeUnit.MICROSECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.time.temporal.ChronoUnit; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class TimeUnitTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(TimeUnitTest.class); + } + + // (loops to 88888 check increments at all time divisions.) + + /** + * convert correctly converts sample values across the units + */ + public void testConvert() { + for (long t = 0; t < 88888; ++t) { + assertEquals(t*60*60*24, + SECONDS.convert(t, DAYS)); + assertEquals(t*60*60, + SECONDS.convert(t, HOURS)); + assertEquals(t*60, + SECONDS.convert(t, MINUTES)); + assertEquals(t, + SECONDS.convert(t, SECONDS)); + assertEquals(t, + SECONDS.convert(1000L*t, MILLISECONDS)); + assertEquals(t, + SECONDS.convert(1000000L*t, MICROSECONDS)); + assertEquals(t, + SECONDS.convert(1000000000L*t, NANOSECONDS)); + + assertEquals(1000L*t*60*60*24, + MILLISECONDS.convert(t, DAYS)); + assertEquals(1000L*t*60*60, + MILLISECONDS.convert(t, HOURS)); + assertEquals(1000L*t*60, + MILLISECONDS.convert(t, MINUTES)); + assertEquals(1000L*t, + MILLISECONDS.convert(t, SECONDS)); + assertEquals(t, + MILLISECONDS.convert(t, MILLISECONDS)); + assertEquals(t, + MILLISECONDS.convert(1000L*t, MICROSECONDS)); + assertEquals(t, + MILLISECONDS.convert(1000000L*t, NANOSECONDS)); + + assertEquals(1000000L*t*60*60*24, + MICROSECONDS.convert(t, DAYS)); + assertEquals(1000000L*t*60*60, + MICROSECONDS.convert(t, HOURS)); + assertEquals(1000000L*t*60, + MICROSECONDS.convert(t, MINUTES)); + assertEquals(1000000L*t, + MICROSECONDS.convert(t, SECONDS)); + assertEquals(1000L*t, + MICROSECONDS.convert(t, MILLISECONDS)); + assertEquals(t, + MICROSECONDS.convert(t, MICROSECONDS)); + assertEquals(t, + MICROSECONDS.convert(1000L*t, NANOSECONDS)); + + assertEquals(1000000000L*t*60*60*24, + NANOSECONDS.convert(t, DAYS)); + assertEquals(1000000000L*t*60*60, + NANOSECONDS.convert(t, HOURS)); + assertEquals(1000000000L*t*60, + NANOSECONDS.convert(t, MINUTES)); + assertEquals(1000000000L*t, + NANOSECONDS.convert(t, SECONDS)); + assertEquals(1000000L*t, + NANOSECONDS.convert(t, MILLISECONDS)); + assertEquals(1000L*t, + NANOSECONDS.convert(t, MICROSECONDS)); + assertEquals(t, + NANOSECONDS.convert(t, NANOSECONDS)); + } + } + + /** + * toNanos correctly converts sample values in different units to + * nanoseconds + */ + public void testToNanos() { + for (long t = 0; t < 88888; ++t) { + assertEquals(t*1000000000L*60*60*24, + DAYS.toNanos(t)); + assertEquals(t*1000000000L*60*60, + HOURS.toNanos(t)); + assertEquals(t*1000000000L*60, + MINUTES.toNanos(t)); + assertEquals(1000000000L*t, + SECONDS.toNanos(t)); + assertEquals(1000000L*t, + MILLISECONDS.toNanos(t)); + assertEquals(1000L*t, + MICROSECONDS.toNanos(t)); + assertEquals(t, + NANOSECONDS.toNanos(t)); + } + } + + /** + * toMicros correctly converts sample values in different units to + * microseconds + */ + public void testToMicros() { + for (long t = 0; t < 88888; ++t) { + assertEquals(t*1000000L*60*60*24, + DAYS.toMicros(t)); + assertEquals(t*1000000L*60*60, + HOURS.toMicros(t)); + assertEquals(t*1000000L*60, + MINUTES.toMicros(t)); + assertEquals(1000000L*t, + SECONDS.toMicros(t)); + assertEquals(1000L*t, + MILLISECONDS.toMicros(t)); + assertEquals(t, + MICROSECONDS.toMicros(t)); + assertEquals(t, + NANOSECONDS.toMicros(t*1000L)); + } + } + + /** + * toMillis correctly converts sample values in different units to + * milliseconds + */ + public void testToMillis() { + for (long t = 0; t < 88888; ++t) { + assertEquals(t*1000L*60*60*24, + DAYS.toMillis(t)); + assertEquals(t*1000L*60*60, + HOURS.toMillis(t)); + assertEquals(t*1000L*60, + MINUTES.toMillis(t)); + assertEquals(1000L*t, + SECONDS.toMillis(t)); + assertEquals(t, + MILLISECONDS.toMillis(t)); + assertEquals(t, + MICROSECONDS.toMillis(t*1000L)); + assertEquals(t, + NANOSECONDS.toMillis(t*1000000L)); + } + } + + /** + * toSeconds correctly converts sample values in different units to + * seconds + */ + public void testToSeconds() { + for (long t = 0; t < 88888; ++t) { + assertEquals(t*60*60*24, + DAYS.toSeconds(t)); + assertEquals(t*60*60, + HOURS.toSeconds(t)); + assertEquals(t*60, + MINUTES.toSeconds(t)); + assertEquals(t, + SECONDS.toSeconds(t)); + assertEquals(t, + MILLISECONDS.toSeconds(t*1000L)); + assertEquals(t, + MICROSECONDS.toSeconds(t*1000000L)); + assertEquals(t, + NANOSECONDS.toSeconds(t*1000000000L)); + } + } + + /** + * toMinutes correctly converts sample values in different units to + * minutes + */ + public void testToMinutes() { + for (long t = 0; t < 88888; ++t) { + assertEquals(t*60*24, + DAYS.toMinutes(t)); + assertEquals(t*60, + HOURS.toMinutes(t)); + assertEquals(t, + MINUTES.toMinutes(t)); + assertEquals(t, + SECONDS.toMinutes(t*60)); + assertEquals(t, + MILLISECONDS.toMinutes(t*1000L*60)); + assertEquals(t, + MICROSECONDS.toMinutes(t*1000000L*60)); + assertEquals(t, + NANOSECONDS.toMinutes(t*1000000000L*60)); + } + } + + /** + * toHours correctly converts sample values in different units to + * hours + */ + public void testToHours() { + for (long t = 0; t < 88888; ++t) { + assertEquals(t*24, + DAYS.toHours(t)); + assertEquals(t, + HOURS.toHours(t)); + assertEquals(t, + MINUTES.toHours(t*60)); + assertEquals(t, + SECONDS.toHours(t*60*60)); + assertEquals(t, + MILLISECONDS.toHours(t*1000L*60*60)); + assertEquals(t, + MICROSECONDS.toHours(t*1000000L*60*60)); + assertEquals(t, + NANOSECONDS.toHours(t*1000000000L*60*60)); + } + } + + /** + * toDays correctly converts sample values in different units to + * days + */ + public void testToDays() { + for (long t = 0; t < 88888; ++t) { + assertEquals(t, + DAYS.toDays(t)); + assertEquals(t, + HOURS.toDays(t*24)); + assertEquals(t, + MINUTES.toDays(t*60*24)); + assertEquals(t, + SECONDS.toDays(t*60*60*24)); + assertEquals(t, + MILLISECONDS.toDays(t*1000L*60*60*24)); + assertEquals(t, + MICROSECONDS.toDays(t*1000000L*60*60*24)); + assertEquals(t, + NANOSECONDS.toDays(t*1000000000L*60*60*24)); + } + } + + /** + * convert saturates positive too-large values to Long.MAX_VALUE + * and negative to LONG.MIN_VALUE + */ + public void testConvertSaturate() { + assertEquals(Long.MAX_VALUE, + NANOSECONDS.convert(Long.MAX_VALUE / 2, SECONDS)); + assertEquals(Long.MIN_VALUE, + NANOSECONDS.convert(-Long.MAX_VALUE / 4, SECONDS)); + assertEquals(Long.MAX_VALUE, + NANOSECONDS.convert(Long.MAX_VALUE / 2, MINUTES)); + assertEquals(Long.MIN_VALUE, + NANOSECONDS.convert(-Long.MAX_VALUE / 4, MINUTES)); + assertEquals(Long.MAX_VALUE, + NANOSECONDS.convert(Long.MAX_VALUE / 2, HOURS)); + assertEquals(Long.MIN_VALUE, + NANOSECONDS.convert(-Long.MAX_VALUE / 4, HOURS)); + assertEquals(Long.MAX_VALUE, + NANOSECONDS.convert(Long.MAX_VALUE / 2, DAYS)); + assertEquals(Long.MIN_VALUE, + NANOSECONDS.convert(-Long.MAX_VALUE / 4, DAYS)); + } + + /** + * toNanos saturates positive too-large values to Long.MAX_VALUE + * and negative to LONG.MIN_VALUE + */ + public void testToNanosSaturate() { + assertEquals(Long.MAX_VALUE, + MILLISECONDS.toNanos(Long.MAX_VALUE / 2)); + assertEquals(Long.MIN_VALUE, + MILLISECONDS.toNanos(-Long.MAX_VALUE / 3)); + } + + /** + * toString returns name of unit + */ + public void testToString() { + assertEquals("SECONDS", SECONDS.toString()); + } + + /** + * name returns name of unit + */ + public void testName() { + assertEquals("SECONDS", SECONDS.name()); + } + + /** + * Timed wait without holding lock throws + * IllegalMonitorStateException + */ + public void testTimedWait_IllegalMonitorException() { + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + Object o = new Object(); + TimeUnit tu = MILLISECONDS; + + try { + tu.timedWait(o, LONG_DELAY_MS); + threadShouldThrow(); + } catch (IllegalMonitorStateException success) {} + }}); + + awaitTermination(t); + } + + /** + * timedWait throws InterruptedException when interrupted + */ + public void testTimedWait_Interruptible() { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + Object o = new Object(); + TimeUnit tu = MILLISECONDS; + + Thread.currentThread().interrupt(); + try { + synchronized (o) { + tu.timedWait(o, LONG_DELAY_MS); + } + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + synchronized (o) { + tu.timedWait(o, LONG_DELAY_MS); + } + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * timedJoin throws InterruptedException when interrupted + */ + public void testTimedJoin_Interruptible() { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + final Thread s = newStartedThread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + Thread.sleep(LONG_DELAY_MS); + }}); + final Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + TimeUnit tu = MILLISECONDS; + Thread.currentThread().interrupt(); + try { + tu.timedJoin(s, LONG_DELAY_MS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + tu.timedJoin(s, LONG_DELAY_MS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + s.interrupt(); + awaitTermination(s); + } + + /** + * timedSleep throws InterruptedException when interrupted + */ + public void testTimedSleep_Interruptible() { + final CountDownLatch pleaseInterrupt = new CountDownLatch(1); + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + TimeUnit tu = MILLISECONDS; + Thread.currentThread().interrupt(); + try { + tu.sleep(LONG_DELAY_MS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + + pleaseInterrupt.countDown(); + try { + tu.sleep(LONG_DELAY_MS); + shouldThrow(); + } catch (InterruptedException success) {} + assertFalse(Thread.interrupted()); + }}); + + await(pleaseInterrupt); + assertThreadStaysAlive(t); + t.interrupt(); + awaitTermination(t); + } + + /** + * a deserialized serialized unit is the same instance + */ + public void testSerialization() throws Exception { + for (TimeUnit x : TimeUnit.values()) + assertSame(x, serialClone(x)); + } + + /** + * tests for toChronoUnit. + */ + public void testToChronoUnit() throws Exception { + assertSame(ChronoUnit.NANOS, NANOSECONDS.toChronoUnit()); + assertSame(ChronoUnit.MICROS, MICROSECONDS.toChronoUnit()); + assertSame(ChronoUnit.MILLIS, MILLISECONDS.toChronoUnit()); + assertSame(ChronoUnit.SECONDS, SECONDS.toChronoUnit()); + assertSame(ChronoUnit.MINUTES, MINUTES.toChronoUnit()); + assertSame(ChronoUnit.HOURS, HOURS.toChronoUnit()); + assertSame(ChronoUnit.DAYS, DAYS.toChronoUnit()); + + // Every TimeUnit has a defined ChronoUnit equivalent + for (TimeUnit x : TimeUnit.values()) + assertSame(x, TimeUnit.of(x.toChronoUnit())); + } + + /** + * tests for TimeUnit.of(ChronoUnit). + */ + public void testTimeUnitOf() throws Exception { + assertSame(NANOSECONDS, TimeUnit.of(ChronoUnit.NANOS)); + assertSame(MICROSECONDS, TimeUnit.of(ChronoUnit.MICROS)); + assertSame(MILLISECONDS, TimeUnit.of(ChronoUnit.MILLIS)); + assertSame(SECONDS, TimeUnit.of(ChronoUnit.SECONDS)); + assertSame(MINUTES, TimeUnit.of(ChronoUnit.MINUTES)); + assertSame(HOURS, TimeUnit.of(ChronoUnit.HOURS)); + assertSame(DAYS, TimeUnit.of(ChronoUnit.DAYS)); + + assertThrows(NullPointerException.class, + () -> TimeUnit.of((ChronoUnit)null)); + + // ChronoUnits either round trip to their TimeUnit + // equivalents, or throw IllegalArgumentException. + for (ChronoUnit cu : ChronoUnit.values()) { + final TimeUnit tu; + try { + tu = TimeUnit.of(cu); + } catch (IllegalArgumentException acceptable) { + continue; + } + assertSame(cu, tu.toChronoUnit()); + } + } + +} diff --git a/jdk/test/java/util/concurrent/tck/TreeMapTest.java b/jdk/test/java/util/concurrent/tck/TreeMapTest.java new file mode 100644 index 00000000000..ebf1dd01b9b --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/TreeMapTest.java @@ -0,0 +1,1111 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.Set; +import java.util.TreeMap; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class TreeMapTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(TreeMapTest.class); + } + + /** + * Returns a new map from Integers 1-5 to Strings "A"-"E". + */ + private static TreeMap map5() { + TreeMap map = new TreeMap(); + assertTrue(map.isEmpty()); + map.put(one, "A"); + map.put(five, "E"); + map.put(three, "C"); + map.put(two, "B"); + map.put(four, "D"); + assertFalse(map.isEmpty()); + assertEquals(5, map.size()); + return map; + } + + /** + * clear removes all pairs + */ + public void testClear() { + TreeMap map = map5(); + map.clear(); + assertEquals(0, map.size()); + } + + /** + * copy constructor creates map equal to source map + */ + public void testConstructFromSorted() { + TreeMap map = map5(); + TreeMap map2 = new TreeMap(map); + assertEquals(map, map2); + } + + /** + * Maps with same contents are equal + */ + public void testEquals() { + TreeMap map1 = map5(); + TreeMap map2 = map5(); + assertEquals(map1, map2); + assertEquals(map2, map1); + map1.clear(); + assertFalse(map1.equals(map2)); + assertFalse(map2.equals(map1)); + } + + /** + * containsKey returns true for contained key + */ + public void testContainsKey() { + TreeMap map = map5(); + assertTrue(map.containsKey(one)); + assertFalse(map.containsKey(zero)); + } + + /** + * containsValue returns true for held values + */ + public void testContainsValue() { + TreeMap map = map5(); + assertTrue(map.containsValue("A")); + assertFalse(map.containsValue("Z")); + } + + /** + * get returns the correct element at the given key, + * or null if not present + */ + public void testGet() { + TreeMap map = map5(); + assertEquals("A", (String)map.get(one)); + TreeMap empty = new TreeMap(); + assertNull(empty.get(one)); + } + + /** + * isEmpty is true of empty map and false for non-empty + */ + public void testIsEmpty() { + TreeMap empty = new TreeMap(); + TreeMap map = map5(); + assertTrue(empty.isEmpty()); + assertFalse(map.isEmpty()); + } + + /** + * firstKey returns first key + */ + public void testFirstKey() { + TreeMap map = map5(); + assertEquals(one, map.firstKey()); + } + + /** + * lastKey returns last key + */ + public void testLastKey() { + TreeMap map = map5(); + assertEquals(five, map.lastKey()); + } + + /** + * keySet.toArray returns contains all keys + */ + public void testKeySetToArray() { + TreeMap map = map5(); + Set s = map.keySet(); + Object[] ar = s.toArray(); + assertTrue(s.containsAll(Arrays.asList(ar))); + assertEquals(5, ar.length); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * descendingkeySet.toArray returns contains all keys + */ + public void testDescendingKeySetToArray() { + TreeMap map = map5(); + Set s = map.descendingKeySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + assertTrue(s.containsAll(Arrays.asList(ar))); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * keySet returns a Set containing all the keys + */ + public void testKeySet() { + TreeMap map = map5(); + Set s = map.keySet(); + assertEquals(5, s.size()); + assertTrue(s.contains(one)); + assertTrue(s.contains(two)); + assertTrue(s.contains(three)); + assertTrue(s.contains(four)); + assertTrue(s.contains(five)); + } + + /** + * keySet is ordered + */ + public void testKeySetOrder() { + TreeMap map = map5(); + Set s = map.keySet(); + Iterator i = s.iterator(); + Integer last = (Integer)i.next(); + assertEquals(last, one); + int count = 1; + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) < 0); + last = k; + ++count; + } + assertEquals(5, count); + } + + /** + * descending iterator of key set is inverse ordered + */ + public void testKeySetDescendingIteratorOrder() { + TreeMap map = map5(); + NavigableSet s = map.navigableKeySet(); + Iterator i = s.descendingIterator(); + Integer last = (Integer)i.next(); + assertEquals(last, five); + int count = 1; + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) > 0); + last = k; + ++count; + } + assertEquals(5, count); + } + + /** + * descendingKeySet is ordered + */ + public void testDescendingKeySetOrder() { + TreeMap map = map5(); + Set s = map.descendingKeySet(); + Iterator i = s.iterator(); + Integer last = (Integer)i.next(); + assertEquals(last, five); + int count = 1; + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) > 0); + last = k; + ++count; + } + assertEquals(5, count); + } + + /** + * descending iterator of descendingKeySet is ordered + */ + public void testDescendingKeySetDescendingIteratorOrder() { + TreeMap map = map5(); + NavigableSet s = map.descendingKeySet(); + Iterator i = s.descendingIterator(); + Integer last = (Integer)i.next(); + assertEquals(last, one); + int count = 1; + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) < 0); + last = k; + ++count; + } + assertEquals(5, count); + } + + /** + * values collection contains all values + */ + public void testValues() { + TreeMap map = map5(); + Collection s = map.values(); + assertEquals(5, s.size()); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * entrySet contains all pairs + */ + public void testEntrySet() { + TreeMap map = map5(); + Set s = map.entrySet(); + assertEquals(5, s.size()); + Iterator it = s.iterator(); + while (it.hasNext()) { + Map.Entry e = (Map.Entry) it.next(); + assertTrue( + (e.getKey().equals(one) && e.getValue().equals("A")) || + (e.getKey().equals(two) && e.getValue().equals("B")) || + (e.getKey().equals(three) && e.getValue().equals("C")) || + (e.getKey().equals(four) && e.getValue().equals("D")) || + (e.getKey().equals(five) && e.getValue().equals("E"))); + } + } + + /** + * descendingEntrySet contains all pairs + */ + public void testDescendingEntrySet() { + TreeMap map = map5(); + Set s = map.descendingMap().entrySet(); + assertEquals(5, s.size()); + Iterator it = s.iterator(); + while (it.hasNext()) { + Map.Entry e = (Map.Entry) it.next(); + assertTrue( + (e.getKey().equals(one) && e.getValue().equals("A")) || + (e.getKey().equals(two) && e.getValue().equals("B")) || + (e.getKey().equals(three) && e.getValue().equals("C")) || + (e.getKey().equals(four) && e.getValue().equals("D")) || + (e.getKey().equals(five) && e.getValue().equals("E"))); + } + } + + /** + * entrySet.toArray contains all entries + */ + public void testEntrySetToArray() { + TreeMap map = map5(); + Set s = map.entrySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + for (int i = 0; i < 5; ++i) { + assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey())); + assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue())); + } + } + + /** + * descendingEntrySet.toArray contains all entries + */ + public void testDescendingEntrySetToArray() { + TreeMap map = map5(); + Set s = map.descendingMap().entrySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + for (int i = 0; i < 5; ++i) { + assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey())); + assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue())); + } + } + + /** + * putAll adds all key-value pairs from the given map + */ + public void testPutAll() { + TreeMap empty = new TreeMap(); + TreeMap map = map5(); + empty.putAll(map); + assertEquals(5, empty.size()); + assertTrue(empty.containsKey(one)); + assertTrue(empty.containsKey(two)); + assertTrue(empty.containsKey(three)); + assertTrue(empty.containsKey(four)); + assertTrue(empty.containsKey(five)); + } + + /** + * remove removes the correct key-value pair from the map + */ + public void testRemove() { + TreeMap map = map5(); + map.remove(five); + assertEquals(4, map.size()); + assertFalse(map.containsKey(five)); + } + + /** + * lowerEntry returns preceding entry. + */ + public void testLowerEntry() { + TreeMap map = map5(); + Map.Entry e1 = map.lowerEntry(three); + assertEquals(two, e1.getKey()); + + Map.Entry e2 = map.lowerEntry(six); + assertEquals(five, e2.getKey()); + + Map.Entry e3 = map.lowerEntry(one); + assertNull(e3); + + Map.Entry e4 = map.lowerEntry(zero); + assertNull(e4); + } + + /** + * higherEntry returns next entry. + */ + public void testHigherEntry() { + TreeMap map = map5(); + Map.Entry e1 = map.higherEntry(three); + assertEquals(four, e1.getKey()); + + Map.Entry e2 = map.higherEntry(zero); + assertEquals(one, e2.getKey()); + + Map.Entry e3 = map.higherEntry(five); + assertNull(e3); + + Map.Entry e4 = map.higherEntry(six); + assertNull(e4); + } + + /** + * floorEntry returns preceding entry. + */ + public void testFloorEntry() { + TreeMap map = map5(); + Map.Entry e1 = map.floorEntry(three); + assertEquals(three, e1.getKey()); + + Map.Entry e2 = map.floorEntry(six); + assertEquals(five, e2.getKey()); + + Map.Entry e3 = map.floorEntry(one); + assertEquals(one, e3.getKey()); + + Map.Entry e4 = map.floorEntry(zero); + assertNull(e4); + } + + /** + * ceilingEntry returns next entry. + */ + public void testCeilingEntry() { + TreeMap map = map5(); + Map.Entry e1 = map.ceilingEntry(three); + assertEquals(three, e1.getKey()); + + Map.Entry e2 = map.ceilingEntry(zero); + assertEquals(one, e2.getKey()); + + Map.Entry e3 = map.ceilingEntry(five); + assertEquals(five, e3.getKey()); + + Map.Entry e4 = map.ceilingEntry(six); + assertNull(e4); + } + + /** + * lowerKey returns preceding element + */ + public void testLowerKey() { + TreeMap q = map5(); + Object e1 = q.lowerKey(three); + assertEquals(two, e1); + + Object e2 = q.lowerKey(six); + assertEquals(five, e2); + + Object e3 = q.lowerKey(one); + assertNull(e3); + + Object e4 = q.lowerKey(zero); + assertNull(e4); + } + + /** + * higherKey returns next element + */ + public void testHigherKey() { + TreeMap q = map5(); + Object e1 = q.higherKey(three); + assertEquals(four, e1); + + Object e2 = q.higherKey(zero); + assertEquals(one, e2); + + Object e3 = q.higherKey(five); + assertNull(e3); + + Object e4 = q.higherKey(six); + assertNull(e4); + } + + /** + * floorKey returns preceding element + */ + public void testFloorKey() { + TreeMap q = map5(); + Object e1 = q.floorKey(three); + assertEquals(three, e1); + + Object e2 = q.floorKey(six); + assertEquals(five, e2); + + Object e3 = q.floorKey(one); + assertEquals(one, e3); + + Object e4 = q.floorKey(zero); + assertNull(e4); + } + + /** + * ceilingKey returns next element + */ + public void testCeilingKey() { + TreeMap q = map5(); + Object e1 = q.ceilingKey(three); + assertEquals(three, e1); + + Object e2 = q.ceilingKey(zero); + assertEquals(one, e2); + + Object e3 = q.ceilingKey(five); + assertEquals(five, e3); + + Object e4 = q.ceilingKey(six); + assertNull(e4); + } + + /** + * pollFirstEntry returns entries in order + */ + public void testPollFirstEntry() { + TreeMap map = map5(); + Map.Entry e = map.pollFirstEntry(); + assertEquals(one, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(two, e.getKey()); + map.put(one, "A"); + e = map.pollFirstEntry(); + assertEquals(one, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(three, e.getKey()); + map.remove(four); + e = map.pollFirstEntry(); + assertEquals(five, e.getKey()); + try { + e.setValue("A"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollFirstEntry(); + assertNull(e); + } + + /** + * pollLastEntry returns entries in order + */ + public void testPollLastEntry() { + TreeMap map = map5(); + Map.Entry e = map.pollLastEntry(); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(four, e.getKey()); + map.put(five, "E"); + e = map.pollLastEntry(); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(three, e.getKey()); + map.remove(two); + e = map.pollLastEntry(); + assertEquals(one, e.getKey()); + try { + e.setValue("E"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollLastEntry(); + assertNull(e); + } + + /** + * size returns the correct values + */ + public void testSize() { + TreeMap map = map5(); + TreeMap empty = new TreeMap(); + assertEquals(0, empty.size()); + assertEquals(5, map.size()); + } + + /** + * toString contains toString of elements + */ + public void testToString() { + TreeMap map = map5(); + String s = map.toString(); + for (int i = 1; i <= 5; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + // Exception tests + + /** + * get(null) of nonempty map throws NPE + */ + public void testGet_NullPointerException() { + TreeMap c = map5(); + try { + c.get(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsKey(null) of nonempty map throws NPE + */ + public void testContainsKey_NullPointerException() { + TreeMap c = map5(); + try { + c.containsKey(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null) throws NPE for nonempty map + */ + public void testRemove1_NullPointerException() { + TreeMap c = new TreeMap(); + c.put("sadsdf", "asdads"); + try { + c.remove(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * A deserialized map equals original + */ + public void testSerialization() throws Exception { + NavigableMap x = map5(); + NavigableMap y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertEquals(x, y); + assertEquals(y, x); + } + + /** + * subMap returns map with keys in requested range + */ + public void testSubMapContents() { + TreeMap map = map5(); + NavigableMap sm = map.subMap(two, true, four, false); + assertEquals(two, sm.firstKey()); + assertEquals(three, sm.lastKey()); + assertEquals(2, sm.size()); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + Iterator r = sm.descendingKeySet().iterator(); + k = (Integer)(r.next()); + assertEquals(three, k); + k = (Integer)(r.next()); + assertEquals(two, k); + assertFalse(r.hasNext()); + + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(two)); + assertEquals(4, map.size()); + assertEquals(1, sm.size()); + assertEquals(three, sm.firstKey()); + assertEquals(three, sm.lastKey()); + assertEquals("C", sm.remove(three)); + assertTrue(sm.isEmpty()); + assertEquals(3, map.size()); + } + + public void testSubMapContents2() { + TreeMap map = map5(); + NavigableMap sm = map.subMap(two, true, three, false); + assertEquals(1, sm.size()); + assertEquals(two, sm.firstKey()); + assertEquals(two, sm.lastKey()); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertFalse(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + assertFalse(i.hasNext()); + Iterator r = sm.descendingKeySet().iterator(); + k = (Integer)(r.next()); + assertEquals(two, k); + assertFalse(r.hasNext()); + + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(two)); + assertEquals(4, map.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertSame(sm.remove(three), null); + assertEquals(4, map.size()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testHeadMapContents() { + TreeMap map = map5(); + NavigableMap sm = map.headMap(four, false); + assertTrue(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(one, k); + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, map.size()); + assertEquals(four, map.firstKey()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testTailMapContents() { + TreeMap map = map5(); + NavigableMap sm = map.tailMap(two, true); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertTrue(sm.containsKey(four)); + assertTrue(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + k = (Integer)(i.next()); + assertEquals(four, k); + k = (Integer)(i.next()); + assertEquals(five, k); + assertFalse(i.hasNext()); + Iterator r = sm.descendingKeySet().iterator(); + k = (Integer)(r.next()); + assertEquals(five, k); + k = (Integer)(r.next()); + assertEquals(four, k); + k = (Integer)(r.next()); + assertEquals(three, k); + k = (Integer)(r.next()); + assertEquals(two, k); + assertFalse(r.hasNext()); + + Iterator ei = sm.entrySet().iterator(); + Map.Entry e; + e = (Map.Entry)(ei.next()); + assertEquals(two, e.getKey()); + assertEquals("B", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(three, e.getKey()); + assertEquals("C", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(four, e.getKey()); + assertEquals("D", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + assertFalse(i.hasNext()); + + NavigableMap ssm = sm.tailMap(four, true); + assertEquals(four, ssm.firstKey()); + assertEquals(five, ssm.lastKey()); + assertEquals("D", ssm.remove(four)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, map.size()); + } + + Random rnd = new Random(666); + BitSet bs; + + /** + * Submaps of submaps subdivide correctly + */ + public void testRecursiveSubMaps() throws Exception { + int mapSize = expensiveTests ? 1000 : 100; + Class cl = TreeMap.class; + NavigableMap map = newMap(cl); + bs = new BitSet(mapSize); + + populate(map, mapSize); + check(map, 0, mapSize - 1, true); + check(map.descendingMap(), 0, mapSize - 1, false); + + mutateMap(map, 0, mapSize - 1); + check(map, 0, mapSize - 1, true); + check(map.descendingMap(), 0, mapSize - 1, false); + + bashSubMap(map.subMap(0, true, mapSize, false), + 0, mapSize - 1, true); + } + + static NavigableMap newMap(Class cl) throws Exception { + NavigableMap result + = (NavigableMap) cl.newInstance(); + assertEquals(0, result.size()); + assertFalse(result.keySet().iterator().hasNext()); + return result; + } + + void populate(NavigableMap map, int limit) { + for (int i = 0, n = 2 * limit / 3; i < n; i++) { + int key = rnd.nextInt(limit); + put(map, key); + } + } + + void mutateMap(NavigableMap map, int min, int max) { + int size = map.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(map, min - 5 + rnd.nextInt(rangeSize + 10)); + } + + // Remove a bunch of entries with iterator + for (Iterator it = map.keySet().iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next()); + it.remove(); + } + } + + // Add entries till we're back to original size + while (map.size() < size) { + int key = min + rnd.nextInt(rangeSize); + assertTrue(key >= min && key <= max); + put(map, key); + } + } + + void mutateSubMap(NavigableMap map, int min, int max) { + int size = map.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(map, min - 5 + rnd.nextInt(rangeSize + 10)); + } + + // Remove a bunch of entries with iterator + for (Iterator it = map.keySet().iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next()); + it.remove(); + } + } + + // Add entries till we're back to original size + while (map.size() < size) { + int key = min - 5 + rnd.nextInt(rangeSize + 10); + if (key >= min && key <= max) { + put(map, key); + } else { + try { + map.put(key, 2 * key); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + } + + void put(NavigableMap map, int key) { + if (map.put(key, 2 * key) == null) + bs.set(key); + } + + void remove(NavigableMap map, int key) { + if (map.remove(key) != null) + bs.clear(key); + } + + void bashSubMap(NavigableMap map, + int min, int max, boolean ascending) { + check(map, min, max, ascending); + check(map.descendingMap(), min, max, !ascending); + + mutateSubMap(map, min, max); + check(map, min, max, ascending); + check(map.descendingMap(), min, max, !ascending); + + // Recurse + if (max - min < 2) + return; + int midPoint = (min + max) / 2; + + // headMap - pick direction and endpoint inclusion randomly + boolean incl = rnd.nextBoolean(); + NavigableMap hm = map.headMap(midPoint, incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubMap(hm, min, midPoint - (incl ? 0 : 1), true); + else + bashSubMap(hm.descendingMap(), min, midPoint - (incl ? 0 : 1), + false); + } else { + if (rnd.nextBoolean()) + bashSubMap(hm, midPoint + (incl ? 0 : 1), max, false); + else + bashSubMap(hm.descendingMap(), midPoint + (incl ? 0 : 1), max, + true); + } + + // tailMap - pick direction and endpoint inclusion randomly + incl = rnd.nextBoolean(); + NavigableMap tm = map.tailMap(midPoint,incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubMap(tm, midPoint + (incl ? 0 : 1), max, true); + else + bashSubMap(tm.descendingMap(), midPoint + (incl ? 0 : 1), max, + false); + } else { + if (rnd.nextBoolean()) { + bashSubMap(tm, min, midPoint - (incl ? 0 : 1), false); + } else { + bashSubMap(tm.descendingMap(), min, midPoint - (incl ? 0 : 1), + true); + } + } + + // subMap - pick direction and endpoint inclusion randomly + int rangeSize = max - min + 1; + int[] endpoints = new int[2]; + endpoints[0] = min + rnd.nextInt(rangeSize); + endpoints[1] = min + rnd.nextInt(rangeSize); + Arrays.sort(endpoints); + boolean lowIncl = rnd.nextBoolean(); + boolean highIncl = rnd.nextBoolean(); + if (ascending) { + NavigableMap sm = map.subMap( + endpoints[0], lowIncl, endpoints[1], highIncl); + if (rnd.nextBoolean()) + bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true); + else + bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false); + } else { + NavigableMap sm = map.subMap( + endpoints[1], highIncl, endpoints[0], lowIncl); + if (rnd.nextBoolean()) + bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false); + else + bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true); + } + } + + /** + * min and max are both inclusive. If max < min, interval is empty. + */ + void check(NavigableMap map, + final int min, final int max, final boolean ascending) { + class ReferenceSet { + int lower(int key) { + return ascending ? lowerAscending(key) : higherAscending(key); + } + int floor(int key) { + return ascending ? floorAscending(key) : ceilingAscending(key); + } + int ceiling(int key) { + return ascending ? ceilingAscending(key) : floorAscending(key); + } + int higher(int key) { + return ascending ? higherAscending(key) : lowerAscending(key); + } + int first() { + return ascending ? firstAscending() : lastAscending(); + } + int last() { + return ascending ? lastAscending() : firstAscending(); + } + int lowerAscending(int key) { + return floorAscending(key - 1); + } + int floorAscending(int key) { + if (key < min) + return -1; + else if (key > max) + key = max; + + // BitSet should support this! Test would run much faster + while (key >= min) { + if (bs.get(key)) + return key; + key--; + } + return -1; + } + int ceilingAscending(int key) { + if (key < min) + key = min; + else if (key > max) + return -1; + int result = bs.nextSetBit(key); + return result > max ? -1 : result; + } + int higherAscending(int key) { + return ceilingAscending(key + 1); + } + private int firstAscending() { + int result = ceilingAscending(min); + return result > max ? -1 : result; + } + private int lastAscending() { + int result = floorAscending(max); + return result < min ? -1 : result; + } + } + ReferenceSet rs = new ReferenceSet(); + + // Test contents using containsKey + int size = 0; + for (int i = min; i <= max; i++) { + boolean bsContainsI = bs.get(i); + assertEquals(bsContainsI, map.containsKey(i)); + if (bsContainsI) + size++; + } + assertEquals(size, map.size()); + + // Test contents using contains keySet iterator + int size2 = 0; + int previousKey = -1; + for (int key : map.keySet()) { + assertTrue(bs.get(key)); + size2++; + assertTrue(previousKey < 0 || + (ascending ? key - previousKey > 0 : key - previousKey < 0)); + previousKey = key; + } + assertEquals(size2, size); + + // Test navigation ops + for (int key = min - 1; key <= max + 1; key++) { + assertEq(map.lowerKey(key), rs.lower(key)); + assertEq(map.floorKey(key), rs.floor(key)); + assertEq(map.higherKey(key), rs.higher(key)); + assertEq(map.ceilingKey(key), rs.ceiling(key)); + } + + // Test extrema + if (map.size() != 0) { + assertEq(map.firstKey(), rs.first()); + assertEq(map.lastKey(), rs.last()); + } else { + assertEq(rs.first(), -1); + assertEq(rs.last(), -1); + try { + map.firstKey(); + shouldThrow(); + } catch (NoSuchElementException success) {} + try { + map.lastKey(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + } + + static void assertEq(Integer i, int j) { + if (i == null) + assertEquals(j, -1); + else + assertEquals((int) i, j); + } + + static boolean eq(Integer i, int j) { + return i == null ? j == -1 : i == j; + } + +} diff --git a/jdk/test/java/util/concurrent/tck/TreeSetTest.java b/jdk/test/java/util/concurrent/tck/TreeSetTest.java new file mode 100644 index 00000000000..eb7b6efd9d0 --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/TreeSetTest.java @@ -0,0 +1,1008 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class TreeSetTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(TreeSetTest.class); + } + + static class MyReverseComparator implements Comparator { + public int compare(Object x, Object y) { + return ((Comparable)y).compareTo(x); + } + } + + /** + * The number of elements to place in collections, arrays, etc. + */ + static final int SIZE = 20; + + /** + * Returns a new set of given size containing consecutive + * Integers 0 ... n. + */ + private TreeSet populatedSet(int n) { + TreeSet q = new TreeSet(); + assertTrue(q.isEmpty()); + for (int i = n - 1; i >= 0; i -= 2) + assertTrue(q.add(new Integer(i))); + for (int i = (n & 1); i < n; i += 2) + assertTrue(q.add(new Integer(i))); + assertFalse(q.isEmpty()); + assertEquals(n, q.size()); + return q; + } + + /** + * Returns a new set of first 5 ints. + */ + private TreeSet set5() { + TreeSet q = new TreeSet(); + assertTrue(q.isEmpty()); + q.add(one); + q.add(two); + q.add(three); + q.add(four); + q.add(five); + assertEquals(5, q.size()); + return q; + } + + /** + * A new set has unbounded capacity + */ + public void testConstructor1() { + assertEquals(0, new TreeSet().size()); + } + + /** + * Initializing from null Collection throws NPE + */ + public void testConstructor3() { + try { + new TreeSet((Collection)null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection of null elements throws NPE + */ + public void testConstructor4() { + try { + new TreeSet(Arrays.asList(new Integer[SIZE])); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Initializing from Collection with some null elements throws NPE + */ + public void testConstructor5() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + new TreeSet(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Set contains all elements of collection used to initialize + */ + public void testConstructor6() { + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + TreeSet q = new TreeSet(Arrays.asList(ints)); + for (int i = 0; i < SIZE; ++i) + assertEquals(ints[i], q.pollFirst()); + } + + /** + * The comparator used in constructor is used + */ + public void testConstructor7() { + MyReverseComparator cmp = new MyReverseComparator(); + TreeSet q = new TreeSet(cmp); + assertEquals(cmp, q.comparator()); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(i); + q.addAll(Arrays.asList(ints)); + for (int i = SIZE - 1; i >= 0; --i) + assertEquals(ints[i], q.pollFirst()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + TreeSet q = new TreeSet(); + assertTrue(q.isEmpty()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.add(new Integer(2)); + q.pollFirst(); + q.pollFirst(); + assertTrue(q.isEmpty()); + } + + /** + * size changes when elements added and removed + */ + public void testSize() { + TreeSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.pollFirst(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * add(null) throws NPE if nonempty + */ + public void testAddNull() { + TreeSet q = populatedSet(SIZE); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Add of comparable element succeeds + */ + public void testAdd() { + TreeSet q = new TreeSet(); + assertTrue(q.add(zero)); + assertTrue(q.add(one)); + } + + /** + * Add of duplicate element fails + */ + public void testAddDup() { + TreeSet q = new TreeSet(); + assertTrue(q.add(zero)); + assertFalse(q.add(zero)); + } + + /** + * Add of non-Comparable throws CCE + */ + public void testAddNonComparable() { + TreeSet q = new TreeSet(); + try { + q.add(new Object()); + q.add(new Object()); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + TreeSet q = new TreeSet(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testAddAll2() { + TreeSet q = new TreeSet(); + Integer[] ints = new Integer[SIZE]; + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + TreeSet q = new TreeSet(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Set contains all elements of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(SIZE - 1 - i); + TreeSet q = new TreeSet(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(new Integer(i), q.pollFirst()); + } + + /** + * pollFirst succeeds unless empty + */ + public void testPollFirst() { + TreeSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst()); + } + assertNull(q.pollFirst()); + } + + /** + * pollLast succeeds unless empty + */ + public void testPollLast() { + TreeSet q = populatedSet(SIZE); + for (int i = SIZE - 1; i >= 0; --i) { + assertEquals(i, q.pollLast()); + } + assertNull(q.pollFirst()); + } + + /** + * remove(x) removes x and returns true if present + */ + public void testRemoveElement() { + TreeSet q = populatedSet(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertTrue(q.contains(i - 1)); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertFalse(q.remove(i + 1)); + assertFalse(q.contains(i + 1)); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + TreeSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.pollFirst(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + TreeSet q = populatedSet(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + q.add(new Integer(1)); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + TreeSet q = populatedSet(SIZE); + TreeSet p = new TreeSet(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + TreeSet q = populatedSet(SIZE); + TreeSet p = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.pollFirst(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + TreeSet q = populatedSet(SIZE); + TreeSet p = populatedSet(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.pollFirst()); + assertFalse(q.contains(x)); + } + } + } + + /** + * lower returns preceding element + */ + public void testLower() { + TreeSet q = set5(); + Object e1 = q.lower(three); + assertEquals(two, e1); + + Object e2 = q.lower(six); + assertEquals(five, e2); + + Object e3 = q.lower(one); + assertNull(e3); + + Object e4 = q.lower(zero); + assertNull(e4); + } + + /** + * higher returns next element + */ + public void testHigher() { + TreeSet q = set5(); + Object e1 = q.higher(three); + assertEquals(four, e1); + + Object e2 = q.higher(zero); + assertEquals(one, e2); + + Object e3 = q.higher(five); + assertNull(e3); + + Object e4 = q.higher(six); + assertNull(e4); + } + + /** + * floor returns preceding element + */ + public void testFloor() { + TreeSet q = set5(); + Object e1 = q.floor(three); + assertEquals(three, e1); + + Object e2 = q.floor(six); + assertEquals(five, e2); + + Object e3 = q.floor(one); + assertEquals(one, e3); + + Object e4 = q.floor(zero); + assertNull(e4); + } + + /** + * ceiling returns next element + */ + public void testCeiling() { + TreeSet q = set5(); + Object e1 = q.ceiling(three); + assertEquals(three, e1); + + Object e2 = q.ceiling(zero); + assertEquals(one, e2); + + Object e3 = q.ceiling(five); + assertEquals(five, e3); + + Object e4 = q.ceiling(six); + assertNull(e4); + } + + /** + * toArray contains all elements in sorted order + */ + public void testToArray() { + TreeSet q = populatedSet(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.pollFirst()); + } + + /** + * toArray(a) contains all elements in sorted order + */ + public void testToArray2() { + TreeSet q = populatedSet(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.pollFirst()); + } + + /** + * iterator iterates through all elements + */ + public void testIterator() { + TreeSet q = populatedSet(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty set has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(new TreeSet().iterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final TreeSet q = new TreeSet(); + q.add(new Integer(2)); + q.add(new Integer(1)); + q.add(new Integer(3)); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertEquals(it.next(), new Integer(2)); + assertEquals(it.next(), new Integer(3)); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + TreeSet q = populatedSet(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized set has same elements + */ + public void testSerialization() throws Exception { + NavigableSet x = populatedSet(SIZE); + NavigableSet y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x, y); + assertEquals(y, x); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.pollFirst(), y.pollFirst()); + } + assertTrue(y.isEmpty()); + } + + /** + * subSet returns set with keys in requested range + */ + public void testSubSetContents() { + TreeSet set = set5(); + SortedSet sm = set.subSet(two, four); + assertEquals(two, sm.first()); + assertEquals(three, sm.last()); + assertEquals(2, sm.size()); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(two)); + assertEquals(4, set.size()); + assertEquals(1, sm.size()); + assertEquals(three, sm.first()); + assertEquals(three, sm.last()); + assertTrue(sm.remove(three)); + assertTrue(sm.isEmpty()); + assertEquals(3, set.size()); + } + + public void testSubSetContents2() { + TreeSet set = set5(); + SortedSet sm = set.subSet(two, three); + assertEquals(1, sm.size()); + assertEquals(two, sm.first()); + assertEquals(two, sm.last()); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertFalse(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(two)); + assertEquals(4, set.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertFalse(sm.remove(three)); + assertEquals(4, set.size()); + } + + /** + * headSet returns set with keys in requested range + */ + public void testHeadSetContents() { + TreeSet set = set5(); + SortedSet sm = set.headSet(four); + assertTrue(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(one, k); + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, set.size()); + assertEquals(four, set.first()); + } + + /** + * tailSet returns set with keys in requested range + */ + public void testTailSetContents() { + TreeSet set = set5(); + SortedSet sm = set.tailSet(two); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertTrue(sm.contains(four)); + assertTrue(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + k = (Integer)(i.next()); + assertEquals(four, k); + k = (Integer)(i.next()); + assertEquals(five, k); + assertFalse(i.hasNext()); + + SortedSet ssm = sm.tailSet(four); + assertEquals(four, ssm.first()); + assertEquals(five, ssm.last()); + assertTrue(ssm.remove(four)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, set.size()); + } + + Random rnd = new Random(666); + BitSet bs; + + /** + * Subsets of subsets subdivide correctly + */ + public void testRecursiveSubSets() throws Exception { + int setSize = expensiveTests ? 1000 : 100; + Class cl = TreeSet.class; + + NavigableSet set = newSet(cl); + bs = new BitSet(setSize); + + populate(set, setSize); + check(set, 0, setSize - 1, true); + check(set.descendingSet(), 0, setSize - 1, false); + + mutateSet(set, 0, setSize - 1); + check(set, 0, setSize - 1, true); + check(set.descendingSet(), 0, setSize - 1, false); + + bashSubSet(set.subSet(0, true, setSize, false), + 0, setSize - 1, true); + } + + /** + * addAll is idempotent + */ + public void testAddAll_idempotent() throws Exception { + Set x = populatedSet(SIZE); + Set y = new TreeSet(x); + y.addAll(x); + assertEquals(x, y); + assertEquals(y, x); + } + + static NavigableSet newSet(Class cl) throws Exception { + NavigableSet result = (NavigableSet) cl.newInstance(); + assertEquals(0, result.size()); + assertFalse(result.iterator().hasNext()); + return result; + } + + void populate(NavigableSet set, int limit) { + for (int i = 0, n = 2 * limit / 3; i < n; i++) { + int element = rnd.nextInt(limit); + put(set, element); + } + } + + void mutateSet(NavigableSet set, int min, int max) { + int size = set.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(set, min - 5 + rnd.nextInt(rangeSize + 10)); + } + + // Remove a bunch of entries with iterator + for (Iterator it = set.iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next()); + it.remove(); + } + } + + // Add entries till we're back to original size + while (set.size() < size) { + int element = min + rnd.nextInt(rangeSize); + assertTrue(element >= min && element <= max); + put(set, element); + } + } + + void mutateSubSet(NavigableSet set, int min, int max) { + int size = set.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(set, min - 5 + rnd.nextInt(rangeSize + 10)); + } + + // Remove a bunch of entries with iterator + for (Iterator it = set.iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next()); + it.remove(); + } + } + + // Add entries till we're back to original size + while (set.size() < size) { + int element = min - 5 + rnd.nextInt(rangeSize + 10); + if (element >= min && element <= max) { + put(set, element); + } else { + try { + set.add(element); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + } + + void put(NavigableSet set, int element) { + if (set.add(element)) + bs.set(element); + } + + void remove(NavigableSet set, int element) { + if (set.remove(element)) + bs.clear(element); + } + + void bashSubSet(NavigableSet set, + int min, int max, boolean ascending) { + check(set, min, max, ascending); + check(set.descendingSet(), min, max, !ascending); + + mutateSubSet(set, min, max); + check(set, min, max, ascending); + check(set.descendingSet(), min, max, !ascending); + + // Recurse + if (max - min < 2) + return; + int midPoint = (min + max) / 2; + + // headSet - pick direction and endpoint inclusion randomly + boolean incl = rnd.nextBoolean(); + NavigableSet hm = set.headSet(midPoint, incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubSet(hm, min, midPoint - (incl ? 0 : 1), true); + else + bashSubSet(hm.descendingSet(), min, midPoint - (incl ? 0 : 1), + false); + } else { + if (rnd.nextBoolean()) + bashSubSet(hm, midPoint + (incl ? 0 : 1), max, false); + else + bashSubSet(hm.descendingSet(), midPoint + (incl ? 0 : 1), max, + true); + } + + // tailSet - pick direction and endpoint inclusion randomly + incl = rnd.nextBoolean(); + NavigableSet tm = set.tailSet(midPoint,incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubSet(tm, midPoint + (incl ? 0 : 1), max, true); + else + bashSubSet(tm.descendingSet(), midPoint + (incl ? 0 : 1), max, + false); + } else { + if (rnd.nextBoolean()) { + bashSubSet(tm, min, midPoint - (incl ? 0 : 1), false); + } else { + bashSubSet(tm.descendingSet(), min, midPoint - (incl ? 0 : 1), + true); + } + } + + // subSet - pick direction and endpoint inclusion randomly + int rangeSize = max - min + 1; + int[] endpoints = new int[2]; + endpoints[0] = min + rnd.nextInt(rangeSize); + endpoints[1] = min + rnd.nextInt(rangeSize); + Arrays.sort(endpoints); + boolean lowIncl = rnd.nextBoolean(); + boolean highIncl = rnd.nextBoolean(); + if (ascending) { + NavigableSet sm = set.subSet( + endpoints[0], lowIncl, endpoints[1], highIncl); + if (rnd.nextBoolean()) + bashSubSet(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true); + else + bashSubSet(sm.descendingSet(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false); + } else { + NavigableSet sm = set.subSet( + endpoints[1], highIncl, endpoints[0], lowIncl); + if (rnd.nextBoolean()) + bashSubSet(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false); + else + bashSubSet(sm.descendingSet(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true); + } + } + + /** + * min and max are both inclusive. If max < min, interval is empty. + */ + void check(NavigableSet set, + final int min, final int max, final boolean ascending) { + class ReferenceSet { + int lower(int element) { + return ascending ? + lowerAscending(element) : higherAscending(element); + } + int floor(int element) { + return ascending ? + floorAscending(element) : ceilingAscending(element); + } + int ceiling(int element) { + return ascending ? + ceilingAscending(element) : floorAscending(element); + } + int higher(int element) { + return ascending ? + higherAscending(element) : lowerAscending(element); + } + int first() { + return ascending ? firstAscending() : lastAscending(); + } + int last() { + return ascending ? lastAscending() : firstAscending(); + } + int lowerAscending(int element) { + return floorAscending(element - 1); + } + int floorAscending(int element) { + if (element < min) + return -1; + else if (element > max) + element = max; + + // BitSet should support this! Test would run much faster + while (element >= min) { + if (bs.get(element)) + return element; + element--; + } + return -1; + } + int ceilingAscending(int element) { + if (element < min) + element = min; + else if (element > max) + return -1; + int result = bs.nextSetBit(element); + return (result > max) ? -1 : result; + } + int higherAscending(int element) { + return ceilingAscending(element + 1); + } + private int firstAscending() { + int result = ceilingAscending(min); + return (result > max) ? -1 : result; + } + private int lastAscending() { + int result = floorAscending(max); + return (result < min) ? -1 : result; + } + } + ReferenceSet rs = new ReferenceSet(); + + // Test contents using containsElement + int size = 0; + for (int i = min; i <= max; i++) { + boolean bsContainsI = bs.get(i); + assertEquals(bsContainsI, set.contains(i)); + if (bsContainsI) + size++; + } + assertEquals(size, set.size()); + + // Test contents using contains elementSet iterator + int size2 = 0; + int previousElement = -1; + for (int element : set) { + assertTrue(bs.get(element)); + size2++; + assertTrue(previousElement < 0 || (ascending ? + element - previousElement > 0 : element - previousElement < 0)); + previousElement = element; + } + assertEquals(size2, size); + + // Test navigation ops + for (int element = min - 1; element <= max + 1; element++) { + assertEq(set.lower(element), rs.lower(element)); + assertEq(set.floor(element), rs.floor(element)); + assertEq(set.higher(element), rs.higher(element)); + assertEq(set.ceiling(element), rs.ceiling(element)); + } + + // Test extrema + if (set.size() != 0) { + assertEq(set.first(), rs.first()); + assertEq(set.last(), rs.last()); + } else { + assertEq(rs.first(), -1); + assertEq(rs.last(), -1); + try { + set.first(); + shouldThrow(); + } catch (NoSuchElementException success) {} + try { + set.last(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + } + + static void assertEq(Integer i, int j) { + if (i == null) + assertEquals(j, -1); + else + assertEquals((int) i, j); + } + + static boolean eq(Integer i, int j) { + return (i == null) ? j == -1 : i == j; + } + +} diff --git a/jdk/test/java/util/concurrent/tck/TreeSubMapTest.java b/jdk/test/java/util/concurrent/tck/TreeSubMapTest.java new file mode 100644 index 00000000000..1b5fa424b1c --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/TreeSubMapTest.java @@ -0,0 +1,1138 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class TreeSubMapTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(TreeSubMapTest.class); + } + + /** + * Returns a new map from Integers 1-5 to Strings "A"-"E". + */ + private static NavigableMap map5() { + TreeMap map = new TreeMap(); + assertTrue(map.isEmpty()); + map.put(zero, "Z"); + map.put(one, "A"); + map.put(five, "E"); + map.put(three, "C"); + map.put(two, "B"); + map.put(four, "D"); + map.put(seven, "F"); + assertFalse(map.isEmpty()); + assertEquals(7, map.size()); + return map.subMap(one, true, seven, false); + } + + private static NavigableMap map0() { + TreeMap map = new TreeMap(); + assertTrue(map.isEmpty()); + return map.tailMap(one, true); + } + + /** + * Returns a new map from Integers -5 to -1 to Strings "A"-"E". + */ + private static NavigableMap dmap5() { + TreeMap map = new TreeMap(); + assertTrue(map.isEmpty()); + map.put(m1, "A"); + map.put(m5, "E"); + map.put(m3, "C"); + map.put(m2, "B"); + map.put(m4, "D"); + assertFalse(map.isEmpty()); + assertEquals(5, map.size()); + return map.descendingMap(); + } + + private static NavigableMap dmap0() { + TreeMap map = new TreeMap(); + assertTrue(map.isEmpty()); + return map; + } + + /** + * clear removes all pairs + */ + public void testClear() { + NavigableMap map = map5(); + map.clear(); + assertEquals(0, map.size()); + } + + /** + * Maps with same contents are equal + */ + public void testEquals() { + NavigableMap map1 = map5(); + NavigableMap map2 = map5(); + assertEquals(map1, map2); + assertEquals(map2, map1); + map1.clear(); + assertFalse(map1.equals(map2)); + assertFalse(map2.equals(map1)); + } + + /** + * containsKey returns true for contained key + */ + public void testContainsKey() { + NavigableMap map = map5(); + assertTrue(map.containsKey(one)); + assertFalse(map.containsKey(zero)); + } + + /** + * containsValue returns true for held values + */ + public void testContainsValue() { + NavigableMap map = map5(); + assertTrue(map.containsValue("A")); + assertFalse(map.containsValue("Z")); + } + + /** + * get returns the correct element at the given key, + * or null if not present + */ + public void testGet() { + NavigableMap map = map5(); + assertEquals("A", (String)map.get(one)); + NavigableMap empty = map0(); + assertNull(empty.get(one)); + } + + /** + * isEmpty is true of empty map and false for non-empty + */ + public void testIsEmpty() { + NavigableMap empty = map0(); + NavigableMap map = map5(); + assertTrue(empty.isEmpty()); + assertFalse(map.isEmpty()); + } + + /** + * firstKey returns first key + */ + public void testFirstKey() { + NavigableMap map = map5(); + assertEquals(one, map.firstKey()); + } + + /** + * lastKey returns last key + */ + public void testLastKey() { + NavigableMap map = map5(); + assertEquals(five, map.lastKey()); + } + + /** + * keySet returns a Set containing all the keys + */ + public void testKeySet() { + NavigableMap map = map5(); + Set s = map.keySet(); + assertEquals(5, s.size()); + assertTrue(s.contains(one)); + assertTrue(s.contains(two)); + assertTrue(s.contains(three)); + assertTrue(s.contains(four)); + assertTrue(s.contains(five)); + } + + /** + * keySet is ordered + */ + public void testKeySetOrder() { + NavigableMap map = map5(); + Set s = map.keySet(); + Iterator i = s.iterator(); + Integer last = (Integer)i.next(); + assertEquals(last, one); + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) < 0); + last = k; + } + } + + /** + * values collection contains all values + */ + public void testValues() { + NavigableMap map = map5(); + Collection s = map.values(); + assertEquals(5, s.size()); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * entrySet contains all pairs + */ + public void testEntrySet() { + NavigableMap map = map5(); + Set s = map.entrySet(); + assertEquals(5, s.size()); + Iterator it = s.iterator(); + while (it.hasNext()) { + Map.Entry e = (Map.Entry) it.next(); + assertTrue( + (e.getKey().equals(one) && e.getValue().equals("A")) || + (e.getKey().equals(two) && e.getValue().equals("B")) || + (e.getKey().equals(three) && e.getValue().equals("C")) || + (e.getKey().equals(four) && e.getValue().equals("D")) || + (e.getKey().equals(five) && e.getValue().equals("E"))); + } + } + + /** + * putAll adds all key-value pairs from the given map + */ + public void testPutAll() { + NavigableMap empty = map0(); + NavigableMap map = map5(); + empty.putAll(map); + assertEquals(5, empty.size()); + assertTrue(empty.containsKey(one)); + assertTrue(empty.containsKey(two)); + assertTrue(empty.containsKey(three)); + assertTrue(empty.containsKey(four)); + assertTrue(empty.containsKey(five)); + } + + /** + * remove removes the correct key-value pair from the map + */ + public void testRemove() { + NavigableMap map = map5(); + map.remove(five); + assertEquals(4, map.size()); + assertFalse(map.containsKey(five)); + } + + /** + * lowerEntry returns preceding entry. + */ + public void testLowerEntry() { + NavigableMap map = map5(); + Map.Entry e1 = map.lowerEntry(three); + assertEquals(two, e1.getKey()); + + Map.Entry e2 = map.lowerEntry(six); + assertEquals(five, e2.getKey()); + + Map.Entry e3 = map.lowerEntry(one); + assertNull(e3); + + Map.Entry e4 = map.lowerEntry(zero); + assertNull(e4); + } + + /** + * higherEntry returns next entry. + */ + public void testHigherEntry() { + NavigableMap map = map5(); + Map.Entry e1 = map.higherEntry(three); + assertEquals(four, e1.getKey()); + + Map.Entry e2 = map.higherEntry(zero); + assertEquals(one, e2.getKey()); + + Map.Entry e3 = map.higherEntry(five); + assertNull(e3); + + Map.Entry e4 = map.higherEntry(six); + assertNull(e4); + } + + /** + * floorEntry returns preceding entry. + */ + public void testFloorEntry() { + NavigableMap map = map5(); + Map.Entry e1 = map.floorEntry(three); + assertEquals(three, e1.getKey()); + + Map.Entry e2 = map.floorEntry(six); + assertEquals(five, e2.getKey()); + + Map.Entry e3 = map.floorEntry(one); + assertEquals(one, e3.getKey()); + + Map.Entry e4 = map.floorEntry(zero); + assertNull(e4); + } + + /** + * ceilingEntry returns next entry. + */ + public void testCeilingEntry() { + NavigableMap map = map5(); + Map.Entry e1 = map.ceilingEntry(three); + assertEquals(three, e1.getKey()); + + Map.Entry e2 = map.ceilingEntry(zero); + assertEquals(one, e2.getKey()); + + Map.Entry e3 = map.ceilingEntry(five); + assertEquals(five, e3.getKey()); + + Map.Entry e4 = map.ceilingEntry(six); + assertNull(e4); + } + + /** + * pollFirstEntry returns entries in order + */ + public void testPollFirstEntry() { + NavigableMap map = map5(); + Map.Entry e = map.pollFirstEntry(); + assertEquals(one, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(two, e.getKey()); + map.put(one, "A"); + e = map.pollFirstEntry(); + assertEquals(one, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(three, e.getKey()); + map.remove(four); + e = map.pollFirstEntry(); + assertEquals(five, e.getKey()); + try { + e.setValue("A"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + assertTrue(map.isEmpty()); + Map.Entry f = map.firstEntry(); + assertNull(f); + e = map.pollFirstEntry(); + assertNull(e); + } + + /** + * pollLastEntry returns entries in order + */ + public void testPollLastEntry() { + NavigableMap map = map5(); + Map.Entry e = map.pollLastEntry(); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(four, e.getKey()); + map.put(five, "E"); + e = map.pollLastEntry(); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(three, e.getKey()); + map.remove(two); + e = map.pollLastEntry(); + assertEquals(one, e.getKey()); + try { + e.setValue("E"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollLastEntry(); + assertNull(e); + } + + /** + * size returns the correct values + */ + public void testSize() { + NavigableMap map = map5(); + NavigableMap empty = map0(); + assertEquals(0, empty.size()); + assertEquals(5, map.size()); + } + + /** + * toString contains toString of elements + */ + public void testToString() { + NavigableMap map = map5(); + String s = map.toString(); + for (int i = 1; i <= 5; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + // Exception tests + + /** + * get(null) of nonempty map throws NPE + */ + public void testGet_NullPointerException() { + NavigableMap c = map5(); + try { + c.get(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * containsKey(null) of nonempty map throws NPE + */ + public void testContainsKey_NullPointerException() { + NavigableMap c = map5(); + try { + c.containsKey(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * put(null,x) throws NPE + */ + public void testPut1_NullPointerException() { + NavigableMap c = map5(); + try { + c.put(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * remove(null) throws NPE + */ + public void testRemove1_NullPointerException() { + NavigableMap c = map5(); + try { + c.remove(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * A deserialized map equals original + */ + public void testSerialization() throws Exception { + NavigableMap x = map5(); + NavigableMap y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertEquals(x, y); + assertEquals(y, x); + } + + /** + * subMap returns map with keys in requested range + */ + public void testSubMapContents() { + NavigableMap map = map5(); + SortedMap sm = map.subMap(two, four); + assertEquals(two, sm.firstKey()); + assertEquals(three, sm.lastKey()); + assertEquals(2, sm.size()); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(two)); + assertEquals(4, map.size()); + assertEquals(1, sm.size()); + assertEquals(three, sm.firstKey()); + assertEquals(three, sm.lastKey()); + assertEquals("C", sm.remove(three)); + assertTrue(sm.isEmpty()); + assertEquals(3, map.size()); + } + + public void testSubMapContents2() { + NavigableMap map = map5(); + SortedMap sm = map.subMap(two, three); + assertEquals(1, sm.size()); + assertEquals(two, sm.firstKey()); + assertEquals(two, sm.lastKey()); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertFalse(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + assertFalse(i.hasNext()); + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(two)); + assertEquals(4, map.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertSame(sm.remove(three), null); + assertEquals(4, map.size()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testHeadMapContents() { + NavigableMap map = map5(); + SortedMap sm = map.headMap(four); + assertTrue(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertFalse(sm.containsKey(four)); + assertFalse(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(one, k); + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, map.size()); + assertEquals(four, map.firstKey()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testTailMapContents() { + NavigableMap map = map5(); + SortedMap sm = map.tailMap(two); + assertFalse(sm.containsKey(one)); + assertTrue(sm.containsKey(two)); + assertTrue(sm.containsKey(three)); + assertTrue(sm.containsKey(four)); + assertTrue(sm.containsKey(five)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + k = (Integer)(i.next()); + assertEquals(four, k); + k = (Integer)(i.next()); + assertEquals(five, k); + assertFalse(i.hasNext()); + + Iterator ei = sm.entrySet().iterator(); + Map.Entry e; + e = (Map.Entry)(ei.next()); + assertEquals(two, e.getKey()); + assertEquals("B", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(three, e.getKey()); + assertEquals("C", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(four, e.getKey()); + assertEquals("D", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(five, e.getKey()); + assertEquals("E", e.getValue()); + assertFalse(i.hasNext()); + + SortedMap ssm = sm.tailMap(four); + assertEquals(four, ssm.firstKey()); + assertEquals(five, ssm.lastKey()); + assertEquals("D", ssm.remove(four)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, map.size()); + } + + /** + * clear removes all pairs + */ + public void testDescendingClear() { + NavigableMap map = dmap5(); + map.clear(); + assertEquals(0, map.size()); + } + + /** + * Maps with same contents are equal + */ + public void testDescendingEquals() { + NavigableMap map1 = dmap5(); + NavigableMap map2 = dmap5(); + assertEquals(map1, map2); + assertEquals(map2, map1); + map1.clear(); + assertFalse(map1.equals(map2)); + assertFalse(map2.equals(map1)); + } + + /** + * containsKey returns true for contained key + */ + public void testDescendingContainsKey() { + NavigableMap map = dmap5(); + assertTrue(map.containsKey(m1)); + assertFalse(map.containsKey(zero)); + } + + /** + * containsValue returns true for held values + */ + public void testDescendingContainsValue() { + NavigableMap map = dmap5(); + assertTrue(map.containsValue("A")); + assertFalse(map.containsValue("Z")); + } + + /** + * get returns the correct element at the given key, + * or null if not present + */ + public void testDescendingGet() { + NavigableMap map = dmap5(); + assertEquals("A", (String)map.get(m1)); + NavigableMap empty = dmap0(); + assertNull(empty.get(m1)); + } + + /** + * isEmpty is true of empty map and false for non-empty + */ + public void testDescendingIsEmpty() { + NavigableMap empty = dmap0(); + NavigableMap map = dmap5(); + assertTrue(empty.isEmpty()); + assertFalse(map.isEmpty()); + } + + /** + * firstKey returns first key + */ + public void testDescendingFirstKey() { + NavigableMap map = dmap5(); + assertEquals(m1, map.firstKey()); + } + + /** + * lastKey returns last key + */ + public void testDescendingLastKey() { + NavigableMap map = dmap5(); + assertEquals(m5, map.lastKey()); + } + + /** + * keySet returns a Set containing all the keys + */ + public void testDescendingKeySet() { + NavigableMap map = dmap5(); + Set s = map.keySet(); + assertEquals(5, s.size()); + assertTrue(s.contains(m1)); + assertTrue(s.contains(m2)); + assertTrue(s.contains(m3)); + assertTrue(s.contains(m4)); + assertTrue(s.contains(m5)); + } + + /** + * keySet is ordered + */ + public void testDescendingKeySetOrder() { + NavigableMap map = dmap5(); + Set s = map.keySet(); + Iterator i = s.iterator(); + Integer last = (Integer)i.next(); + assertEquals(last, m1); + while (i.hasNext()) { + Integer k = (Integer)i.next(); + assertTrue(last.compareTo(k) > 0); + last = k; + } + } + + /** + * values collection contains all values + */ + public void testDescendingValues() { + NavigableMap map = dmap5(); + Collection s = map.values(); + assertEquals(5, s.size()); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * keySet.toArray returns contains all keys + */ + public void testDescendingAscendingKeySetToArray() { + NavigableMap map = dmap5(); + Set s = map.keySet(); + Object[] ar = s.toArray(); + assertTrue(s.containsAll(Arrays.asList(ar))); + assertEquals(5, ar.length); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * descendingkeySet.toArray returns contains all keys + */ + public void testDescendingDescendingKeySetToArray() { + NavigableMap map = dmap5(); + Set s = map.descendingKeySet(); + Object[] ar = s.toArray(); + assertEquals(5, ar.length); + assertTrue(s.containsAll(Arrays.asList(ar))); + ar[0] = m10; + assertFalse(s.containsAll(Arrays.asList(ar))); + } + + /** + * Values.toArray contains all values + */ + public void testDescendingValuesToArray() { + NavigableMap map = dmap5(); + Collection v = map.values(); + Object[] ar = v.toArray(); + ArrayList s = new ArrayList(Arrays.asList(ar)); + assertEquals(5, ar.length); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); + } + + /** + * entrySet contains all pairs + */ + public void testDescendingEntrySet() { + NavigableMap map = dmap5(); + Set s = map.entrySet(); + assertEquals(5, s.size()); + Iterator it = s.iterator(); + while (it.hasNext()) { + Map.Entry e = (Map.Entry) it.next(); + assertTrue( + (e.getKey().equals(m1) && e.getValue().equals("A")) || + (e.getKey().equals(m2) && e.getValue().equals("B")) || + (e.getKey().equals(m3) && e.getValue().equals("C")) || + (e.getKey().equals(m4) && e.getValue().equals("D")) || + (e.getKey().equals(m5) && e.getValue().equals("E"))); + } + } + + /** + * putAll adds all key-value pairs from the given map + */ + public void testDescendingPutAll() { + NavigableMap empty = dmap0(); + NavigableMap map = dmap5(); + empty.putAll(map); + assertEquals(5, empty.size()); + assertTrue(empty.containsKey(m1)); + assertTrue(empty.containsKey(m2)); + assertTrue(empty.containsKey(m3)); + assertTrue(empty.containsKey(m4)); + assertTrue(empty.containsKey(m5)); + } + + /** + * remove removes the correct key-value pair from the map + */ + public void testDescendingRemove() { + NavigableMap map = dmap5(); + map.remove(m5); + assertEquals(4, map.size()); + assertFalse(map.containsKey(m5)); + } + + /** + * lowerEntry returns preceding entry. + */ + public void testDescendingLowerEntry() { + NavigableMap map = dmap5(); + Map.Entry e1 = map.lowerEntry(m3); + assertEquals(m2, e1.getKey()); + + Map.Entry e2 = map.lowerEntry(m6); + assertEquals(m5, e2.getKey()); + + Map.Entry e3 = map.lowerEntry(m1); + assertNull(e3); + + Map.Entry e4 = map.lowerEntry(zero); + assertNull(e4); + } + + /** + * higherEntry returns next entry. + */ + public void testDescendingHigherEntry() { + NavigableMap map = dmap5(); + Map.Entry e1 = map.higherEntry(m3); + assertEquals(m4, e1.getKey()); + + Map.Entry e2 = map.higherEntry(zero); + assertEquals(m1, e2.getKey()); + + Map.Entry e3 = map.higherEntry(m5); + assertNull(e3); + + Map.Entry e4 = map.higherEntry(m6); + assertNull(e4); + } + + /** + * floorEntry returns preceding entry. + */ + public void testDescendingFloorEntry() { + NavigableMap map = dmap5(); + Map.Entry e1 = map.floorEntry(m3); + assertEquals(m3, e1.getKey()); + + Map.Entry e2 = map.floorEntry(m6); + assertEquals(m5, e2.getKey()); + + Map.Entry e3 = map.floorEntry(m1); + assertEquals(m1, e3.getKey()); + + Map.Entry e4 = map.floorEntry(zero); + assertNull(e4); + } + + /** + * ceilingEntry returns next entry. + */ + public void testDescendingCeilingEntry() { + NavigableMap map = dmap5(); + Map.Entry e1 = map.ceilingEntry(m3); + assertEquals(m3, e1.getKey()); + + Map.Entry e2 = map.ceilingEntry(zero); + assertEquals(m1, e2.getKey()); + + Map.Entry e3 = map.ceilingEntry(m5); + assertEquals(m5, e3.getKey()); + + Map.Entry e4 = map.ceilingEntry(m6); + assertNull(e4); + } + + /** + * pollFirstEntry returns entries in order + */ + public void testDescendingPollFirstEntry() { + NavigableMap map = dmap5(); + Map.Entry e = map.pollFirstEntry(); + assertEquals(m1, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(m2, e.getKey()); + map.put(m1, "A"); + e = map.pollFirstEntry(); + assertEquals(m1, e.getKey()); + assertEquals("A", e.getValue()); + e = map.pollFirstEntry(); + assertEquals(m3, e.getKey()); + map.remove(m4); + e = map.pollFirstEntry(); + assertEquals(m5, e.getKey()); + try { + e.setValue("A"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollFirstEntry(); + assertNull(e); + } + + /** + * pollLastEntry returns entries in order + */ + public void testDescendingPollLastEntry() { + NavigableMap map = dmap5(); + Map.Entry e = map.pollLastEntry(); + assertEquals(m5, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(m4, e.getKey()); + map.put(m5, "E"); + e = map.pollLastEntry(); + assertEquals(m5, e.getKey()); + assertEquals("E", e.getValue()); + e = map.pollLastEntry(); + assertEquals(m3, e.getKey()); + map.remove(m2); + e = map.pollLastEntry(); + assertEquals(m1, e.getKey()); + try { + e.setValue("E"); + shouldThrow(); + } catch (UnsupportedOperationException success) {} + e = map.pollLastEntry(); + assertNull(e); + } + + /** + * size returns the correct values + */ + public void testDescendingSize() { + NavigableMap map = dmap5(); + NavigableMap empty = dmap0(); + assertEquals(0, empty.size()); + assertEquals(5, map.size()); + } + + /** + * toString contains toString of elements + */ + public void testDescendingToString() { + NavigableMap map = dmap5(); + String s = map.toString(); + for (int i = 1; i <= 5; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + // Exception testDescendings + + /** + * get(null) of nonempty map throws NPE + */ + public void testDescendingGet_NullPointerException() { + NavigableMap c = dmap5(); + try { + c.get(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * put(null,x) throws NPE + */ + public void testDescendingPut1_NullPointerException() { + NavigableMap c = dmap5(); + try { + c.put(null, "whatever"); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * A deserialized map equals original + */ + public void testDescendingSerialization() throws Exception { + NavigableMap x = dmap5(); + NavigableMap y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertEquals(x, y); + assertEquals(y, x); + } + + /** + * subMap returns map with keys in requested range + */ + public void testDescendingSubMapContents() { + NavigableMap map = dmap5(); + SortedMap sm = map.subMap(m2, m4); + assertEquals(m2, sm.firstKey()); + assertEquals(m3, sm.lastKey()); + assertEquals(2, sm.size()); + assertFalse(sm.containsKey(m1)); + assertTrue(sm.containsKey(m2)); + assertTrue(sm.containsKey(m3)); + assertFalse(sm.containsKey(m4)); + assertFalse(sm.containsKey(m5)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + assertFalse(i.hasNext()); + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(m2)); + assertEquals(4, map.size()); + assertEquals(1, sm.size()); + assertEquals(m3, sm.firstKey()); + assertEquals(m3, sm.lastKey()); + assertEquals("C", sm.remove(m3)); + assertTrue(sm.isEmpty()); + assertEquals(3, map.size()); + } + + public void testDescendingSubMapContents2() { + NavigableMap map = dmap5(); + SortedMap sm = map.subMap(m2, m3); + assertEquals(1, sm.size()); + assertEquals(m2, sm.firstKey()); + assertEquals(m2, sm.lastKey()); + assertFalse(sm.containsKey(m1)); + assertTrue(sm.containsKey(m2)); + assertFalse(sm.containsKey(m3)); + assertFalse(sm.containsKey(m4)); + assertFalse(sm.containsKey(m5)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + assertFalse(i.hasNext()); + Iterator j = sm.keySet().iterator(); + j.next(); + j.remove(); + assertFalse(map.containsKey(m2)); + assertEquals(4, map.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertSame(sm.remove(m3), null); + assertEquals(4, map.size()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testDescendingHeadMapContents() { + NavigableMap map = dmap5(); + SortedMap sm = map.headMap(m4); + assertTrue(sm.containsKey(m1)); + assertTrue(sm.containsKey(m2)); + assertTrue(sm.containsKey(m3)); + assertFalse(sm.containsKey(m4)); + assertFalse(sm.containsKey(m5)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m1, k); + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, map.size()); + assertEquals(m4, map.firstKey()); + } + + /** + * headMap returns map with keys in requested range + */ + public void testDescendingTailMapContents() { + NavigableMap map = dmap5(); + SortedMap sm = map.tailMap(m2); + assertFalse(sm.containsKey(m1)); + assertTrue(sm.containsKey(m2)); + assertTrue(sm.containsKey(m3)); + assertTrue(sm.containsKey(m4)); + assertTrue(sm.containsKey(m5)); + Iterator i = sm.keySet().iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + k = (Integer)(i.next()); + assertEquals(m4, k); + k = (Integer)(i.next()); + assertEquals(m5, k); + assertFalse(i.hasNext()); + + Iterator ei = sm.entrySet().iterator(); + Map.Entry e; + e = (Map.Entry)(ei.next()); + assertEquals(m2, e.getKey()); + assertEquals("B", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(m3, e.getKey()); + assertEquals("C", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(m4, e.getKey()); + assertEquals("D", e.getValue()); + e = (Map.Entry)(ei.next()); + assertEquals(m5, e.getKey()); + assertEquals("E", e.getValue()); + assertFalse(i.hasNext()); + + SortedMap ssm = sm.tailMap(m4); + assertEquals(m4, ssm.firstKey()); + assertEquals(m5, ssm.lastKey()); + assertEquals("D", ssm.remove(m4)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, map.size()); + } + +} diff --git a/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java b/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java new file mode 100644 index 00000000000..afc0604075d --- /dev/null +++ b/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java @@ -0,0 +1,1139 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import junit.framework.Test; +import junit.framework.TestSuite; + +public class TreeSubSetTest extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + public static Test suite() { + return new TestSuite(TreeSubSetTest.class); + } + + static class MyReverseComparator implements Comparator { + public int compare(Object x, Object y) { + return ((Comparable)y).compareTo(x); + } + } + + /** + * Returns a new set of given size containing consecutive + * Integers 0 ... n. + */ + private NavigableSet populatedSet(int n) { + TreeSet q = new TreeSet(); + assertTrue(q.isEmpty()); + + for (int i = n - 1; i >= 0; i -= 2) + assertTrue(q.add(new Integer(i))); + for (int i = (n & 1); i < n; i += 2) + assertTrue(q.add(new Integer(i))); + assertTrue(q.add(new Integer(-n))); + assertTrue(q.add(new Integer(n))); + NavigableSet s = q.subSet(new Integer(0), true, new Integer(n), false); + assertFalse(s.isEmpty()); + assertEquals(n, s.size()); + return s; + } + + /** + * Returns a new set of first 5 ints. + */ + private NavigableSet set5() { + TreeSet q = new TreeSet(); + assertTrue(q.isEmpty()); + q.add(one); + q.add(two); + q.add(three); + q.add(four); + q.add(five); + q.add(zero); + q.add(seven); + NavigableSet s = q.subSet(one, true, seven, false); + assertEquals(5, s.size()); + return s; + } + + private NavigableSet dset5() { + TreeSet q = new TreeSet(); + assertTrue(q.isEmpty()); + q.add(m1); + q.add(m2); + q.add(m3); + q.add(m4); + q.add(m5); + NavigableSet s = q.descendingSet(); + assertEquals(5, s.size()); + return s; + } + + private static NavigableSet set0() { + TreeSet set = new TreeSet(); + assertTrue(set.isEmpty()); + return set.tailSet(m1, false); + } + + private static NavigableSet dset0() { + TreeSet set = new TreeSet(); + assertTrue(set.isEmpty()); + return set; + } + + /** + * A new set has unbounded capacity + */ + public void testConstructor1() { + assertEquals(0, set0().size()); + } + + /** + * isEmpty is true before add, false after + */ + public void testEmpty() { + NavigableSet q = set0(); + assertTrue(q.isEmpty()); + assertTrue(q.add(new Integer(1))); + assertFalse(q.isEmpty()); + assertTrue(q.add(new Integer(2))); + q.pollFirst(); + q.pollFirst(); + assertTrue(q.isEmpty()); + } + + /** + * size changes when elements added and removed + */ + public void testSize() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.pollFirst(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * add(null) throws NPE + */ + public void testAddNull() { + NavigableSet q = set0(); + try { + q.add(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Add of comparable element succeeds + */ + public void testAdd() { + NavigableSet q = set0(); + assertTrue(q.add(six)); + } + + /** + * Add of duplicate element fails + */ + public void testAddDup() { + NavigableSet q = set0(); + assertTrue(q.add(six)); + assertFalse(q.add(six)); + } + + /** + * Add of non-Comparable throws CCE + */ + public void testAddNonComparable() { + NavigableSet q = set0(); + try { + q.add(new Object()); + q.add(new Object()); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * addAll(null) throws NPE + */ + public void testAddAll1() { + NavigableSet q = set0(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testAddAll2() { + NavigableSet q = set0(); + Integer[] ints = new Integer[SIZE]; + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testAddAll3() { + NavigableSet q = set0(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i + SIZE); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Set contains all elements of successful addAll + */ + public void testAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(SIZE - 1 - i); + NavigableSet q = set0(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(new Integer(i), q.pollFirst()); + } + + /** + * poll succeeds unless empty + */ + public void testPoll() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst()); + } + assertNull(q.pollFirst()); + } + + /** + * remove(x) removes x and returns true if present + */ + public void testRemoveElement() { + NavigableSet q = populatedSet(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertTrue(q.contains(i - 1)); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.contains(i)); + assertTrue(q.remove(i)); + assertFalse(q.contains(i)); + assertFalse(q.remove(i + 1)); + assertFalse(q.contains(i + 1)); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testContains() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.pollFirst(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testClear() { + NavigableSet q = populatedSet(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertTrue(q.add(new Integer(1))); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testContainsAll() { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = set0(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testRetainAll() { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.pollFirst(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = populatedSet(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.pollFirst()); + assertFalse(q.contains(x)); + } + } + } + + /** + * lower returns preceding element + */ + public void testLower() { + NavigableSet q = set5(); + Object e1 = q.lower(three); + assertEquals(two, e1); + + Object e2 = q.lower(six); + assertEquals(five, e2); + + Object e3 = q.lower(one); + assertNull(e3); + + Object e4 = q.lower(zero); + assertNull(e4); + } + + /** + * higher returns next element + */ + public void testHigher() { + NavigableSet q = set5(); + Object e1 = q.higher(three); + assertEquals(four, e1); + + Object e2 = q.higher(zero); + assertEquals(one, e2); + + Object e3 = q.higher(five); + assertNull(e3); + + Object e4 = q.higher(six); + assertNull(e4); + } + + /** + * floor returns preceding element + */ + public void testFloor() { + NavigableSet q = set5(); + Object e1 = q.floor(three); + assertEquals(three, e1); + + Object e2 = q.floor(six); + assertEquals(five, e2); + + Object e3 = q.floor(one); + assertEquals(one, e3); + + Object e4 = q.floor(zero); + assertNull(e4); + } + + /** + * ceiling returns next element + */ + public void testCeiling() { + NavigableSet q = set5(); + Object e1 = q.ceiling(three); + assertEquals(three, e1); + + Object e2 = q.ceiling(zero); + assertEquals(one, e2); + + Object e3 = q.ceiling(five); + assertEquals(five, e3); + + Object e4 = q.ceiling(six); + assertNull(e4); + } + + /** + * toArray contains all elements in sorted order + */ + public void testToArray() { + NavigableSet q = populatedSet(SIZE); + Object[] o = q.toArray(); + for (int i = 0; i < o.length; i++) + assertSame(o[i], q.pollFirst()); + } + + /** + * toArray(a) contains all elements in sorted order + */ + public void testToArray2() { + NavigableSet q = populatedSet(SIZE); + Integer[] ints = new Integer[SIZE]; + Integer[] array = q.toArray(ints); + assertSame(ints, array); + for (int i = 0; i < ints.length; i++) + assertSame(ints[i], q.pollFirst()); + } + + /** + * iterator iterates through all elements + */ + public void testIterator() { + NavigableSet q = populatedSet(SIZE); + Iterator it = q.iterator(); + int i; + for (i = 0; it.hasNext(); i++) + assertTrue(q.contains(it.next())); + assertEquals(i, SIZE); + assertIteratorExhausted(it); + } + + /** + * iterator of empty set has no elements + */ + public void testEmptyIterator() { + assertIteratorExhausted(set0().iterator()); + } + + /** + * iterator.remove removes current element + */ + public void testIteratorRemove() { + final NavigableSet q = set0(); + q.add(new Integer(2)); + q.add(new Integer(1)); + q.add(new Integer(3)); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertEquals(2, it.next()); + assertEquals(3, it.next()); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testToString() { + NavigableSet q = populatedSet(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized set has same elements + */ + public void testSerialization() throws Exception { + NavigableSet x = populatedSet(SIZE); + NavigableSet y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x, y); + assertEquals(y, x); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.pollFirst(), y.pollFirst()); + } + assertTrue(y.isEmpty()); + } + + /** + * subSet returns set with keys in requested range + */ + public void testSubSetContents() { + NavigableSet set = set5(); + SortedSet sm = set.subSet(two, four); + assertEquals(two, sm.first()); + assertEquals(three, sm.last()); + assertEquals(2, sm.size()); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(two)); + assertEquals(4, set.size()); + assertEquals(1, sm.size()); + assertEquals(three, sm.first()); + assertEquals(three, sm.last()); + assertTrue(sm.remove(three)); + assertTrue(sm.isEmpty()); + assertEquals(3, set.size()); + } + + public void testSubSetContents2() { + NavigableSet set = set5(); + SortedSet sm = set.subSet(two, three); + assertEquals(1, sm.size()); + assertEquals(two, sm.first()); + assertEquals(two, sm.last()); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertFalse(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(two)); + assertEquals(4, set.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertFalse(sm.remove(three)); + assertEquals(4, set.size()); + } + + /** + * headSet returns set with keys in requested range + */ + public void testHeadSetContents() { + NavigableSet set = set5(); + SortedSet sm = set.headSet(four); + assertTrue(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertFalse(sm.contains(four)); + assertFalse(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(one, k); + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, set.size()); + assertEquals(four, set.first()); + } + + /** + * tailSet returns set with keys in requested range + */ + public void testTailSetContents() { + NavigableSet set = set5(); + SortedSet sm = set.tailSet(two); + assertFalse(sm.contains(one)); + assertTrue(sm.contains(two)); + assertTrue(sm.contains(three)); + assertTrue(sm.contains(four)); + assertTrue(sm.contains(five)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(two, k); + k = (Integer)(i.next()); + assertEquals(three, k); + k = (Integer)(i.next()); + assertEquals(four, k); + k = (Integer)(i.next()); + assertEquals(five, k); + assertFalse(i.hasNext()); + + SortedSet ssm = sm.tailSet(four); + assertEquals(four, ssm.first()); + assertEquals(five, ssm.last()); + assertTrue(ssm.remove(four)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, set.size()); + } + + /** + * size changes when elements added and removed + */ + public void testDescendingSize() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(SIZE - i, q.size()); + q.pollFirst(); + } + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.size()); + q.add(new Integer(i)); + } + } + + /** + * Add of comparable element succeeds + */ + public void testDescendingAdd() { + NavigableSet q = dset0(); + assertTrue(q.add(m6)); + } + + /** + * Add of duplicate element fails + */ + public void testDescendingAddDup() { + NavigableSet q = dset0(); + assertTrue(q.add(m6)); + assertFalse(q.add(m6)); + } + + /** + * Add of non-Comparable throws CCE + */ + public void testDescendingAddNonComparable() { + NavigableSet q = dset0(); + try { + q.add(new Object()); + q.add(new Object()); + shouldThrow(); + } catch (ClassCastException success) {} + } + + /** + * addAll(null) throws NPE + */ + public void testDescendingAddAll1() { + NavigableSet q = dset0(); + try { + q.addAll(null); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with null elements throws NPE + */ + public void testDescendingAddAll2() { + NavigableSet q = dset0(); + Integer[] ints = new Integer[SIZE]; + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * addAll of a collection with any null elements throws NPE after + * possibly adding some elements + */ + public void testDescendingAddAll3() { + NavigableSet q = dset0(); + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE - 1; ++i) + ints[i] = new Integer(i + SIZE); + try { + q.addAll(Arrays.asList(ints)); + shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * Set contains all elements of successful addAll + */ + public void testDescendingAddAll5() { + Integer[] empty = new Integer[0]; + Integer[] ints = new Integer[SIZE]; + for (int i = 0; i < SIZE; ++i) + ints[i] = new Integer(SIZE - 1 - i); + NavigableSet q = dset0(); + assertFalse(q.addAll(Arrays.asList(empty))); + assertTrue(q.addAll(Arrays.asList(ints))); + for (int i = 0; i < SIZE; ++i) + assertEquals(new Integer(i), q.pollFirst()); + } + + /** + * poll succeeds unless empty + */ + public void testDescendingPoll() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertEquals(i, q.pollFirst()); + } + assertNull(q.pollFirst()); + } + + /** + * remove(x) removes x and returns true if present + */ + public void testDescendingRemoveElement() { + NavigableSet q = populatedSet(SIZE); + for (int i = 1; i < SIZE; i += 2) { + assertTrue(q.remove(new Integer(i))); + } + for (int i = 0; i < SIZE; i += 2) { + assertTrue(q.remove(new Integer(i))); + assertFalse(q.remove(new Integer(i + 1))); + } + assertTrue(q.isEmpty()); + } + + /** + * contains(x) reports true when elements added but not yet removed + */ + public void testDescendingContains() { + NavigableSet q = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.contains(new Integer(i))); + q.pollFirst(); + assertFalse(q.contains(new Integer(i))); + } + } + + /** + * clear removes all elements + */ + public void testDescendingClear() { + NavigableSet q = populatedSet(SIZE); + q.clear(); + assertTrue(q.isEmpty()); + assertEquals(0, q.size()); + assertTrue(q.add(new Integer(1))); + assertFalse(q.isEmpty()); + q.clear(); + assertTrue(q.isEmpty()); + } + + /** + * containsAll(c) is true when c contains a subset of elements + */ + public void testDescendingContainsAll() { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = dset0(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(q.containsAll(p)); + assertFalse(p.containsAll(q)); + p.add(new Integer(i)); + } + assertTrue(p.containsAll(q)); + } + + /** + * retainAll(c) retains only those elements of c and reports true if changed + */ + public void testDescendingRetainAll() { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = populatedSet(SIZE); + for (int i = 0; i < SIZE; ++i) { + boolean changed = q.retainAll(p); + if (i == 0) + assertFalse(changed); + else + assertTrue(changed); + + assertTrue(q.containsAll(p)); + assertEquals(SIZE - i, q.size()); + p.pollFirst(); + } + } + + /** + * removeAll(c) removes only those elements of c and reports true if changed + */ + public void testDescendingRemoveAll() { + for (int i = 1; i < SIZE; ++i) { + NavigableSet q = populatedSet(SIZE); + NavigableSet p = populatedSet(i); + assertTrue(q.removeAll(p)); + assertEquals(SIZE - i, q.size()); + for (int j = 0; j < i; ++j) { + Integer x = (Integer)(p.pollFirst()); + assertFalse(q.contains(x)); + } + } + } + + /** + * lower returns preceding element + */ + public void testDescendingLower() { + NavigableSet q = dset5(); + Object e1 = q.lower(m3); + assertEquals(m2, e1); + + Object e2 = q.lower(m6); + assertEquals(m5, e2); + + Object e3 = q.lower(m1); + assertNull(e3); + + Object e4 = q.lower(zero); + assertNull(e4); + } + + /** + * higher returns next element + */ + public void testDescendingHigher() { + NavigableSet q = dset5(); + Object e1 = q.higher(m3); + assertEquals(m4, e1); + + Object e2 = q.higher(zero); + assertEquals(m1, e2); + + Object e3 = q.higher(m5); + assertNull(e3); + + Object e4 = q.higher(m6); + assertNull(e4); + } + + /** + * floor returns preceding element + */ + public void testDescendingFloor() { + NavigableSet q = dset5(); + Object e1 = q.floor(m3); + assertEquals(m3, e1); + + Object e2 = q.floor(m6); + assertEquals(m5, e2); + + Object e3 = q.floor(m1); + assertEquals(m1, e3); + + Object e4 = q.floor(zero); + assertNull(e4); + } + + /** + * ceiling returns next element + */ + public void testDescendingCeiling() { + NavigableSet q = dset5(); + Object e1 = q.ceiling(m3); + assertEquals(m3, e1); + + Object e2 = q.ceiling(zero); + assertEquals(m1, e2); + + Object e3 = q.ceiling(m5); + assertEquals(m5, e3); + + Object e4 = q.ceiling(m6); + assertNull(e4); + } + + /** + * toArray contains all elements + */ + public void testDescendingToArray() { + NavigableSet q = populatedSet(SIZE); + Object[] o = q.toArray(); + Arrays.sort(o); + for (int i = 0; i < o.length; i++) + assertEquals(o[i], q.pollFirst()); + } + + /** + * toArray(a) contains all elements + */ + public void testDescendingToArray2() { + NavigableSet q = populatedSet(SIZE); + Integer[] ints = new Integer[SIZE]; + assertSame(ints, q.toArray(ints)); + Arrays.sort(ints); + for (int i = 0; i < ints.length; i++) + assertEquals(ints[i], q.pollFirst()); + } + + /** + * iterator iterates through all elements + */ + public void testDescendingIterator() { + NavigableSet q = populatedSet(SIZE); + int i = 0; + Iterator it = q.iterator(); + while (it.hasNext()) { + assertTrue(q.contains(it.next())); + ++i; + } + assertEquals(i, SIZE); + } + + /** + * iterator of empty set has no elements + */ + public void testDescendingEmptyIterator() { + NavigableSet q = dset0(); + int i = 0; + Iterator it = q.iterator(); + while (it.hasNext()) { + assertTrue(q.contains(it.next())); + ++i; + } + assertEquals(0, i); + } + + /** + * iterator.remove removes current element + */ + public void testDescendingIteratorRemove() { + final NavigableSet q = dset0(); + q.add(new Integer(2)); + q.add(new Integer(1)); + q.add(new Integer(3)); + + Iterator it = q.iterator(); + it.next(); + it.remove(); + + it = q.iterator(); + assertEquals(2, it.next()); + assertEquals(3, it.next()); + assertFalse(it.hasNext()); + } + + /** + * toString contains toStrings of elements + */ + public void testDescendingToString() { + NavigableSet q = populatedSet(SIZE); + String s = q.toString(); + for (int i = 0; i < SIZE; ++i) { + assertTrue(s.contains(String.valueOf(i))); + } + } + + /** + * A deserialized serialized set has same elements + */ + public void testDescendingSerialization() throws Exception { + NavigableSet x = dset5(); + NavigableSet y = serialClone(x); + + assertNotSame(x, y); + assertEquals(x.size(), y.size()); + assertEquals(x.toString(), y.toString()); + assertEquals(x, y); + assertEquals(y, x); + while (!x.isEmpty()) { + assertFalse(y.isEmpty()); + assertEquals(x.pollFirst(), y.pollFirst()); + } + assertTrue(y.isEmpty()); + } + + /** + * subSet returns set with keys in requested range + */ + public void testDescendingSubSetContents() { + NavigableSet set = dset5(); + SortedSet sm = set.subSet(m2, m4); + assertEquals(m2, sm.first()); + assertEquals(m3, sm.last()); + assertEquals(2, sm.size()); + assertFalse(sm.contains(m1)); + assertTrue(sm.contains(m2)); + assertTrue(sm.contains(m3)); + assertFalse(sm.contains(m4)); + assertFalse(sm.contains(m5)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(m2)); + assertEquals(4, set.size()); + assertEquals(1, sm.size()); + assertEquals(m3, sm.first()); + assertEquals(m3, sm.last()); + assertTrue(sm.remove(m3)); + assertTrue(sm.isEmpty()); + assertEquals(3, set.size()); + } + + public void testDescendingSubSetContents2() { + NavigableSet set = dset5(); + SortedSet sm = set.subSet(m2, m3); + assertEquals(1, sm.size()); + assertEquals(m2, sm.first()); + assertEquals(m2, sm.last()); + assertFalse(sm.contains(m1)); + assertTrue(sm.contains(m2)); + assertFalse(sm.contains(m3)); + assertFalse(sm.contains(m4)); + assertFalse(sm.contains(m5)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + assertFalse(i.hasNext()); + Iterator j = sm.iterator(); + j.next(); + j.remove(); + assertFalse(set.contains(m2)); + assertEquals(4, set.size()); + assertEquals(0, sm.size()); + assertTrue(sm.isEmpty()); + assertFalse(sm.remove(m3)); + assertEquals(4, set.size()); + } + + /** + * headSet returns set with keys in requested range + */ + public void testDescendingHeadSetContents() { + NavigableSet set = dset5(); + SortedSet sm = set.headSet(m4); + assertTrue(sm.contains(m1)); + assertTrue(sm.contains(m2)); + assertTrue(sm.contains(m3)); + assertFalse(sm.contains(m4)); + assertFalse(sm.contains(m5)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m1, k); + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + assertFalse(i.hasNext()); + sm.clear(); + assertTrue(sm.isEmpty()); + assertEquals(2, set.size()); + assertEquals(m4, set.first()); + } + + /** + * tailSet returns set with keys in requested range + */ + public void testDescendingTailSetContents() { + NavigableSet set = dset5(); + SortedSet sm = set.tailSet(m2); + assertFalse(sm.contains(m1)); + assertTrue(sm.contains(m2)); + assertTrue(sm.contains(m3)); + assertTrue(sm.contains(m4)); + assertTrue(sm.contains(m5)); + Iterator i = sm.iterator(); + Object k; + k = (Integer)(i.next()); + assertEquals(m2, k); + k = (Integer)(i.next()); + assertEquals(m3, k); + k = (Integer)(i.next()); + assertEquals(m4, k); + k = (Integer)(i.next()); + assertEquals(m5, k); + assertFalse(i.hasNext()); + + SortedSet ssm = sm.tailSet(m4); + assertEquals(m4, ssm.first()); + assertEquals(m5, ssm.last()); + assertTrue(ssm.remove(m4)); + assertEquals(1, ssm.size()); + assertEquals(3, sm.size()); + assertEquals(4, set.size()); + } + + /** + * addAll is idempotent + */ + public void testAddAll_idempotent() throws Exception { + Set x = populatedSet(SIZE); + Set y = new TreeSet(x); + y.addAll(x); + assertEquals(x, y); + assertEquals(y, x); + } + +} diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java index 0eb7c874249..d9a87bb8115 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ public class DoubleStreamTestDataProvider { private static final double[] pseudoRandom; private static final Object[][] testData; + private static final Object[][] testSmallData; private static final Object[][] spliteratorTestData; static { @@ -78,11 +79,15 @@ public class DoubleStreamTestDataProvider { static { { - List list = new ArrayList<>(); + List listSmall = new ArrayList<>(); + List list1000 = new ArrayList<>(); + List list = null; for (Object[] data : arrays) { final Object name = data[0]; final double[] doubles = (double[]) data[1]; + list = doubles.length >= 1000 ? list1000 : listSmall; + list.add(new Object[]{"array:" + name, TestData.Factory.ofArray("array:" + name, doubles)}); @@ -93,7 +98,9 @@ public class DoubleStreamTestDataProvider { list.add(new Object[]{"SpinedList:" + name, TestData.Factory.ofSpinedBuffer("SpinedList:" + name, isl)}); } - testData = list.toArray(new Object[0][]); + testSmallData = listSmall.toArray(new Object[0][]); + list1000.addAll(listSmall); + testData = list1000.toArray(new Object[0][]); } { @@ -136,6 +143,11 @@ public class DoubleStreamTestDataProvider { return testData; } + @DataProvider(name = "DoubleStreamTestData.small") + public static Object[][] makeSmallDoubleStreamTestData() { + return testSmallData; + } + // returns an array of (String name, Supplier>) @DataProvider(name = "DoubleSpliterator") public static Object[][] spliteratorProvider() { diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java index dded670d167..945cd9580e5 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ public class IntStreamTestDataProvider { private static final int[] pseudoRandom; private static final Object[][] testData; + private static final Object[][] testSmallData; private static final Object[][] spliteratorTestData; static { @@ -78,11 +79,15 @@ public class IntStreamTestDataProvider { static { { - List list = new ArrayList<>(); + List listSmall = new ArrayList<>(); + List list1000 = new ArrayList<>(); + List list = null; for (Object[] data : arrays) { final Object name = data[0]; final int[] ints = (int[]) data[1]; + list = ints.length >= 1000 ? list1000 : listSmall; + list.add(new Object[]{"array:" + name, TestData.Factory.ofArray("array:" + name, ints)}); @@ -98,7 +103,9 @@ public class IntStreamTestDataProvider { list.add(streamDataDescr("IntStream.rangeClosed(0,l): " + ints.length, () -> IntStream.rangeClosed(0, ints.length))); } - testData = list.toArray(new Object[0][]); + testSmallData = listSmall.toArray(new Object[0][]); + list1000.addAll(listSmall); + testData = list1000.toArray(new Object[0][]); } { @@ -150,6 +157,11 @@ public class IntStreamTestDataProvider { return testData; } + @DataProvider(name = "IntStreamTestData.small") + public static Object[][] makeSmallIntStreamTestData() { + return testSmallData; + } + // returns an array of (String name, Supplier>) @DataProvider(name = "IntSpliterator") public static Object[][] spliteratorProvider() { diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java index 4ce7ae6d217..80b1dcc1019 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ public class LongStreamTestDataProvider { private static final long[] pseudoRandom; private static final Object[][] testData; + private static final Object[][] testSmallData; private static final Object[][] spliteratorTestData; static { @@ -78,11 +79,15 @@ public class LongStreamTestDataProvider { static { { - List list = new ArrayList<>(); + List listSmall = new ArrayList<>(); + List list1000 = new ArrayList<>(); + List list = null; for (Object[] data : arrays) { final Object name = data[0]; final long[] longs = (long[]) data[1]; + list = longs.length >= 1000 ? list1000 : listSmall; + list.add(new Object[]{"array:" + name, TestData.Factory.ofArray("array:" + name, longs)}); @@ -98,7 +103,9 @@ public class LongStreamTestDataProvider { list.add(streamDataDescr("LongStream.longRangeClosed(0,l): " + longs.length, () -> LongStream.rangeClosed(0, longs.length))); } - testData = list.toArray(new Object[0][]); + testSmallData = listSmall.toArray(new Object[0][]); + list1000.addAll(listSmall); + testData = list1000.toArray(new Object[0][]); } { @@ -150,6 +157,11 @@ public class LongStreamTestDataProvider { return testData; } + @DataProvider(name = "LongStreamTestData.small") + public static Object[][] makeSmallLongStreamTestData() { + return testSmallData; + } + // returns an array of (String name, Supplier>) @DataProvider(name = "LongSpliterator") public static Object[][] spliteratorProvider() { diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java index 6f772f391ee..8a849015260 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ public class StreamTestDataProvider { private static final Integer[] pseudoRandom; private static final Object[][] testData; + private static final Object[][] testSmallData; private static final Object[][] withNullTestData; private static final Object[][] spliteratorTestData; @@ -84,12 +85,16 @@ public class StreamTestDataProvider { static { { - List list = new ArrayList<>(); + List listSmall = new ArrayList<>(); + List list1000 = new ArrayList<>(); + List list = null; for (Object[] data : arrays) { final Object name = data[0]; final Integer[] ints = (Integer[])data[1]; final List intsAsList = Arrays.asList(ints); + list = ints.length >= 1000 ? list1000 : listSmall; + list.add(arrayDataDescr("array:" + name, ints)); list.add(collectionDataDescr("ArrayList.asList:" + name, intsAsList)); list.add(collectionDataDescr("ArrayList:" + name, new ArrayList<>(intsAsList))); @@ -114,7 +119,9 @@ public class StreamTestDataProvider { // @@@ Add more } - testData = list.toArray(new Object[0][]); + testSmallData = listSmall.toArray(new Object[0][]); + list1000.addAll(listSmall); + testData = list1000.toArray(new Object[0][]); } // Simple combination of numbers and null values, probably excessive but may catch @@ -192,6 +199,11 @@ public class StreamTestDataProvider { return testData; } + @DataProvider(name = "StreamTestData.small") + public static Object[][] makeSmallStreamTestData() { + return testSmallData; + } + @DataProvider(name = "withNull:StreamTestData") public static Object[][] makeStreamWithNullTestData() { return withNullTestData; diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java index 453ec6e952c..afbedc871da 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @summary flat-map operations - * @bug 8044047 + * @bug 8044047 8076458 */ package org.openjdk.tests.java.util.stream; @@ -140,7 +140,10 @@ public class FlatMapOpTest extends OpTestCase { result = exerciseOps(data, s-> s.flatMap(e -> Stream.empty())); assertEquals(0, result.size()); + } + @Test(dataProvider = "StreamTestData.small", dataProviderClass = StreamTestDataProvider.class) + public void testOpsX(String name, TestData.OfRef data) { exerciseOps(data, s -> s.flatMap(mfLt)); exerciseOps(data, s -> s.flatMap(integerRangeMapper)); exerciseOps(data, s -> s.flatMap((Integer e) -> IntStream.range(0, e).boxed().limit(10))); @@ -156,7 +159,10 @@ public class FlatMapOpTest extends OpTestCase { result = exerciseOps(data, s -> s.flatMap(i -> IntStream.empty())); assertEquals(0, result.size()); + } + @Test(dataProvider = "IntStreamTestData.small", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOpsX(String name, TestData.OfInt data) { exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, e))); exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, e).limit(10))); } @@ -171,7 +177,10 @@ public class FlatMapOpTest extends OpTestCase { result = exerciseOps(data, s -> LongStream.empty()); assertEquals(0, result.size()); + } + @Test(dataProvider = "LongStreamTestData.small", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOpsX(String name, TestData.OfLong data) { exerciseOps(data, s -> s.flatMap(e -> LongStream.range(0, e))); exerciseOps(data, s -> s.flatMap(e -> LongStream.range(0, e).limit(10))); } @@ -186,7 +195,10 @@ public class FlatMapOpTest extends OpTestCase { result = exerciseOps(data, s -> DoubleStream.empty()); assertEquals(0, result.size()); + } + @Test(dataProvider = "DoubleStreamTestData.small", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOpsX(String name, TestData.OfDouble data) { exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, (int) e).asDoubleStream())); exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, (int) e).limit(10).asDoubleStream())); } diff --git a/jdk/test/javax/imageio/MultiReadTest.java b/jdk/test/javax/imageio/MultiReadTest.java index daea61610be..2e19d0b360c 100644 --- a/jdk/test/javax/imageio/MultiReadTest.java +++ b/jdk/test/javax/imageio/MultiReadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ public class MultiReadTest { private static final int max = 5; public static void main(String[] args) throws IOException { - final String[] formats = { "bmp", "png", "gif", "jpg" }; + final String[] formats = { "bmp", "png", "gif", "jpg", "tif" }; for (String f : formats) { test(f); diff --git a/jdk/test/javax/imageio/plugins/jpeg/JpegRawImageTypeTest.java b/jdk/test/javax/imageio/plugins/jpeg/JpegRawImageTypeTest.java new file mode 100644 index 00000000000..8749ca0daa6 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/jpeg/JpegRawImageTypeTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8143562 + * @summary Test verifies whether getRawImageType API returns proper raw + * image type when color space is of type YCbCr. + * @run main JpegRawImageTypeTest + */ + +import java.io.File; +import java.util.Iterator; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.stream.ImageInputStream; + +public class JpegRawImageTypeTest { + + public static void main(String[] args) throws Exception { + + //nomarkers.jpg has YCbCr color space + String fileName = "nomarkers.jpg"; + String sep = System.getProperty("file.separator"); + String dir = System.getProperty("test.src", "."); + String filePath = dir+sep+fileName; + System.out.println("Test file: " + filePath); + File imageFile = new File(filePath); + + ImageInputStream inputStream = ImageIO. + createImageInputStream(imageFile); + Iterator readers = ImageIO.getImageReaders(inputStream); + + if(readers.hasNext()) { + ImageReader reader = readers.next(); + reader.setInput(inputStream); + + ImageTypeSpecifier typeSpecifier = reader.getRawImageType(0); + //check if ImageTypeSpecifier is null for YCbCr JPEG Image + if (typeSpecifier == null) { + throw new RuntimeException("ImageReader returns null raw image" + + " type"); + } + } + } +} diff --git a/jdk/test/javax/imageio/plugins/shared/BitDepth.java b/jdk/test/javax/imageio/plugins/shared/BitDepth.java index 9f1e2ee6da9..4e051738590 100644 --- a/jdk/test/javax/imageio/plugins/shared/BitDepth.java +++ b/jdk/test/javax/imageio/plugins/shared/BitDepth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,11 @@ /** * @test - * @bug 4413109 4418221 6607198 + * @bug 4413109 4418221 6607198 8147448 * @run main BitDepth - * @summary Checks that the PNG and JPEG writers can handle various - * BufferedImage types. An optional list of arguments may be used to - * test a different format writer or writers. + * @summary Checks that ImageIO writers for standard formats can handle + * various BufferedImage RGB types. An optional list of arguments + * may be used to test the writers for a different list of formats. */ import java.awt.Color; @@ -81,21 +81,19 @@ public class BitDepth { BufferedImage.TYPE_INT_BGR, BufferedImage.TYPE_3BYTE_BGR, BufferedImage.TYPE_USHORT_565_RGB, - BufferedImage.TYPE_USHORT_555_RGB - }; - - private static final int[] biRGBATypes = { + BufferedImage.TYPE_USHORT_555_RGB, BufferedImage.TYPE_INT_ARGB, BufferedImage.TYPE_INT_ARGB_PRE, BufferedImage.TYPE_4BYTE_ABGR, BufferedImage.TYPE_4BYTE_ABGR_PRE }; - private static final int[] biGrayTypes = { - BufferedImage.TYPE_BYTE_GRAY, - BufferedImage.TYPE_USHORT_GRAY, - BufferedImage.TYPE_BYTE_BINARY - }; + //private static final int[] biGrayTypes = { + // BufferedImage.TYPE_BYTE_GRAY, + // BufferedImage.TYPE_USHORT_GRAY, + // BufferedImage.TYPE_BYTE_BINARY + //}; + private static final String[] biTypeNames = { "CUSTOM", @@ -116,7 +114,7 @@ public class BitDepth { private int width = 80; private int height = 80; - private String[] format = { "png", "jpeg" }; + private String[] format = { "png", "jpeg", "tif", "bmp", "gif" }; public BitDepth(String[] args) throws IOException { if (args.length > 0) { @@ -129,10 +127,28 @@ public class BitDepth { } private void testFormat(String format) throws IOException { + boolean allOK = true; for (int i = 0; i < biRGBTypes.length; i++) { + int type = biRGBTypes[i]; + + + // TODO: remove the following 'if' block after the 8147448 fix + if ( format.toLowerCase().equals("bmp") && ( + (type == BufferedImage.TYPE_INT_ARGB ) || + (type == BufferedImage.TYPE_INT_ARGB_PRE ) || + (type == BufferedImage.TYPE_4BYTE_ABGR ) || + (type == BufferedImage.TYPE_4BYTE_ABGR_PRE ))) { + + System.err.println("cannot use " + biTypeNames[type] + + " for bmp because of JDK-8147448.\t" + + " please update the test after fix of this bug!"); + continue; + } + + System.out.println("Testing " + format + " writer for type " + biTypeNames[type]); File f = testWriteRGB(format, type); @@ -143,6 +159,8 @@ public class BitDepth { allOK = allOK && ok; } + + if (format.equals("png")) { System.out.println("Testing png writer for black stripe"); boolean ok = testPNGByteBinary(); @@ -154,8 +172,8 @@ public class BitDepth { } } - private File testWriteRGB(String format, int type) - throws IOException { + private File testWriteRGB(String format, int type) throws IOException { + BufferedImage bi = new BufferedImage(width, height, type); Graphics2D g = bi.createGraphics(); diff --git a/jdk/test/javax/imageio/plugins/shared/ImageWriterCompressionTest.java b/jdk/test/javax/imageio/plugins/shared/ImageWriterCompressionTest.java new file mode 100644 index 00000000000..9f633c0d300 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/shared/ImageWriterCompressionTest.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageOutputStream; + +/** + * @test @bug 6488522 + * @summary Check the compression support in imageio ImageWriters + * @run main ImageWriterCompressionTest + */ +public class ImageWriterCompressionTest { + + // ignore jpg (fail): + // Caused by: javax.imageio.IIOException: Invalid argument to native writeImage + private static final Set IGNORE_FILE_SUFFIXES + = new HashSet(Arrays.asList(new String[] { + "bmp", "gif", + "jpg", "jpeg" + } )); + + public static void main(String[] args) { + Locale.setDefault(Locale.US); + + final BufferedImage image + = new BufferedImage(512, 512, BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = image.createGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + g2d.scale(2.0, 2.0); + + g2d.setColor(Color.red); + g2d.draw(new Rectangle2D.Float(10, 10, 100, 100)); + g2d.setColor(Color.blue); + g2d.fill(new Rectangle2D.Float(12, 12, 98, 98)); + g2d.setColor(Color.green); + g2d.setFont(new Font(Font.SERIF, Font.BOLD, 14)); + + for (int i = 0; i < 15; i++) { + g2d.drawString("Testing Compression ...", 20, 20 + i * 16); + } + + final String[] fileSuffixes = ImageIO.getWriterFileSuffixes(); + + final Set testedWriterClasses = new HashSet(); + + for (String suffix : fileSuffixes) { + + if (!IGNORE_FILE_SUFFIXES.contains(suffix)) { + final Iterator itWriters + = ImageIO.getImageWritersBySuffix(suffix); + + final ImageWriter writer; + final ImageWriteParam writerParams; + + if (itWriters.hasNext()) { + writer = itWriters.next(); + + if (testedWriterClasses.add(writer.getClass().getName())) { + writerParams = writer.getDefaultWriteParam(); + + if (writerParams.canWriteCompressed()) { + testCompression(image, writer, writerParams, suffix); + } + } + } else { + throw new RuntimeException("Unable to get writer !"); + } + } + } + } catch (IOException ioe) { + throw new RuntimeException("IO failure", ioe); + } + finally { + g2d.dispose(); + } + } + + private static void testCompression(final BufferedImage image, + final ImageWriter writer, + final ImageWriteParam writerParams, + final String suffix) + throws IOException + { + System.out.println("Compression types: " + + Arrays.toString(writerParams.getCompressionTypes())); + + // Test Compression modes: + try { + writerParams.setCompressionMode(ImageWriteParam.MODE_DISABLED); + saveImage(image, writer, writerParams, "disabled", suffix); + } catch (Exception e) { + System.out.println("CompressionMode Disabled not supported: "+ e.getMessage()); + } + + try { + writerParams.setCompressionMode(ImageWriteParam.MODE_DEFAULT); + saveImage(image, writer, writerParams, "default", suffix); + } catch (Exception e) { + System.out.println("CompressionMode Default not supported: "+ e.getMessage()); + } + + writerParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + writerParams.setCompressionType(selectCompressionType(suffix, + writerParams.getCompressionTypes())); + + System.out.println("Selected Compression type: " + + writerParams.getCompressionType()); + + long prev = Long.MAX_VALUE; + for (int i = 10; i >= 0; i--) { + float quality = 0.1f * i; + writerParams.setCompressionQuality(quality); + + long len = saveImage(image, writer, writerParams, + String.format("explicit-%.1f", quality), suffix); + + if (len <= 0) { + throw new RuntimeException("zero file length !"); + } else if (len > prev) { + throw new RuntimeException("Incorrect file length: " + len + + " larger than previous: " + prev + " !"); + } + prev = len; + } + } + + private static String selectCompressionType(final String suffix, + final String[] types) + { + switch (suffix) { + case "tif": + case "tiff": + return "LZW"; + default: + return types[0]; + } + } + + private static long saveImage(final BufferedImage image, + final ImageWriter writer, + final ImageWriteParam writerParams, + final String mode, + final String suffix) throws IOException + { + final File imgFile = new File("WriterCompressionTest-" + + mode + '.' + suffix); + System.out.println("Writing file: " + imgFile.getAbsolutePath()); + + final ImageOutputStream imgOutStream + = ImageIO.createImageOutputStream(new FileOutputStream(imgFile)); + try { + writer.setOutput(imgOutStream); + writer.write(null, new IIOImage(image, null, null), writerParams); + } finally { + imgOutStream.close(); + } + return imgFile.length(); + } +} diff --git a/jdk/test/javax/imageio/plugins/tiff/MultiPageTest/MultiPageTest.java b/jdk/test/javax/imageio/plugins/tiff/MultiPageTest/MultiPageTest.java new file mode 100644 index 00000000000..2edb9a1f1c5 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/MultiPageTest/MultiPageTest.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @library /lib/testlibrary/ + * @build jdk.testlibrary.* + * + * @bug 8145776 + * @author a.stepanov + * @summary A simple write-read test for the multi-page tiff. + * Create the file programmaticaly, then do some simple checks + * (number of pages, sizes, colors). Use -Dseed=X to set + * the random generator seed. + * + * @run main MultiPageTest + * @key randomness + */ + + +import java.awt.*; +import java.awt.image.*; +import java.io.*; + +import java.util.*; + +import javax.imageio.*; +import javax.imageio.stream.*; + +import jdk.testlibrary.RandomFactory; + + +public class MultiPageTest { + + private final String fileName; + + private final int NUM_IMAGES = 51; + + private final static Random rnd = RandomFactory.getRandom(); + + private final int w[], h[]; + private final Color colors[]; + private final int BLACK_SIZE = 100; + + private final int imageType; + + + public MultiPageTest(int type, String tName) { + + imageType = type; + fileName = "test__" + tName + ".tif"; + + w = new int[NUM_IMAGES + 4]; + h = new int[NUM_IMAGES + 4]; + + for (int i = 2; i < NUM_IMAGES + 2; i++) { + w[i] = 10 + rnd.nextInt(21); + h[i] = 10 + rnd.nextInt(21); + } + + w[0] = BLACK_SIZE; h[0] = BLACK_SIZE; + w[1] = BLACK_SIZE; h[1] = BLACK_SIZE; + w[NUM_IMAGES + 2] = BLACK_SIZE; h[NUM_IMAGES + 2] = BLACK_SIZE; + w[NUM_IMAGES + 3] = BLACK_SIZE; h[NUM_IMAGES + 3] = BLACK_SIZE; + + + colors = new Color[NUM_IMAGES + 4]; + for (int i = 2; i < NUM_IMAGES + 2; ++i) { + colors[i] = new Color( + rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); + } + + colors[0] = Color.black; + colors[1] = Color.black; + colors[NUM_IMAGES + 2] = Color.black; + colors[NUM_IMAGES + 3] = Color.black; + } + + + private ImageWriter getTIFFWriter() throws Exception { + + Iterator writers = ImageIO.getImageWritersByFormatName("TIFF"); + if (!writers.hasNext()) { + throw new RuntimeException("No writers available for " + fileName); + } + return writers.next(); + } + + private ImageReader getTIFFReader() throws Exception { + + Iterator readers = ImageIO.getImageReadersByFormatName("TIFF"); + if (!readers.hasNext()) { + throw new RuntimeException("No readers available for " + fileName); + } + return readers.next(); + } + + + private void createImage() throws Exception { + + OutputStream s = new BufferedOutputStream(new FileOutputStream(fileName)); + try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) { + + ImageWriter writer = getTIFFWriter(); + writer.setOutput(ios); + + Graphics g; + + BufferedImage blackImg = + new BufferedImage(BLACK_SIZE, BLACK_SIZE, imageType); + g = blackImg.getGraphics(); + g.setColor(Color.black); + g.fillRect(0, 0, BLACK_SIZE, BLACK_SIZE); + + writer.prepareWriteSequence(null); + + for (int i = 2; i < NUM_IMAGES + 2; i++) { + BufferedImage img = new BufferedImage(w[i], h[i], imageType); + + g = img.getGraphics(); + g.setColor(colors[i]); + g.fillRect(0, 0, w[i], h[i]); + + writer.writeToSequence(new IIOImage(img, null, null), null); + } + + writer.endWriteSequence(); + + // check: insert to the beginning + writer.writeInsert(0, new IIOImage(blackImg, null, null), null); + + // check: insert to non-zero position + writer.writeInsert(1, new IIOImage(blackImg, null, null), null); + + // check: append to the end by index + writer.writeInsert(NUM_IMAGES + 2, + new IIOImage(blackImg, null, null), null); + + // check: append to the end using index "-1" + writer.writeInsert(-1, new IIOImage(blackImg, null, null), null); + + ios.flush(); + writer.dispose(); + } + s.close(); + } + + + + private void readAndCheckImage() throws Exception { + + ImageReader reader = getTIFFReader(); + + ImageInputStream s = ImageIO.createImageInputStream(new File(fileName)); + reader.setInput(s); + + + // check number of pages + if ((NUM_IMAGES + 4) != reader.getNumImages(true)) { + throw new RuntimeException("invalid number of images!"); + } + + // check colors / sizes + for (int i = 0; i < NUM_IMAGES + 4; i++) { + + BufferedImage img = reader.read(i); + + int imw = w[i], imh = h[i]; + + if ( (img.getWidth() != imw) || (img.getHeight() != imh) ) { + throw new RuntimeException("NOK: size(" + i + ")"); + } + + Color + c1 = new Color(img.getRGB(0, 0)), + c2 = new Color(img.getRGB(imw / 2, imh / 2)), + c3 = new Color(img.getRGB(imw - 1, imh - 1)); + if (! (c1.equals(colors[i]) && c1.equals(c2) && c1.equals(c3) ) ) { + throw new RuntimeException("NOK: color(" + i + ")"); + } + } + + reader.dispose(); + s.close(); + } + + public void doTest() throws Exception { + createImage(); + readAndCheckImage(); + } + + public static void main(String[] args) throws Exception { + + int types[] = new int[]{ + BufferedImage.TYPE_INT_RGB, + BufferedImage.TYPE_INT_ARGB, + BufferedImage.TYPE_INT_ARGB_PRE, + BufferedImage.TYPE_INT_BGR, + BufferedImage.TYPE_3BYTE_BGR, + BufferedImage.TYPE_4BYTE_ABGR, + BufferedImage.TYPE_4BYTE_ABGR_PRE + }; + + String names[] = new String[]{ + "TYPE_INT_RGB", + "TYPE_INT_ARGB", + "TYPE_INT_ARGB_PRE", + "TYPE_INT_BGR", + "TYPE_3BYTE_BGR", + "TYPE_4BYTE_ABGR", + "TYPE_4BYTE_ABGR_PRE" + }; + + for (int i = 0; i < types.length; i++) { + System.out.println("image type: " + names[i]); + (new MultiPageTest(types[i], names[i])).doTest(); + } + } +} diff --git a/jdk/test/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java b/jdk/test/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java index 274f9d8e255..d7f0d38cdee 100644 --- a/jdk/test/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java +++ b/jdk/test/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ * @bug 7105780 * @summary Add SSLSocket client/SSLEngine server to templates directory. * @run main/othervm SSLSocketSSLEngineTemplate + * @key intermittent */ /** diff --git a/jdk/test/javax/sound/sampled/AudioInputStream/SkipOnConvertSampleSize.java b/jdk/test/javax/sound/sampled/AudioInputStream/SkipOnConvertSampleSize.java new file mode 100644 index 00000000000..9ed02136301 --- /dev/null +++ b/jdk/test/javax/sound/sampled/AudioInputStream/SkipOnConvertSampleSize.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 6459818 + * @summary Audio A-law and law decoder skip() method not implemented + * @author Klaus Jaensch + */ +public class SkipOnConvertSampleSize { + + private static final int TEST_FRAME_LENGTH = 20000; + + private static void testskipping(final Encoding encoding) throws Exception { + + // create temporary PCM_SIGNED audio file + int pcmBufSize = TEST_FRAME_LENGTH * 2; + byte[] tempAudioBuf = new byte[pcmBufSize]; + for (int i = 0; i < TEST_FRAME_LENGTH; i++) { + // fill with noise + tempAudioBuf[i * 2] = (byte) ((Math.random() - 1) * Byte.MAX_VALUE); + tempAudioBuf[i * 2 + 1] = (byte) ((Math.random() - 1) + * Byte.MAX_VALUE); + } + final ByteArrayInputStream bis = new ByteArrayInputStream(tempAudioBuf); + AudioFormat format = new AudioFormat(8000, 16, 1, true, false); + final AudioInputStream testAis = new AudioInputStream(bis, format, + TEST_FRAME_LENGTH); + final AudioFormat lawFormat; + final byte[] alawAudioBuf; + try (AudioInputStream lawStream = AudioSystem.getAudioInputStream( + encoding, testAis)) { + + lawFormat = lawStream.getFormat(); + int alawFrameSize = lawFormat.getFrameSize(); + + int lawBufSize = TEST_FRAME_LENGTH * alawFrameSize; + alawAudioBuf = new byte[lawBufSize]; + int r1 = 0; + int totalRead = 0; + while ((r1 = lawStream.read(alawAudioBuf, totalRead, + lawBufSize - totalRead)) != -1) { + totalRead += r1; + } + } + + // Convert back to PCM + + ByteArrayInputStream alawBis = new ByteArrayInputStream(alawAudioBuf); + AudioInputStream lawAis = new AudioInputStream(alawBis, lawFormat, + TEST_FRAME_LENGTH); + try (AudioInputStream convPcmStream = AudioSystem.getAudioInputStream( + Encoding.PCM_SIGNED, lawAis)) { + final AudioFormat convPcmAudioFormat = convPcmStream.getFormat(); + final int convPcmFrameSize = convPcmAudioFormat.getFrameSize(); + + // skip half of the stream + final long toSkip = (TEST_FRAME_LENGTH / 2) * convPcmFrameSize; + long skipped = 0; + do { + skipped += convPcmStream.skip(toSkip - skipped); + } while (skipped < toSkip); + int r2 = convPcmStream.read(new byte[convPcmFrameSize]); + // if skip is not correctly implemented we are at the end of the + // stream + if (r2 == -1) { + throw new RuntimeException( + "Skip method of decoder not correctly implemented!"); + } + // otherwise we could read the rest ... + // we don't do it here + } + } + + public static void main(final String[] args) throws Exception { + testskipping(Encoding.ALAW); + testskipping(Encoding.ULAW); + } +} diff --git a/jdk/test/javax/sound/sampled/DirectAudio/bug6400879.java b/jdk/test/javax/sound/sampled/DirectAudio/bug6400879.java index 8ddae19a0aa..770e774f609 100644 --- a/jdk/test/javax/sound/sampled/DirectAudio/bug6400879.java +++ b/jdk/test/javax/sound/sampled/DirectAudio/bug6400879.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,12 +21,13 @@ * questions. */ -/* @test - @bug 6400879 - @bug 7100140 - @summary Tests that Start/Stop sequence doesn't hang - @author Alexey Menkov - @run main bug6400879 +/* + * @test + * @bug 6400879 7100140 + * @summary Tests that Start/Stop sequence doesn't hang + * @author Alexey Menkov + * @run main bug6400879 + * @key intermittent */ import javax.sound.sampled.*; diff --git a/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeWaveExtensible.java b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeWaveExtensible.java new file mode 100644 index 00000000000..59f9d24ade1 --- /dev/null +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/RecognizeWaveExtensible.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * @test + * @bug 8147407 + */ +public final class RecognizeWaveExtensible { + + private static byte[] data = { + 82, 73, 70, 70, 72, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 40, + 0, 0, 0, -2, -1, 1, 0, 64, 31, 0, 0, 0, 125, 0, 0, 4, 0, 32, 0, 22, + 0, 32, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 16, 0, -128, 0, 0, -86, 0, + 56, -101, 113, 102, 97, 99, 116, 4, 0, 0, 0, 0, 0, 0, 0, 100, 97, + 116, 97, 0, 0, 0, 0 + }; + + public static void main(final String[] args) throws Exception { + final InputStream is = new ByteArrayInputStream(data); + final AudioFileFormat aff = AudioSystem.getAudioFileFormat(is); + System.out.println("AudioFileFormat: " + aff); + try (AudioInputStream ais = AudioSystem.getAudioInputStream(is)) { + System.out.println("AudioFormat: " + ais.getFormat()); + } + System.out.println("new String(data) = " + new String(data)); + } +} diff --git a/jdk/test/javax/sound/sampled/spi/AudioFileReader/ShortHeader.java b/jdk/test/javax/sound/sampled/spi/AudioFileReader/ShortHeader.java new file mode 100644 index 00000000000..1f30587889b --- /dev/null +++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/ShortHeader.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.nio.file.Files; +import java.util.Arrays; + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileReader; + +import static java.util.ServiceLoader.load; + +/** + * @test + * @bug 8131974 + * @summary Short files should be reported as unsupported + */ +public final class ShortHeader { + + private static byte[] W = {-12, 3, 45}; + + private static byte[] R = new byte[3]; + + public static void main(final String[] args) throws Exception { + final File file = Files.createTempFile("audio", "test").toFile(); + file.deleteOnExit(); + try (final OutputStream fos = new FileOutputStream(file)) { + fos.write(W); + } + + testAS(file); + for (final AudioFileReader afr : load(AudioFileReader.class)) { + testAFR(afr, file); + } + } + + /** + * Tests the part of AudioSystem API, which implemented via + * AudioFileReader. + * + * @see AudioSystem#getAudioFileFormat(InputStream) + * @see AudioSystem#getAudioFileFormat(File) + * @see AudioSystem#getAudioFileFormat(URL) + * @see AudioSystem#getAudioInputStream(InputStream) + * @see AudioSystem#getAudioInputStream(File) + * @see AudioSystem#getAudioInputStream(URL) + */ + private static void testAS(final File file) throws IOException { + try { + AudioSystem.getAudioFileFormat(file); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + AudioSystem.getAudioFileFormat(file.toURL()); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + AudioSystem.getAudioInputStream(file); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + AudioSystem.getAudioInputStream(file.toURL()); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + + // AudioSystem.getAudioXXX(stream) should properly reset the stream + + try (FileInputStream fis = new FileInputStream(file); + InputStream stream = new BufferedInputStream(fis)) { + + try { + AudioSystem.getAudioFileFormat(stream); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + AudioSystem.getAudioInputStream(stream); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + stream.read(R, 0, R.length); + } + + if (!Arrays.equals(R, W)) { + System.err.println("Expected = " + Arrays.toString(W)); + System.err.println("Actual = " + Arrays.toString(R)); + throw new RuntimeException(); + } + } + /** + * Tests the AudioFileReader API directly. + * + * @see AudioFileReader#getAudioFileFormat(InputStream) + * @see AudioFileReader#getAudioFileFormat(File) + * @see AudioFileReader#getAudioFileFormat(URL) + * @see AudioFileReader#getAudioInputStream(InputStream) + * @see AudioFileReader#getAudioInputStream(File) + * @see AudioFileReader#getAudioInputStream(URL) + */ + private static void testAFR(final AudioFileReader fcp, final File file) + throws Exception { + try { + fcp.getAudioFileFormat(file); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + fcp.getAudioFileFormat(file.toURL()); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + fcp.getAudioInputStream(file); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + fcp.getAudioInputStream(file.toURL()); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + + // AudioFileReader should properly reset the stream + + try (FileInputStream fis = new FileInputStream(file); + InputStream stream = new BufferedInputStream(fis)) { + + try { + fcp.getAudioFileFormat(stream); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + fcp.getAudioInputStream(stream); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + stream.read(R, 0, R.length); + } + + if (!Arrays.equals(R, W)) { + System.err.println("Expected = " + Arrays.toString(W)); + System.err.println("Actual = " + Arrays.toString(R)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/sound/sampled/spi/AudioFileWriter/WriteUnsupportedAudioFormat.java b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/WriteUnsupportedAudioFormat.java new file mode 100644 index 00000000000..893205944c3 --- /dev/null +++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/WriteUnsupportedAudioFormat.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +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.AudioSystem; +import javax.sound.sampled.spi.AudioFileWriter; + +import static java.util.ServiceLoader.load; +import static javax.sound.sampled.AudioFileFormat.Type.AIFC; +import static javax.sound.sampled.AudioFileFormat.Type.AIFF; +import static javax.sound.sampled.AudioFileFormat.Type.AU; +import static javax.sound.sampled.AudioFileFormat.Type.SND; +import static javax.sound.sampled.AudioFileFormat.Type.WAVE; + +/** + * @test + * @bug 8064800 + */ +public final class WriteUnsupportedAudioFormat { + + /** + * We will try to use all formats, in this case all our providers will be + * covered by supported/unsupported formats. + */ + private static final List formats = new ArrayList<>(23000); + + private static final AudioFormat.Encoding[] encodings = { + AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW, + AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED, + AudioFormat.Encoding.PCM_FLOAT, new AudioFormat.Encoding("Test") + }; + + private static final int[] sampleRates = { + /*AudioSystem.NOT_SPECIFIED,*/ 8000, 11025, 16000, 22050, 32000, + 37800, 44056, 44100, 47250, 48000, 50000, 50400, 88200, 96000, + 176400, 192000, 352800, 2822400, 5644800 + }; + + private static final int[] sampleBits = { + /*AudioSystem.NOT_SPECIFIED, 4,*/ 8,/* 11,*/ 16/*, 20*/, 24, + 32/*, 48, 64, 128*/ + }; + + public static final int BUFFER_LEN = 127; + + private static final int[] channels = { + /*AudioSystem.NOT_SPECIFIED,*/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 + }; + + static final Type[] types = { + WAVE, AU, AIFF, AIFC, SND, new Type("TestName", "TestExt") + }; + + private static final File FILE; + + static { + try { + FILE = File.createTempFile("sound", null); + } catch (final IOException e) { + throw new RuntimeException(e); + } + FILE.deleteOnExit(); + + for (final Boolean end : new boolean[]{false, true}) { + for (final int sampleSize : sampleBits) { + for (final int sampleRate : sampleRates) { + for (final int channel : channels) { + for (final AudioFormat.Encoding enc : encodings) { + + if (enc.equals(AudioFormat.Encoding.PCM_FLOAT) + && sampleSize != 32) { + continue; + } + if (enc.equals(AudioFormat.Encoding.ALAW) + && sampleSize != 8) { + continue; + } + if (enc.equals(AudioFormat.Encoding.ULAW) + && sampleSize != 8) { + continue; + } + + final int frameSize = ((sampleSize + 7) / 8) + * channel; + formats.add( + new AudioFormat(enc, sampleRate, sampleSize, + channel, frameSize, + sampleRate, end)); + } + } + } + } + } + } + + public static void main(final String[] args) throws Exception { + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat format : formats) { + testAS(type, format); + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + testAFW(afw, type, format); + } + } + } + } + + /** + * Tests the part of AudioSystem API, which implemented via AudioFileWriter. + */ + private static void testAS(final AudioFileFormat.Type type, + final AudioFormat format) throws Exception { + final AudioInputStream ais = getStream(format); + final OutputStream buffer = new ByteArrayOutputStream(BUFFER_LEN); + + if (AudioSystem.isFileTypeSupported(type, ais)) { + if (!AudioSystem.isFileTypeSupported(type)) { + throw new RuntimeException(type + ", " + format); + } + try { + AudioSystem.write(ais, type, buffer); + AudioSystem.write(ais, type, FILE); + } catch (final IllegalArgumentException e) { + throw new RuntimeException(type + ", " + format, e); + } + } else { + try { + AudioSystem.write(ais, type, buffer); + throw new RuntimeException(type + ", " + format); + } catch (final IllegalArgumentException ignored) { + } + try { + AudioSystem.write(ais, type, FILE); + throw new RuntimeException(type + ", " + format); + } catch (final IllegalArgumentException ignored) { + } + } + } + + /** + * Tests the AudioFileWriter API directly. + */ + private static void testAFW(final AudioFileWriter afw, + final AudioFileFormat.Type type, + final AudioFormat format) throws Exception { + final AudioInputStream ais = getStream(format); + final OutputStream buffer = new ByteArrayOutputStream(BUFFER_LEN); + + if (afw.isFileTypeSupported(type, ais)) { + if (!afw.isFileTypeSupported(type)) { + throw new RuntimeException(type + "," + format + ',' + afw); + } + try { + afw.write(ais, type, buffer); + afw.write(ais, type, FILE); + } catch (final IllegalArgumentException e) { + throw new RuntimeException(type + "," + format + ',' + afw, e); + } + } else { + try { + afw.write(ais, type, buffer); + throw new RuntimeException(type + "," + format + ',' + afw); + } catch (final IllegalArgumentException ignored) { + } + try { + afw.write(ais, type, FILE); + throw new RuntimeException(type + "," + format + ',' + afw); + } catch (final IllegalArgumentException ignored) { + } + } + } + + private static AudioInputStream getStream(final AudioFormat format) { + final InputStream in = new ByteArrayInputStream(new byte[BUFFER_LEN]); + return new AudioInputStream(in, format, 10); + } +} diff --git a/jdk/test/javax/sound/sampled/spi/FormatConversionProvider/GetAudioStreamConversionSupported.java b/jdk/test/javax/sound/sampled/spi/FormatConversionProvider/GetAudioStreamConversionSupported.java new file mode 100644 index 00000000000..c12e13f9b71 --- /dev/null +++ b/jdk/test/javax/sound/sampled/spi/FormatConversionProvider/GetAudioStreamConversionSupported.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.spi.FormatConversionProvider; + +import static java.util.ServiceLoader.load; + +/** + * @test + * @bug 8146144 + */ +public final class GetAudioStreamConversionSupported { + + static final AudioFormat.Encoding[] encodings = { + AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW, + AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED, + AudioFormat.Encoding.PCM_FLOAT, new AudioFormat.Encoding("Test") + }; + + public static void main(final String[] args) { + for (final int sampleSize : new int[]{4, 8, 16, 24, 32}) { + for (final AudioFormat.Encoding enc : encodings) { + for (final Boolean endian : new boolean[]{false, true}) { + testAS(enc, endian, sampleSize); + for (final FormatConversionProvider fcp : load + (FormatConversionProvider.class)) { + testFCP(fcp, enc, endian, sampleSize); + } + } + } + } + } + + /** + * Tests the part of AudioSystem API, which implemented via + * FormatConversionProvider. + *

          + * AudioSystem always support conversion to the same encoding/format. + */ + private static void testAS(final AudioFormat.Encoding enc, + final Boolean endian, final int sampleSize) { + final AudioInputStream ais = getStream(enc, endian, sampleSize); + final AudioFormat format = ais.getFormat(); + if (!AudioSystem.isConversionSupported(enc, format)) { + throw new RuntimeException("Format: " + format); + } + if (!AudioSystem.isConversionSupported(format, format)) { + throw new RuntimeException("Format: " + format); + } + AudioSystem.getAudioInputStream(enc, ais); + AudioSystem.getAudioInputStream(format, ais); + } + + /** + * Tests the FormatConversionProvider API directly. + */ + private static void testFCP(final FormatConversionProvider fcp, + final AudioFormat.Encoding enc, + final Boolean endian, final int sampleSize) { + System.out.println("fcp = " + fcp); + final AudioInputStream ais = getStream(enc, endian, sampleSize); + final AudioFormat frmt = ais.getFormat(); + if (fcp.isConversionSupported(enc, frmt)) { + try { + fcp.getAudioInputStream(enc, ais); + } catch (final IllegalArgumentException ex) { + throw new RuntimeException("Format: " + frmt, ex); + } + } else { + try { + fcp.getAudioInputStream(enc, ais); + throw new RuntimeException("Format: " + frmt); + } catch (final IllegalArgumentException ignored) { + } + try { + fcp.getAudioInputStream(frmt, ais); + throw new RuntimeException("Format: " + frmt); + } catch (final IllegalArgumentException ignored) { + } + } + if (fcp.isConversionSupported(frmt, frmt)) { + try { + fcp.getAudioInputStream(enc, ais); + fcp.getAudioInputStream(frmt, ais); + } catch (final IllegalArgumentException ex) { + throw new RuntimeException("Format: " + frmt, ex); + } + } else { + try { + fcp.getAudioInputStream(frmt, ais); + throw new RuntimeException("Format: " + frmt); + } catch (final IllegalArgumentException ignored) { + } + } + } + + private static AudioInputStream getStream(final AudioFormat.Encoding enc, + final Boolean end, + final int sampleSize) { + final AudioFormat ftmt + = new AudioFormat(enc, 8000, sampleSize, 1, 1, 8000, end); + final byte[] fakedata = new byte[100]; + final InputStream in = new ByteArrayInputStream(fakedata); + return new AudioInputStream(in, ftmt, fakedata.length); + } +} diff --git a/jdk/test/javax/sound/sampled/spi/FormatConversionProvider/GetTargetIsSupported.java b/jdk/test/javax/sound/sampled/spi/FormatConversionProvider/GetTargetIsSupported.java new file mode 100644 index 00000000000..2a44b89ff19 --- /dev/null +++ b/jdk/test/javax/sound/sampled/spi/FormatConversionProvider/GetTargetIsSupported.java @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.spi.FormatConversionProvider; + +import static java.util.ServiceLoader.load; + +/** + * @test + * @bug 8146144 + */ +public final class GetTargetIsSupported { + + /** + * We will try to use all formats, in this case all our providers will be + * covered by supported/unsupported formats. + */ + private static final List formats = new ArrayList<>(23000); + + private static final Encoding[] encodings = { + Encoding.ALAW, Encoding.ULAW, Encoding.PCM_SIGNED, + Encoding.PCM_UNSIGNED, Encoding.PCM_FLOAT, new Encoding("Test") + }; + + private static final int[] sampleRates = { + AudioSystem.NOT_SPECIFIED, 8000, 11025, 16000, 22050, 32000, 37800, + 44056, 44100, 47250, 48000, 50000, 50400, 88200, 96000, 176400, + 192000, 352800, 2822400, 5644800 + }; + + private static final int[] sampleBits = { + AudioSystem.NOT_SPECIFIED, 4, 8, 11, 16, 20, 24, 32, 48, 64, 128 + }; + + private static final int[] channels = { + AudioSystem.NOT_SPECIFIED, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 + }; + + static { + for (final Boolean end : new boolean[]{false, true}) { + for (final int sampleSize : sampleBits) { + for (final int sampleRate : sampleRates) { + for (final int channel : channels) { + for (final Encoding enc : encodings) { + formats.add(new AudioFormat(enc, sampleRate, + sampleSize, channel, + 1, sampleRate, end)); + } + } + } + } + } + } + + public static void main(final String[] args) { + for (final AudioFormat format : formats) { + testAS(format); + for (final FormatConversionProvider fcp : load + (FormatConversionProvider.class)) { + testFCP(fcp, format); + } + } + } + + /** + * Tests the part of AudioSystem API, which implemented via + * FormatConversionProvider. + * + * @see AudioSystem#getTargetEncodings(Encoding) + * @see AudioSystem#getTargetEncodings(AudioFormat) + * @see AudioSystem#getTargetFormats(Encoding, AudioFormat) + * @see AudioSystem#isConversionSupported(AudioFormat, AudioFormat) + * @see AudioSystem#isConversionSupported(Encoding, AudioFormat) + */ + private static void testAS(final AudioFormat source) { + Encoding[] all = AudioSystem.getTargetEncodings(source.getEncoding()); + Encoding[] part = AudioSystem.getTargetEncodings(source); + + // Check encodings which are reported as supported + for (final Encoding enc : part) { + // If encoding is reported for the source format means that + // the list of target formats should not be empty + AudioFormat[] targets = AudioSystem.getTargetFormats(enc, source); + // all reported formats should be supported + for (final AudioFormat target : targets) { + if (!AudioSystem.isConversionSupported(target, source)) { + throw new RuntimeException("Error:" + enc); + } + if (!enc.equals(target.getEncoding())) { + throw new RuntimeException("Error:" + enc); + } + } + // If encoding is reported for the source format means that + // conversion source -> encoding is supported + if (!AudioSystem.isConversionSupported(enc, source)) { + throw new RuntimeException("Error:" + enc); + } + // encoding for a particular source should be included in the + // list of all encodings for the source's encoding + if (!Arrays.asList(all).contains(enc)) { + throw new RuntimeException("Error:" + enc); + } + // If conversion source -> encoding is supported then an + // array of target formats should not be empty + if (source.getEncoding().equals(enc)) { + // this is unspecified but we works this way + if (!isContains(source, targets)) { + throw new RuntimeException("Error:" + enc); + } + } else { + if (targets.length == 0) { + throw new RuntimeException("Error:" + enc); + } + } + } + + // Check all encodings + for (final Encoding enc : encodings) { + AudioFormat[] targets = AudioSystem.getTargetFormats(enc, source); + // If target format is reported for the source format means that + // conversion source -> target is supported + for (final AudioFormat target : targets) { + if (!AudioSystem.isConversionSupported(target, source)) { + throw new RuntimeException("Error:" + enc); + } + if (!enc.equals(target.getEncoding())) { + throw new RuntimeException("Error:" + enc); + } + } + if (AudioSystem.isConversionSupported(enc, source)) { + // encoding for a particular source should be included in the + // list of all encodings for the source's encoding + if (!Arrays.asList(all).contains(enc)) { + throw new RuntimeException("Error:" + enc); + } + if (!Arrays.asList(part).contains(enc)) { + System.out.println("enc = " + enc); + System.out.println("part = " + Arrays.toString(part)); + System.out.println("source = " + source); + throw new RuntimeException("Error:" + enc); + } + // If conversion source -> encoding is supported then an + // array of target formats should not be empty + if (source.getEncoding().equals(enc)) { + // this is unspecified but we works this way + if (!isContains(source, targets)) { + throw new RuntimeException("Error:" + enc); + } + } else { + if (targets.length == 0) { + throw new RuntimeException("Error:" + enc); + } + } + } else { + // If conversion source -> encoding is not supported then an + // array of target formats should be empty + if (targets.length != 0) { + throw new RuntimeException("Error:" + enc); + } + if (Arrays.asList(part).contains(enc)) { + throw new RuntimeException("Error:" + enc); + } + } + } + } + + /** + * Tests the FormatConversionProvider API directly. + * + * @see FormatConversionProvider#getTargetEncodings() + * @see FormatConversionProvider#getTargetEncodings(AudioFormat) + * @see FormatConversionProvider#getTargetFormats(Encoding, AudioFormat) + * @see FormatConversionProvider#isTargetEncodingSupported(Encoding) + * @see FormatConversionProvider#isConversionSupported(Encoding, + * AudioFormat) + * @see FormatConversionProvider#isConversionSupported(AudioFormat, + * AudioFormat) + */ + private static void testFCP(final FormatConversionProvider fcp, + final AudioFormat source) { + final Encoding[] all = fcp.getTargetEncodings(); + for (final Encoding enc : all) { + if (!fcp.isTargetEncodingSupported(enc)) { + throw new RuntimeException("Error:" + enc); + } + } + + // Check encodings which are reported as supported + final Encoding[] part = fcp.getTargetEncodings(source); + for (final Encoding enc : part) { + // If encoding is reported for the source format means that + // the list of target formats should not be empty for this encoding + AudioFormat[] targets = fcp.getTargetFormats(enc, source); + // all reported formats should be supported + for (final AudioFormat target : targets) { + if (!fcp.isConversionSupported(target, source)) { + throw new RuntimeException("Error:" + enc); + } + if (!enc.equals(target.getEncoding())) { + throw new RuntimeException("Error:" + enc); + } + } + // If encoding is reported for the source format means that + // conversion source -> encoding is supported + if (!fcp.isConversionSupported(enc, source)) { + throw new RuntimeException("Error:" + enc); + } + // If conversion source -> encoding is supported then an + // array of target formats should not be empty + if (targets.length == 0) { + throw new RuntimeException("Error:" + enc); + } + // encoding for a particular source should be included in the + // list of all encodings for the source's encoding + if (!Arrays.asList(all).contains(enc)) { + throw new RuntimeException("Error:" + enc); + } + } + // Check all encodings + for (final Encoding enc : encodings) { + AudioFormat[] targets = fcp.getTargetFormats(enc, source); + // If target format is reported for the source format means that + // conversion source -> target is supported + for (final AudioFormat target : targets) { + if (!fcp.isConversionSupported(target, source)) { + throw new RuntimeException("Error:" + enc); + } + if (!enc.equals(target.getEncoding())) { + throw new RuntimeException("Error:" + enc); + } + } + if (fcp.isConversionSupported(enc, source)) { + // If conversion source -> encoding is supported then an + // array of target formats should not be empty + if (targets.length == 0) { + throw new RuntimeException("Error:" + enc); + } + // encoding for a particular source should be included in the + // list of all encodings for the source's encoding + if (!Arrays.asList(all).contains(enc)) { + throw new RuntimeException("Error:" + enc); + } + if (!Arrays.asList(part).contains(enc)) { + throw new RuntimeException("Error:" + enc); + } + } else { + // If conversion source -> encoding is not supported then an + // array of target formats should be empty + if (targets.length != 0) { + throw new RuntimeException("Error:" + enc); + } + if (Arrays.asList(part).contains(enc)) { + throw new RuntimeException("Error:" + enc); + } + } + } + } + + private static boolean isContains(AudioFormat obj, AudioFormat[] array) { + for (final AudioFormat format : array) { + if (obj.matches(format)) { + return true; + } + } + return false; + } +} diff --git a/jdk/test/javax/swing/Action/8133039/bug8133039.java b/jdk/test/javax/swing/Action/8133039/bug8133039.java new file mode 100644 index 00000000000..94ad929707b --- /dev/null +++ b/jdk/test/javax/swing/Action/8133039/bug8133039.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import sun.swing.UIAction; + +/** + * @test + * @bug 8133039 + * @summary Provide public API to sun.swing.UIAction#isEnabled(Object) + * @author Alexander Scherbatiy + */ +public class bug8133039 { + + private static volatile int ACTION_PERFORMED_CALLS = 0; + private static volatile int ACTION_ACCEPTED_CALLS = 0; + + public static void main(String[] args) throws Exception { + testActionNotification(); + testPopupAction(); + } + + private static void testActionNotification() { + + KeyEvent keyEvent = new KeyEvent(new JLabel("Test"), 0, 0, 0, 0, 'A'); + SenderObject rejectedSenderObject = new SenderObject(); + SwingUtilities.notifyAction(new TestAction(false), null, keyEvent, + rejectedSenderObject, 0); + + if (rejectedSenderObject.accepted) { + throw new RuntimeException("The sender is incorrectly accepted!"); + } + + if (rejectedSenderObject.performed) { + throw new RuntimeException("The action is incorrectly performed!"); + } + + SenderObject acceptedSenderObject = new SenderObject(); + SwingUtilities.notifyAction(new TestAction(true), null, keyEvent, + acceptedSenderObject, 0); + + if (!acceptedSenderObject.accepted) { + throw new RuntimeException("The sender is not accepted!"); + } + + if (!acceptedSenderObject.performed) { + throw new RuntimeException("The action is not performed!"); + } + } + + private static void testPopupAction() throws Exception { + + SwingUtilities.invokeAndWait(bug8133039::createAndShowGUI); + + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.waitForIdle(); + + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); + + if (ACTION_ACCEPTED_CALLS != 1) { + throw new RuntimeException("Method accept is not invoked!"); + } + + if (ACTION_PERFORMED_CALLS != 1) { + throw new RuntimeException("Method actionPerformed is not invoked!"); + } + + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); + + if (ACTION_ACCEPTED_CALLS != 2) { + throw new RuntimeException("Method accept is not invoked!"); + } + + if (ACTION_PERFORMED_CALLS != 1) { + throw new RuntimeException("Method actionPerformed is invoked twice!"); + } + } + + private static void createAndShowGUI() { + + JFrame frame = new JFrame(); + frame.setSize(300, 300); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JComboBox comboBox = new JComboBox<>(new String[]{"1", "2", "3"}); + + Action showPopupAction = new ShowPopupAction(); + comboBox.getInputMap().put(KeyStroke.getKeyStroke("A"), "showPopup"); + comboBox.getActionMap().put("showPopup", showPopupAction); + + frame.getContentPane().add(comboBox); + frame.setVisible(true); + } + + private static class ShowPopupAction extends UIAction { + + public ShowPopupAction() { + super("showPopup"); + } + + @Override + public void actionPerformed(ActionEvent e) { + ACTION_PERFORMED_CALLS++; + Object src = e.getSource(); + if (src instanceof JComboBox) { + ((JComboBox) src).showPopup(); + } + } + + @Override + public boolean accept(Object sender) { + ACTION_ACCEPTED_CALLS++; + if (sender instanceof JComboBox) { + JComboBox c = (JComboBox) sender; + return !c.isPopupVisible(); + } + return false; + } + } + + private static class SenderObject { + + private boolean accepted; + private boolean performed; + } + + private static class TestAction extends AbstractAction { + + private final boolean acceptSender; + + public TestAction(boolean acceptSender) { + this.acceptSender = acceptSender; + } + + @Override + public boolean accept(Object sender) { + ((SenderObject) sender).accepted = acceptSender; + return acceptSender; + } + + @Override + public void actionPerformed(ActionEvent e) { + ((SenderObject) e.getSource()).performed = true; + } + } +} diff --git a/jdk/test/javax/swing/JFileChooser/8016665/JFileChooserOrientation.java b/jdk/test/javax/swing/JFileChooser/8016665/JFileChooserOrientation.java new file mode 100644 index 00000000000..4296d48fd2d --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/8016665/JFileChooserOrientation.java @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8016665 + * @summary verifies different behaviour of JFileChooser changing orientation + * @run main JFileChooserOrientation + */ +import java.awt.Color; +import java.awt.ComponentOrientation; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class JFileChooserOrientation { + + private static JFrame frame; + private static GridBagLayout layout; + private static JPanel panel; + private static JPanel lookAndFeelPanel; + private static JPanel orientationPanel; + private static JPanel passFailPanel; + private static JTextArea instructionsTextArea; + private static JLabel lookAndFeelLabel; + private static JLabel orientationLabel; + private static JComboBox lookAndFeelComboBox; + private static JComboBox orientationComboBox; + + private static JButton fileChooserButton; + private static JButton passButton; + private static JButton failButton; + private static JFileChooser openChooser; + private static UIManager.LookAndFeelInfo[] lookAndFeelArray; + + private static final String orientationLTR = " Left to Right"; + private static final String orientationRTL = " Right to Left"; + private static final String fileChooserString = "Show File Chooser"; + + public static void main(String[] args) throws Exception { + createManualTestUI(); + } + + private static void createManualTestUI() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + layout = new GridBagLayout(); + GridBagConstraints gbc = new GridBagConstraints(); + panel = new JPanel(layout); + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridx = 0; + gbc.gridy = 0; + instructionsTextArea = new JTextArea(); + String instructions + = "1) Select Look and feel from combobox" + + "\n2) Select component orientation" + + "\n3) Click on \"Show File Chooser\"" + + "\n4) Check if orientation is as selected" + + "\n5) Press \"Cancel\" on the File Chooser Dialog" + + "\n\n Perform steps 1- 4 for all LAFs & orientations" + + "\n If all are correct press Pass or else press Fail"; + instructionsTextArea.setText(instructions); + instructionsTextArea.setBorder( + BorderFactory.createLineBorder(Color.black)); + panel.add(instructionsTextArea, gbc); + + lookAndFeelPanel = new JPanel(); + lookAndFeelPanel.setBorder( + BorderFactory.createLineBorder(Color.black)); + lookAndFeelLabel = new JLabel("Look And Feel: "); + gbc.gridx = 0; + gbc.gridy = 0; + lookAndFeelPanel.add(lookAndFeelLabel, gbc); + + lookAndFeelComboBox = new JComboBox(); + lookAndFeelArray = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem + : lookAndFeelArray) { + lookAndFeelComboBox.addItem(lookAndFeelItem.getClassName()); + } + gbc.gridx = 1; + gbc.gridy = 0; + lookAndFeelPanel.add(lookAndFeelComboBox, gbc); + gbc.gridx = 0; + gbc.gridy = 1; + panel.add(lookAndFeelPanel, gbc); + + orientationPanel = new JPanel(); + orientationPanel.setBorder( + BorderFactory.createLineBorder(Color.black)); + orientationLabel = new JLabel("Orientation: "); + gbc.gridx = 0; + gbc.gridy = 0; + orientationPanel.add(orientationLabel, gbc); + + orientationComboBox = new JComboBox(); + orientationComboBox.addItem(orientationLTR); + orientationComboBox.addItem(orientationRTL); + gbc.gridx = 1; + gbc.gridy = 0; + orientationPanel.add(orientationComboBox, gbc); + gbc.gridx = 0; + gbc.gridy = 2; + panel.add(orientationPanel, gbc); + + fileChooserButton = new JButton(fileChooserString); + fileChooserButton.setActionCommand(fileChooserString); + + fileChooserButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + try { + showFileChooser(); + } catch (Exception ex) { + Logger.getLogger(JFileChooserOrientation.class + .getName()).log(Level.SEVERE, null, ex); + } + + } + }); + gbc.gridx = 0; + gbc.gridy = 3; + panel.add(fileChooserButton, gbc); + + passFailPanel = new JPanel(); + passFailPanel.setBorder(BorderFactory.createLineBorder(Color.black)); + passButton = new JButton(" Pass "); + passButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + pass(); + } catch (Exception ex) { + Logger.getLogger(JFileChooserOrientation.class + .getName()).log(Level.SEVERE, null, ex); + } + } + }); + gbc.gridx = 0; + gbc.gridy = 0; + passFailPanel.add(passButton, gbc); + failButton = new JButton(" Fail "); + failButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + fail(); + } catch (Exception ex) { + Logger.getLogger(JFileChooserOrientation.class + .getName()).log(Level.SEVERE, null, ex); + } + } + }); + gbc.gridx = 1; + gbc.gridy = 0; + passFailPanel.add(failButton, gbc); + gbc.gridx = 0; + gbc.gridy = 4; + panel.add(passFailPanel, gbc); + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setContentPane(panel); + frame.pack(); + frame.setVisible(true); + } + }); + } + + private static void pass() throws Exception + { + + frame.dispose(); + + } + + private static void fail() throws Exception + { + + frame.dispose(); + System.err.println(lookAndFeelComboBox.getSelectedItem().toString() + + " : Incorrect Orientation"); + } + + private static void showFileChooser() throws Exception { + if (tryLookAndFeel(lookAndFeelComboBox.getSelectedItem().toString())) { + + openChooser = new JFileChooser(); + + ComponentOrientation orientation + = ComponentOrientation.UNKNOWN; + + switch (orientationComboBox.getSelectedItem().toString()) { + case orientationLTR: + orientation = ComponentOrientation.LEFT_TO_RIGHT; + break; + case orientationRTL: + orientation = ComponentOrientation.RIGHT_TO_LEFT; + break; + } + openChooser.setComponentOrientation(orientation); + openChooser.showOpenDialog(frame); + + } + } + private static boolean tryLookAndFeel(String lookAndFeelString) + throws Exception { + try { + UIManager.setLookAndFeel( + lookAndFeelString); + } catch (UnsupportedLookAndFeelException + | ClassNotFoundException + | InstantiationException + | IllegalAccessException e) { + return false; + } + return true; + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/4769772/TestJInternalFrameIconify.java b/jdk/test/javax/swing/JInternalFrame/4769772/TestJInternalFrameIconify.java new file mode 100644 index 00000000000..12bd49d1b49 --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/4769772/TestJInternalFrameIconify.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4769772 + * @summary JInternalFrame.setIcon(true) before JDesktopPane.add(JIF) causes wrong state + * @run main TestJInternalFrameIconify + */ +import java.beans.PropertyVetoException; +import javax.swing.JFrame; +import javax.swing.JDesktopPane; +import javax.swing.JInternalFrame; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import java.awt.Robot; +import javax.swing.SwingUtilities; + +public class TestJInternalFrameIconify { + + private static JDesktopPane desktopPane; + private static JFrame frame; + private static Robot robot; + private static volatile String errorMessage = ""; + + public static void main(String[] args) throws Exception { + robot = new java.awt.Robot(); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + String lookAndFeelString = lookAndFeelItem.getClassName(); + if (tryLookAndFeel(lookAndFeelString)) { + createUI(lookAndFeelString); + robot.waitForIdle(); + executeTest(lookAndFeelString); + } + } + if (!"".equals(errorMessage)) { + throw new RuntimeException(errorMessage); + } + } + + private static boolean tryLookAndFeel(String lookAndFeelString) { + try { + UIManager.setLookAndFeel(lookAndFeelString); + return true; + } catch (UnsupportedLookAndFeelException | ClassNotFoundException | + InstantiationException | IllegalAccessException e) { + errorMessage += e.getMessage() + "\n"; + System.err.println("Caught Exception: " + e.getMessage()); + return false; + } + } + + private static void createUI(String lookAndFeelString) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame(lookAndFeelString); + desktopPane = new JDesktopPane(); + frame.getContentPane().add(desktopPane); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JInternalFrame f = new JInternalFrame("Child ", true, true, + true, true); + f.setSize(200, 300); + f.setLocation(20, 20); + try { + f.setIcon(true); + } catch (PropertyVetoException ex) { + errorMessage += ex.getMessage() + "\n"; + } + desktopPane.add(f); + f.setVisible(true); + + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + }); + + } + + private static void executeTest(String lookAndFeelString) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + JInternalFrame internalFrames[] + = desktopPane.getAllFrames(); + if (internalFrames[0].isShowing()) { + errorMessage += "Test Failed for " + + lookAndFeelString + " look and feel\n"; + System.err.println(errorMessage); + } + } finally { + frame.dispose(); + } + } + }); + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/8145060/TestJInternalFrameMinimize.java b/jdk/test/javax/swing/JInternalFrame/8145060/TestJInternalFrameMinimize.java new file mode 100644 index 00000000000..a8e4001e704 --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/8145060/TestJInternalFrameMinimize.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8145060 + * @summary Minimizing a JInternalFrame not shifting focus to frame below it + * @library ../../regtesthelpers + * @build Util + * @run main TestJInternalFrameMinimize + */ +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.beans.PropertyVetoException; +import javax.swing.JFrame; +import javax.swing.JDesktopPane; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.Timer; + +public class TestJInternalFrameMinimize { + + private static JDesktopPane desktopPane; + private static JFrame frame = new JFrame("Test Frame"); + private static int count = 0; + private static JMenu menu; + private static JMenuBar menuBar; + private static JMenuItem menuItem; + private static Robot robot; + private static ActionListener listener; + private static Timer timer; + private static int counter; + private static boolean testFailed; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + createUI(); + } + }); + robot.waitForIdle(); + executeTest(); + if (testFailed) { + throw new RuntimeException("Test Failed"); + } + dispose(); + } + + private static void createUI() { + + desktopPane = new JDesktopPane(); + frame.getContentPane().add(desktopPane); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + menuBar = new JMenuBar(); + frame.setJMenuBar(menuBar); + + menu = new JMenu("File"); + menuBar.add(menu); + + menuItem = new JMenuItem("New Child"); + menuItem.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JInternalFrame f = new JInternalFrame("Child " + + (++count), true, true, true, true); + f.setSize(200, 300); + f.setLocation(count * 20, count * 20); + desktopPane.add(f); + f.setVisible(true); + } + }); + menu.add(menuItem); + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void executeTest() throws Exception { + + Point point = Util.getCenterPoint(menu); + performMouseOperations(point); + point = Util.getCenterPoint(menuItem); + performMouseOperations(point); + point = Util.getCenterPoint(menu); + performMouseOperations(point); + point = Util.getCenterPoint(menuItem); + performMouseOperations(point); + point = Util.getCenterPoint(menu); + performMouseOperations(point); + point = Util.getCenterPoint(menuItem); + performMouseOperations(point); + point = Util.getCenterPoint(menu); + performMouseOperations(point); + point = Util.getCenterPoint(menuItem); + performMouseOperations(point); + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + JInternalFrame internalFrame + = desktopPane.getSelectedFrame(); + if (internalFrame != null) { + try { + internalFrame.setIcon(true); + ++counter; + } catch (PropertyVetoException ex) { + } + } + if (counter == 4) { + try { + timer.stop(); + JInternalFrame currentSelectedFrame + = desktopPane.getSelectedFrame(); + if (internalFrame.equals(currentSelectedFrame)) { + frame.dispose(); + testFailed = true; + } + } catch (Exception ex) { + } + } + } + }; + } + }); + timer = new Timer(100, listener); + timer.start(); + robot.delay(1000); + } + + private static void dispose() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.dispose(); + } + }); + } + + private static void performMouseOperations(Point point) { + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.delay(1000); + robot.waitForIdle(); + } +} diff --git a/jdk/test/javax/swing/JMenu/8067346/bug8067346.java b/jdk/test/javax/swing/JMenu/8067346/bug8067346.java index ffa2fe4a034..561bf466127 100644 --- a/jdk/test/javax/swing/JMenu/8067346/bug8067346.java +++ b/jdk/test/javax/swing/JMenu/8067346/bug8067346.java @@ -27,7 +27,6 @@ @requires (os.family == "windows") @run main bug8067346 */ -import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; import java.awt.Insets; import javax.swing.JFrame; import javax.swing.JMenu; @@ -56,9 +55,17 @@ public class bug8067346 { bug8067346 test = new bug8067346(); try { // set windows look and feel - UIManager.setLookAndFeel(new WindowsLookAndFeel()); + String lnf = + "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; + UIManager.setLookAndFeel(lnf); } catch (UnsupportedLookAndFeelException e) { runTest = false; + } catch (ClassNotFoundException e) { + runTest = false; + } catch (InstantiationException e) { + runTest = false; + } catch (IllegalAccessException e) { + runTest = false; } if(runTest) { test.createUI(); diff --git a/jdk/test/javax/swing/JOptionPane/8139213/OptionPaneTest.java b/jdk/test/javax/swing/JOptionPane/8139213/OptionPaneTest.java new file mode 100644 index 00000000000..0230ce1b022 --- /dev/null +++ b/jdk/test/javax/swing/JOptionPane/8139213/OptionPaneTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8139213 + * @summary Mac OS Aqua X LAF: JOptionPane truncates the first button + * @run main OptionPaneTest + */ +import java.awt.Component; +import java.awt.Insets; +import java.awt.Robot; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +public class OptionPaneTest { + + private volatile static boolean testFailed; + private static JDialog dialog; + private static Robot robot; + + public static void main(final String[] args) throws Exception { + robot = new Robot(); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + JOptionPane optionPane = new JOptionPane("JOptionPane", + JOptionPane.INFORMATION_MESSAGE, + JOptionPane.DEFAULT_OPTION, + null, + new String[]{"3", "2", "1"}, + null); + dialog = optionPane.createDialog("JOptionPane"); + int width = 0; + Component[] comps = optionPane.getComponents(); + for (Component comp : comps) { + if (comp instanceof JPanel) { + Component[] child = ((JPanel) comp).getComponents(); + for (Component c : child) { + if (c instanceof JButton) { + width += c.getWidth(); + } + } + } + } + Insets in = optionPane.getInsets(); + width += in.left + in.right; + if (width > optionPane.getWidth()) { + testFailed = true; + } + } finally { + dialog.dispose(); + } + } + }); + robot.waitForIdle(); + if (testFailed) { + throw new RuntimeException("Test Failed"); + } + } +} diff --git a/jdk/test/javax/swing/JProgressBar/8015748/JProgressBarOrientationRobotTest.java b/jdk/test/javax/swing/JProgressBar/8015748/JProgressBarOrientationRobotTest.java new file mode 100644 index 00000000000..bc2a6855f87 --- /dev/null +++ b/jdk/test/javax/swing/JProgressBar/8015748/JProgressBarOrientationRobotTest.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8015748 + * @summary verifies ProgressBar RightToLeft orientations for all Look and Feels + * @library ../../regtesthelpers + * @build Util + * @run main JProgressBarOrientationRobotTest + */ +import java.awt.Color; +import java.awt.ComponentOrientation; +import java.awt.Point; +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class JProgressBarOrientationRobotTest { + + private static JFrame frame; + private static JProgressBar progressBar; + private static Robot robot; + private static Color colorCenter; + private static Color colorLeft; + private static Color colorRight; + private static final int widthBuffer = 20; + private static volatile String errorString = ""; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.waitForIdle(); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + executeCase(lookAndFeelItem.getClassName(), + lookAndFeelItem.getName()); + + } + if (!"".equals(errorString)) { + System.err.println(errorString); + } + } + + private static void executeCase(String lookAndFeelString, + String shortenedLandFeelString) throws Exception { + if (tryLookAndFeel(lookAndFeelString)) { + createUI(shortenedLandFeelString); + robot.waitForIdle(); + + createLTR(); + robot.delay(1000); + runTestCase(); + robot.delay(1000); + testCaseLTR(shortenedLandFeelString); + robot.delay(1000); + + createRTL(); + robot.delay(1000); + runTestCase(); + robot.delay(1000); + testCaseRTL(shortenedLandFeelString); + robot.delay(1000); + + cleanUp(); + } + + } + + private static void createUI(final String shortenedLookAndFeelString) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + progressBar = new JProgressBar(); + progressBar.setValue(30); + frame = new JFrame(shortenedLookAndFeelString); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().add(progressBar); + frame.pack(); + frame.setSize(500, frame.getSize().height); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); + } + }); + } + + private static void createLTR() + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + progressBar.applyComponentOrientation( + ComponentOrientation.LEFT_TO_RIGHT); + progressBar.repaint(); + } + }); + } + + private static void createRTL() + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + progressBar.applyComponentOrientation( + ComponentOrientation.RIGHT_TO_LEFT); + progressBar.repaint(); + } + }); + } + + private static void runTestCase() throws Exception { + Point centerPoint = Util.getCenterPoint(progressBar); + colorCenter = robot.getPixelColor(centerPoint.x, centerPoint.y); + colorRight = robot.getPixelColor( + (centerPoint.x + progressBar.getWidth() / 2 - widthBuffer), + centerPoint.y); + colorLeft = robot.getPixelColor( + (centerPoint.x - progressBar.getWidth() / 2 + widthBuffer), + centerPoint.y); + robot.waitForIdle(); + } + + private static void testCaseLTR(String shortenedLookAndFeelString) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + + if (colorCenter.equals(colorRight)) { + if (!colorCenter.equals(colorLeft)) { + System.out.println("[" + shortenedLookAndFeelString + + "]: LTR orientation test passed"); + } + } else { + frame.dispose(); + String error = "[" + shortenedLookAndFeelString + + "]: [Error]: LTR orientation test failed"; + errorString += error; + System.err.println(error); + } + } + }); + + } + + private static void testCaseRTL(String shortenedLookAndFeelString) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + if (colorCenter.equals(colorLeft)) { + if (!colorCenter.equals(colorRight)) { + System.out.println("[" + shortenedLookAndFeelString + + "]: RTL orientation test passed"); + } + } else { + frame.dispose(); + String error = "[" + shortenedLookAndFeelString + + "]: [Error]: LTR orientation test failed"; + errorString += error; + System.err.println(error); + } + } + }); + } + + private static void cleanUp() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + + private static boolean tryLookAndFeel(String lookAndFeelString) + throws Exception { + try { + UIManager.setLookAndFeel( + lookAndFeelString); + + } catch (UnsupportedLookAndFeelException + | ClassNotFoundException + | InstantiationException + | IllegalAccessException e) { + errorString += e.getMessage() + "\n"; + System.err.println("[Exception]: " + e.getMessage()); + return false; + } + return true; + } +} diff --git a/jdk/test/javax/swing/JSpinner/8008657/bug8008657.java b/jdk/test/javax/swing/JSpinner/8008657/bug8008657.java index 3cbe7a61d03..1acb45da597 100644 --- a/jdk/test/javax/swing/JSpinner/8008657/bug8008657.java +++ b/jdk/test/javax/swing/JSpinner/8008657/bug8008657.java @@ -32,6 +32,8 @@ import javax.swing.SpinnerDateModel; import javax.swing.SpinnerModel; import javax.swing.SpinnerNumberModel; import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; /** * @test @@ -44,18 +46,28 @@ public class bug8008657 { private static Robot robot; private static JSpinner spinner; + private static JFrame frame; public static void main(String[] args) throws Exception { robot = new Robot(); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + executeCase(lookAndFeelItem.getClassName()); + } - SwingUtilities.invokeAndWait(() -> { + } + static void executeCase(String lookAndFeelString) throws Exception { + if (tryLookAndFeel(lookAndFeelString)) { + SwingUtilities.invokeAndWait(() -> { createDateSpinner(); createAndShowUI(); }); robot.waitForIdle(); testSpinner(false); + cleanUp(); SwingUtilities.invokeAndWait(() -> { createNumberSpinner(); @@ -64,14 +76,16 @@ public class bug8008657 { robot.waitForIdle(); testSpinner(true); + cleanUp(); + } } - static void testSpinner(boolean checkHorizontalAligment) throws Exception { SwingUtilities.invokeAndWait(() -> { spinner.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); - }); + + }); robot.waitForIdle(); SwingUtilities.invokeAndWait(() -> { @@ -145,10 +159,34 @@ public class bug8008657 { } static void createAndShowUI() { - JFrame frame = new JFrame("Test"); + frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 100); frame.getContentPane().add(spinner); frame.setVisible(true); } + + private static void cleanUp() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + + private static boolean tryLookAndFeel(String lookAndFeelString) + throws Exception { + try { + UIManager.setLookAndFeel( + lookAndFeelString); + + } catch (UnsupportedLookAndFeelException + | ClassNotFoundException + | InstantiationException + | IllegalAccessException e) { + return false; + } + return true; + } } diff --git a/jdk/test/javax/swing/JTabbedPane/8134116/Bug8134116.java b/jdk/test/javax/swing/JTabbedPane/8134116/Bug8134116.java index 15aa9f43260..ed408d969d9 100644 --- a/jdk/test/javax/swing/JTabbedPane/8134116/Bug8134116.java +++ b/jdk/test/javax/swing/JTabbedPane/8134116/Bug8134116.java @@ -4,7 +4,6 @@ import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; import javax.accessibility.Accessible; -import javax.accessibility.AccessibleComponent; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; @@ -19,6 +18,8 @@ import javax.swing.plaf.nimbus.NimbusLookAndFeel; */ public class Bug8134116 { + private static volatile Exception exception = null; + public static void main(String args[]) throws Exception { try { @@ -29,75 +30,138 @@ public class Bug8134116 { SwingUtilities.invokeAndWait(() -> { JPanel panel0 = new JPanel(); + JPanel panel2 = new JPanel(); BadPane badPane = new BadPane(); badPane.add("zero", panel0); - badPane.add("one", null); + badPane.add("one", null); // no component + badPane.add("", panel2); // no title + badPane.add("", null); // no component, no title + // but give it that via a tabComponent + JPanel tabComponent = new JPanel(); + JLabel tabComponentLabel = new JLabel("three"); + tabComponent.add(tabComponentLabel); + badPane.setTabComponentAt(3, tabComponent); JFrame frame = new JFrame(); frame.add(badPane); frame.setSize(300, 300); frame.setVisible(true); - AccessibleContext ac = badPane.getAccessibleContext(); - Accessible page0 = ac.getAccessibleChild(0); - if (page0 == null) { - // Not something being tested, but checking anyway - throw new RuntimeException("getAccessibleChild(0) is null"); - } - Accessible page1 = ac.getAccessibleChild(1); - if (page1 == null) { - // Not something being tested, but checking anyway - throw new RuntimeException("getAccessibleChild(1) is null"); - } - // page0 and page1 are a JTabbedPane.Page, a private inner class - // and is an AccessibleContext - // and implements Accessible and AccessibleComponent - AccessibleContext pac0 = page0.getAccessibleContext(); - AccessibleContext pac1 = page1.getAccessibleContext(); + try { + AccessibleContext ac = badPane.getAccessibleContext(); + Accessible page0 = ac.getAccessibleChild(0); + if (page0 == null) { + // Not something being tested, but checking anyway + throw new RuntimeException("getAccessibleChild(0) is null"); + } + Accessible page1 = ac.getAccessibleChild(1); + if (page1 == null) { + // Not something being tested, but checking anyway + throw new RuntimeException("getAccessibleChild(1) is null"); + } + Accessible page2 = ac.getAccessibleChild(2); + Accessible page3 = ac.getAccessibleChild(3); + // page0 - page3 are JTabbedPane.Page, a private inner class + // and is an AccessibleContext + // and implements Accessible and AccessibleComponent + AccessibleContext pac0 = page0.getAccessibleContext(); + AccessibleContext pac1 = page1.getAccessibleContext(); + AccessibleContext pac2 = page2.getAccessibleContext(); + AccessibleContext pac3 = page3.getAccessibleContext(); - // the following would fail if JDK-8134116 fix not present + // test Page.getBounds + // ensure no IndexOutOfBoundsException + Rectangle r0 = pac0.getAccessibleComponent().getBounds(); + // make sure second Bounds is different than first + Rectangle r1 = pac1.getAccessibleComponent().getBounds(); + if (r1.equals(r0)) { + String msg = "Second tab should not have same bounds as first tab"; + throw new RuntimeException(msg); + } - // test Page.getBounds - // ensure no IndexOutOfBoundsException - pac0.getAccessibleComponent().getBounds(); + // test Page.getAccessibleStateSet + // At this point page 0 is selected + AccessibleStateSet accSS0 = pac0.getAccessibleStateSet(); + if (!accSS0.contains(AccessibleState.SELECTED)) { + String msg = "Empty title -> AccessibleState.SELECTED not set"; + throw new RuntimeException(msg); + } + // select second tab + badPane.setSelectedIndex(1); + AccessibleStateSet accSS1 = pac1.getAccessibleStateSet(); + if (!accSS1.contains(AccessibleState.SELECTED)) { + String msg = "Second tab selected but AccessibleState.SELECTED not set"; + throw new RuntimeException(msg); + } + // select third tab + badPane.setSelectedIndex(2); + AccessibleStateSet accSS2 = pac2.getAccessibleStateSet(); + if (!accSS1.contains(AccessibleState.SELECTED)) { + String msg = "Third tab selected but AccessibleState.SELECTED not set"; + throw new RuntimeException(msg); + } + // select fourth tab + badPane.setSelectedIndex(3); + AccessibleStateSet accSS3 = pac3.getAccessibleStateSet(); + if (!accSS1.contains(AccessibleState.SELECTED)) { + String msg = "Fourth tab selected but AccessibleState.SELECTED not set"; + throw new RuntimeException(msg); + } - // test Page.getAccessibleStateSet - // At this point page 0 is selected - AccessibleStateSet accSS0 = pac0.getAccessibleStateSet(); - if (!accSS0.contains(AccessibleState.SELECTED)) { - String msg = "Empty title -> AccessibleState.SELECTED not set"; - throw new RuntimeException(msg); - } + // test Page.getAccessibleIndexInParent + if (pac0.getAccessibleIndexInParent() == -1) { + String msg = "Empty title -> negative AccessibleIndexInParent"; + throw new RuntimeException(msg); + } + if (pac0.getAccessibleIndexInParent() != 0) { + String msg = "first tab is not at index 0 in parent"; + throw new RuntimeException(msg); + } + if (pac1.getAccessibleIndexInParent() != 1) { + String msg = "second tab (null component) is not at index 1 in parent"; + throw new RuntimeException(msg); + } + if (pac2.getAccessibleIndexInParent() != 2) { + String msg = "third tab (empty title) string is not at index 2 in parent"; + throw new RuntimeException(msg); + } + if (pac3.getAccessibleIndexInParent() != 3) { + String msg = "fourth tab (empty title, null component, has tabComponent) string is not at index 3 in parent"; + throw new RuntimeException(msg); + } - // test Page.getAccessibleIndexInParent - if (pac0.getAccessibleIndexInParent() == -1) { - String msg = "Empty title -> negative AccessibleIndexInParent"; - throw new RuntimeException(msg); - } + // test Page.getAccessibleName + String accName = pac0.getAccessibleName(); + if (!accName.equals("zero")) { + String msg = "Empty title -> empty AccessibleName"; + throw new RuntimeException(msg); + } + // test Page.getAccessibleName when component is null + accName = pac1.getAccessibleName(); + if (!accName.equals("one")) { + String msg = "AccessibleName of null panel not 'one'"; + throw new RuntimeException(msg); + } - // test Page.getAccessibleName - String accName = pac0.getAccessibleName(); - if (!accName.equals("zero")) { - String msg = "Empty title -> empty AccessibleName"; - throw new RuntimeException(msg); - } - // test Page.getAccessibleName when component is null - accName = pac1.getAccessibleName(); - if (!accName.equals("one")) { - String msg = "AccessibleName of null panel not 'one'"; - throw new RuntimeException(msg); - } + // test Page.setDisplayedMnemonicIndex + // Empty title -> IllegalArgumnetException + badPane.setDisplayedMnemonicIndexAt(0, 1); - // test Page.setDisplayedMnemonicIndex - // Empty title -> IllegalArgumnetException - badPane.setDisplayedMnemonicIndexAt(0, 1); - - // test Page.updateDisplayedMnemonicIndex - badPane.setMnemonicAt(0, KeyEvent.VK_Z); - if (badPane.getDisplayedMnemonicIndexAt(0) == -1) { - String msg="Empty title -> getDisplayedMnemonicIndexAt failure"; - throw new RuntimeException(msg); + // test Page.updateDisplayedMnemonicIndex + badPane.setMnemonicAt(0, KeyEvent.VK_Z); + if (badPane.getDisplayedMnemonicIndexAt(0) == -1) { + String msg="Empty title -> getDisplayedMnemonicIndexAt failure"; + throw new RuntimeException(msg); + } + } catch (Exception e) { + exception = e; } }); + if (exception != null) { + System.out.println("Test failed: " + exception.getMessage()); + throw exception; + } else { + System.out.println("Test passed."); + } } // The following is likely what is being done in Burp Suite diff --git a/jdk/test/javax/swing/LookAndFeel/8146276/NimbusGlueTest.java b/jdk/test/javax/swing/LookAndFeel/8146276/NimbusGlueTest.java new file mode 100644 index 00000000000..cd64ee723ab --- /dev/null +++ b/jdk/test/javax/swing/LookAndFeel/8146276/NimbusGlueTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8146276 + * @summary Right aligned toolbar component does not appear + * @run main NimbusGlueTest + */ +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JToolBar; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import java.awt.Robot; +import javax.swing.UnsupportedLookAndFeelException; + +public class NimbusGlueTest { + + private static JFrame frame; + private static Robot robot; + private static volatile String errorMessage = ""; + private static JToolBar bar; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + String lookAndFeelString = lookAndFeelItem.getClassName(); + if (tryLookAndFeel(lookAndFeelString)) { + createUI(); + performTest(); + robot.waitForIdle(); + } + } + if (!"".equals(errorMessage)) { + throw new RuntimeException(errorMessage); + } + } + + private static boolean tryLookAndFeel(String lookAndFeelString) { + try { + UIManager.setLookAndFeel(lookAndFeelString); + return true; + } catch (UnsupportedLookAndFeelException | ClassNotFoundException | + InstantiationException | IllegalAccessException e) { + errorMessage += e.getMessage() + "\n"; + System.err.println("Caught Exception: " + e.getMessage()); + return false; + } + } + + private static void performTest() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + int width = 0; + for (Component comp : bar.getComponents()) { + width += comp.getWidth(); + } + if (width > 600) { + errorMessage = "Test Failed"; + } + } finally { + frame.dispose(); + } + + } + }); + } + + private static void createUI() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame = new JFrame(); + bar = new JToolBar(); + bar.add(createButton(1)); + bar.add(createButton(2)); + bar.add(Box.createHorizontalGlue()); + bar.add(createButton(3)); + frame.add(bar, BorderLayout.NORTH); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(600, 400); + frame.setVisible(true); + } + }); + } + + private static JButton createButton(int id) { + JButton b = new JButton("B: " + id); + b.setPreferredSize(new Dimension(60, b.getPreferredSize().height)); + return b; + } +} diff --git a/jdk/test/javax/swing/text/html/HTMLEditorKit/7104635/HTMLEditorKitWriterBug.java b/jdk/test/javax/swing/text/html/HTMLEditorKit/7104635/HTMLEditorKitWriterBug.java new file mode 100644 index 00000000000..d37f9fd69d6 --- /dev/null +++ b/jdk/test/javax/swing/text/html/HTMLEditorKit/7104635/HTMLEditorKitWriterBug.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7104635 + * @summary HTMLEditorKit fails to write down some html files + * @run main HTMLEditorKitWriterBug + */ +import java.io.CharArrayReader; +import java.io.CharArrayWriter; +import javax.swing.text.html.HTMLDocument; +import javax.swing.text.html.HTMLEditorKit; + +public class HTMLEditorKitWriterBug { + + public static void main(String[] args) { + String htmlDoc = "

          "; + try { + HTMLEditorKit kit = new HTMLEditorKit(); + Class c = Class.forName( + "javax.swing.text.html.parser.ParserDelegator"); + HTMLEditorKit.Parser parser = (HTMLEditorKit.Parser) c.newInstance(); + HTMLDocument doc = (HTMLDocument) kit.createDefaultDocument(); + HTMLEditorKit.ParserCallback htmlReader = doc.getReader(0); + parser.parse(new CharArrayReader(htmlDoc.toCharArray()), + htmlReader, true); + htmlReader.flush(); + CharArrayWriter writer = new CharArrayWriter(1000); + kit.write(writer, doc, 0, doc.getLength()); + writer.flush(); + } catch (Exception ex) { + throw new RuntimeException("Test Failed " + ex); + } + } +} diff --git a/jdk/test/jdk/Version/Basic.java b/jdk/test/jdk/Version/Basic.java new file mode 100644 index 00000000000..b94180c8daf --- /dev/null +++ b/jdk/test/jdk/Version/Basic.java @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Unit test for jdk.Version. + * @bug 8072379 + */ + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.util.stream.Collectors; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import jdk.Version; +import static java.lang.System.out; + +public class Basic { + private static final Class IAE + = IllegalArgumentException.class; + private static final Class NPE + = NullPointerException.class; + private static final Class NFE + = NumberFormatException.class; + private static final Class VERSION = Version.class; + + private static final BigInteger TOO_BIG + = (BigInteger.valueOf(Integer.MAX_VALUE)).add(BigInteger.ONE); + private static final String TOO_BIG_STR = TOO_BIG.toString(); + + public static void main(String ... args) { + + //// Tests for parse(), major(), minor(), security(), pre(), + //// build(), opt(), version(), toString() + // v M m sec pre bld opt + + // $VNUM + test("9", 9, 0, 0, "", 0, ""); + test("9.1", 9, 1, 0, "", 0, ""); + test("9.0.1", 9, 0, 1, "", 0, ""); + test("404.1.2", 404, 1, 2, "", 0, ""); + test("9.1.2.3", 9, 1, 2, "", 0, ""); + test("1000.0.0.0.0.0.99999999", 1000, 0, 0, "", 0, ""); + + tryCatch(null, NPE); + tryCatch("", IAE); + tryCatch("foo", IAE); + tryCatch("7a", IAE); + tryCatch("0", IAE); + tryCatch("09", IAE); + tryCatch("9.0", IAE); + tryCatch("9.0.", IAE); + tryCatch("1.9,1", IAE); + tryCatch(TOO_BIG_STR, NFE); + + // $PRE + test("9-ea", 9, 0, 0, "ea", 0, ""); + test("9-internal", 9, 0, 0, "internal", 0, ""); + test("9-0", 9, 0, 0, "0", 0, ""); + test("9.2.7-8", 9, 2, 7, "8", 0, ""); + test("1-ALL", 1, 0, 0, "ALL", 0, ""); + test("2.3.4.5-1a", 2, 3, 4, "1a", 0, ""); + test("1-" + TOO_BIG_STR, 1, 0, 0, TOO_BIG_STR, 0, ""); + + tryCatch("9:-ea", IAE); + tryCatch("3.14159-", IAE); + tryCatch("3.14159-%", IAE); + + // $BUILD + test("9+0", 9, 0, 0, "", 0, ""); + test("3.14+9999900", 3, 14, 0, "", 9999900, ""); + test("9-pre+105", 9, 0, 0, "pre", 105, ""); + test("6.0.42-8beta+4", 6, 0, 42, "8beta", 4, ""); + + tryCatch("9+", IAE); + tryCatch("7+a", IAE); + tryCatch("9+00", IAE); + tryCatch("4.2+01", IAE); + tryCatch("4.2+1a", IAE); + tryCatch("1+" + TOO_BIG_STR, NFE); + + // $OPT + test("9+-foo", 9, 0, 0, "", 0, "foo"); + test("9-pre-opt", 9, 0, 0, "pre", 0, "opt"); + test("42+---bar", 42, 0, 0, "", 0, "--bar"); + test("2.91+-8061493-", 2, 91, 0, "", 0, "8061493-"); + test("24+-foo.bar", 24, 0, 0, "", 0, "foo.bar"); + test("9-ribbit+17-...", 9, 0, 0, "ribbit", 17, "..."); + test("7+1-" + TOO_BIG_STR, 7,0, 0, "", 1, TOO_BIG_STR); + + tryCatch("9-pre+-opt", IAE); + tryCatch("1.4142+-", IAE); + tryCatch("2.9979+-%", IAE); + + //// Test for current() + testCurrent(); + + //// Test for equals{IgnoreOpt}?(), hashCode(), compareTo{IgnoreOpt}?() + // compare: after "<" == -1, equal == 0, before ">" == 1 + // v0 v1 eq eqNO cmp cmpNO + testEHC("9", "9", true, true, 0, 0); + + testEHC("8", "9", false, false, -1, -1); + testEHC("9", "10", false, false, -1, -1); + testEHC("9", "8", false, false, 1, 1); + + // $OPT comparison + testEHC("9", "9+-oink", false, true, -1, 0); + testEHC("9+-ribbit", "9+-moo", false, true, 1, 0); + testEHC("9-quack+3-ribbit", + "9-quack+3-moo", false, true, 1, 0); + testEHC("9.1+7", "9.1+7-moo-baa-la", false, true, -1, 0); + + // numeric vs. non-numeric $PRE + testEHC("9.1.1.2-2a", "9.1.1.2-12", false, false, 1, 1); + testEHC("9.1.1.2-12", "9.1.1.2-4", false, false, 1, 1); + + testEHC("27.16", "27.16+120", false, false, 1, 1); + testEHC("10", "10-ea", false, false, 1, 1); + testEHC("10.1+1", "10.1-ea+1", false, false, 1, 1); + testEHC("10.0.1+22", "10.0.1+21", false, false, 1, 1); + + // numeric vs. non-numeric $PRE + testEHC("9.1.1.2-12", "9.1.1.2-a2", false, false, -1, -1); + testEHC("9.1.1.2-1", "9.1.1.2-4", false, false, -1, -1); + + testEHC("9-internal", "9", false, false, -1, -1); + testEHC("9-ea+120", "9+120", false, false, -1, -1); + testEHC("9-ea+120", "9+120", false, false, -1, -1); + testEHC("9+101", "9", false, false, -1, -1); + testEHC("9+101", "9+102", false, false, -1, -1); + testEHC("1.9-ea", "9-ea", false, false, -1, -1); + + if (fail != 0) + throw new RuntimeException((fail + pass) + " tests: " + + fail + " failure(s), first", first); + else + out.println("all " + (fail + pass) + " tests passed"); + + } + + private static void test(String s, Integer major, Integer minor, + Integer sec, String pre, Integer build, + String opt) + { + Version v = testParse(s); + + testStr(v.toString(), s); + + testInt(v.major(), major); + testInt(v.minor(), minor); + testInt(v.security(), sec); + testStr((v.pre().isPresent() ? v.pre().get() : ""), pre); + testInt((v.build().isPresent() ? v.build().get() : 0), build); + testStr((v.optional().isPresent() ? v.optional().get() : ""), opt); + + testVersion(v.version(), s); + } + + private static Version testParse(String s) { + Version v = Version.parse(s); + pass(); + return v; + } + + private static void testInt(int got, int exp) { + if (got != exp) { + fail("testInt()", Integer.toString(exp), Integer.toString(got)); + } else { + pass(); + } + } + + private static void testStr(String got, String exp) { + if (!got.equals(exp)) { + fail("testStr()", exp, got); + } else { + pass(); + } + } + + private static void tryCatch(String s, Class ex) { + Throwable t = null; + try { + Version.parse(s); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) { + t = x; + } else + x.printStackTrace(); + } + if ((t == null) && (ex != null)) + fail(s, ex); + else + pass(); + } + + private static void testCurrent() { + Version current = Version.current(); + String javaVer = System.getProperty("java.version"); + + // java.version == $VNUM(\-$PRE) + String [] ver = javaVer.split("-"); + List javaVerVNum + = Arrays.stream(ver[0].split("\\.")) + .map(v -> Integer.parseInt(v)) + .collect(Collectors.toList()); + if (!javaVerVNum.equals(current.version())) { + fail("testCurrent() version()", javaVerVNum.toString(), + current.version().toString()); + } else { + pass(); + } + + Optional javaVerPre + = (ver.length == 2) + ? Optional.ofNullable(ver[1]) + : Optional.empty(); + if (!javaVerPre.equals(current.pre())) { + fail("testCurrent() pre()", javaVerPre.toString(), + current.pre().toString()); + } else { + pass(); + } + + testEHC(current.toString(), javaVer, true, true, 0, 0); + } + + private static void testVersion(List vnum, String s) { + List svnum = new ArrayList(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + Character c = s.charAt(i); + if (Character.isDigit(c)) { + sb.append(c); + } else { + svnum.add(Integer.parseInt(sb.toString())); + sb = new StringBuilder(); + if (c == '+' || c == '-') { + break; + } + } + } + if (sb.length() > 0) { + svnum.add(Integer.parseInt(sb.toString())); + } + + if (!svnum.equals(vnum)) { + fail("testVersion() equals()", svnum.toString(), vnum.toString()); + } else { + pass(); + } + } + + private static void testEHC(String s0, String s1, boolean eq, boolean eqNO, + int cmp, int cmpNO) + { + Version v0 = Version.parse(s0); + Version v1 = Version.parse(s1); + + testEquals(v0, v1, eq); + testEqualsNO(v0, v1, eqNO); + + testHashCode(v0, v1, eq); + + testCompare(v0, v1, cmp); + testCompareNO(v0, v1, cmpNO); + } + + private static void testEqualsNO(Version v0, Version v1, boolean eq) { + if ((eq && !v0.equalsIgnoreOpt(v1)) + || (!eq && v0.equalsIgnoreOpt(v1))) { + fail("equalsIgnoreOpt() " + Boolean.toString(eq), + v0.toString(), v1.toString()); + } else { + pass(); + } + } + + private static void testEquals(Version v0, Version v1, boolean eq) { + if ((eq && !v0.equals(v1)) || (!eq && v0.equals(v1))) { + fail("equals() " + Boolean.toString(eq), + v0.toString(), v1.toString()); + } else { + pass(); + } + } + + private static void testHashCode(Version v0, Version v1, boolean eq) { + int h0 = v0.hashCode(); + int h1 = v1.hashCode(); + if (eq) { + testInt(h0, h1); + } else if (h0 == h1) { + fail(String.format("hashCode() %s", h0), + Integer.toString(h0), + Integer.toString(h1)); + } else { // !eq && (h0 != h1) + pass(); + } + } + + private static void testCompareNO(Version v0, Version v1, int compare) + { + try { + Method m = VERSION.getMethod("compareToIgnoreOpt", VERSION); + int cmp = (int) m.invoke(v0, v1); + checkCompare(v0, v1, compare, cmp); + } catch (IllegalAccessException | InvocationTargetException | + NoSuchMethodException ex) { + fail(String.format("compareToIgnoreOpt() invocation: %s", + ex.getClass()), + null); + } + } + + private static void testCompare(Version v0, Version v1, int compare) { + try { + Method m = VERSION.getMethod("compareTo", VERSION); + int cmp = (int) m.invoke(v0, v1); + checkCompare(v0, v1, compare, cmp); + } catch (IllegalAccessException | InvocationTargetException | + NoSuchMethodException ex) { + fail(String.format("compareTo() invocation: %s", ex.getClass()), + null); + } + } + + private static void checkCompare(Version v0, Version v1, + int compare, int cmp) + { + if (((cmp == 0) && (compare == 0)) + || (compare == (cmp / Math.abs(cmp == 0 ? 1 : cmp)))) { + pass(); + } else { + fail(String.format("compare() (cmp = %s) (compare = %s)", + cmp, compare), + v0.toString(), v1.toString()); + } + } + + private static int fail = 0; + private static int pass = 0; + + private static Throwable first; + + static void pass() { + pass++; + } + + static void fail(String fs, Class ex) { + String s = "'" + fs + "'"; + if (ex != null) + s += ": " + ex.getName() + " not thrown"; + if (first == null) + setFirst(s); + System.err.println("FAILED: " + s); + fail++; + } + + static void fail(String t, String exp, String got) { + String s = t + ": Expected '" + exp + "', got '" + got + "'"; + if (first == null) + setFirst(s); + System.err.println("FAILED: " + s); + fail++; + } + + private static void setFirst(String s) { + try { + throw new RuntimeException(s); + } catch (RuntimeException x) { + first = x; + } + } +} diff --git a/jdk/test/jdk/internal/misc/JavaLangAccess/FormatUnsigned.java b/jdk/test/jdk/internal/misc/JavaLangAccess/FormatUnsigned.java deleted file mode 100644 index e1e4b4288e1..00000000000 --- a/jdk/test/jdk/internal/misc/JavaLangAccess/FormatUnsigned.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import jdk.internal.misc.JavaLangAccess; -import jdk.internal.misc.SharedSecrets; - -/* - * @test - * @bug 8050114 - * @summary Test JavaLangAccess.formatUnsignedInt/-Long - * @modules java.base/jdk.internal.misc - */ -public class FormatUnsigned { - - static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); - - public static void testFormatUnsignedInt() { - testFormatUnsignedInt("7fffffff", Integer.MAX_VALUE, 8, 4, 0, 8); - testFormatUnsignedInt("80000000", Integer.MIN_VALUE, 8, 4, 0, 8); - testFormatUnsignedInt("4711", 04711, 4, 3, 0, 4); - testFormatUnsignedInt("4711", 0x4711, 4, 4, 0, 4); - testFormatUnsignedInt("1010", 0b1010, 4, 1, 0, 4); - testFormatUnsignedInt("00001010", 0b1010, 8, 1, 0, 8); - testFormatUnsignedInt("\u0000\u000000001010", 0b1010, 10, 1, 2, 8); - } - - public static void testFormatUnsignedLong() { - testFormatUnsignedLong("7fffffffffffffff", Long.MAX_VALUE, 16, 4, 0, 16); - testFormatUnsignedLong("8000000000000000", Long.MIN_VALUE, 16, 4, 0, 16); - testFormatUnsignedLong("4711", 04711L, 4, 3, 0, 4); - testFormatUnsignedLong("4711", 0x4711L, 4, 4, 0, 4); - testFormatUnsignedLong("1010", 0b1010L, 4, 1, 0, 4); - testFormatUnsignedLong("00001010", 0b1010L, 8, 1, 0, 8); - testFormatUnsignedLong("\u0000\u000000001010", 0b1010L, 10, 1, 2, 8); - } - - public static void testFormatUnsignedInt(String expected, int value, int arraySize, int shift, int offset, int length) { - char[] chars = new char[arraySize]; - jla.formatUnsignedInt(value, shift, chars, offset, length); - String s = new String(chars); - if (!expected.equals(s)) { - throw new Error(s + " should be equal to expected " + expected); - } - } - - public static void testFormatUnsignedLong(String expected, long value, int arraySize, int shift, int offset, int length) { - char[] chars = new char[arraySize]; - jla.formatUnsignedLong(value, shift, chars, offset, length); - String s = new String(chars); - if (!expected.equals(s)) { - throw new Error(s + " should be equal to expected " + expected); - } - } - - public static void main(String[] args) { - testFormatUnsignedInt(); - testFormatUnsignedLong(); - } -} diff --git a/jdk/test/jdk/internal/ref/Cleaner/ExitOnThrow.java b/jdk/test/jdk/internal/ref/Cleaner/ExitOnThrow.java new file mode 100644 index 00000000000..994cee3f896 --- /dev/null +++ b/jdk/test/jdk/internal/ref/Cleaner/ExitOnThrow.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4954921 8009259 + * @library /test/lib/share/classes + * @build jdk.test.lib.* + * @build jdk.test.lib.process.* + * @run main ExitOnThrow + * @summary Ensure that if a cleaner throws an exception then the VM exits + */ +import java.util.Arrays; + +import jdk.internal.ref.Cleaner; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class ExitOnThrow { + + static final String cp = System.getProperty("test.classes", "."); + + public static void main(String[] args) throws Exception { + if (args.length == 0) { + String[] cmd = JDKToolLauncher.createUsingTestJDK("java") + .addToolArg("-cp") + .addToolArg(cp) + .addToolArg("ExitOnThrow") + .addToolArg("-executeCleaner") + .getCommand(); + ProcessBuilder pb = new ProcessBuilder(cmd); + OutputAnalyzer out = ProcessTools.executeProcess(pb); + System.out.println("======================"); + System.out.println(Arrays.toString(cmd)); + String msg = " stdout: [" + out.getStdout() + "]\n" + + " stderr: [" + out.getStderr() + "]\n" + + " exitValue = " + out.getExitValue() + "\n"; + System.out.println(msg); + + if (out.getExitValue() != 1) + throw new RuntimeException("Unexpected exit code: " + + out.getExitValue()); + + } else { + Cleaner.create(new Object(), + () -> { throw new RuntimeException("Foo!"); } ); + while (true) { + System.gc(); + Thread.sleep(100); + } + } + } + +} diff --git a/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java b/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java index 299a9ca65db..390c4fa0c69 100644 --- a/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java +++ b/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java @@ -21,12 +21,21 @@ * questions. */ +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.CertPath; +import java.security.cert.CertificateFactory; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.zip.ZipFile; +import jdk.security.jarsigner.JarSigner; public class CreateMultiReleaseTestJars { final private String main = @@ -120,14 +129,21 @@ public class CreateMultiReleaseTestJars { String testsrc = System.getProperty("test.src","."); String testdir = findTestDir(testsrc); String keystore = testdir + "/sun/security/tools/jarsigner/JarSigning.keystore"; - String[] jsArgs = { - "-keystore", keystore, - "-storepass", "bbbbbb", - "-signedJar", "signed-multi-release.jar", - "multi-release.jar", "b" - }; - sun.security.tools.jarsigner.Main.main(jsArgs); + // jarsigner -keystore keystore -storepass "bbbbbb" + // -signedJar signed-multi-release.jar multi-release.jar b + + char[] password = "bbbbbb".toCharArray(); + KeyStore ks = KeyStore.getInstance(new File(keystore), password); + PrivateKey pkb = (PrivateKey)ks.getKey("b", password); + CertPath cp = CertificateFactory.getInstance("X.509") + .generateCertPath(Arrays.asList(ks.getCertificateChain("b"))); + JarSigner js = new JarSigner.Builder(pkb, cp).build(); + try (ZipFile in = new ZipFile("multi-release.jar"); + FileOutputStream os = new FileOutputStream("signed-multi-release.jar")) + { + js.sign(in, os); + } } String findTestDir(String dir) throws IOException { diff --git a/jdk/test/sun/applet/DeprecatedAppletViewer/DeprecatedAppletViewer.java b/jdk/test/sun/applet/DeprecatedAppletViewer/DeprecatedAppletViewer.java new file mode 100644 index 00000000000..f3b43f83eee --- /dev/null +++ b/jdk/test/sun/applet/DeprecatedAppletViewer/DeprecatedAppletViewer.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +/** + * @test + * @bug 8074165 + * @modules java.desktop/sun.applet + * @run main/othervm -Duser.language=en DeprecatedAppletViewer + */ +public final class DeprecatedAppletViewer { + + private static final String TEXT = "AppletViewer is deprecated."; + + public static void main(final String[] args) { + final PrintStream old = System.out; + final ByteArrayOutputStream baos = new ByteArrayOutputStream(1000); + final PrintStream ps = new PrintStream(baos); + try { + System.setOut(ps); + sun.applet.Main.main(new String[]{}); + } finally { + System.setOut(old); + } + + final String text = new String(baos.toByteArray()); + if (!text.contains(TEXT)) { + System.err.println("The text should contain: \"" + TEXT + "\""); + System.err.println("But the current text is: "); + System.err.println(text); + throw new RuntimeException("Error"); + } + } +} diff --git a/jdk/test/sun/java2d/marlin/ArrayCacheSizeTest.java b/jdk/test/sun/java2d/marlin/ArrayCacheSizeTest.java index 8c40fe4cfae..79fc9ac0ff4 100644 --- a/jdk/test/sun/java2d/marlin/ArrayCacheSizeTest.java +++ b/jdk/test/sun/java2d/marlin/ArrayCacheSizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,12 @@ import sun.java2d.marlin.ArrayCache; -/** +/* * @test * @bug 8144445 * @summary Check the ArrayCache getNewLargeSize() method * @run main ArrayCacheSizeTest + * @modules java.desktop/sun.java2d.marlin */ public class ArrayCacheSizeTest { diff --git a/jdk/test/sun/java2d/marlin/CeilAndFloorTests.java b/jdk/test/sun/java2d/marlin/CeilAndFloorTests.java index 5f7fcc153c2..81d9faea97f 100644 --- a/jdk/test/sun/java2d/marlin/CeilAndFloorTests.java +++ b/jdk/test/sun/java2d/marlin/CeilAndFloorTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import sun.java2d.marlin.FloatMath; * @test * @summary Check for correct implementation of FloatMath.ceil/floor * @run main CeilAndFloorTests + * @modules java.desktop/sun.java2d.marlin */ public class CeilAndFloorTests { diff --git a/jdk/test/sun/java2d/marlin/TextClipErrorTest.java b/jdk/test/sun/java2d/marlin/TextClipErrorTest.java new file mode 100644 index 00000000000..efce137256c --- /dev/null +++ b/jdk/test/sun/java2d/marlin/TextClipErrorTest.java @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.geom.Path2D; +import java.awt.geom.PathIterator; +import static java.awt.geom.PathIterator.SEG_CLOSE; +import static java.awt.geom.PathIterator.SEG_CUBICTO; +import static java.awt.geom.PathIterator.SEG_LINETO; +import static java.awt.geom.PathIterator.SEG_MOVETO; +import static java.awt.geom.PathIterator.SEG_QUADTO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * @test @bug 8144718 + * @summary Check the Stroker.drawBezApproxForArc() bug (stoke with round + * joins): if cosext2 > 0.5, it generates curves with NaN coordinates + * @run main TextClipErrorTest + */ +public class TextClipErrorTest { + + static final boolean SAVE_IMAGE = false; + static final boolean SERIALIZE = false; + + public static void main(String[] args) { + Locale.setDefault(Locale.US); + + // initialize j.u.l Looger: + final Logger log = Logger.getLogger("sun.java2d.marlin"); + log.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + Throwable th = record.getThrown(); + // detect potential Throwable thrown by XxxArrayCache.check(): + if (th != null && th.getClass() == Throwable.class) { + StackTraceElement[] stackElements = th.getStackTrace(); + + for (int i = 0; i < stackElements.length; i++) { + StackTraceElement e = stackElements[i]; + + if (e.getClassName().startsWith("sun.java2d.marlin") + && e.getClassName().contains("ArrayCache") + && "check".equals(e.getMethodName())) + { + System.out.println("Test failed:\n" + + record.getMessage()); + th.printStackTrace(System.out); + + throw new RuntimeException("Test failed: ", th); + } + } + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }); + + log.info("TextClipErrorTest: start"); + + // enable Marlin logging & internal checks: + System.setProperty("sun.java2d.renderer.log", "true"); + System.setProperty("sun.java2d.renderer.useLogger", "true"); + System.setProperty("sun.java2d.renderer.doChecks", "true"); + + BufferedImage image = new BufferedImage(256, 256, + BufferedImage.TYPE_INT_ARGB); + + Graphics2D g2d = image.createGraphics(); + g2d.setColor(Color.red); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + Font font = g2d.getFont(); + FontRenderContext frc = new FontRenderContext( + new AffineTransform(), true, true); + + g2d.setStroke(new BasicStroke(4.0f, + BasicStroke.CAP_ROUND, + BasicStroke.JOIN_ROUND)); + + final Shape badShape; + if (SERIALIZE) { + final GlyphVector gv1 = font.createGlyphVector(frc, "\u00d6"); + final Shape textShape = gv1.getOutline(); + + final AffineTransform at1 = AffineTransform.getTranslateInstance( + -2091202.554154681, 5548.601436981691); + badShape = at1.createTransformedShape(textShape); + serializeShape(badShape); + } else { + badShape = deserializeShape(); + } + + g2d.draw(badShape); + + // Draw anything within bounds and it fails: + g2d.draw(new Line2D.Double(10, 20, 30, 40)); + + if (SAVE_IMAGE) { + final File file = new File("TextClipErrorTest.png"); + System.out.println("Writing file: " + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } + } catch (IOException ex) { + ex.printStackTrace(); + } finally { + g2d.dispose(); + log.info("TextClipErrorTest: end"); + } + } + + private static void serializeShape(Shape shape) { + final double[] coords = new double[6]; + + final int len = 32; + final ArrayList typeList = new ArrayList(len); + final ArrayList coordsList = new ArrayList(len); + + for (PathIterator pi = shape.getPathIterator(null); + !pi.isDone(); pi.next()) + { + switch (pi.currentSegment(coords)) { + case SEG_MOVETO: + typeList.add(SEG_MOVETO); + coordsList.add(Arrays.copyOf(coords, 2)); + break; + case SEG_LINETO: + typeList.add(SEG_LINETO); + coordsList.add(Arrays.copyOf(coords, 2)); + break; + case SEG_QUADTO: + typeList.add(SEG_QUADTO); + coordsList.add(Arrays.copyOf(coords, 4)); + break; + case SEG_CUBICTO: + typeList.add(SEG_CUBICTO); + coordsList.add(Arrays.copyOf(coords, 6)); + break; + case SEG_CLOSE: + typeList.add(SEG_CLOSE); + coordsList.add(null); + break; + default: + } + } + + final StringBuilder sb = new StringBuilder(1024); + // types: + sb.append("private static final int[] SHAPE_TYPES = new int[]{\n"); + for (Integer i : typeList) { + sb.append(i).append(",\n"); + } + sb.append("};\n"); + + // coords: + sb.append("private static final double[][] SHAPE_COORDS = new double[][]{\n"); + for (double[] c : coordsList) { + if (c == null) { + sb.append("null,\n"); + } else { + sb.append("new double[]{"); + for (int i = 0; i < c.length; i++) { + sb.append(c[i]).append(","); + } + sb.append("},\n"); + } + } + sb.append("};\n"); + + System.out.println("Shape size: " + typeList.size()); + System.out.println("Serialized shape:\n" + sb.toString()); + } + + private static Shape deserializeShape() { + final Path2D.Double path = new Path2D.Double(); + + for (int i = 0; i < SHAPE_TYPES.length; i++) { + double[] coords = SHAPE_COORDS[i]; + + switch (SHAPE_TYPES[i]) { + case SEG_MOVETO: + path.moveTo(coords[0], coords[1]); + break; + case SEG_LINETO: + path.lineTo(coords[0], coords[1]); + break; + case SEG_QUADTO: + path.quadTo(coords[0], coords[1], + coords[2], coords[3]); + break; + case SEG_CUBICTO: + path.curveTo(coords[0], coords[1], + coords[2], coords[3], + coords[4], coords[5]); + break; + case SEG_CLOSE: + path.closePath(); + break; + default: + } + } + + return path; + } + + // generated code: + private static final int[] SHAPE_TYPES = new int[]{ + 0, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 4, + 0, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 4, + 0, + 1, + 1, + 1, + 1, + 4, + 0, + 1, + 1, + 1, + 1, + 4, + }; + + private static final double[][] SHAPE_COORDS = new double[][]{ + new double[]{-2091197.819779681, 5540.648311981691,}, + new double[]{-2091199.116654681, 5540.648311981691, -2091199.874467181, 5541.609249481691,}, + new double[]{-2091200.632279681, 5542.570186981691, -2091200.632279681, 5544.242061981691,}, + new double[]{-2091200.632279681, 5545.882686981691, -2091199.874467181, 5546.843624481691,}, + new double[]{-2091199.116654681, 5547.804561981691, -2091197.819779681, 5547.804561981691,}, + new double[]{-2091196.538529681, 5547.804561981691, -2091195.780717181, 5546.843624481691,}, + new double[]{-2091195.022904681, 5545.882686981691, -2091195.022904681, 5544.242061981691,}, + new double[]{-2091195.022904681, 5542.570186981691, -2091195.780717181, 5541.609249481691,}, + new double[]{-2091196.538529681, 5540.648311981691, -2091197.819779681, 5540.648311981691,}, + null, + new double[]{-2091197.819779681, 5539.695186981691,}, + new double[]{-2091195.991654681, 5539.695186981691, -2091194.890092181, 5540.929561981691,}, + new double[]{-2091193.788529681, 5542.163936981691, -2091193.788529681, 5544.242061981691,}, + new double[]{-2091193.788529681, 5546.304561981691, -2091194.890092181, 5547.538936981691,}, + new double[]{-2091195.991654681, 5548.773311981691, -2091197.819779681, 5548.773311981691,}, + new double[]{-2091199.663529681, 5548.773311981691, -2091200.772904681, 5547.538936981691,}, + new double[]{-2091201.882279681, 5546.304561981691, -2091201.882279681, 5544.242061981691,}, + new double[]{-2091201.882279681, 5542.163936981691, -2091200.772904681, 5540.929561981691,}, + new double[]{-2091199.663529681, 5539.695186981691, -2091197.819779681, 5539.695186981691,}, + null, + new double[]{-2091197.210404681, 5537.835811981691,}, + new double[]{-2091196.022904681, 5537.835811981691,}, + new double[]{-2091196.022904681, 5539.023311981691,}, + new double[]{-2091197.210404681, 5539.023311981691,}, + new double[]{-2091197.210404681, 5537.835811981691,}, + null, + new double[]{-2091199.632279681, 5537.835811981691,}, + new double[]{-2091198.444779681, 5537.835811981691,}, + new double[]{-2091198.444779681, 5539.023311981691,}, + new double[]{-2091199.632279681, 5539.023311981691,}, + new double[]{-2091199.632279681, 5537.835811981691,}, + null, + }; + +} diff --git a/jdk/test/sun/misc/Cleaner/exitOnThrow.sh b/jdk/test/sun/misc/Cleaner/exitOnThrow.sh deleted file mode 100644 index 4a22114ab18..00000000000 --- a/jdk/test/sun/misc/Cleaner/exitOnThrow.sh +++ /dev/null @@ -1,48 +0,0 @@ -#! /bin/sh - -# -# Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# -# @test -# @bug 4954921 8009259 -# @summary Ensure that if a cleaner throws an exception then the VM exits -# -# @build ExitOnThrow -# @run shell exitOnThrow.sh - -# Command-line usage: sh exitOnThrow.sh /path/to/build - -if [ -z "$TESTJAVA" ]; then - if [ $# -lt 1 ]; then exit 1; fi - TESTJAVA=$1; shift - TESTCLASSES=`pwd` -fi - -if $TESTJAVA/bin/java ${TESTVMOPTS} -cp $TESTCLASSES ExitOnThrow; then - echo Failed: VM exited normally - exit 1 -else - echo Passed: VM exited with code $? - exit 0 -fi diff --git a/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java b/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java index 207485afe63..8c8049bdf5c 100644 --- a/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java +++ b/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java @@ -42,13 +42,13 @@ import java.util.Random; /* * @test + * @requires sun.arch.data.model == "64" * @build TestMaxCachedBufferSize * @run main/othervm TestMaxCachedBufferSize * @run main/othervm -Djdk.nio.maxCachedBufferSize=0 TestMaxCachedBufferSize * @run main/othervm -Djdk.nio.maxCachedBufferSize=2000 TestMaxCachedBufferSize * @run main/othervm -Djdk.nio.maxCachedBufferSize=100000 TestMaxCachedBufferSize * @run main/othervm -Djdk.nio.maxCachedBufferSize=10000000 TestMaxCachedBufferSize - * * @summary Test the implementation of the jdk.nio.maxCachedBufferSize property. */ public class TestMaxCachedBufferSize { diff --git a/jdk/test/sun/security/jca/PreferredProviderTest.java b/jdk/test/sun/security/jca/PreferredProviderTest.java index 7120817a1b5..b7eace2d90e 100644 --- a/jdk/test/sun/security/jca/PreferredProviderTest.java +++ b/jdk/test/sun/security/jca/PreferredProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @bug 8076359 8133151 + * @bug 8076359 8133151 8145344 * @summary Test the value for new jdk.security.provider.preferred security property * @requires os.name == "SunOS" */ @@ -40,8 +40,9 @@ import javax.crypto.NoSuchPaddingException; public class PreferredProviderTest { private static final List SPARC_DATA = Arrays.asList( - new DataTuple("SHA-256", "SUN"), new DataTuple("SHA-384", "SUN"), - new DataTuple("SHA-512", "SUN")); + new DataTuple("SHA1", "SUN"), new DataTuple("SHA-1", "SUN"), + new DataTuple("SHA-224", "SUN"), new DataTuple("SHA-256", "SUN"), + new DataTuple("SHA-384", "SUN"), new DataTuple("SHA-512", "SUN")); private static final List X86_DATA = Arrays .asList(new DataTuple("RSA", "SunRsaSign")); @@ -52,7 +53,7 @@ public class PreferredProviderTest { String actualProvider = null; if (type.equals("sparcv9")) { if (!preferredProvider.equals( - "AES:SunJCE, SHA-256:SUN, SHA-384:SUN, SHA-512:SUN")) { + "AES:SunJCE, SHA1:SUN, SHA-224:SUN, SHA-256:SUN, SHA-384:SUN, SHA-512:SUN")) { throw new RuntimeException( "Test Failed: wrong jdk.security.provider.preferred " + "value on solaris-sparcv9"); diff --git a/langtools/.hgtags b/langtools/.hgtags index 3786fbae996..90a13fb7426 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -345,3 +345,4 @@ cb73b474703e2de266542b505cffd658bcc052da jdk-9+99 51136404ee5e6cd5868b60d66ebd55a02170b508 jdk-9+100 3b3bea483542bc08278af529fb25f2e5930da945 jdk-9+101 6149fc30cd710eb3484dc9863d8837ecaedb96b6 jdk-9+102 +94cfc50c1b8a74fd7b0ed2e9e4f4a9dab4f2c6a1 jdk-9+103 diff --git a/langtools/make/CompileInterim.gmk b/langtools/make/CompileInterim.gmk index 018343bb4ae..2ccd58feaa2 100644 --- a/langtools/make/CompileInterim.gmk +++ b/langtools/make/CompileInterim.gmk @@ -46,7 +46,7 @@ $(eval $(call SetupJavaCompilation,BUILD_INTERIM_LANGTOOLS, \ $(SUPPORT_OUTPUTDIR)/gensrc/jdk.compiler \ $(SUPPORT_OUTPUTDIR)/gensrc/jdk.javadoc \ $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdeps, \ - EXCLUDES := sun jdk, \ + EXCLUDES := sun, \ COPY := .gif .png .xml .css .js javax.tools.JavaCompilerTool, \ BIN := $(BUILDTOOLS_OUTPUTDIR)/langtools_interim_classes, \ JAR := $(INTERIM_LANGTOOLS_JAR))) diff --git a/langtools/make/gensrc/Gensrc-jdk.javadoc.gmk b/langtools/make/gensrc/Gensrc-jdk.javadoc.gmk index 1d9ab44b32b..3720b1be5ae 100644 --- a/langtools/make/gensrc/Gensrc-jdk.javadoc.gmk +++ b/langtools/make/gensrc/Gensrc-jdk.javadoc.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,12 @@ include GensrcCommon.gmk -$(eval $(call SetupVersionProperties,JAVADOC_VERSION,\ +$(eval $(call SetupVersionProperties,OLD_JAVADOC_VERSION,\ com/sun/tools/javadoc/resources/version.properties)) +$(eval $(call SetupVersionProperties,JAVADOC_VERSION,\ + jdk/javadoc/internal/tool/resources/version.properties)) + $(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, $(JAVADOC_VERSION))) all: $(COMPILE_PROPERTIES) diff --git a/langtools/make/netbeans/langtools/build.xml b/langtools/make/netbeans/langtools/build.xml index 9e6c4cfddc8..0013b62228e 100644 --- a/langtools/make/netbeans/langtools/build.xml +++ b/langtools/make/netbeans/langtools/build.xml @@ -93,7 +93,11 @@ - + + + diff --git a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java index 85da537519f..950daf73328 100644 --- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java +++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java @@ -104,7 +104,7 @@ public class ToolProvider { } private static final String systemDocumentationToolName - = "com.sun.tools.javadoc.api.JavadocTool"; + = "jdk.javadoc.internal.api.JavadocTool"; /** * Returns the Java™ programming language documentation tool provided diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java index 9456af32f9c..68e36be3f44 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java @@ -26,9 +26,7 @@ package com.sun.tools.javac.code; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import javax.lang.model.element.ElementVisitor; import javax.tools.JavaFileObject; @@ -39,7 +37,6 @@ import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.Completer; import com.sun.tools.javac.code.Symbol.CompletionFailure; import com.sun.tools.javac.code.Symbol.MethodSymbol; -import com.sun.tools.javac.code.Symbol.OperatorSymbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; @@ -50,7 +47,6 @@ import com.sun.tools.javac.code.Type.JCPrimitiveType; import com.sun.tools.javac.code.Type.JCVoidType; import com.sun.tools.javac.code.Type.MethodType; import com.sun.tools.javac.code.Type.UnknownType; -import com.sun.tools.javac.jvm.ByteCodes; import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Context; @@ -65,7 +61,6 @@ import com.sun.tools.javac.util.Names; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.Kind.*; -import static com.sun.tools.javac.jvm.ByteCodes.*; import static com.sun.tools.javac.code.TypeTag.*; /** A class that defines all predefined constants and operators @@ -193,6 +188,7 @@ public class Symtab { public final Type autoCloseableType; public final Type trustMeType; public final Type lambdaMetafactory; + public final Type stringConcatFactory; public final Type repeatableType; public final Type documentedType; public final Type elementTypeType; @@ -472,6 +468,7 @@ public class Symtab { trustMeType = enterClass("java.lang.SafeVarargs"); nativeHeaderType = enterClass("java.lang.annotation.Native"); lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory"); + stringConcatFactory = enterClass("java.lang.invoke.StringConcatFactory"); functionalInterfaceType = enterClass("java.lang.FunctionalInterface"); synthesizeEmptyInterfaceIfMissing(autoCloseableType); @@ -479,6 +476,7 @@ public class Symtab { synthesizeEmptyInterfaceIfMissing(serializableType); synthesizeEmptyInterfaceIfMissing(lambdaMetafactory); synthesizeEmptyInterfaceIfMissing(serializedLambdaType); + synthesizeEmptyInterfaceIfMissing(stringConcatFactory); synthesizeBoxTypeIfMissing(doubleType); synthesizeBoxTypeIfMissing(floatType); synthesizeBoxTypeIfMissing(voidType); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java index 35185e73afc..7ce6ccd17ec 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java @@ -68,6 +68,7 @@ import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; +import static com.sun.tools.javac.code.TypeTag.ARRAY; import static com.sun.tools.javac.code.TypeTag.DEFERRED; import static com.sun.tools.javac.code.TypeTag.FORALL; import static com.sun.tools.javac.code.TypeTag.METHOD; @@ -275,7 +276,7 @@ public class ArgumentAttr extends JCTree.Visitor { res.type != null && res.type.hasTag(FORALL) || (res.flags() & Flags.VARARGS) != 0 || (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && - exprTree.type.isRaw())) { + exprTree.type.isRaw() && !exprTree.type.hasTag(ARRAY))) { tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED; } else { tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index d5bc1cdedef..f62d866bacb 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -239,7 +239,7 @@ public class Attr extends JCTree.Visitor { //this means we are dealing with a partially inferred poly expression owntype = shouldCheck ? resultInfo.pt : found; if (resultInfo.checkMode.installPostInferenceHook()) { - inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), + inferenceContext.addFreeTypeListener(List.of(found), instantiatedContext -> { ResultInfo pendingResult = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index 583a34bf8df..73533e7ab43 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -1812,7 +1812,7 @@ public class LambdaToMethod extends TreeTranslator { TranslationContext(T tree) { this.tree = tree; - this.owner = owner(); + this.owner = owner(true); this.depth = frameStack.size() - 1; this.prev = context(); ClassSymbol csym = diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index f7dd6da221d..83ed8adbef5 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -25,8 +25,6 @@ package com.sun.tools.javac.jvm; -import java.util.*; - import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; @@ -45,7 +43,6 @@ import com.sun.tools.javac.tree.JCTree.*; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.Kind.*; -import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.jvm.ByteCodes.*; import static com.sun.tools.javac.jvm.CRTFlags.*; @@ -69,12 +66,12 @@ public class Gen extends JCTree.Visitor { private final TreeMaker make; private final Names names; private final Target target; - private final Map stringBufferAppend; private Name accessDollar; private final Types types; private final Lower lower; private final Flow flow; private final Annotate annotate; + private final StringConcat concat; /** Format of stackmap tables to be generated. */ private final Code.StackMapFormat stackMap; @@ -105,8 +102,9 @@ public class Gen extends JCTree.Visitor { make = TreeMaker.instance(context); target = Target.instance(context); types = Types.instance(context); + concat = StringConcat.instance(context); + methodType = new MethodType(null, null, null, syms.methodClass); - stringBufferAppend = new HashMap<>(); accessDollar = names. fromString("access" + target.syntheticNameChar()); flow = Flow.instance(context); @@ -753,6 +751,18 @@ public class Gen extends JCTree.Visitor { } } + public Code getCode() { + return code; + } + + public Items getItems() { + return items; + } + + public Env getAttrEnv() { + return attrEnv; + } + /** Visitor class for expressions which might be constant expressions. * This class is a subset of TreeScanner. Intended to visit trees pruned by * Lower as long as constant expressions looking for references to any @@ -1895,25 +1905,7 @@ public class Gen extends JCTree.Visitor { OperatorSymbol operator = (OperatorSymbol) tree.operator; Item l; if (operator.opcode == string_add) { - // Generate code to make a string buffer - makeStringBuffer(tree.pos()); - - // Generate code for first string, possibly save one - // copy under buffer - l = genExpr(tree.lhs, tree.lhs.type); - if (l.width() > 0) { - code.emitop0(dup_x1 + 3 * (l.width() - 1)); - } - - // Load first string and append to buffer. - l.load(); - appendString(tree.lhs); - - // Append all other strings to buffer. - appendStrings(tree.rhs); - - // Convert buffer to string. - bufferToString(tree.pos()); + l = concat.makeConcat(tree); } else { // Generate code for first expression l = genExpr(tree.lhs, tree.lhs.type); @@ -2026,13 +2018,7 @@ public class Gen extends JCTree.Visitor { public void visitBinary(JCBinary tree) { OperatorSymbol operator = (OperatorSymbol)tree.operator; if (operator.opcode == string_add) { - // Create a string buffer. - makeStringBuffer(tree.pos()); - // Append all strings to buffer. - appendStrings(tree); - // Convert buffer to string. - bufferToString(tree.pos()); - result = items.makeStackItem(syms.stringType); + result = concat.makeConcat(tree); } else if (tree.hasTag(AND)) { CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER); if (!lcond.isFalse()) { @@ -2066,67 +2052,7 @@ public class Gen extends JCTree.Visitor { result = completeBinop(tree.lhs, tree.rhs, operator); } } -//where - /** Make a new string buffer. - */ - void makeStringBuffer(DiagnosticPosition pos) { - code.emitop2(new_, makeRef(pos, syms.stringBuilderType)); - code.emitop0(dup); - callMethod( - pos, syms.stringBuilderType, names.init, List.nil(), false); - } - /** Append value (on tos) to string buffer (on tos - 1). - */ - void appendString(JCTree tree) { - Type t = tree.type.baseType(); - if (!t.isPrimitive() && t.tsym != syms.stringType.tsym) { - t = syms.objectType; - } - items.makeMemberItem(getStringBufferAppend(tree, t), false).invoke(); - } - Symbol getStringBufferAppend(JCTree tree, Type t) { - Assert.checkNull(t.constValue()); - Symbol method = stringBufferAppend.get(t); - if (method == null) { - method = rs.resolveInternalMethod(tree.pos(), - attrEnv, - syms.stringBuilderType, - names.append, - List.of(t), - null); - stringBufferAppend.put(t, method); - } - return method; - } - - /** Add all strings in tree to string buffer. - */ - void appendStrings(JCTree tree) { - tree = TreeInfo.skipParens(tree); - if (tree.hasTag(PLUS) && tree.type.constValue() == null) { - JCBinary op = (JCBinary) tree; - if (op.operator.kind == MTH && - ((OperatorSymbol) op.operator).opcode == string_add) { - appendStrings(op.lhs); - appendStrings(op.rhs); - return; - } - } - genExpr(tree, tree.type).load(); - appendString(tree); - } - - /** Convert string buffer on tos to string. - */ - void bufferToString(DiagnosticPosition pos) { - callMethod( - pos, - syms.stringBuilderType, - names.toString, - List.nil(), - false); - } /** Complete generating code for operation, with left operand * already on stack. @@ -2173,8 +2099,8 @@ public class Gen extends JCTree.Visitor { } public void visitTypeCast(JCTypeCast tree) { - setTypeAnnotationPositions(tree.pos); result = genExpr(tree.expr, tree.clazz.type).load(); + setTypeAnnotationPositions(tree.pos); // Additional code is only needed if we cast to a reference type // which is not statically a supertype of the expression's type. // For basic types, the coerce(...) in genExpr(...) will do @@ -2191,8 +2117,8 @@ public class Gen extends JCTree.Visitor { } public void visitTypeTest(JCInstanceOf tree) { - setTypeAnnotationPositions(tree.pos); genExpr(tree.expr, tree.expr.type).load(); + setTypeAnnotationPositions(tree.pos); code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type)); result = items.makeStackItem(syms.booleanType); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java new file mode 100644 index 00000000000..bb5436bd96c --- /dev/null +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 com.sun.tools.javac.jvm; + +import com.sun.tools.javac.code.*; +import com.sun.tools.javac.comp.Resolve; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.util.*; + +import static com.sun.tools.javac.code.Kinds.Kind.MTH; +import static com.sun.tools.javac.code.TypeTag.DOUBLE; +import static com.sun.tools.javac.code.TypeTag.LONG; +import static com.sun.tools.javac.jvm.ByteCodes.*; +import static com.sun.tools.javac.tree.JCTree.Tag.PLUS; +import com.sun.tools.javac.jvm.Items.*; + +import java.util.HashMap; +import java.util.Map; + +/** This lowers the String concatenation to something that JVM can understand. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public abstract class StringConcat { + + /** + * Maximum number of slots for String Concat call. + * JDK's StringConcatFactory does not support more than that. + */ + private static final int MAX_INDY_CONCAT_ARG_SLOTS = 200; + private static final char TAG_ARG = '\u0001'; + private static final char TAG_CONST = '\u0002'; + + protected final Gen gen; + protected final Symtab syms; + protected final Names names; + protected final TreeMaker make; + protected final Types types; + protected final Map sbAppends; + protected final Resolve rs; + + protected static final Context.Key concatKey = new Context.Key<>(); + + public static StringConcat instance(Context context) { + StringConcat instance = context.get(concatKey); + if (instance == null) { + instance = makeConcat(context); + } + return instance; + } + + private static StringConcat makeConcat(Context context) { + Target target = Target.instance(context); + String opt = Options.instance(context).get("stringConcat"); + if (target.hasStringConcatFactory()) { + if (opt == null) { + opt = "indyWithConstants"; + } + } else { + if (opt != null && !"inline".equals(opt)) { + Assert.error("StringConcatFactory-based string concat is requested on a platform that does not support it."); + } + opt = "inline"; + } + + switch (opt) { + case "inline": + return new Inline(context); + case "indy": + return new IndyPlain(context); + case "indyWithConstants": + return new IndyConstants(context); + default: + Assert.error("Unknown stringConcat: " + opt); + throw new IllegalStateException("Unknown stringConcat: " + opt); + } + } + + protected StringConcat(Context context) { + context.put(concatKey, this); + gen = Gen.instance(context); + syms = Symtab.instance(context); + types = Types.instance(context); + names = Names.instance(context); + make = TreeMaker.instance(context); + rs = Resolve.instance(context); + sbAppends = new HashMap<>(); + } + + public abstract Item makeConcat(JCTree.JCAssignOp tree); + public abstract Item makeConcat(JCTree.JCBinary tree); + + protected List collectAll(JCTree tree) { + return collect(tree, List.nil()); + } + + protected List collectAll(JCTree.JCExpression lhs, JCTree.JCExpression rhs) { + return List.nil() + .appendList(collectAll(lhs)) + .appendList(collectAll(rhs)); + } + + private List collect(JCTree tree, List res) { + tree = TreeInfo.skipParens(tree); + if (tree.hasTag(PLUS) && tree.type.constValue() == null) { + JCTree.JCBinary op = (JCTree.JCBinary) tree; + if (op.operator.kind == MTH && + ((Symbol.OperatorSymbol) op.operator).opcode == string_add) { + return res + .appendList(collect(op.lhs, res)) + .appendList(collect(op.rhs, res)); + } + } + return res.append(tree); + } + + /** + * "Legacy" bytecode flavor: emit the StringBuilder.append chains for string + * concatenation. + */ + private static class Inline extends StringConcat { + public Inline(Context context) { + super(context); + } + + @Override + public Item makeConcat(JCTree.JCAssignOp tree) { + // Generate code to make a string builder + JCDiagnostic.DiagnosticPosition pos = tree.pos(); + + // Create a string builder. + newStringBuilder(tree); + + // Generate code for first string, possibly save one + // copy under builder + Item l = gen.genExpr(tree.lhs, tree.lhs.type); + if (l.width() > 0) { + gen.getCode().emitop0(dup_x1 + 3 * (l.width() - 1)); + } + + // Load first string and append to builder. + l.load(); + appendString(tree.lhs); + + // Append all other strings to builder. + List args = collectAll(tree.rhs); + for (JCTree t : args) { + gen.genExpr(t, t.type).load(); + appendString(t); + } + + // Convert builder to string. + builderToString(pos); + + return l; + } + + @Override + public Item makeConcat(JCTree.JCBinary tree) { + JCDiagnostic.DiagnosticPosition pos = tree.pos(); + + // Create a string builder. + newStringBuilder(tree); + + // Append all strings to builder. + List args = collectAll(tree); + for (JCTree t : args) { + gen.genExpr(t, t.type).load(); + appendString(t); + } + + // Convert builder to string. + builderToString(pos); + + return gen.getItems().makeStackItem(syms.stringType); + } + + private JCDiagnostic.DiagnosticPosition newStringBuilder(JCTree tree) { + JCDiagnostic.DiagnosticPosition pos = tree.pos(); + gen.getCode().emitop2(new_, gen.makeRef(pos, syms.stringBuilderType)); + gen.getCode().emitop0(dup); + gen.callMethod(pos, syms.stringBuilderType, names.init, List.nil(), false); + return pos; + } + + private void appendString(JCTree tree) { + Type t = tree.type.baseType(); + if (!t.isPrimitive() && t.tsym != syms.stringType.tsym) { + t = syms.objectType; + } + + Assert.checkNull(t.constValue()); + Symbol method = sbAppends.get(t); + if (method == null) { + method = rs.resolveInternalMethod(tree.pos(), gen.getAttrEnv(), syms.stringBuilderType, names.append, List.of(t), null); + sbAppends.put(t, method); + } + + gen.getItems().makeMemberItem(method, false).invoke(); + } + + private void builderToString(JCDiagnostic.DiagnosticPosition pos) { + gen.callMethod(pos, syms.stringBuilderType, names.toString, List.nil(), false); + } + } + + /** + * Base class for indified concatenation bytecode flavors. + */ + private static abstract class Indy extends StringConcat { + public Indy(Context context) { + super(context); + } + + @Override + public Item makeConcat(JCTree.JCAssignOp tree) { + List args = collectAll(tree.lhs, tree.rhs); + Item l = gen.genExpr(tree.lhs, tree.lhs.type); + emit(args, tree.type, tree.pos()); + return l; + } + + @Override + public Item makeConcat(JCTree.JCBinary tree) { + List args = collectAll(tree.lhs, tree.rhs); + emit(args, tree.type, tree.pos()); + return gen.getItems().makeStackItem(syms.stringType); + } + + protected abstract void emit(List args, Type type, JCDiagnostic.DiagnosticPosition pos); + + /** Peel the argument list into smaller chunks. */ + protected List> split(List args) { + ListBuffer> splits = new ListBuffer<>(); + + int slots = 0; + + // Need to peel, so that neither call has more than acceptable number + // of slots for the arguments. + ListBuffer cArgs = new ListBuffer<>(); + for (JCTree t : args) { + int needSlots = (t.type.getTag() == LONG || t.type.getTag() == DOUBLE) ? 2 : 1; + if (slots + needSlots >= MAX_INDY_CONCAT_ARG_SLOTS) { + splits.add(cArgs.toList()); + cArgs.clear(); + slots = 0; + } + cArgs.add(t); + slots += needSlots; + } + + // Flush the tail slice + if (!cArgs.isEmpty()) { + splits.add(cArgs.toList()); + } + + return splits.toList(); + } + } + + /** + * Emits the invokedynamic call to JDK java.lang.invoke.StringConcatFactory, + * without handling constants specially. + * + * We bypass empty strings, because they have no meaning at this level. This + * captures the Java language trick to force String concat with e.g. ("" + int)-like + * expression. Down here, we already know we are in String concat business, and do + * not require these markers. + */ + private static class IndyPlain extends Indy { + public IndyPlain(Context context) { + super(context); + } + + /** Emit the indy concat for all these arguments, possibly peeling along the way */ + protected void emit(List args, Type type, JCDiagnostic.DiagnosticPosition pos) { + List> split = split(args); + + for (List t : split) { + Assert.check(!t.isEmpty(), "Arguments list is empty"); + + ListBuffer dynamicArgs = new ListBuffer<>(); + for (JCTree arg : t) { + Object constVal = arg.type.constValue(); + if ("".equals(constVal)) continue; + if (arg.type == syms.botType) { + dynamicArgs.add(types.boxedClass(syms.voidType).type); + } else { + dynamicArgs.add(arg.type); + } + gen.genExpr(arg, arg.type).load(); + } + + doCall(type, pos, dynamicArgs.toList()); + } + + // More that one peel slice produced: concatenate the results + if (split.size() > 1) { + ListBuffer argTypes = new ListBuffer<>(); + for (int c = 0; c < split.size(); c++) { + argTypes.append(syms.stringType); + } + doCall(type, pos, argTypes.toList()); + } + } + + /** Produce the actual invokedynamic call to StringConcatFactory */ + private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, List dynamicArgTypes) { + Type.MethodType indyType = new Type.MethodType(dynamicArgTypes, + type, + List.nil(), + syms.methodClass); + + int prevPos = make.pos; + try { + make.at(pos); + + List bsm_staticArgs = List.of(syms.methodHandleLookupType, + syms.stringType, + syms.methodTypeType); + + Symbol bsm = rs.resolveInternalMethod(pos, + gen.getAttrEnv(), + syms.stringConcatFactory, + names.makeConcat, + bsm_staticArgs, + null); + + Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcat, + syms.noSymbol, + ClassFile.REF_invokeStatic, + (Symbol.MethodSymbol)bsm, + indyType, + List.nil().toArray()); + + Items.Item item = gen.getItems().makeDynamicItem(dynSym); + item.invoke(); + } finally { + make.at(prevPos); + } + } + } + + /** + * Emits the invokedynamic call to JDK java.lang.invoke.StringConcatFactory. + * This code concatenates all known constants into the recipe, possibly escaping + * some constants separately. + * + * We also bypass empty strings, because they have no meaning at this level. This + * captures the Java language trick to force String concat with e.g. ("" + int)-like + * expression. Down here, we already know we are in String concat business, and do + * not require these markers. + */ + private static final class IndyConstants extends Indy { + public IndyConstants(Context context) { + super(context); + } + + @Override + protected void emit(List args, Type type, JCDiagnostic.DiagnosticPosition pos) { + List> split = split(args); + + for (List t : split) { + Assert.check(!t.isEmpty(), "Arguments list is empty"); + + StringBuilder recipe = new StringBuilder(t.size()); + ListBuffer dynamicArgs = new ListBuffer<>(); + ListBuffer staticArgs = new ListBuffer<>(); + + for (JCTree arg : t) { + Object constVal = arg.type.constValue(); + if ("".equals(constVal)) continue; + if (arg.type == syms.botType) { + // Concat the null into the recipe right away + recipe.append((String) null); + } else if (constVal != null) { + // Concat the String representation of the constant, except + // for the case it contains special tags, which requires us + // to expose it as detached constant. + String a = arg.type.stringValue(); + if (a.indexOf(TAG_CONST) != -1 || a.indexOf(TAG_ARG) != -1) { + recipe.append(TAG_CONST); + staticArgs.add(a); + } else { + recipe.append(a); + } + } else { + // Ordinary arguments come through the dynamic arguments. + recipe.append(TAG_ARG); + dynamicArgs.add(arg.type); + gen.genExpr(arg, arg.type).load(); + } + } + + doCall(type, pos, recipe.toString(), staticArgs.toList(), dynamicArgs.toList()); + } + + // More that one peel slice produced: concatenate the results + // All arguments are assumed to be non-constant Strings. + if (split.size() > 1) { + ListBuffer argTypes = new ListBuffer<>(); + StringBuilder recipe = new StringBuilder(); + for (int c = 0; c < split.size(); c++) { + argTypes.append(syms.stringType); + recipe.append(TAG_ARG); + } + doCall(type, pos, recipe.toString(), List.nil(), argTypes.toList()); + } + } + + /** Produce the actual invokedynamic call to StringConcatFactory */ + private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, String recipe, List staticArgs, List dynamicArgTypes) { + Type.MethodType indyType = new Type.MethodType(dynamicArgTypes, + type, + List.nil(), + syms.methodClass); + + int prevPos = make.pos; + try { + make.at(pos); + + ListBuffer constTypes = new ListBuffer<>(); + ListBuffer constants = new ListBuffer<>(); + for (Object t : staticArgs) { + constants.add(t); + constTypes.add(syms.stringType); + } + + List bsm_staticArgs = List.of(syms.methodHandleLookupType, + syms.stringType, + syms.methodTypeType) + .append(syms.stringType) + .appendList(constTypes); + + Symbol bsm = rs.resolveInternalMethod(pos, + gen.getAttrEnv(), + syms.stringConcatFactory, + names.makeConcatWithConstants, + bsm_staticArgs, + null); + + Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcatWithConstants, + syms.noSymbol, + ClassFile.REF_invokeStatic, + (Symbol.MethodSymbol)bsm, + indyType, + List.of(recipe).appendList(constants).toArray()); + + Items.Item item = gen.getItems().makeDynamicItem(dynSym); + item.invoke(); + } finally { + make.at(prevPos); + } + } + } + +} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java index aeb2b11adc2..df70c50b8ec 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java @@ -135,4 +135,10 @@ public enum Target { return hasInvokedynamic(); } + /** Does the target JDK contain StringConcatFactory class? + */ + public boolean hasStringConcatFactory() { + return compareTo(JDK1_9) >= 0; + } + } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java index 4f5b11f07a5..213277432c0 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java @@ -179,6 +179,10 @@ public class Names { public final Name altMetafactory; public final Name dollarThis; + // string concat + public final Name makeConcat; + public final Name makeConcatWithConstants; + public final Name.Table table; public Names(Context context) { @@ -316,6 +320,10 @@ public class Names { lambda = fromString("lambda$"); metafactory = fromString("metafactory"); altMetafactory = fromString("altMetafactory"); + + // string concat + makeConcat = fromString("makeConcat"); + makeConcatWithConstants = fromString("makeConcatWithConstants"); } protected Name.Table createTable(Options options) { diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/package-info.java index ace69c00622..36a9f5c224c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,11 @@ */ /** +

          +Note: The declarations in this package have been superseded by those +in the package {@code jdk.javadoc.doclet}. +

          + The Doclet API (also called the Javadoc API) provides a mechanism for clients to inspect the source-level structure of programs and libraries, including javadoc comments embedded in the source. diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java index 5a41b1d654e..16578ea9ada 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/Taglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,14 @@ import com.sun.javadoc.*; /** * The interface for a custom tag used by Doclets. A custom - * tag must implement this interface. To be loaded and used by + * tag must implement this interface. + * + *

          + * Note: This interface has been superseded by one + * in the new package {@code jdk.javadoc.doclet.taglet}. + *

          + * + * To be loaded and used by * doclets at run-time, the taglet must have a static method called * register that accepts a {@link java.util.Map} as an * argument with the following signature: diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/package-info.java index 7c8766c4f69..a9eb28cbea5 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/package-info.java @@ -31,4 +31,5 @@ This code and its internal interfaces are subject to change or deletion without notice. */ + package com.sun.tools.doclets.formats.html.markup; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/package-info.java index dadc9e1500d..d2f2618e64d 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,7 @@ */ /** - This is the default doclet provided with JDK that produces Javadoc's - default HTML-formatted API output. For more documentation + This produces Javadoc's HTML-formatted API output. For more documentation on this doclet, please refer to the link below. @see @@ -36,4 +35,5 @@ This code and its internal interfaces are subject to change or deletion without notice. */ + package com.sun.tools.doclets.formats.html; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java index 27154a72162..07936a8d1c9 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.io.*; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; + import javax.tools.JavaFileManager; import com.sun.javadoc.*; @@ -37,6 +38,7 @@ import com.sun.tools.javac.jvm.Profile; import com.sun.tools.doclets.internal.toolkit.builders.BuilderFactory; import com.sun.tools.doclets.internal.toolkit.taglets.*; import com.sun.tools.doclets.internal.toolkit.util.*; +import com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap.GetterSetter; import com.sun.tools.javac.util.StringUtils; /** @@ -304,6 +306,13 @@ public abstract class Configuration { */ public SortedSet packages; + // The following three fields provide caches for use by all instances of VisibleMemberMap. + public final Map propertiesCache = new HashMap<>(); + public final Map classPropertiesMap = new HashMap<>(); + public final Map getterSetterMap = new HashMap<>(); + + public DocFileFactory docFileFactory; + /** * Constructor. Constructs the message retriever with resource file. */ diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/package-info.java index ef8b4acf1c1..c11193fc36a 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/package-info.java @@ -37,4 +37,5 @@ This code and its internal interfaces are subject to change or deletion without notice. */ + package com.sun.tools.doclets.internal.toolkit.builders; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/package-info.java index e8bcae2fed3..30bc952e01b 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/package-info.java @@ -53,4 +53,5 @@ This code and its internal interfaces are subject to change or deletion without notice. */ + package com.sun.tools.doclets.internal.toolkit; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/package-info.java index 43750f1d774..cad2426bf1f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/package-info.java @@ -48,4 +48,5 @@ This code and its internal interfaces are subject to change or deletion without notice. */ + package com.sun.tools.doclets.internal.toolkit.taglets; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java index db34c5cc5c9..7c0b88db18c 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,6 @@ package com.sun.tools.doclets.internal.toolkit.util; -import java.util.Map; -import java.util.WeakHashMap; - import javax.tools.JavaFileManager; import javax.tools.JavaFileManager.Location; import javax.tools.StandardJavaFileManager; @@ -45,15 +42,13 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; * * @since 1.8 */ -abstract class DocFileFactory { - private static final Map factories = new WeakHashMap<>(); - +public abstract class DocFileFactory { /** * Get the appropriate factory, based on the file manager given in the * configuration. */ static synchronized DocFileFactory getFactory(Configuration configuration) { - DocFileFactory f = factories.get(configuration); + DocFileFactory f = configuration.docFileFactory; if (f == null) { JavaFileManager fm = configuration.getFileManager(); if (fm instanceof StandardJavaFileManager) { @@ -61,7 +56,7 @@ abstract class DocFileFactory { } else { throw new IllegalStateException(); } - factories.put(configuration, f); + configuration.docFileFactory = f; } return f; } diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java index 487215ca4a0..7a1abfb1eec 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java @@ -101,9 +101,9 @@ public class VisibleMemberMap { private final Configuration configuration; private final Utils utils; - private static final Map propertiesCache = new HashMap<>(); - private static final Map classPropertiesMap = new HashMap<>(); - private static final Map getterSetterMap = new HashMap<>(); + private final Map propertiesCache; + private final Map classPropertiesMap; + private final Map getterSetterMap; /** * Construct a VisibleMemberMap of the given type for the given @@ -123,6 +123,9 @@ public class VisibleMemberMap { this.kind = kind; this.configuration = configuration; this.utils = configuration.utils; + propertiesCache = configuration.propertiesCache; + classPropertiesMap = configuration.classPropertiesMap; + getterSetterMap = configuration.getterSetterMap; new ClassMembers(classdoc, STARTLEVEL).build(); } @@ -713,7 +716,7 @@ public class VisibleMemberMap { } } - private class GetterSetter { + public class GetterSetter { private final ProgramElementDoc getter; private final ProgramElementDoc setter; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/package-info.java index 1319ccd0877..da4d9455716 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/links/package-info.java @@ -31,4 +31,5 @@ This code and its internal interfaces are subject to change or deletion without notice. */ + package com.sun.tools.doclets.internal.toolkit.util.links; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/package-info.java index 2e898013ffb..ef49b0ab1e2 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/package-info.java @@ -32,4 +32,5 @@ This code and its internal interfaces are subject to change or deletion without notice. */ + package com.sun.tools.doclets.internal.toolkit.util; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/package-info.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/package-info.java index 0ced35a2c62..735bfa5c5cc 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/package-info.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,11 @@ */ /** +

          +Note: The declarations in this package have been superseded by those +in the new package {@code jdk.javadoc.doclet}. +

          + As of JDK version 1.5, replaced by {@code com.sun.tools.doclets.internal.toolkit.util}. @@ -32,4 +37,5 @@ This code and its internal interfaces are subject to change or deletion without notice. */ + package com.sun.tools.doclets; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java index a1c31b6e722..9e3419f5449 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/Start.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,7 +103,11 @@ public class Start extends ToolOption.Helper { this(programName, errWriter, warnWriter, noticeWriter, defaultDocletClassName, null); } - Start(String programName, + public Start(PrintWriter pw) { + this(javadocName, pw, pw, pw, standardDocletClassName); + } + + public Start(String programName, PrintWriter errWriter, PrintWriter warnWriter, PrintWriter noticeWriter, @@ -139,7 +143,7 @@ public class Start extends ToolOption.Helper { this(javadocName, docletParentClassLoader); } - Start() { + public Start() { this(javadocName); } @@ -212,7 +216,7 @@ public class Start extends ToolOption.Helper { /** * Main program - external wrapper */ - int begin(String... argv) { + public int begin(String... argv) { boolean ok = begin(null, argv, Collections. emptySet()); return ok ? 0 : 1; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/Doclet.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/Doclet.java new file mode 100644 index 00000000000..9e7885675a6 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/Doclet.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.doclet; + +import java.util.ListIterator; +import java.util.Locale; +import java.util.Set; + +import javax.lang.model.SourceVersion; + +/** + * The user doclet must implement this interface, as described in the + *
          package description. + * Each implementation of a Doclet must provide a public no-argument constructor + * to be used by tools to instantiate the doclet. The tool infrastructure will + * interact with classes implementing this interface as follows: + *
            + *
          1. The tool will create an instance of a doclet using the no-arg constructor + * of the doclet class. + *
          2. Next, the tool calls the {@link #init init} method with an appropriate locale + * and reporter. + *
          3. Afterwards, the tool calls {@link #getSupportedOptions getSupportedOptions}, + * and {@link #getSupportedSourceVersion getSupportedSourceVersion}. + * These methods are only called once. + *
          4. As appropriate, the tool calls the {@link #run run} method on the doclet + * object, giving it a DocletEnvironment object, from which the doclet can determine + * the elements to be included in the documentation. + *
          + *

          + * If a doclet object is created and used without the above protocol being followed, + * then the doclet's behavior is not defined by this interface specification. + *

          To start the doclet, pass {@code -doclet} followed by the fully-qualified + * name of the entry point class (i.e. the implementation of this interface) on + * the javadoc tool command line. + * + * @since 9 + */ +public interface Doclet { + + /** + * Initializes this doclet with the given locale and error reporter. + * This locale will be used by the reporter and the doclet components. + * It is recommended to call this as early as possible, for a + * uniform localized user experience, + * @param locale the locale to be used + * @param reporter the reporter to be used + */ + public void init(Locale locale, Reporter reporter); + + /** + * Returns a name identifying the doclet. A name is a simple identifier + * without white spaces, as defined in The Java™ Language Specification, + * section 6.2 "Names and Identifiers". + * @return name of the Doclet + */ + public abstract String getName(); + + /** + * Returns all the supported options. + * + * @return a Set containing all the supported options, an empty set if none. + */ + public Set

          + * Note: The declarations in this package supersede those + * in the older package {@code com.sun.javadoc}. For details on the + * mapping of old types to new types, see the + * Migration Guide. + *

          + * + *

          + * Doclets are invoked by javadoc and this API can be used to write out + * program information to files. For example, the standard doclet is + * invoked by default, to generate HTML documentation. + *

          + + * The invocation is defined by the interface {@link jdk.javadoc.doclet.Doclet} + * -- the {@link jdk.javadoc.doclet.Doclet#run(DocletEnvironment) run} interface + * method, defines the entry point. + *

          + *    public boolean run(DocletEnvironment environment)
          + * 
          + * The {@link jdk.javadoc.doclet.DocletEnvironment} instance holds the environment that the + * doclet will be initialized with. From this environment all other information can be + * extracted, in the form of {@link javax.lang.model} elements. One can further use the + * APIs and utilities described by {@link javax.lang.model} to query Elements and Types. + *

          + * + * + *

          Terminology

          + * + * + * When calling javadoc, one can pass in package names and source file names -- + * these are called the specified PackageElements and TypeElements. + * Javadoc options are also passed in; the access control Javadoc options + * ({@code -public}, {@code -protected}, {@code -package}, + * and {@code -private}) are used to filter program elements, producing a + * result set, called the included set, or "selected" set. + *

          + + * + * A qualified element name is one that has its package + * name prepended to it, such as {@code java.lang.String}. A non-qualified + * name has no package name, such as {@code String}. + *

          + * + * + *

          Example

          + * + * The following is an example doclet that displays information of a class + * and its members, supporting an option "someoption". + *
          + * import com.sun.source.doctree.DocCommentTree;
          + * import com.sun.source.util.DocTrees;
          + * import java.io.IOException;
          + * import java.util.Collections;
          + * import java.util.Set;
          + * import javax.lang.model.SourceVersion;
          + * import javax.lang.model.element.Element;
          + * import javax.lang.model.element.TypeElement;
          + * import jdk.javadoc.doclet.*;
          + *
          + * public class Example implements Doclet {
          + *
          + *     @Override
          + *     public void init(Locale locale, Reporter reporter) {
          + *        return;
          + *     }
          + *
          + *     @Override
          + *     public boolean run(RootDoc root) {
          + *         // cache the DocTrees utility class to access DocComments
          + *         DocTrees docTrees = root.getDocTrees();
          + *
          + *         // location of an element in the same directory as overview.html
          + *         try {
          + *             Element barElement = null;
          + *             for (Element e : root.getIncludedClasses()) {
          + *                 if (e.getSimpleName().toString().equals("FooBar")) {
          + *                     barElement = e;
          + *                 }
          + *             }
          + *             DocCommentTree docCommentTree =
          + *                     docTrees.getDocCommentTree(barElement, "overview.html");
          + *             if (docCommentTree != null) {
          + *                 System.out.println("Overview html: " +
          + *                         docCommentTree.getFullBody());
          + *             }
          + *         } catch (IOException missing) {
          + *             System.err.println("No overview.html found.");
          + *         }
          + *
          + *         for (TypeElement t : root.getIncludedClasses()) {
          + *             System.out.println(t.getKind() + ":" + t);
          + *             for (Element e : t.getEnclosedElements()) {
          + *                 DocCommentTree docCommentTree = docTrees.getDocCommentTree(e);
          + *                 if (docCommentTree != null) {
          + *                     System.out.println("Element (" + e.getKind() + ": " +
          + *                             e + ") has the following comments:");
          + *                     System.out.println("Entire body: " + docCommentTree.getFullBody());
          + *                     System.out.println("Block tags: " + docCommentTree.getBlockTags());
          + *                 } else {
          + *                     System.out.println("no comment.");
          + *                 }
          + *             }
          + *         }
          + *         return true;
          + *     }
          + *
          + *     @Override
          + *     public String getName() {
          + *         return "Example";
          + *     }
          + *
          + *   private String someOption;
          + *
          + *   @Override
          + *   public Set<Option> getSupportedOptions() {
          + *       Option[] options = {
          + *           new Option() {
          + *               public int getArgumentCount() {
          + *                   return 1;
          + *               }
          + *               public String getDescription() {
          + *                   return "someoption";
          + *               }
          + *               public Option.Kind getKind() {
          + *                   return Option.Kind.STANDARD;
          + *               }
          + *               public String getName() {
          + *                   return "someoption";
          + *               }
          + *               public String getParameters() {
          + *                   return "url";
          + *               }
          + *               public boolean matches(String option) {
          + *                  String opt = option.startsWith("-") ? option.substring(1) : option;
          + *                  return getName().equals(opt);
          + *               }
          + *               public boolean process(String option, ListIterator<String> arguments) {
          + *                  overviewpath = arguments.next();
          + *                  return true;
          + *               }
          + *          }
          + *      };
          + *      return new HashSet<Option>(Arrays.asList(options));
          + *     }
          + *
          + *     @Override
          + *     public SourceVersion getSupportedSourceVersion() {
          + *         // support the latest release
          + *         return SourceVersion.latest();
          + *     }
          + * }
          + * 
          + *

          + * This doclet when invoked with a command line, such as: + *

          + *     javadoc -doclet Example -sourcepath <source-location>
          + * 
          + * will produce an output, such as: + *
          + *  Overview.html: overview comments
          + *  ...
          + *  ...
          + *  CLASS: SomeKlass
          + *  .....
          + *  Element (METHOD: main(java.lang.String...)) has the following comments:
          + *  Entire body: The main entry point.
          + *  Block tags: @param an array of Strings
          + *  ...
          + * 
          + * + *

          Migration Guide

          + * + *

          Many of the types in the old {@code com.sun.javadoc} API do not have equivalents in this + * package. Instead, types in the {@code javax.lang.model} and {@code com.sun.source} APIs + * are used instead. + * + *

          The following table gives a guide to the mapping from old types to their replacements. + * In some cases, there is no direct equivalent. + * + * + +
          Guide for mapping old types to new types
          Old TypeNew Type +
          AnnotatedTypejavax.lang.model.type.Type +
          AnnotationDescjavax.lang.model.element.AnnotationMirror +
          AnnotationDesc.ElementValuePairjavax.lang.model.element.AnnotationValue +
          AnnotationTypeDocjavax.lang.model.element.TypeElement +
          AnnotationTypeElementDocjavax.lang.model.element.ExecutableElement +
          AnnotationValuejavax.lang.model.element.AnnotationValue +
          ClassDocjavax.lang.model.element.TypeElement +
          ConstructorDocjavax.lang.model.element.ExecutableElement +
          Docjavax.lang.model.element.Element +
          DocErrorReporterjdk.javadoc.doclet.Reporter +
          Docletjdk.javadoc.doclet.Doclet +
          ExecutableMemberDocjavax.lang.model.element.ExecutableElement +
          FieldDocjavax.lang.model.element.VariableElement +
          LanguageVersionjavax.lang.model.SourceVersion +
          MemberDocjavax.lang.model.element.Element +
          MethodDocjavax.lang.model.element.ExecutableElement +
          PackageDocjavax.lang.model.element.PackageElement +
          Parameterjavax.lang.model.element.VariableElement +
          ParameterizedTypejavax.lang.model.type.DeclaredType +
          ParamTagcom.sun.source.doctree.ParamTree +
          ProgramElementDocjavax.lang.model.element.Element +
          RootDocjdk.javadoc.doclet.DocletEnvironment +
          SeeTagcom.sun.source.doctree.LinkTree
          com.sun.source.doctree.SeeTree +
          SerialFieldTagcom.sun.source.doctree.SerialFieldTree +
          SourcePositioncom.sun.source.util.SourcePositions +
          Tagcom.sun.source.doctree.DocTree +
          ThrowsTagcom.sun.source.doctree.ThrowsTree +
          Typejavax.lang.model.type.Type +
          TypeVariablejavax.lang.model.type.TypeVariable +
          WildcardTypejavax.lang.model.type.WildcardType + *
          + * + * @see jdk.javadoc.doclet.Doclet + * @see jdk.javadoc.doclet.DocletEnvironment + * @since 9 +*/ + +package jdk.javadoc.doclet; diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/taglet/Taglet.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/taglet/Taglet.java new file mode 100644 index 00000000000..f102bd55314 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/taglet/Taglet.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.doclet.taglet; + +import java.util.List; +import java.util.Set; + +import com.sun.source.doctree.DocTree; + +/** + * The interface for a custom tag used by Doclets. A custom + * tag must implement this interface, and must have a public + * default constructor (i.e. a public constructor with no + * parameters), by which, the doclet will instantiate and + * register the custom tag. + * + * @since 9 + */ + +public interface Taglet { + + /** + * Returns the set of locations in which a taglet may be used. + * @return the set of locations in which a taglet may be used + * allowed in or an empty set. + */ + Set getAllowedLocations(); + + /** + * Indicates the tag is an inline or a body tag. + * @return true if this Taglet + * is an inline tag, false otherwise. + */ + public abstract boolean isInlineTag(); + + /** + * Returns the name of the tag. + * @return the name of this custom tag. + */ + public abstract String getName(); + + /** + * Given the {@link DocTree DocTree} representation of this custom + * tag, return its string representation, which is output + * to the generated page. + * @param tag the Tag representation of this custom tag. + * @return the string representation of this Tag. + */ + public abstract String toString(DocTree tag); + + /** + * Given a List of {@link DocTree DocTrees} representing this custom + * tag, return its string representation, which is output + * to the generated page. This method should + * return null if this taglet represents an inline or body tag. + * @param tags the list of DocTrees representing this custom tag. + * @return the string representation of this Tag. + */ + public abstract String toString(List tags); + + /** + * The kind of location. + */ + public static enum Location { + /** In an Overview document. */ + OVERVIEW, + /** In the documentation for a package. */ + PACKAGE, + /** In the documentation for a class, interface or enum. */ + TYPE, + /** In the documentation for a constructor. */ + CONSTRUCTOR, + /** In the documentation for a method. */ + METHOD, + /** In the documentation for a field. */ + FIELD + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/taglet/package-info.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/taglet/package-info.java new file mode 100644 index 00000000000..066f5e61472 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/taglet/package-info.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +/** + * The Taglet API provides a way to declare custom tags that can be + * used by the standard doclet. + * + *

          + * Note: The declarations in this package supersede those + * in the older package {@code com.sun.tools.doclets}. + *

          + * + * @since 9 + */ +package jdk.javadoc.doclet.taglet; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTaskImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTaskImpl.java similarity index 95% rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTaskImpl.java rename to langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTaskImpl.java index 18d24b1e6b5..97ec41633c9 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTaskImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTaskImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,21 +23,20 @@ * questions. */ -package com.sun.tools.javadoc.api; +package jdk.javadoc.internal.api; -import com.sun.tools.javac.util.ClientCodeException; +import java.util.Collections; import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; import javax.tools.DocumentationTool.DocumentationTask; import javax.tools.JavaFileObject; +import com.sun.tools.javac.util.ClientCodeException; import com.sun.tools.javac.util.Context; -import com.sun.tools.javadoc.Start; -import java.util.Collections; - import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; +import jdk.javadoc.internal.tool.Start; /** * Provides access to functionality specific to the JDK documentation tool, diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTool.java similarity index 94% rename from langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTool.java rename to langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTool.java index 2aa5c1691dd..8b91c15df2e 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTool.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/api/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * questions. */ -package com.sun.tools.javadoc.api; +package jdk.javadoc.internal.api; import java.io.InputStream; import java.io.OutputStream; @@ -52,7 +52,7 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.Log; -import com.sun.tools.javadoc.ToolOption; +import jdk.javadoc.internal.tool.ToolOption; /** * Provides access to functionality specific to the JDK documentation tool, @@ -150,10 +150,7 @@ public class JavadocTool implements DocumentationTool { PrintWriter err_pw = new PrintWriter(err == null ? System.err : err, true); PrintWriter out_pw = new PrintWriter(out == null ? System.out : out); try { - String standardDocletName = "com.sun.tools.doclets.standard.Standard"; - ClassLoader cl = getClass().getClassLoader(); - return com.sun.tools.javadoc.Main.execute( - "javadoc", err_pw, err_pw, out_pw, standardDocletName, cl, arguments); + return jdk.javadoc.internal.tool.Main.execute(arguments, err_pw); } finally { err_pw.flush(); out_pw.flush(); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java new file mode 100644 index 00000000000..d82da4653cd --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.util.List; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.util.SimpleTypeVisitor9; + +import com.sun.tools.javac.util.DefinedBy; +import com.sun.tools.javac.util.DefinedBy.Api; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; + +import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.*; + +/** + * Print method and constructor info. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert Field + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public abstract class AbstractExecutableMemberWriter extends AbstractMemberWriter { + + public AbstractExecutableMemberWriter(SubWriterHolderWriter writer, TypeElement typeElement) { + super(writer, typeElement); + } + + public AbstractExecutableMemberWriter(SubWriterHolderWriter writer) { + super(writer); + } + + /** + * Add the type parameters for the executable member. + * + * @param member the member to write type parameters for. + * @param htmltree the content tree to which the parameters will be added. + */ + protected void addTypeParameters(ExecutableElement member, Content htmltree) { + Content typeParameters = getTypeParameters(member); + if (!typeParameters.isEmpty()) { + htmltree.addContent(typeParameters); + htmltree.addContent(writer.getSpace()); + } + } + + /** + * Get the type parameters for the executable member. + * + * @param member the member for which to get the type parameters. + * @return the type parameters. + */ + protected Content getTypeParameters(ExecutableElement member) { + LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, MEMBER_TYPE_PARAMS, member); + return writer.getTypeParameterLinks(linkInfo); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getDeprecatedLink(Element member) { + StringBuilder sb = new StringBuilder(); + sb.append(utils.getFullyQualifiedName(member)); + if (!utils.isConstructor(member)) { + sb.append("."); + sb.append(member.getSimpleName().toString()); + } + sb.append(utils.flatSignature((ExecutableElement) member)); + + return writer.getDocLink(MEMBER, member, sb.toString()); + } + + /** + * Add the summary link for the member. + * + * @param context the id of the context where the link will be printed + * @param te the classDoc that we should link to + * @param member the member being linked to + * @param tdSummary the content tree to which the link will be added + */ + @Override + protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement te, Element member, + Content tdSummary) { + ExecutableElement ee = (ExecutableElement)member; + Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink, + writer.getDocLink(context, te, ee, + name(ee), false)); + Content code = HtmlTree.CODE(memberLink); + addParameters(ee, false, code, name(ee).length() - 1); + tdSummary.addContent(code); + } + + /** + * Add the inherited summary link for the member. + * + * @param te the type element that we should link to + * @param member the member being linked to + * @param linksTree the content tree to which the link will be added + */ + @Override + protected void addInheritedSummaryLink(TypeElement te, Element member, Content linksTree) { + linksTree.addContent(writer.getDocLink(MEMBER, te, member, name(member), false)); + } + + /** + * Add the parameter for the executable member. + * + * @param member the member to write parameter for. + * @param param the parameter that needs to be written. + * @param isVarArg true if this is a link to var arg. + * @param tree the content tree to which the parameter information will be added. + */ + protected void addParam(ExecutableElement member, VariableElement param, + boolean isVarArg, Content tree) { + Content link = writer.getLink(new LinkInfoImpl(configuration, EXECUTABLE_MEMBER_PARAM, + param.asType()).varargs(isVarArg)); + tree.addContent(link); + if(name(param).length() > 0) { + tree.addContent(writer.getSpace()); + tree.addContent(name(param)); + } + } + + /** + * Add the receiver annotations information. + * + * @param member the member to write receiver annotations for. + * @param rcvrType the receiver type. + * @param descList list of annotation description. + * @param tree the content tree to which the information will be added. + */ + protected void addReceiverAnnotations(ExecutableElement member, TypeMirror rcvrType, + List annotationMirrors, Content tree) { + writer.addReceiverAnnotationInfo(member, rcvrType, annotationMirrors, tree); + tree.addContent(writer.getSpace()); + tree.addContent(utils.getTypeName(rcvrType, false)); + LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, RECEIVER_TYPE, rcvrType); + tree.addContent(writer.getTypeParameterLinks(linkInfo)); + tree.addContent(writer.getSpace()); + tree.addContent("this"); + } + + + /** + * Add all the parameters for the executable member. + * + * @param member the member to write parameters for. + * @param htmltree the content tree to which the parameters information will be added. + */ + protected void addParameters(ExecutableElement member, Content htmltree, int indentSize) { + addParameters(member, true, htmltree, indentSize); + } + + /** + * Add all the parameters for the executable member. + * + * @param member the member to write parameters for. + * @param includeAnnotations true if annotation information needs to be added. + * @param htmltree the content tree to which the parameters information will be added. + */ + protected void addParameters(ExecutableElement member, + boolean includeAnnotations, Content htmltree, int indentSize) { + htmltree.addContent("("); + String sep = ""; + List parameters = member.getParameters(); + String indent = makeSpace(indentSize + 1); + TypeMirror rcvrType = member.getReceiverType(); + if (includeAnnotations && rcvrType != null && utils.isAnnotated(rcvrType)) { + List annotationMirrors = rcvrType.getAnnotationMirrors(); + addReceiverAnnotations(member, rcvrType, annotationMirrors, htmltree); + sep = "," + DocletConstants.NL + indent; + } + int paramstart; + for (paramstart = 0; paramstart < parameters.size(); paramstart++) { + htmltree.addContent(sep); + VariableElement param = parameters.get(paramstart); + + if (param.getKind() != ElementKind.INSTANCE_INIT) { + if (includeAnnotations) { + boolean foundAnnotations = + writer.addAnnotationInfo(indent.length(), + member, param, htmltree); + if (foundAnnotations) { + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); + } + } + addParam(member, param, + (paramstart == parameters.size() - 1) && member.isVarArgs(), htmltree); + break; + } + } + + for (int i = paramstart + 1; i < parameters.size(); i++) { + htmltree.addContent(","); + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); + if (includeAnnotations) { + boolean foundAnnotations = + writer.addAnnotationInfo(indent.length(), member, parameters.get(i), + htmltree); + if (foundAnnotations) { + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); + } + } + addParam(member, parameters.get(i), (i == parameters.size() - 1) && member.isVarArgs(), + htmltree); + } + htmltree.addContent(")"); + } + + /** + * Add exceptions for the executable member. + * + * @param member the member to write exceptions for. + * @param htmltree the content tree to which the exceptions information will be added. + */ + protected void addExceptions(ExecutableElement member, Content htmltree, int indentSize) { + List exceptions = member.getThrownTypes(); + if (!exceptions.isEmpty()) { + String indent = makeSpace(indentSize + 1 - 7); + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); + htmltree.addContent("throws "); + indent = makeSpace(indentSize + 1); + Content link = writer.getLink(new LinkInfoImpl(configuration, MEMBER, exceptions.get(0))); + htmltree.addContent(link); + for(int i = 1; i < exceptions.size(); i++) { + htmltree.addContent(","); + htmltree.addContent(DocletConstants.NL); + htmltree.addContent(indent); + Content exceptionLink = writer.getLink(new LinkInfoImpl(configuration, MEMBER, + exceptions.get(i))); + htmltree.addContent(exceptionLink); + } + } + } + + protected TypeElement implementsMethodInIntfac(ExecutableElement method, + List intfacs) { + for (TypeElement intf : intfacs) { + List methods = utils.getMethods(intf); + if (!methods.isEmpty()) { + for (ExecutableElement md : methods) { + if (name(md).equals(name(method)) && + md.toString().equals(method.toString())) { + return intf; + } + } + } + } + return null; + } + + /** + * For backward compatibility, include an anchor using the erasures of the + * parameters. NOTE: We won't need this method anymore after we fix + * see tags so that they use the type instead of the erasure. + * + * @param executableElement the ExecutableElement to anchor to. + * @return the 1.4.x style anchor for the executable element. + */ + protected String getErasureAnchor(ExecutableElement executableElement) { + final StringBuilder buf = new StringBuilder(name(executableElement) + "("); + List parameters = executableElement.getParameters(); + boolean foundTypeVariable = false; + for (int i = 0; i < parameters.size(); i++) { + if (i > 0) { + buf.append(","); + } + TypeMirror t = parameters.get(i).asType(); + SimpleTypeVisitor9 stv = new SimpleTypeVisitor9() { + boolean foundTypeVariable = false; + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Boolean visitArray(ArrayType t, Void p) { + visit(t.getComponentType()); + buf.append(utils.getDimension(t)); + return foundTypeVariable; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Boolean visitTypeVariable(TypeVariable t, Void p) { + buf.append(utils.asTypeElement(t).getQualifiedName()); + foundTypeVariable = true; + return foundTypeVariable; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Boolean visitDeclared(DeclaredType t, Void p) { + buf.append(utils.getQualifiedTypeName(t)); + return foundTypeVariable; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Boolean defaultAction(TypeMirror e, Void p) { + buf.append(e.toString()); + return foundTypeVariable; + } + }; + + boolean isTypeVariable = stv.visit(t); + if (!foundTypeVariable) { + foundTypeVariable = isTypeVariable; + } + } + buf.append(")"); + return foundTypeVariable ? writer.getName(buf.toString()) : null; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java new file mode 100644 index 00000000000..b9d4d36c2a5 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java @@ -0,0 +1,461 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.nio.file.*; +import java.util.*; +import java.util.zip.*; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.SimpleElementVisitor9; + +import com.sun.source.doctree.DocTree; +import com.sun.tools.javac.util.DefinedBy; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocFile; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.IndexBuilder; + +/** + * Generate Index for all the Member Names with Indexing in + * Unicode Order. This class is a base class for {@link SingleIndexWriter} and + * {@link SplitIndexWriter}. It uses the functionality from + * {@link HtmlDocletWriter} to generate the Index Contents. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @see IndexBuilder + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class AbstractIndexWriter extends HtmlDocletWriter { + + /** + * The index of all the members with unicode character. + */ + protected IndexBuilder indexbuilder; + + /** + * This constructor will be used by {@link SplitIndexWriter}. Initializes + * path to this file and relative path from this file. + * + * @param configuration The current configuration + * @param path Path to the file which is getting generated. + * @param indexbuilder Unicode based Index from {@link IndexBuilder} + */ + protected AbstractIndexWriter(ConfigurationImpl configuration, + DocPath path, + IndexBuilder indexbuilder) + throws IOException { + super(configuration, path); + this.indexbuilder = indexbuilder; + } + + /** + * Get the index label for navigation bar. + * + * @return a content tree for the tree label + */ + protected Content getNavLinkIndex() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, indexLabel); + return li; + } + + /** + * Add the member information for the unicode character along with the + * list of the members. + * + * @param uc Unicode for which member list information to be generated + * @param memberlist List of members for the unicode character + * @param contentTree the content tree to which the information will be added + */ + protected void addContents(Character uc, Collection memberlist, + Content contentTree) { + addHeading(uc, contentTree); + // Display the list only if there are elements to be displayed. + if (!memberlist.isEmpty()) { + Content dl = new HtmlTree(HtmlTag.DL); + for (Element element : memberlist) { + addDescription(dl, element); + } + contentTree.addContent(dl); + } + } + + protected void addSearchContents(Character uc, List searchList, + Content contentTree) { + addHeading(uc, contentTree); + // Display the list only if there are elements to be displayed. + if (!searchList.isEmpty()) { + Content dl = new HtmlTree(HtmlTag.DL); + for (SearchIndexItem sii : searchList) { + addDescription(sii, dl); + } + contentTree.addContent(dl); + } + } + + protected void addContents(Character uc, List memberlist, + List searchList, Content contentTree) { + addHeading(uc, contentTree); + int memberListSize = memberlist.size(); + int searchListSize = searchList.size(); + int i = 0; + int j = 0; + Content dl = new HtmlTree(HtmlTag.DL); + while (i < memberListSize && j < searchListSize) { + String name = utils.getSimpleName(memberlist.get(i)); + if (name.compareTo(searchList.get(j).getLabel()) < 0) { + addDescription(dl, memberlist.get(i)); + i++; + } else if (name.compareTo(searchList.get(j).getLabel()) > 0) { + addDescription(searchList.get(j), dl); + j++; + } else { + addDescription(dl, memberlist.get(i)); + addDescription(searchList.get(j), dl); + j++; + i++; + } + } + if (i >= memberListSize) { + while (j < searchListSize) { + addDescription(searchList.get(j), dl); + j++; + } + } + if (j >= searchListSize) { + while (i < memberListSize) { + addDescription(dl, memberlist.get(i)); + i++; + } + } + contentTree.addContent(dl); + } + + protected void addHeading(Character uc, Content contentTree) { + String unicode = uc.toString(); + contentTree.addContent(getMarkerAnchorForIndex(unicode)); + Content headContent = new StringContent(unicode); + Content heading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, false, + HtmlStyle.title, headContent); + contentTree.addContent(heading); + } + + protected void addDescription(Content dl, Element element) { + SearchIndexItem si = new SearchIndexItem(); + new SimpleElementVisitor9() { + + @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL) + public Void visitPackage(PackageElement e, Void p) { + addDescription(e, dl, si); + configuration.packageSearchIndex.add(si); + return null; + } + + @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL) + public Void visitType(TypeElement e, Void p) { + addDescription(e, dl, si); + configuration.typeSearchIndex.add(si); + return null; + } + + @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL) + protected Void defaultAction(Element e, Void p) { + addDescription(e, dl, si); + configuration.memberSearchIndex.add(si); + return null; + } + + }.visit(element); + } + + /** + * Add one line summary comment for the package. + * + * @param pkg the package to be documented + * @param dlTree the content tree to which the description will be added + */ + protected void addDescription(PackageElement pkg, Content dlTree, SearchIndexItem si) { + Content link = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))); + si.setLabel(utils.getPackageName(pkg)); + si.setCategory(getResource("doclet.Packages").toString()); + Content dt = HtmlTree.DT(link); + dt.addContent(" - "); + dt.addContent(getResource("doclet.package")); + dt.addContent(" " + utils.getPackageName(pkg)); + dlTree.addContent(dt); + Content dd = new HtmlTree(HtmlTag.DD); + addSummaryComment(pkg, dd); + dlTree.addContent(dd); + } + + /** + * Add one line summary comment for the class. + * + * @param typeElement the class being documented + * @param dlTree the content tree to which the description will be added + */ + protected void addDescription(TypeElement typeElement, Content dlTree, SearchIndexItem si) { + Content link = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.INDEX, typeElement).strong(true)); + si.setContainingPackage(utils.getPackageName(utils.containingPackage(typeElement))); + si.setLabel(utils.getSimpleName(typeElement)); + si.setCategory(getResource("doclet.Types").toString()); + Content dt = HtmlTree.DT(link); + dt.addContent(" - "); + addClassInfo(typeElement, dt); + dlTree.addContent(dt); + Content dd = new HtmlTree(HtmlTag.DD); + addComment(typeElement, dd); + dlTree.addContent(dd); + } + + /** + * Add the classkind (class, interface, exception), error of the class + * passed. + * + * @param te the class being documented + * @param contentTree the content tree to which the class info will be added + */ + protected void addClassInfo(TypeElement te, Content contentTree) { + contentTree.addContent(getResource("doclet.in", + utils.getTypeElementName(te, false), + getPackageLink(utils.containingPackage(te), + utils.getPackageName(utils.containingPackage(te))) + )); + } + + /** + * Add description for Class, Field, Method or Constructor. + * + * @param member the member of the Class Kind + * @param dlTree the content tree to which the description will be added + * @param si search index item + */ + protected void addDescription(Element member, Content dlTree, SearchIndexItem si) { + + si.setContainingPackage(utils.getPackageName(utils.containingPackage(member))); + si.setContainingClass(utils.getSimpleName(utils.getEnclosingTypeElement(member))); + String name = utils.getSimpleName(member); + if (utils.isExecutableElement(member)) { + ExecutableElement ee = (ExecutableElement)member; + name = name + utils.flatSignature(ee); + si.setLabel(name); + if (!((utils.signature(ee)).equals(utils.flatSignature(ee)))) { + si.setUrl(getName(getAnchor(ee))); + } + + } else { + si.setLabel(name); + } + si.setCategory(getResource("doclet.Members").toString()); + Content span = HtmlTree.SPAN(HtmlStyle.memberNameLink, + getDocLink(LinkInfoImpl.Kind.INDEX, member, name)); + Content dt = HtmlTree.DT(span); + dt.addContent(" - "); + addMemberDesc(member, dt); + dlTree.addContent(dt); + Content dd = new HtmlTree(HtmlTag.DD); + addComment(member, dd); + dlTree.addContent(dd); + } + + protected void addDescription(SearchIndexItem sii, Content dlTree) { + String path = pathToRoot.isEmpty() ? "" : pathToRoot.getPath() + "/"; + path += sii.getUrl(); + HtmlTree labelLink = HtmlTree.A(path, new StringContent(sii.getLabel())); + Content dt = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.searchTagLink, labelLink)); + dt.addContent(" - "); + dt.addContent(getResource("doclet.Search_tag_in", sii.getHolder())); + dlTree.addContent(dt); + Content dd = new HtmlTree(HtmlTag.DD); + if (sii.getDescription().isEmpty()) { + dd.addContent(getSpace()); + } else { + dd.addContent(sii.getDescription()); + } + dlTree.addContent(dd); + } + + /** + * Add comment for each element in the index. If the element is deprecated + * and it has a @deprecated tag, use that comment. Else if the containing + * class for this element is deprecated, then add the word "Deprecated." at + * the start and then print the normal comment. + * + * @param element Index element + * @param contentTree the content tree to which the comment will be added + */ + protected void addComment(Element element, Content contentTree) { + List tags; + Content span = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.block); + if (utils.isDeprecated(element)) { + div.addContent(span); + tags = utils.getBlockTags(element, DocTree.Kind.DEPRECATED); + if (!tags.isEmpty()) + addInlineDeprecatedComment(element, tags.get(0), div); + contentTree.addContent(div); + } else { + TypeElement encl = utils.getEnclosingTypeElement(element); + while (encl != null) { + if (utils.isDeprecated(encl)) { + div.addContent(span); + contentTree.addContent(div); + break; + } + encl = utils.getEnclosingTypeElement(encl); + } + addSummaryComment(element, contentTree); + } + } + + /** + * Add description about the Static Variable/Method/Constructor for a + * member. + * + * @param member MemberDoc for the member within the Class Kind + * @param contentTree the content tree to which the member description will be added + */ + protected void addMemberDesc(Element member, Content contentTree) { + TypeElement containing = utils.getEnclosingTypeElement(member); + String classdesc = utils.getTypeElementName(containing, true) + " "; + if (utils.isField(member)) { + Content resource = getResource(utils.isStatic(member) + ? "doclet.Static_variable_in" + : "doclet.Variable_in", classdesc); + contentTree.addContent(resource); + } else if (utils.isConstructor(member)) { + contentTree.addContent( + getResource("doclet.Constructor_for", classdesc)); + } else if (utils.isMethod(member)) { + Content resource = getResource(utils.isStatic(member) + ? "doclet.Static_method_in" + : "doclet.Method_in", classdesc); + contentTree.addContent(resource); + } + addPreQualifiedClassLink(LinkInfoImpl.Kind.INDEX, containing, + false, contentTree); + } + + /** + * Get the marker anchor which will be added to the index documentation tree. + * + * @param anchorNameForIndex the anchor name attribute for index page + * @return a content tree for the marker anchor + */ + public Content getMarkerAnchorForIndex(String anchorNameForIndex) { + return getMarkerAnchor(getNameForIndex(anchorNameForIndex), null); + } + + /** + * Generate a valid HTML name for member index page. + * + * @param unicode the string that needs to be converted to valid HTML name. + * @return a valid HTML name string. + */ + public String getNameForIndex(String unicode) { + return "I:" + getName(unicode); + } + + protected void createSearchIndexFiles() { + createSearchIndexFile(DocPaths.PACKAGE_SEARCH_INDEX_JSON, DocPaths.PACKAGE_SEARCH_INDEX_ZIP, + configuration.packageSearchIndex); + createSearchIndexFile(DocPaths.TYPE_SEARCH_INDEX_JSON, DocPaths.TYPE_SEARCH_INDEX_ZIP, + configuration.typeSearchIndex); + createSearchIndexFile(DocPaths.MEMBER_SEARCH_INDEX_JSON, DocPaths.MEMBER_SEARCH_INDEX_ZIP, + configuration.memberSearchIndex); + createSearchIndexFile(DocPaths.TAG_SEARCH_INDEX_JSON, DocPaths.TAG_SEARCH_INDEX_ZIP, + configuration.tagSearchIndex); + } + + protected void createSearchIndexFile(DocPath searchIndexFile, DocPath searchIndexZip, + List searchIndex) { + if (!searchIndex.isEmpty()) { + try { + StringBuilder searchVar = new StringBuilder("["); + boolean first = true; + DocFile searchFile = DocFile.createFileForOutput(configuration, searchIndexFile); + Path p = Paths.get(searchFile.getPath()); + for (SearchIndexItem item : searchIndex) { + if (first) { + searchVar.append(item.toString()); + first = false; + } else { + searchVar.append(",").append(item.toString()); + } + } + searchVar.append("]"); + Files.write(p, searchVar.toString().getBytes()); + DocFile zipFile = DocFile.createFileForOutput(configuration, searchIndexZip); + try (FileOutputStream fos = new FileOutputStream(zipFile.getPath()); + ZipOutputStream zos = new ZipOutputStream(fos)) { + zipFile(searchFile.getPath(), searchIndexFile, zos); + } + Files.delete(p); + } catch (IOException ie) { + throw new DocletAbortException(ie); + } + } + } + + protected void zipFile(String inputFile, DocPath file, ZipOutputStream zos) { + try { + try { + ZipEntry ze = new ZipEntry(file.getPath()); + zos.putNextEntry(ze); + try (FileInputStream fis = new FileInputStream(new File(inputFile))) { + byte[] buf = new byte[2048]; + int len = fis.read(buf); + while (len > 0) { + zos.write(buf, 0, len); + len = fis.read(buf); + } + } + } finally { + zos.closeEntry(); + } + } catch (IOException e) { + throw new DocletAbortException(e); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java new file mode 100644 index 00000000000..c963b909a52 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java @@ -0,0 +1,708 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.util.*; +import java.util.stream.Collectors; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.SimpleElementVisitor9; + +import com.sun.source.doctree.DocTree; +import com.sun.tools.javac.util.DefinedBy; +import com.sun.tools.javac.util.DefinedBy.Api; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet; +import jdk.javadoc.internal.doclets.toolkit.util.MethodTypes; +import jdk.javadoc.internal.doclets.toolkit.util.Utils; +import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap; + +import static javax.lang.model.element.Modifier.*; + +/** + * The base class for member writers. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert Field + * @author Atul M Dambalkar + * @author Jamie Ho (Re-write) + * @author Bhavesh Patel (Modified) + */ +public abstract class AbstractMemberWriter { + + protected final ConfigurationImpl configuration; + protected final Utils utils; + protected final SubWriterHolderWriter writer; + protected final TypeElement typeElement; + protected Map typeMap = new LinkedHashMap<>(); + protected Set methodTypes = EnumSet.noneOf(MethodTypes.class); + private int methodTypesOr = 0; + public final boolean nodepr; + + protected boolean printedSummaryHeader = false; + + public AbstractMemberWriter(SubWriterHolderWriter writer, TypeElement typeElement) { + this.configuration = writer.configuration; + this.writer = writer; + this.nodepr = configuration.nodeprecated; + this.typeElement = typeElement; + this.utils = writer.configuration.utils; + } + + public AbstractMemberWriter(SubWriterHolderWriter writer) { + this(writer, null); + } + + /*** abstracts ***/ + + /** + * Add the summary label for the member. + * + * @param memberTree the content tree to which the label will be added + */ + public abstract void addSummaryLabel(Content memberTree); + + /** + * Get the summary for the member summary table. + * + * @return a string for the table summary + */ + public abstract String getTableSummary(); + + /** + * Get the caption for the member summary table. + * + * @return a string for the table caption + */ + public abstract Content getCaption(); + + /** + * Get the summary table header for the member. + * + * @param member the member to be documented + * @return the summary table header + */ + public abstract List getSummaryTableHeader(Element member); + + /** + * Add inherited summary label for the member. + * + * @param typeElement the TypeElement to which to link to + * @param inheritedTree the content tree to which the inherited summary label will be added + */ + public abstract void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree); + + /** + * Add the anchor for the summary section of the member. + * + * @param typeElement the TypeElement to be documented + * @param memberTree the content tree to which the summary anchor will be added + */ + public abstract void addSummaryAnchor(TypeElement typeElement, Content memberTree); + + /** + * Add the anchor for the inherited summary section of the member. + * + * @param typeElement the TypeElement to be documented + * @param inheritedTree the content tree to which the inherited summary anchor will be added + */ + public abstract void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree); + + /** + * Add the summary type for the member. + * + * @param member the member to be documented + * @param tdSummaryType the content tree to which the type will be added + */ + protected abstract void addSummaryType(Element member, Content tdSummaryType); + + /** + * Add the summary link for the member. + * + * @param typeElement the TypeElement to be documented + * @param member the member to be documented + * @param tdSummary the content tree to which the link will be added + */ + protected void addSummaryLink(TypeElement typeElement, Element member, Content tdSummary) { + addSummaryLink(LinkInfoImpl.Kind.MEMBER, typeElement, member, tdSummary); + } + + /** + * Add the summary link for the member. + * + * @param context the id of the context where the link will be printed + * @param typeElement the TypeElement to be documented + * @param member the member to be documented + * @param tdSummary the content tree to which the summary link will be added + */ + protected abstract void addSummaryLink(LinkInfoImpl.Kind context, + TypeElement typeElement, Element member, Content tdSummary); + + /** + * Add the inherited summary link for the member. + * + * @param typeElement the TypeElement to be documented + * @param member the member to be documented + * @param linksTree the content tree to which the inherited summary link will be added + */ + protected abstract void addInheritedSummaryLink(TypeElement typeElement, + Element member, Content linksTree); + + /** + * Get the deprecated link. + * + * @param member the member being linked to + * @return a content tree representing the link + */ + protected abstract Content getDeprecatedLink(Element member); + + /** + * Get the navigation summary link. + * + * @param typeElement the TypeElement to be documented + * @param link true if its a link else the label to be printed + * @return a content tree for the navigation summary link. + */ + protected abstract Content getNavSummaryLink(TypeElement typeElement, boolean link); + + /** + * Add the navigation detail link. + * + * @param link true if its a link else the label to be printed + * @param liNav the content tree to which the navigation detail link will be added + */ + protected abstract void addNavDetailLink(boolean link, Content liNav); + + /** + * Add the member name to the content tree. + * + * @param name the member name to be added to the content tree. + * @param htmltree the content tree to which the name will be added. + */ + protected void addName(String name, Content htmltree) { + htmltree.addContent(name); + } + + protected String typeString(Element member) { + return new SimpleElementVisitor9() { + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public String visitExecutable(ExecutableElement e, Void p) { + return utils.isMethod(e) ? e.getReturnType().toString() : ""; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public String visitVariable(VariableElement e, Void p) { + return e.toString(); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected String defaultAction(Element e, Void p) { + return ""; + } + }.visit(member); + } + + /** + * Add the modifier for the member. The modifiers are ordered as specified + * by The Java Language Specification. + * + * @param member the member for which teh modifier will be added. + * @param htmltree the content tree to which the modifier information will be added. + */ + protected void addModifiers(Element member, Content htmltree) { + Set set = new TreeSet<>(member.getModifiers()); + + // remove the ones we really don't need + set.remove(NATIVE); + set.remove(SYNCHRONIZED); + set.remove(STRICTFP); + + // According to JLS, we should not be showing public modifier for + // interface methods. + if ((utils.isField(member) || utils.isMethod(member)) + && writer instanceof ClassWriterImpl + && utils.isInterface(((ClassWriterImpl) writer).getTypeElement())) { + // Remove the implicit abstract and public modifiers + if (utils.isMethod(member) && utils.isInterface(member.getEnclosingElement())) { + set.remove(ABSTRACT); + set.remove(PUBLIC); + } + if (!utils.isMethod(member)) { + set.remove(PUBLIC); + } + } + if (!set.isEmpty()) { + String mods = set.stream().map(m -> m.toString()).collect(Collectors.joining(" ")); + htmltree.addContent(mods); + htmltree.addContent(writer.getSpace()); + } + } + + protected String makeSpace(int len) { + if (len <= 0) { + return ""; + } + StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; i++) { + sb.append(' '); + } + return sb.toString(); + } + + /** + * Add the modifier and type for the member in the member summary. + * + * @param member the member to add the type for + * @param type the type to add + * @param tdSummaryType the content tree to which the modified and type will be added + */ + protected void addModifierAndType(Element member, TypeMirror type, + Content tdSummaryType) { + HtmlTree code = new HtmlTree(HtmlTag.CODE); + addModifier(member, code); + if (type == null) { + code.addContent(utils.isClass(member) ? "class" : "interface"); + code.addContent(writer.getSpace()); + } else { + List list = utils.isExecutableElement(member) + ? ((ExecutableElement)member).getTypeParameters() + : null; + if (list != null && !list.isEmpty()) { + Content typeParameters = ((AbstractExecutableMemberWriter) this) + .getTypeParameters((ExecutableElement)member); + code.addContent(typeParameters); + //Code to avoid ugly wrapping in member summary table. + if (typeParameters.charCount() > 10) { + code.addContent(new HtmlTree(HtmlTag.BR)); + } else { + code.addContent(writer.getSpace()); + } + code.addContent( + writer.getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.SUMMARY_RETURN_TYPE, type))); + } else { + code.addContent( + writer.getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.SUMMARY_RETURN_TYPE, type))); + } + + } + tdSummaryType.addContent(code); + } + + /** + * Add the modifier for the member. + * + * @param member the member to add the type for + * @param code the content tree to which the modified will be added + */ + private void addModifier(Element member, Content code) { + if (utils.isProtected(member)) { + code.addContent("protected "); + } else if (utils.isPrivate(member)) { + code.addContent("private "); + } else if (!utils.isPublic(member)) { // Package private + code.addContent(configuration.getText("doclet.Package_private")); + code.addContent(" "); + } + boolean isAnnotatedTypeElement = utils.isAnnotationType(member.getEnclosingElement()); + if (!isAnnotatedTypeElement && utils.isMethod(member)) { + if (!utils.isInterface(member.getEnclosingElement()) && utils.isAbstract(member)) { + code.addContent("abstract "); + } + if (utils.isDefault(member)) { + code.addContent("default "); + } + } + if (utils.isStatic(member)) { + code.addContent("static "); + } + } + + /** + * Add the deprecated information for the given member. + * + * @param member the member being documented. + * @param contentTree the content tree to which the deprecated information will be added. + */ + protected void addDeprecatedInfo(Element member, Content contentTree) { + Content output = (new DeprecatedTaglet()).getTagletOutput(member, + writer.getTagletWriterInstance(false)); + if (!output.isEmpty()) { + Content deprecatedContent = output; + Content div = HtmlTree.DIV(HtmlStyle.block, deprecatedContent); + contentTree.addContent(div); + } + } + + /** + * Add the comment for the given member. + * + * @param member the member being documented. + * @param htmltree the content tree to which the comment will be added. + */ + protected void addComment(Element member, Content htmltree) { + if (!utils.getBody(member).isEmpty()) { + writer.addInlineComment(member, htmltree); + } + } + + protected String name(Element member) { + return utils.getSimpleName(member); + } + + /** + * Get the header for the section. + * + * @param member the member being documented. + * @return a header content for the section. + */ + protected Content getHead(Element member) { + Content memberContent = new StringContent(name(member)); + Content heading = HtmlTree.HEADING(HtmlConstants.MEMBER_HEADING, memberContent); + return heading; + } + + /** + * Return true if the given ProgramElement is inherited + * by the class that is being documented. + * + * @param ped The ProgramElement being checked. + * return true if the ProgramElement is being inherited and + * false otherwise. + */ + protected boolean isInherited(Element ped){ + return (!utils.isPrivate(ped) && + (!utils.isPackagePrivate(ped) || + ped.getEnclosingElement().equals(ped.getEnclosingElement()))); + } + + /** + * Add deprecated information to the documentation tree + * + * @param deprmembers list of deprecated members + * @param headingKey the caption for the deprecated members table + * @param tableSummary the summary for the deprecated members table + * @param tableHeader table headers for the deprecated members table + * @param contentTree the content tree to which the deprecated members table will be added + */ + protected void addDeprecatedAPI(Collection deprmembers, String headingKey, + String tableSummary, List tableHeader, Content contentTree) { + if (deprmembers.size() > 0) { + Content caption = writer.getTableCaption(configuration.getResource(headingKey)); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption) + : HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption); + table.addContent(writer.getSummaryTableHeader(tableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (Element member : deprmembers) { + HtmlTree td = HtmlTree.TD(HtmlStyle.colOne, getDeprecatedLink(member)); + List deprTrees = utils.getBlockTags(member, DocTree.Kind.DEPRECATED); + if (!deprTrees.isEmpty()) { + writer.addInlineDeprecatedComment(member, deprTrees.get(0), td); + } + HtmlTree tr = HtmlTree.TR(td); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + tbody.addContent(tr); + } + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + Content ul = HtmlTree.UL(HtmlStyle.blockList, li); + contentTree.addContent(ul); + } + } + + /** + * Add use information to the documentation tree. + * + * @param mems list of program elements for which the use information will be added + * @param heading the section heading + * @param tableSummary the summary for the use table + * @param contentTree the content tree to which the use information will be added + */ + protected void addUseInfo(List mems, + Content heading, String tableSummary, Content contentTree) { + if (mems == null || mems.isEmpty()) { + return; + } + List members = mems; + boolean printedUseTableHeader = false; + if (members.size() > 0) { + Content caption = writer.getTableCaption(heading); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) + : HtmlTree.TABLE(HtmlStyle.useSummary, tableSummary, caption); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (Element element : members) { + TypeElement te = utils.getEnclosingTypeElement(element); + if (!printedUseTableHeader) { + table.addContent(writer.getSummaryTableHeader( + this.getSummaryTableHeader(element), "col")); + printedUseTableHeader = true; + } + HtmlTree tr = new HtmlTree(HtmlTag.TR); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + HtmlTree tdFirst = new HtmlTree(HtmlTag.TD); + tdFirst.addStyle(HtmlStyle.colFirst); + writer.addSummaryType(this, element, tdFirst); + tr.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); + if (te != null + && !utils.isConstructor(element) + && !utils.isClass(element) + && !utils.isInterface(element) + && !utils.isAnnotationType(element)) { + HtmlTree name = new HtmlTree(HtmlTag.SPAN); + name.addStyle(HtmlStyle.typeNameLabel); + name.addContent(name(te) + "."); + tdLast.addContent(name); + } + addSummaryLink(utils.isClass(element) || utils.isInterface(element) + ? LinkInfoImpl.Kind.CLASS_USE + : LinkInfoImpl.Kind.MEMBER, + te, element, tdLast); + writer.addSummaryLinkComment(this, element, tdLast); + tr.addContent(tdLast); + tbody.addContent(tr); + } + table.addContent(tbody); + contentTree.addContent(table); + } + } + + /** + * Add the navigation detail link. + * + * @param members the members to be linked + * @param liNav the content tree to which the navigation detail link will be added + */ + protected void addNavDetailLink(SortedSet members, Content liNav) { + addNavDetailLink(!members.isEmpty(), liNav); + } + + /** + * Add the navigation summary link. + * + * @param members members to be linked + * @param visibleMemberMap the visible inherited members map + * @param liNav the content tree to which the navigation summary link will be added + */ + protected void addNavSummaryLink(SortedSet members, + VisibleMemberMap visibleMemberMap, Content liNav) { + if (!members.isEmpty()) { + liNav.addContent(getNavSummaryLink(null, true)); + return; + } + + TypeElement superClass = utils.getSuperClass(typeElement); + while (superClass != null) { + if (visibleMemberMap.hasMembersFor(superClass)) { + liNav.addContent(getNavSummaryLink(superClass, true)); + return; + } + superClass = utils.getSuperClass(superClass); + } + liNav.addContent(getNavSummaryLink(null, false)); + } + + protected void serialWarning(Element e, String key, String a1, String a2) { + if (configuration.serialwarn) { + configuration.getDocletSpecificMsg().warning(e, key, a1, a2); + } + } + + /** + * Add the member summary for the given class. + * + * @param tElement the class that is being documented + * @param member the member being documented + * @param firstSentenceTags the first sentence tags to be added to the summary + * @param tableContents the list of contents to which the documentation will be added + * @param counter the counter for determining id and style for the table row + */ + public void addMemberSummary(TypeElement tElement, Element member, + List firstSentenceTags, List tableContents, int counter) { + HtmlTree tdSummaryType = new HtmlTree(HtmlTag.TD); + tdSummaryType.addStyle(HtmlStyle.colFirst); + writer.addSummaryType(this, member, tdSummaryType); + HtmlTree tdSummary = new HtmlTree(HtmlTag.TD); + setSummaryColumnStyle(tdSummary); + addSummaryLink(tElement, member, tdSummary); + writer.addSummaryLinkComment(this, member, firstSentenceTags, tdSummary); + HtmlTree tr = HtmlTree.TR(tdSummaryType); + tr.addContent(tdSummary); + if (utils.isMethod(member) && !utils.isAnnotationType(member)) { + int methodType = utils.isStatic(member) ? MethodTypes.STATIC.value() : + MethodTypes.INSTANCE.value(); + if (utils.isInterface(member.getEnclosingElement())) { + methodType = utils.isAbstract(member) + ? methodType | MethodTypes.ABSTRACT.value() + : methodType | MethodTypes.DEFAULT.value(); + } else { + methodType = utils.isAbstract(member) + ? methodType | MethodTypes.ABSTRACT.value() + : methodType | MethodTypes.CONCRETE.value(); + } + if (utils.isDeprecated(member) || utils.isDeprecated(typeElement)) { + methodType = methodType | MethodTypes.DEPRECATED.value(); + } + methodTypesOr = methodTypesOr | methodType; + String tableId = "i" + counter; + typeMap.put(tableId, methodType); + tr.addAttr(HtmlAttr.ID, tableId); + } + if (counter%2 == 0) + tr.addStyle(HtmlStyle.altColor); + else + tr.addStyle(HtmlStyle.rowColor); + tableContents.add(tr); + } + + /** + * Generate the method types set and return true if the method summary table + * needs to show tabs. + * + * @return true if the table should show tabs + */ + public boolean showTabs() { + int value; + for (MethodTypes type : EnumSet.allOf(MethodTypes.class)) { + value = type.value(); + if ((value & methodTypesOr) == value) { + methodTypes.add(type); + } + } + boolean showTabs = methodTypes.size() > 1; + if (showTabs) { + methodTypes.add(MethodTypes.ALL); + } + return showTabs; + } + + /** + * Set the style for the summary column. + * + * @param tdTree the column for which the style will be set + */ + public void setSummaryColumnStyle(HtmlTree tdTree) { + tdTree.addStyle(HtmlStyle.colLast); + } + + /** + * Add inherited member summary for the given class and member. + * + * @param tElement the class the inherited member belongs to + * @param nestedClass the inherited member that is summarized + * @param isFirst true if this is the first member in the list + * @param isLast true if this is the last member in the list + * @param linksTree the content tree to which the summary will be added + */ + public void addInheritedMemberSummary(TypeElement tElement, + Element nestedClass, boolean isFirst, boolean isLast, + Content linksTree) { + writer.addInheritedMemberSummary(this, tElement, nestedClass, isFirst, + linksTree); + } + + /** + * Get the inherited summary header for the given class. + * + * @param tElement the class the inherited member belongs to + * @return a content tree for the inherited summary header + */ + public Content getInheritedSummaryHeader(TypeElement tElement) { + Content inheritedTree = writer.getMemberTreeHeader(); + writer.addInheritedSummaryHeader(this, tElement, inheritedTree); + return inheritedTree; + } + + /** + * Get the inherited summary links tree. + * + * @return a content tree for the inherited summary links + */ + public Content getInheritedSummaryLinksTree() { + return new HtmlTree(HtmlTag.CODE); + } + + /** + * Get the summary table tree for the given class. + * + * @param tElement the class for which the summary table is generated + * @param tableContents list of contents to be displayed in the summary table + * @return a content tree for the summary table + */ + public Content getSummaryTableTree(TypeElement tElement, List tableContents) { + return writer.getSummaryTableTree(this, tElement, tableContents, showTabs()); + } + + /** + * Get the member tree to be documented. + * + * @param memberTree the content tree of member to be documented + * @return a content tree that will be added to the class documentation + */ + public Content getMemberTree(Content memberTree) { + return writer.getMemberTree(memberTree); + } + + /** + * Get the member tree to be documented. + * + * @param memberTree the content tree of member to be documented + * @param isLastContent true if the content to be added is the last content + * @return a content tree that will be added to the class documentation + */ + public Content getMemberTree(Content memberTree, boolean isLastContent) { + if (isLastContent) + return HtmlTree.UL(HtmlStyle.blockListLast, memberTree); + else + return HtmlTree.UL(HtmlStyle.blockList, memberTree); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java new file mode 100644 index 00000000000..26061a83b8d --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.PackageElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; + +/** + * Abstract class to generate the overview files in + * Frame and Non-Frame format. This will be sub-classed by to + * generate overview-frame.html as well as overview-summary.html. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter { + + /** + * A Set of Packages to be documented. + */ + protected SortedSet packages; + + /** + * Constructor. Also initializes the packages variable. + * + * @param configuration The current configuration + * @param filename Name of the package index file to be generated. + */ + public AbstractPackageIndexWriter(ConfigurationImpl configuration, + DocPath filename) throws IOException { + super(configuration, filename); + packages = configuration.packages; + } + + /** + * Adds the navigation bar header to the documentation tree. + * + * @param body the document tree to which the navigation bar header will be added + */ + protected abstract void addNavigationBarHeader(Content body); + + /** + * Adds the navigation bar footer to the documentation tree. + * + * @param body the document tree to which the navigation bar footer will be added + */ + protected abstract void addNavigationBarFooter(Content body); + + /** + * Adds the overview header to the documentation tree. + * + * @param body the document tree to which the overview header will be added + */ + protected abstract void addOverviewHeader(Content body); + + /** + * Adds the packages list to the documentation tree. + * + * @param packages a collection of packagedoc objects + * @param text caption for the table + * @param tableSummary summary for the table + * @param body the document tree to which the packages list will be added + */ + protected abstract void addPackagesList(Collection packages, String text, + String tableSummary, Content body); + + /** + * Generate and prints the contents in the package index file. Call appropriate + * methods from the sub-class in order to generate Frame or Non + * Frame format. + * + * @param title the title of the window. + * @param includeScript boolean set true if windowtitle script is to be included + */ + protected void buildPackageIndexFile(String title, boolean includeScript) throws IOException { + String windowOverview = configuration.getText(title); + Content body = getBody(includeScript, getWindowTitle(windowOverview)); + addNavigationBarHeader(body); + addOverviewHeader(body); + addIndex(body); + addOverview(body); + addNavigationBarFooter(body); + printHtmlDocument(configuration.metakeywords.getOverviewMetaKeywords(title, + configuration.doctitle), includeScript, body); + } + + /** + * Default to no overview, override to add overview. + * + * @param body the document tree to which the overview will be added + */ + protected void addOverview(Content body) throws IOException { + } + + /** + * Adds the frame or non-frame package index to the documentation tree. + * + * @param body the document tree to which the index will be added + */ + protected void addIndex(Content body) { + addIndexContents(packages, "doclet.Package_Summary", + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Package_Summary"), + configuration.getText("doclet.packages")), body); + } + + /** + * Adds package index contents. Call appropriate methods from + * the sub-classes. Adds it to the body HtmlTree + * + * @param packages a collection of packages to be documented + * @param text string which will be used as the heading + * @param tableSummary summary for the table + * @param body the document tree to which the index contents will be added + */ + protected void addIndexContents(Collection packages, String text, + String tableSummary, Content body) { + if (!packages.isEmpty()) { + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV)) + ? HtmlTree.NAV() + : new HtmlTree(HtmlTag.DIV); + htmlTree.addStyle(HtmlStyle.indexNav); + HtmlTree ul = new HtmlTree(HtmlTag.UL); + addAllClassesLink(ul); + htmlTree.addContent(ul); + body.addContent(htmlTree); + addPackagesList(packages, text, tableSummary, body); + } + } + + /** + * Adds the doctitle to the documentation tree, if it is specified on the command line. + * + * @param body the document tree to which the title will be added + */ + protected void addConfigurationTitle(Content body) { + if (configuration.doctitle.length() > 0) { + Content title = new RawHtml(configuration.doctitle); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, + HtmlStyle.title, title); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + body.addContent(div); + } + } + + /** + * Returns highlighted "Overview", in the navigation bar as this is the + * overview page. + * + * @return a Content object to be added to the documentation tree + */ + protected Content getNavLinkContents() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, overviewLabel); + return li; + } + + /** + * Do nothing. This will be overridden. + * + * @param div the document tree to which the all classes link will be added + */ + protected void addAllClassesLink(Content div) { + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java new file mode 100644 index 00000000000..68ede24c0cf --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + + +/** + * Abstract class to print the class hierarchy page for all the Classes. This + * is sub-classed by {@link PackageTreeWriter} and {@link TreeWriter} to + * generate the Package Tree and global Tree(for all the classes and packages) + * pages. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + */ +public abstract class AbstractTreeWriter extends HtmlDocletWriter { + + /** + * The class and interface tree built by using {@link ClassTree} + */ + protected final ClassTree classtree; + + /** + * Constructor initializes classtree variable. This constructor will be used + * while generating global tree file "overview-tree.html". + * + * @param configuration The current configuration + * @param filename File to be generated. + * @param classtree Tree built by {@link ClassTree}. + * @throws IOException + * @throws DocletAbortException + */ + protected AbstractTreeWriter(ConfigurationImpl configuration, + DocPath filename, ClassTree classtree) + throws IOException { + super(configuration, filename); + this.classtree = classtree; + } + + /** + * Add each level of the class tree. For each sub-class or + * sub-interface indents the next level information. + * Recurses itself to add sub-classes info. + * + * @param parent the superclass or superinterface of the sset + * @param collection a collection of the sub-classes at this level + * @param isEnum true if we are generating a tree for enums + * @param contentTree the content tree to which the level information will be added + */ + protected void addLevelInfo(TypeElement parent, Collection collection, + boolean isEnum, Content contentTree) { + if (!collection.isEmpty()) { + Content ul = new HtmlTree(HtmlTag.UL); + for (TypeElement local : collection) { + HtmlTree li = new HtmlTree(HtmlTag.LI); + li.addStyle(HtmlStyle.circle); + addPartialInfo(local, li); + addExtendsImplements(parent, local, li); + addLevelInfo(local, classtree.directSubClasses(local, isEnum), + isEnum, li); // Recurse + ul.addContent(li); + } + contentTree.addContent(ul); + } + } + + /** + * Add the heading for the tree depending upon tree type if it's a + * Class Tree or Interface tree. + * + * @param sset classes which are at the most base level, all the + * other classes in this run will derive from these classes + * @param heading heading for the tree + * @param div the content tree to which the tree will be added + */ + protected void addTree(SortedSet sset, String heading, HtmlTree div) { + addTree(sset, heading, div, false); + } + + protected void addTree(SortedSet sset, String heading, + HtmlTree div, boolean isEnums) { + if (!sset.isEmpty()) { + TypeElement firstTypeElement = sset.first(); + Content headingContent = getResource(heading); + Content sectionHeading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, true, + headingContent); + HtmlTree htmlTree; + if (configuration.allowTag(HtmlTag.SECTION)) { + htmlTree = HtmlTree.SECTION(sectionHeading); + } else { + div.addContent(sectionHeading); + htmlTree = div; + } + addLevelInfo(!utils.isInterface(firstTypeElement) ? firstTypeElement : null, + sset, isEnums, htmlTree); + if (configuration.allowTag(HtmlTag.SECTION)) { + div.addContent(htmlTree); + } + } + } + + /** + * Add information regarding the classes which this class extends or + * implements. + * + * @param parent the parent class of the class being documented + * @param typeElement the TypeElement under consideration + * @param contentTree the content tree to which the information will be added + */ + protected void addExtendsImplements(TypeElement parent, TypeElement typeElement, + Content contentTree) { + SortedSet interfaces = new TreeSet<>(utils.makeGeneralPurposeComparator()); + typeElement.getInterfaces().stream().forEach((t) -> { + interfaces.add(utils.asTypeElement(t)); + }); + if (interfaces.size() > (utils.isInterface(typeElement) ? 1 : 0)) { + boolean isFirst = true; + for (TypeElement intf : interfaces) { + if (parent != intf) { + if (utils.isPublic(intf) || utils.isLinkable(intf)) { + if (isFirst) { + isFirst = false; + if (utils.isInterface(typeElement)) { + contentTree.addContent(" ("); + contentTree.addContent(getResource("doclet.also")); + contentTree.addContent(" extends "); + } else { + contentTree.addContent(" (implements "); + } + } else { + contentTree.addContent(", "); + } + addPreQualifiedClassLink(LinkInfoImpl.Kind.TREE, intf, contentTree); + } + } + } + if (!isFirst) { + contentTree.addContent(")"); + } + } + } + + /** + * Add information about the class kind, if it's a "class" or "interface". + * + * @param typeElement the class being documented + * @param contentTree the content tree to which the information will be added + */ + protected void addPartialInfo(TypeElement typeElement, Content contentTree) { + addPreQualifiedStrongClassLink(LinkInfoImpl.Kind.TREE, typeElement, contentTree); + } + + /** + * Get the tree label for the navigation bar. + * + * @return a content tree for the tree label + */ + protected Content getNavLinkTree() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, treeLabel); + return li; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesFrameWriter.java new file mode 100644 index 00000000000..6ba6f0afc4c --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesFrameWriter.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.IndexBuilder; + + +/** + * Generate the file with list of all the classes in this run. This page will be + * used in the left-hand bottom frame, when "All Classes" link is clicked in + * the left-hand top frame. The name of the generated file is + * "allclasses-frame.html". + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Doug Kramer + * @author Bhavesh Patel (Modified) + */ +public class AllClassesFrameWriter extends HtmlDocletWriter { + + /** + * Index of all the classes. + */ + protected IndexBuilder indexbuilder; + + /** + * BR tag to be used within a document tree. + */ + final HtmlTree BR = new HtmlTree(HtmlTag.BR); + + /** + * Construct AllClassesFrameWriter object. Also initializes the indexbuilder + * variable in this class. + * @param configuration The current configuration + * @param filename Path to the file which is getting generated. + * @param indexbuilder Unicode based Index from {@link IndexBuilder} + * @throws IOException + * @throws DocletAbortException + */ + public AllClassesFrameWriter(ConfigurationImpl configuration, + DocPath filename, IndexBuilder indexbuilder) + throws IOException { + super(configuration, filename); + this.indexbuilder = indexbuilder; + } + + /** + * Create AllClassesFrameWriter object. Then use it to generate the + * "allclasses-frame.html" file. Generate the file in the current or the + * destination directory. + * + * @param indexbuilder IndexBuilder object for all classes index. + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration, + IndexBuilder indexbuilder) { + AllClassesFrameWriter allclassgen; + DocPath filename = DocPaths.ALLCLASSES_FRAME; + try { + allclassgen = new AllClassesFrameWriter(configuration, + filename, indexbuilder); + allclassgen.buildAllClassesFile(true); + allclassgen.close(); + filename = DocPaths.ALLCLASSES_NOFRAME; + allclassgen = new AllClassesFrameWriter(configuration, + filename, indexbuilder); + allclassgen.buildAllClassesFile(false); + allclassgen.close(); + } catch (IOException exc) { + configuration.standardmessage. + error("doclet.exception_encountered", + exc.toString(), filename); + throw new DocletAbortException(exc); + } + } + + /** + * Print all the classes in the file. + * @param wantFrames True if we want frames. + */ + protected void buildAllClassesFile(boolean wantFrames) throws IOException { + String label = configuration.getText("doclet.All_Classes"); + Content body = getBody(false, getWindowTitle(label)); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, + HtmlStyle.bar, allclassesLabel); + body.addContent(heading); + Content ul = new HtmlTree(HtmlTag.UL); + // Generate the class links and add it to the tdFont tree. + addAllClasses(ul, wantFrames); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN)) + ? HtmlTree.MAIN(HtmlStyle.indexContainer, ul) + : HtmlTree.DIV(HtmlStyle.indexContainer, ul); + body.addContent(htmlTree); + printHtmlDocument(null, false, body); + } + + /** + * Use the sorted index of all the classes and add all the classes to the + * content list. + * + * @param content HtmlTree content to which all classes information will be added + * @param wantFrames True if we want frames. + */ + protected void addAllClasses(Content content, boolean wantFrames) { + for (Character unicode : indexbuilder.index()) { + addContents(indexbuilder.getMemberList(unicode), wantFrames, content); + } + } + + /** + * Given a list of classes, generate links for each class or interface. + * If the class kind is interface, print it in the italics font. Also all + * links should target the right-hand frame. If clicked on any class name + * in this page, appropriate class page should get opened in the right-hand + * frame. + * + * @param classlist Sorted list of classes. + * @param wantFrames True if we want frames. + * @param content HtmlTree content to which the links will be added + */ + protected void addContents(Iterable classlist, boolean wantFrames, + Content content) { + for (Element element : classlist) { + TypeElement typeElement = (TypeElement)element; + if (!utils.isCoreClass(typeElement)) { + continue; + } + Content label = interfaceName(typeElement, false); + Content linkContent; + if (wantFrames) { + linkContent = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.ALL_CLASSES_FRAME, typeElement).label(label).target("classFrame")); + } else { + linkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, typeElement).label(label)); + } + Content li = HtmlTree.LI(linkContent); + content.addContent(li); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java new file mode 100644 index 00000000000..0bb63a68f93 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import java.util.Arrays; +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; + + +/** + * Writes annotation type field documentation in HTML format. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public class AnnotationTypeFieldWriterImpl extends AbstractMemberWriter + implements AnnotationTypeFieldWriter, MemberSummaryWriter { + + /** + * Construct a new AnnotationTypeFieldWriterImpl. + * + * @param writer the writer that will write the output. + * @param annotationType the AnnotationType that holds this member. + */ + public AnnotationTypeFieldWriterImpl(SubWriterHolderWriter writer, + TypeElement annotationType) { + super(writer, annotationType); + } + + /** + * {@inheritDoc} + */ + public Content getMemberSummaryHeader(TypeElement typeElement, + Content memberSummaryTree) { + memberSummaryTree.addContent( + HtmlConstants.START_OF_ANNOTATION_TYPE_FIELD_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, typeElement, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public Content getMemberTreeHeader() { + return writer.getMemberTreeHeader(); + } + + /** + * {@inheritDoc} + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + writer.addMemberTree(memberSummaryTree, memberTree); + } + + /** + * {@inheritDoc} + */ + public void addAnnotationFieldDetailsMarker(Content memberDetails) { + memberDetails.addContent(HtmlConstants.START_OF_ANNOTATION_TYPE_FIELD_DETAILS); + } + + /** + * {@inheritDoc} + */ + public void addAnnotationDetailsTreeHeader(TypeElement typeElement, + Content memberDetailsTree) { + if (!writer.printedAnnotationFieldHeading) { + memberDetailsTree.addContent(writer.getMarkerAnchor( + SectionName.ANNOTATION_TYPE_FIELD_DETAIL)); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.fieldDetailsLabel); + memberDetailsTree.addContent(heading); + writer.printedAnnotationFieldHeading = true; + } + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDocTreeHeader(Element member, + Content annotationDetailsTree) { + annotationDetailsTree.addContent( + writer.getMarkerAnchor(name(member))); + Content annotationDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(name(member)); + annotationDocTree.addContent(heading); + return annotationDocTree; + } + + /** + * {@inheritDoc} + */ + public Content getSignature(Element member) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(member, pre); + addModifiers(member, pre); + Content link = + writer.getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.MEMBER, getType(member))); + pre.addContent(link); + pre.addContent(writer.getSpace()); + if (configuration.linksource) { + Content memberName = new StringContent(name(member)); + writer.addSrcLink(member, memberName, pre); + } else { + addName(name(member), pre); + } + return pre; + } + + /** + * {@inheritDoc} + */ + public void addDeprecated(Element member, Content annotationDocTree) { + addDeprecatedInfo(member, annotationDocTree); + } + + /** + * {@inheritDoc} + */ + public void addComments(Element member, Content annotationDocTree) { + addComment(member, annotationDocTree); + } + + /** + * {@inheritDoc} + */ + public void addTags(Element member, Content annotationDocTree) { + writer.addTagsInfo(member, annotationDocTree); + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDetails(Content annotationDetailsTree) { + if (configuration.allowTag(HtmlTag.SECTION)) { + HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(annotationDetailsTree)); + return htmlTree; + } + return getMemberTree(annotationDetailsTree); + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDoc(Content annotationDocTree, + boolean isLastContent) { + return getMemberTree(annotationDocTree, isLastContent); + } + + /** + * Close the writer. + */ + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Field_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Field_Summary"), + configuration.getText("doclet.fields")); + } + + /** + * {@inheritDoc} + */ + public Content getCaption() { + return configuration.getResource("doclet.Fields"); + } + + /** + * {@inheritDoc} + */ + public List getSummaryTableHeader(Element member) { + List header = Arrays.asList(writer.getModifierTypeHeader(), + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Fields"), + configuration.getText("doclet.Description"))); + return header; + } + + /** + * {@inheritDoc} + */ + public void addSummaryAnchor(TypeElement typeElement, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + SectionName.ANNOTATION_TYPE_FIELD_SUMMARY)); + } + + /** + * {@inheritDoc} + */ + public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member, + Content tdSummary) { + Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink, + writer.getDocLink(context, member, name(member), false)); + Content code = HtmlTree.CODE(memberLink); + tdSummary.addContent(code); + } + + /** + * {@inheritDoc} + */ + protected void addInheritedSummaryLink(TypeElement typeElement, + Element member, Content linksTree) { + //Not applicable. + } + + /** + * {@inheritDoc} + */ + protected void addSummaryType(Element member, Content tdSummaryType) { + addModifierAndType(member, getType(member), tdSummaryType); + } + + /** + * {@inheritDoc} + */ + protected Content getDeprecatedLink(Element member) { + return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, + member, utils.getFullyQualifiedName(member)); + } + + /** + * {@inheritDoc} + */ + protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { + if (link) { + return writer.getHyperLink( + SectionName.ANNOTATION_TYPE_FIELD_SUMMARY, + writer.getResource("doclet.navField")); + } else { + return writer.getResource("doclet.navField"); + } + } + + /** + * {@inheritDoc} + */ + protected void addNavDetailLink(boolean link, Content liNav) { + if (link) { + liNav.addContent(writer.getHyperLink( + SectionName.ANNOTATION_TYPE_FIELD_DETAIL, + writer.getResource("doclet.navField"))); + } else { + liNav.addContent(writer.getResource("doclet.navField")); + } + } + private TypeMirror getType(Element member) { + if (utils.isConstructor(member)) + return null; + if (utils.isExecutableElement(member)) + return utils.getReturnType((ExecutableElement)member); + return member.asType(); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java new file mode 100644 index 00000000000..221e467101b --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import java.util.Arrays; +import java.util.List; + +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; + + +/** + * Writes annotation type optional member documentation in HTML format. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Jamie Ho + * @author Bhavesh Patel (Modified) + */ +public class AnnotationTypeOptionalMemberWriterImpl extends + AnnotationTypeRequiredMemberWriterImpl + implements AnnotationTypeOptionalMemberWriter, MemberSummaryWriter { + + /** + * Construct a new AnnotationTypeOptionalMemberWriterImpl. + * + * @param writer the writer that will write the output. + * @param annotationType the AnnotationType that holds this member. + */ + public AnnotationTypeOptionalMemberWriterImpl(SubWriterHolderWriter writer, + TypeElement annotationType) { + super(writer, annotationType); + } + + /** + * {@inheritDoc} + */ + public Content getMemberSummaryHeader(TypeElement typeElement, + Content memberSummaryTree) { + memberSummaryTree.addContent( + HtmlConstants.START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, typeElement, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + writer.addMemberTree(memberSummaryTree, memberTree); + } + + /** + * {@inheritDoc} + */ + public void addDefaultValueInfo(Element member, Content annotationDocTree) { + if (utils.isAnnotationType(member)) { + ExecutableElement ee = (ExecutableElement)member; + AnnotationValue value = ee.getDefaultValue(); + if (value != null) { + Content dt = HtmlTree.DT(writer.getResource("doclet.Default")); + Content dl = HtmlTree.DL(dt); + Content dd = HtmlTree.DD(new StringContent(value.toString())); + dl.addContent(dd); + annotationDocTree.addContent(dl); + } + } + } + + /** + * {@inheritDoc} + */ + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Annotation_Type_Optional_Member_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Annotation_Type_Optional_Member_Summary"), + configuration.getText("doclet.annotation_type_optional_members")); + } + + /** + * {@inheritDoc} + */ + public Content getCaption() { + return configuration.getResource("doclet.Annotation_Type_Optional_Members"); + } + + /** + * {@inheritDoc} + */ + public List getSummaryTableHeader(Element member) { + List header = Arrays.asList(writer.getModifierTypeHeader(), + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Annotation_Type_Optional_Member"), + configuration.getText("doclet.Description"))); + return header; + } + + /** + * {@inheritDoc} + */ + public void addSummaryAnchor(TypeElement typeElement, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + SectionName.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY)); + } + + /** + * {@inheritDoc} + */ + protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { + if (link) { + return writer.getHyperLink( + SectionName.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY, + writer.getResource("doclet.navAnnotationTypeOptionalMember")); + } else { + return writer.getResource("doclet.navAnnotationTypeOptionalMember"); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java new file mode 100644 index 00000000000..531d0a033f5 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.Arrays; +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; + + +/** + * Writes annotation type required member documentation in HTML format. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Jamie Ho + * @author Bhavesh Patel (Modified) + */ +public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter + implements AnnotationTypeRequiredMemberWriter, MemberSummaryWriter { + + /** + * Construct a new AnnotationTypeRequiredMemberWriterImpl. + * + * @param writer the writer that will write the output. + * @param annotationType the AnnotationType that holds this member. + */ + public AnnotationTypeRequiredMemberWriterImpl(SubWriterHolderWriter writer, + TypeElement annotationType) { + super(writer, annotationType); + } + + /** + * {@inheritDoc} + */ + public Content getMemberSummaryHeader(TypeElement typeElement, + Content memberSummaryTree) { + memberSummaryTree.addContent( + HtmlConstants.START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, typeElement, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public Content getMemberTreeHeader() { + return writer.getMemberTreeHeader(); + } + + /** + * {@inheritDoc} + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + writer.addMemberTree(memberSummaryTree, memberTree); + } + + /** + * {@inheritDoc} + */ + public void addAnnotationDetailsMarker(Content memberDetails) { + memberDetails.addContent(HtmlConstants.START_OF_ANNOTATION_TYPE_DETAILS); + } + + /** + * {@inheritDoc} + */ + public void addAnnotationDetailsTreeHeader(TypeElement classDoc, + Content memberDetailsTree) { + if (!writer.printedAnnotationHeading) { + memberDetailsTree.addContent(writer.getMarkerAnchor( + SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL)); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.annotationTypeDetailsLabel); + memberDetailsTree.addContent(heading); + writer.printedAnnotationHeading = true; + } + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDocTreeHeader(Element member, + Content annotationDetailsTree) { + String simpleName = name(member); + annotationDetailsTree.addContent(writer.getMarkerAnchor(simpleName + + utils.signature((ExecutableElement) member))); + Content annotationDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(simpleName); + annotationDocTree.addContent(heading); + return annotationDocTree; + } + + /** + * {@inheritDoc} + */ + public Content getSignature(Element member) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(member, pre); + addModifiers(member, pre); + Content link = + writer.getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.MEMBER, getType(member))); + pre.addContent(link); + pre.addContent(writer.getSpace()); + if (configuration.linksource) { + Content memberName = new StringContent(name(member)); + writer.addSrcLink(member, memberName, pre); + } else { + addName(name(member), pre); + } + return pre; + } + + /** + * {@inheritDoc} + */ + public void addDeprecated(Element member, Content annotationDocTree) { + addDeprecatedInfo(member, annotationDocTree); + } + + /** + * {@inheritDoc} + */ + public void addComments(Element member, Content annotationDocTree) { + addComment(member, annotationDocTree); + } + + /** + * {@inheritDoc} + */ + public void addTags(Element member, Content annotationDocTree) { + writer.addTagsInfo(member, annotationDocTree); + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDetails(Content annotationDetailsTree) { + if (configuration.allowTag(HtmlTag.SECTION)) { + HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(annotationDetailsTree)); + return htmlTree; + } + return getMemberTree(annotationDetailsTree); + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDoc(Content annotationDocTree, + boolean isLastContent) { + return getMemberTree(annotationDocTree, isLastContent); + } + + /** + * Close the writer. + */ + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Annotation_Type_Required_Member_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Annotation_Type_Required_Member_Summary"), + configuration.getText("doclet.annotation_type_required_members")); + } + + /** + * {@inheritDoc} + */ + public Content getCaption() { + return configuration.getResource("doclet.Annotation_Type_Required_Members"); + } + + /** + * {@inheritDoc} + */ + public List getSummaryTableHeader(Element member) { + List header = Arrays.asList(writer.getModifierTypeHeader(), + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Annotation_Type_Required_Member"), + configuration.getText("doclet.Description"))); + return header; + } + + /** + * {@inheritDoc} + */ + public void addSummaryAnchor(TypeElement typeElement, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + SectionName.ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY)); + } + + /** + * {@inheritDoc} + */ + public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member, + Content tdSummary) { + Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink, + writer.getDocLink(context, member, name(member), false)); + Content code = HtmlTree.CODE(memberLink); + tdSummary.addContent(code); + } + + /** + * {@inheritDoc} + */ + protected void addInheritedSummaryLink(TypeElement typeElement, + Element member, Content linksTree) { + //Not applicable. + } + + /** + * {@inheritDoc} + */ + protected void addSummaryType(Element member, Content tdSummaryType) { + addModifierAndType(member, getType(member), tdSummaryType); + } + + /** + * {@inheritDoc} + */ + protected Content getDeprecatedLink(Element member) { + String name = utils.getFullyQualifiedName(member) + "." + member.getSimpleName(); + return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, name); + } + + /** + * {@inheritDoc} + */ + protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { + if (link) { + return writer.getHyperLink( + SectionName.ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY, + writer.getResource("doclet.navAnnotationTypeRequiredMember")); + } else { + return writer.getResource("doclet.navAnnotationTypeRequiredMember"); + } + } + + /** + * {@inheritDoc} + */ + protected void addNavDetailLink(boolean link, Content liNav) { + if (link) { + liNav.addContent(writer.getHyperLink( + SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL, + writer.getResource("doclet.navAnnotationTypeMember"))); + } else { + liNav.addContent(writer.getResource("doclet.navAnnotationTypeMember")); + } + } + + private TypeMirror getType(Element member) { + return utils.isExecutableElement(member) + ? utils.getReturnType((ExecutableElement) member) + : member.asType(); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java new file mode 100644 index 00000000000..3d6a248da57 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.IOException; +import java.util.List; + +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import com.sun.source.doctree.DocTree; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder; +import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap; + +/** + * Generate the Class Information Page. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @see java.util.Collections + * @see java.util.List + * @see java.util.ArrayList + * @see java.util.HashMap + * + * @author Atul M Dambalkar + * @author Robert Field + * @author Bhavesh Patel (Modified) + */ +public class AnnotationTypeWriterImpl extends SubWriterHolderWriter + implements AnnotationTypeWriter { + + protected TypeElement annotationType; + + protected TypeMirror prev; + + protected TypeMirror next; + + /** + * @param configuration the configuration + * @param annotationType the annotation type being documented. + * @param prevType the previous class that was documented. + * @param nextType the next class being documented. + * @throws java.lang.Exception + */ + public AnnotationTypeWriterImpl(ConfigurationImpl configuration, + TypeElement annotationType, TypeMirror prevType, TypeMirror nextType) + throws Exception { + super(configuration, DocPath.forClass(configuration.utils, annotationType)); + this.annotationType = annotationType; + configuration.currentTypeElement = annotationType; + this.prev = prevType; + this.next = nextType; + } + + /** + * Get this package link. + * + * @return a content tree for the package link + */ + @Override + protected Content getNavLinkPackage() { + Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY, + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get the class link. + * + * @return a content tree for the class link + */ + @Override + protected Content getNavLinkClass() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, classLabel); + return li; + } + + /** + * Get the class use link. + * + * @return a content tree for the class use link + */ + @Override + protected Content getNavLinkClassUse() { + Content linkContent = getHyperLink(DocPaths.CLASS_USE.resolve(filename), useLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get link to previous class. + * + * @return a content tree for the previous class link + */ + @Override + public Content getNavLinkPrevious() { + Content li; + if (prev != null) { + Content prevLink = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS, utils.asTypeElement(prev)) + .label(prevclassLabel).strong(true)); + li = HtmlTree.LI(prevLink); + } + else + li = HtmlTree.LI(prevclassLabel); + return li; + } + + /** + * Get link to next class. + * + * @return a content tree for the next class link + */ + @Override + public Content getNavLinkNext() { + Content li; + if (next != null) { + Content nextLink = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS, utils.asTypeElement(next)) + .label(nextclassLabel).strong(true)); + li = HtmlTree.LI(nextLink); + } + else + li = HtmlTree.LI(nextclassLabel); + return li; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getHeader(String header) { + HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getSimpleName(annotationType))); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.header); + PackageElement pkg = utils.containingPackage(annotationType); + if (!pkg.isUnnamed()) { + Content pkgNameContent = new StringContent(utils.getPackageName(pkg)); + Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, pkgNameContent); + div.addContent(pkgNameDiv); + } + LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_HEADER, annotationType); + Content headerContent = new StringContent(header); + Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, true, + HtmlStyle.title, headerContent); + heading.addContent(getTypeParameterLinks(linkInfo)); + div.addContent(heading); + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + } else { + bodyTree.addContent(div); + } + return bodyTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getAnnotationContentHeader() { + return getContentHeader(); + } + + /** + * {@inheritDoc} + */ + @Override + public void addFooter(Content contentTree) { + contentTree.addContent(HtmlConstants.END_OF_CLASS_DATA); + Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : contentTree; + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + contentTree.addContent(htmlTree); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void printDocument(Content contentTree) throws IOException { + printHtmlDocument(configuration.metakeywords.getMetaKeywords(annotationType), + true, contentTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getAnnotationInfoTreeHeader() { + return getMemberTreeHeader(); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getAnnotationInfo(Content annotationInfoTree) { + return getMemberTree(HtmlStyle.description, annotationInfoTree); + } + + /** + * {@inheritDoc} + */ + @Override + public void addAnnotationTypeSignature(String modifiers, Content annotationInfoTree) { + annotationInfoTree.addContent(new HtmlTree(HtmlTag.BR)); + Content pre = new HtmlTree(HtmlTag.PRE); + addAnnotationInfo(annotationType, pre); + pre.addContent(modifiers); + LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_SIGNATURE, annotationType); + Content annotationName = new StringContent(utils.getSimpleName(annotationType)); + Content parameterLinks = getTypeParameterLinks(linkInfo); + if (configuration.linksource) { + addSrcLink(annotationType, annotationName, pre); + pre.addContent(parameterLinks); + } else { + Content span = HtmlTree.SPAN(HtmlStyle.memberNameLabel, annotationName); + span.addContent(parameterLinks); + pre.addContent(span); + } + annotationInfoTree.addContent(pre); + } + + /** + * {@inheritDoc} + */ + @Override + public void addAnnotationTypeDescription(Content annotationInfoTree) { + if(!configuration.nocomment) { + if (!utils.getBody(annotationType).isEmpty()) { + addInlineComment(annotationType, annotationInfoTree); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addAnnotationTypeTagInfo(Content annotationInfoTree) { + if(!configuration.nocomment) { + addTagsInfo(annotationType, annotationInfoTree); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addAnnotationTypeDeprecationInfo(Content annotationInfoTree) { + Content hr = new HtmlTree(HtmlTag.HR); + annotationInfoTree.addContent(hr); + List deprs = utils.getBlockTags(annotationType, DocTree.Kind.DEPRECATED); + if (utils.isDeprecated(annotationType)) { + CommentHelper ch = utils.getCommentHelper(annotationType); + Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase); + Content div = HtmlTree.DIV(HtmlStyle.block, deprLabel); + if (!deprs.isEmpty()) { + + List commentTags = ch.getDescription(configuration, deprs.get(0)); + if (!commentTags.isEmpty()) { + div.addContent(getSpace()); + addInlineDeprecatedComment(annotationType, deprs.get(0), div); + } + } + annotationInfoTree.addContent(div); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getNavLinkTree() { + Content treeLinkContent = getHyperLink(DocPaths.PACKAGE_TREE, + treeLabel, "", ""); + Content li = HtmlTree.LI(treeLinkContent); + return li; + } + + /** + * Add summary details to the navigation bar. + * + * @param subDiv the content tree to which the summary detail links will be added + */ + @Override + protected void addSummaryDetailLinks(Content subDiv) { + try { + Content div = HtmlTree.DIV(getNavSummaryLinks()); + div.addContent(getNavDetailLinks()); + subDiv.addContent(div); + } catch (Exception e) { + throw new DocletAbortException(e); + } + } + + /** + * Get summary links for navigation bar. + * + * @return the content tree for the navigation summary links + * @throws java.lang.Exception + */ + protected Content getNavSummaryLinks() throws Exception { + Content li = HtmlTree.LI(summaryLabel); + li.addContent(getSpace()); + Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); + MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) + configuration.getBuilderFactory().getMemberSummaryBuilder(this); + Content liNavField = new HtmlTree(HtmlTag.LI); + addNavSummaryLink(memberSummaryBuilder, + "doclet.navField", + VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS, liNavField); + addNavGap(liNavField); + ulNav.addContent(liNavField); + Content liNavReq = new HtmlTree(HtmlTag.LI); + addNavSummaryLink(memberSummaryBuilder, + "doclet.navAnnotationTypeRequiredMember", + VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED, liNavReq); + addNavGap(liNavReq); + ulNav.addContent(liNavReq); + Content liNavOpt = new HtmlTree(HtmlTag.LI); + addNavSummaryLink(memberSummaryBuilder, + "doclet.navAnnotationTypeOptionalMember", + VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL, liNavOpt); + ulNav.addContent(liNavOpt); + return ulNav; + } + + /** + * Add the navigation summary link. + * + * @param builder builder for the member to be documented + * @param label the label for the navigation + * @param type type to be documented + * @param liNav the content tree to which the navigation summary link will be added + */ + protected void addNavSummaryLink(MemberSummaryBuilder builder, + String label, VisibleMemberMap.Kind type, Content liNav) { + AbstractMemberWriter writer = ((AbstractMemberWriter) builder. + getMemberSummaryWriter(type)); + if (writer == null) { + liNav.addContent(getResource(label)); + } else { + liNav.addContent(writer.getNavSummaryLink(null, + ! builder.getVisibleMemberMap(type).noVisibleMembers())); + } + } + + /** + * Get detail links for the navigation bar. + * + * @return the content tree for the detail links + * @throws java.lang.Exception + */ + protected Content getNavDetailLinks() throws Exception { + Content li = HtmlTree.LI(detailLabel); + li.addContent(getSpace()); + Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); + MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) + configuration.getBuilderFactory().getMemberSummaryBuilder(this); + AbstractMemberWriter writerField = + ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS)); + AbstractMemberWriter writerOptional = + ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL)); + AbstractMemberWriter writerRequired = + ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED)); + Content liNavField = new HtmlTree(HtmlTag.LI); + if (writerField != null) { + writerField.addNavDetailLink(!utils.getAnnotationFields(annotationType).isEmpty(), liNavField); + } else { + liNavField.addContent(getResource("doclet.navField")); + } + addNavGap(liNavField); + ulNav.addContent(liNavField); + if (writerOptional != null){ + Content liNavOpt = new HtmlTree(HtmlTag.LI); + writerOptional.addNavDetailLink(!annotationType.getAnnotationMirrors().isEmpty(), liNavOpt); + ulNav.addContent(liNavOpt); + } else if (writerRequired != null){ + Content liNavReq = new HtmlTree(HtmlTag.LI); + writerRequired.addNavDetailLink(!annotationType.getAnnotationMirrors().isEmpty(), liNavReq); + ulNav.addContent(liNavReq); + } else { + Content liNav = HtmlTree.LI(getResource("doclet.navAnnotationTypeMember")); + ulNav.addContent(liNav); + } + return ulNav; + } + + /** + * Add gap between navigation bar elements. + * + * @param liNav the content tree to which the gap will be added + */ + protected void addNavGap(Content liNav) { + liNav.addContent(getSpace()); + liNav.addContent("|"); + liNav.addContent(getSpace()); + } + + /** + * {@inheritDoc} + */ + @Override + public TypeElement getAnnotationTypeElement() { + return annotationType; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java new file mode 100644 index 00000000000..9e3834dffba --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java @@ -0,0 +1,554 @@ +/* + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; + +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; +import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + +/** + * Generate class usage information. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert G. Field + * @author Bhavesh Patel (Modified) + */ +public class ClassUseWriter extends SubWriterHolderWriter { + + final TypeElement typeElement; + Set pkgToPackageAnnotations = null; + final Map> pkgToClassTypeParameter; + final Map> pkgToClassAnnotations; + final Map> pkgToMethodTypeParameter; + final Map> pkgToMethodArgTypeParameter; + final Map> pkgToMethodReturnTypeParameter; + final Map> pkgToMethodAnnotations; + final Map> pkgToMethodParameterAnnotations; + final Map> pkgToFieldTypeParameter; + final Map> pkgToFieldAnnotations; + final Map> pkgToSubclass; + final Map> pkgToSubinterface; + final Map> pkgToImplementingClass; + final Map> pkgToField; + final Map> pkgToMethodReturn; + final Map> pkgToMethodArgs; + final Map> pkgToMethodThrows; + final Map> pkgToConstructorAnnotations; + final Map> pkgToConstructorParameterAnnotations; + final Map> pkgToConstructorArgs; + final Map> pkgToConstructorArgTypeParameter; + final Map> pkgToConstructorThrows; + final SortedSet pkgSet; + final MethodWriterImpl methodSubWriter; + final ConstructorWriterImpl constrSubWriter; + final FieldWriterImpl fieldSubWriter; + final NestedClassWriterImpl classSubWriter; + // Summary for various use tables. + final String classUseTableSummary; + final String subclassUseTableSummary; + final String subinterfaceUseTableSummary; + final String fieldUseTableSummary; + final String methodUseTableSummary; + final String constructorUseTableSummary; + + /** + * The HTML tree for main tag. + */ + protected HtmlTree mainTree = HtmlTree.MAIN(); + + /** + * Constructor. + * + * @param filename the file to be generated. + * @throws IOException + * @throws DocletAbortException + */ + public ClassUseWriter(ConfigurationImpl configuration, + ClassUseMapper mapper, DocPath filename, + TypeElement typeElement) throws IOException { + super(configuration, filename); + this.typeElement = typeElement; + if (mapper.classToPackageAnnotations.containsKey(typeElement)) { + pkgToPackageAnnotations = new TreeSet<>(utils.makeClassUseComparator()); + pkgToPackageAnnotations.addAll(mapper.classToPackageAnnotations.get(typeElement)); + } + configuration.currentTypeElement = typeElement; + this.pkgSet = new TreeSet<>(utils.makePackageComparator()); + this.pkgToClassTypeParameter = pkgDivide(mapper.classToClassTypeParam); + this.pkgToClassAnnotations = pkgDivide(mapper.classToClassAnnotations); + this.pkgToMethodTypeParameter = pkgDivide(mapper.classToMethodTypeParam); + this.pkgToMethodArgTypeParameter = pkgDivide(mapper.classToMethodArgTypeParam); + this.pkgToFieldTypeParameter = pkgDivide(mapper.classToFieldTypeParam); + this.pkgToFieldAnnotations = pkgDivide(mapper.annotationToField); + this.pkgToMethodReturnTypeParameter = pkgDivide(mapper.classToMethodReturnTypeParam); + this.pkgToMethodAnnotations = pkgDivide(mapper.classToMethodAnnotations); + this.pkgToMethodParameterAnnotations = pkgDivide(mapper.classToMethodParamAnnotation); + this.pkgToSubclass = pkgDivide(mapper.classToSubclass); + this.pkgToSubinterface = pkgDivide(mapper.classToSubinterface); + this.pkgToImplementingClass = pkgDivide(mapper.classToImplementingClass); + this.pkgToField = pkgDivide(mapper.classToField); + this.pkgToMethodReturn = pkgDivide(mapper.classToMethodReturn); + this.pkgToMethodArgs = pkgDivide(mapper.classToMethodArgs); + this.pkgToMethodThrows = pkgDivide(mapper.classToMethodThrows); + this.pkgToConstructorAnnotations = pkgDivide(mapper.classToConstructorAnnotations); + this.pkgToConstructorParameterAnnotations = pkgDivide(mapper.classToConstructorParamAnnotation); + this.pkgToConstructorArgs = pkgDivide(mapper.classToConstructorArgs); + this.pkgToConstructorArgTypeParameter = pkgDivide(mapper.classToConstructorArgTypeParam); + this.pkgToConstructorThrows = pkgDivide(mapper.classToConstructorThrows); + //tmp test + if (pkgSet.size() > 0 && + mapper.classToPackage.containsKey(this.typeElement) && + !pkgSet.equals(mapper.classToPackage.get(this.typeElement))) { + configuration.reporter.print(Diagnostic.Kind.WARNING, + "Internal error: package sets don't match: " + + pkgSet + " with: " + mapper.classToPackage.get(this.typeElement)); + } + methodSubWriter = new MethodWriterImpl(this); + constrSubWriter = new ConstructorWriterImpl(this); + fieldSubWriter = new FieldWriterImpl(this); + classSubWriter = new NestedClassWriterImpl(this); + classUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.classes")); + subclassUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.subclasses")); + subinterfaceUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.subinterfaces")); + fieldUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.fields")); + methodUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.methods")); + constructorUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.constructors")); + } + + /** + * Write out class use pages. + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration, ClassTree classtree) { + ClassUseMapper mapper = new ClassUseMapper(configuration, classtree); + for (TypeElement aClass : configuration.root.getIncludedClasses()) { + // If -nodeprecated option is set and the containing package is marked + // as deprecated, do not generate the class-use page. We will still generate + // the class-use page if the class is marked as deprecated but the containing + // package is not since it could still be linked from that package-use page. + if (!(configuration.nodeprecated && + configuration.utils.isDeprecated(configuration.utils.containingPackage(aClass)))) + ClassUseWriter.generate(configuration, mapper, aClass); + } + for (PackageElement pkg : configuration.packages) { + // If -nodeprecated option is set and the package is marked + // as deprecated, do not generate the package-use page. + if (!(configuration.nodeprecated && configuration.utils.isDeprecated(pkg))) + PackageUseWriter.generate(configuration, mapper, pkg); + } + } + + private Map> pkgDivide(Map> classMap) { + Map> map = new HashMap<>(); + List elements = (List) classMap.get(typeElement); + if (elements != null) { + Collections.sort(elements, utils.makeClassUseComparator()); + for (Element e : elements) { + PackageElement pkg = utils.containingPackage(e); + pkgSet.add(pkg); + List inPkg = map.get(pkg); + if (inPkg == null) { + inPkg = new ArrayList<>(); + map.put(pkg, inPkg); + } + inPkg.add(e); + } + } + return map; + } + + /** + * Generate a class page. + */ + public static void generate(ConfigurationImpl configuration, ClassUseMapper mapper, + TypeElement typeElement) { + ClassUseWriter clsgen; + DocPath path = DocPath.forPackage(configuration.utils, typeElement) + .resolve(DocPaths.CLASS_USE) + .resolve(DocPath.forName(configuration.utils, typeElement)); + try { + clsgen = new ClassUseWriter(configuration, mapper, path, typeElement); + clsgen.generateClassUseFile(); + clsgen.close(); + } catch (IOException exc) { + configuration.standardmessage. + error("doclet.exception_encountered", + exc.toString(), path.getPath()); + throw new DocletAbortException(exc); + } + } + + /** + * Generate the class use elements. + */ + protected void generateClassUseFile() throws IOException { + HtmlTree body = getClassUseHeader(); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.classUseContainer); + if (pkgSet.size() > 0) { + addClassUse(div); + } else { + div.addContent(getResource("doclet.ClassUse_No.usage.of.0", + utils.getFullyQualifiedName(typeElement))); + } + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + body.addContent(mainTree); + } else { + body.addContent(div); + } + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : body; + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(htmlTree); + } + printHtmlDocument(null, true, body); + } + + /** + * Add the class use documentation. + * + * @param contentTree the content tree to which the class use information will be added + */ + protected void addClassUse(Content contentTree) throws IOException { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + if (configuration.packages.size() > 1) { + addPackageList(ul); + addPackageAnnotationList(ul); + } + addClassList(ul); + contentTree.addContent(ul); + } + + /** + * Add the packages elements that use the given class. + * + * @param contentTree the content tree to which the packages elements will be added + */ + protected void addPackageList(Content contentTree) throws IOException { + Content caption = getTableCaption(configuration.getResource( + "doclet.ClassUse_Packages.that.use.0", + getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)))); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) + : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (PackageElement pkg : pkgSet) { + HtmlTree tr = new HtmlTree(HtmlTag.TR); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + addPackageUse(pkg, tr); + tbody.addContent(tr); + } + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + contentTree.addContent(li); + } + + /** + * Add the package annotation elements. + * + * @param contentTree the content tree to which the package annotation elements will be added + */ + protected void addPackageAnnotationList(Content contentTree) throws IOException { + if (!utils.isAnnotationType(typeElement) || + pkgToPackageAnnotations == null || + pkgToPackageAnnotations.isEmpty()) { + return; + } + Content caption = getTableCaption(configuration.getResource( + "doclet.ClassUse_PackageAnnotation", + getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)))); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) + : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (PackageElement pkg : pkgToPackageAnnotations) { + HtmlTree tr = new HtmlTree(HtmlTag.TR); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, getPackageLink(pkg)); + tr.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); + addSummaryComment(pkg, tdLast); + tr.addContent(tdLast); + tbody.addContent(tr); + } + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + contentTree.addContent(li); + } + + /** + * Add the class elements that use the given class. + * + * @param contentTree the content tree to which the class elements will be added + */ + protected void addClassList(Content contentTree) throws IOException { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + for (PackageElement pkg : pkgSet) { + Content markerAnchor = getMarkerAnchor(getPackageAnchorName(pkg)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(markerAnchor) + : HtmlTree.LI(HtmlStyle.blockList, markerAnchor); + Content link = getResource("doclet.ClassUse_Uses.of.0.in.1", + getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, + typeElement)), + getPackageLink(pkg, utils.getPackageName(pkg))); + Content heading = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, link); + htmlTree.addContent(heading); + addClassUse(pkg, htmlTree); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + } + Content li = HtmlTree.LI(HtmlStyle.blockList, ul); + contentTree.addContent(li); + } + + /** + * Add the package use information. + * + * @param pkg the package that uses the given class + * @param contentTree the content tree to which the package use information will be added + */ + protected void addPackageUse(PackageElement pkg, Content contentTree) throws IOException { + Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, + getHyperLink(getPackageAnchorName(pkg), new StringContent(utils.getPackageName(pkg)))); + contentTree.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); + addSummaryComment(pkg, tdLast); + contentTree.addContent(tdLast); + } + + /** + * Add the class use information. + * + * @param pkg the package that uses the given class + * @param contentTree the content tree to which the class use information will be added + */ + protected void addClassUse(PackageElement pkg, Content contentTree) throws IOException { + Content classLink = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)); + Content pkgLink = getPackageLink(pkg, utils.getPackageName(pkg)); + classSubWriter.addUseInfo(pkgToClassAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_Annotation", classLink, + pkgLink), classUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToClassTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_TypeParameter", classLink, + pkgLink), classUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToSubclass.get(pkg), + configuration.getResource("doclet.ClassUse_Subclass", classLink, + pkgLink), subclassUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToSubinterface.get(pkg), + configuration.getResource("doclet.ClassUse_Subinterface", classLink, + pkgLink), subinterfaceUseTableSummary, contentTree); + classSubWriter.addUseInfo(pkgToImplementingClass.get(pkg), + configuration.getResource("doclet.ClassUse_ImplementingClass", classLink, + pkgLink), classUseTableSummary, contentTree); + fieldSubWriter.addUseInfo(pkgToField.get(pkg), + configuration.getResource("doclet.ClassUse_Field", classLink, + pkgLink), fieldUseTableSummary, contentTree); + fieldSubWriter.addUseInfo(pkgToFieldAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_FieldAnnotations", classLink, + pkgLink), fieldUseTableSummary, contentTree); + fieldSubWriter.addUseInfo(pkgToFieldTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_FieldTypeParameter", classLink, + pkgLink), fieldUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_MethodAnnotations", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodParameterAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_MethodParameterAnnotations", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_MethodTypeParameter", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodReturn.get(pkg), + configuration.getResource("doclet.ClassUse_MethodReturn", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodReturnTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_MethodReturnTypeParameter", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodArgs.get(pkg), + configuration.getResource("doclet.ClassUse_MethodArgs", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodArgTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_MethodArgsTypeParameters", classLink, + pkgLink), methodUseTableSummary, contentTree); + methodSubWriter.addUseInfo(pkgToMethodThrows.get(pkg), + configuration.getResource("doclet.ClassUse_MethodThrows", classLink, + pkgLink), methodUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorAnnotations", classLink, + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorParameterAnnotations.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorParameterAnnotations", classLink, + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorArgs.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorArgs", classLink, + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorArgTypeParameter.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorArgsTypeParameters", classLink, + pkgLink), constructorUseTableSummary, contentTree); + constrSubWriter.addUseInfo(pkgToConstructorThrows.get(pkg), + configuration.getResource("doclet.ClassUse_ConstructorThrows", classLink, + pkgLink), constructorUseTableSummary, contentTree); + } + + /** + * Get the header for the class use Listing. + * + * @return a content tree representing the class use header + */ + protected HtmlTree getClassUseHeader() { + String cltype = configuration.getText(utils.isInterface(typeElement) + ? "doclet.Interface" + : "doclet.Class"); + String clname = utils.getFullyQualifiedName(typeElement); + String title = configuration.getText("doclet.Window_ClassUse_Header", + cltype, clname); + HtmlTree bodyTree = getBody(true, getWindowTitle(title)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + ContentBuilder headContent = new ContentBuilder(); + headContent.addContent(getResource("doclet.ClassUse_Title", cltype)); + headContent.addContent(new HtmlTree(HtmlTag.BR)); + headContent.addContent(clname); + Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, + true, HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + } else { + bodyTree.addContent(div); + } + return bodyTree; + } + + /** + * Get this package link. + * + * @return a content tree for the package link + */ + protected Content getNavLinkPackage() { + Content linkContent = + getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get class page link. + * + * @return a content tree for the class page link + */ + protected Content getNavLinkClass() { + Content linkContent = getLink(new LinkInfoImpl( + configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement) + .label(configuration.getText("doclet.Class"))); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get the use link. + * + * @return a content tree for the use link + */ + protected Content getNavLinkClassUse() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, useLabel); + return li; + } + + /** + * Get the tree link. + * + * @return a content tree for the tree link + */ + protected Content getNavLinkTree() { + Content linkContent = utils.isEnclosingPackageIncluded(typeElement) + ? getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), treeLabel) + : getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), treeLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java new file mode 100644 index 00000000000..37bc63c57e6 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java @@ -0,0 +1,759 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.IOException; +import java.util.*; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.SimpleElementVisitor8; + +import com.sun.source.doctree.DocTree; +import com.sun.tools.javac.util.DefinedBy; +import com.sun.tools.javac.util.DefinedBy.Api; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.ClassWriter; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder; +import jdk.javadoc.internal.doclets.toolkit.taglets.ParamTaglet; +import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; +import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; +import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap; +import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind; + +/** + * Generate the Class Information Page. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @see javax.lang.model.element.TypeElement + * @see java.util.Collections + * @see java.util.List + * @see java.util.ArrayList + * @see java.util.HashMap + * + * @author Atul M Dambalkar + * @author Robert Field + * @author Bhavesh Patel (Modified) + */ +public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWriter { + + protected final TypeElement typeElement; + + protected final ClassTree classtree; + + protected final TypeElement prev; + + protected final TypeElement next; + + /** + * @param configuration the configuration data for the doclet + * @param typeElement the class being documented. + * @param prevClass the previous class that was documented. + * @param nextClass the next class being documented. + * @param classTree the class tree for the given class. + * @throws java.io.IOException + */ + public ClassWriterImpl(ConfigurationImpl configuration, TypeElement typeElement, + TypeElement prevClass, TypeElement nextClass, ClassTree classTree) + throws IOException { + super(configuration, DocPath.forClass(configuration.utils, typeElement)); + this.typeElement = typeElement; + configuration.currentTypeElement = typeElement; + this.classtree = classTree; + this.prev = prevClass; + this.next = nextClass; + } + + /** + * Get this package link. + * + * @return a content tree for the package link + */ + @Override + protected Content getNavLinkPackage() { + Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY, + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get the class link. + * + * @return a content tree for the class link + */ + @Override + protected Content getNavLinkClass() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, classLabel); + return li; + } + + /** + * Get the class use link. + * + * @return a content tree for the class use link + */ + @Override + protected Content getNavLinkClassUse() { + Content linkContent = getHyperLink(DocPaths.CLASS_USE.resolve(filename), useLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get link to previous class. + * + * @return a content tree for the previous class link + */ + @Override + public Content getNavLinkPrevious() { + Content li; + if (prev != null) { + Content prevLink = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS, prev) + .label(prevclassLabel).strong(true)); + li = HtmlTree.LI(prevLink); + } + else + li = HtmlTree.LI(prevclassLabel); + return li; + } + + /** + * Get link to next class. + * + * @return a content tree for the next class link + */ + @Override + public Content getNavLinkNext() { + Content li; + if (next != null) { + Content nextLink = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS, next) + .label(nextclassLabel).strong(true)); + li = HtmlTree.LI(nextLink); + } + else + li = HtmlTree.LI(nextclassLabel); + return li; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getHeader(String header) { + HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getSimpleName(typeElement))); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.header); + PackageElement pkg = utils.containingPackage(typeElement); + if (!pkg.isUnnamed()) { + Content pkgNameContent = new StringContent(utils.getPackageName(pkg)); + Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, pkgNameContent); + div.addContent(pkgNameDiv); + } + LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_HEADER, typeElement); + //Let's not link to ourselves in the header. + linkInfo.linkToSelf = false; + Content headerContent = new StringContent(header); + Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING, true, + HtmlStyle.title, headerContent); + heading.addContent(getTypeParameterLinks(linkInfo)); + div.addContent(heading); + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + } else { + bodyTree.addContent(div); + } + return bodyTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getClassContentHeader() { + return getContentHeader(); + } + + /** + * {@inheritDoc} + */ + @Override + public void addFooter(Content contentTree) { + contentTree.addContent(HtmlConstants.END_OF_CLASS_DATA); + Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : contentTree; + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + contentTree.addContent(htmlTree); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void printDocument(Content contentTree) throws IOException { + printHtmlDocument(configuration.metakeywords.getMetaKeywords(typeElement), + true, contentTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getClassInfoTreeHeader() { + return getMemberTreeHeader(); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getClassInfo(Content classInfoTree) { + return getMemberTree(HtmlStyle.description, classInfoTree); + } + + /** + * {@inheritDoc} + */ + @Override + public void addClassSignature(String modifiers, Content classInfoTree) { + classInfoTree.addContent(new HtmlTree(HtmlTag.BR)); + Content pre = new HtmlTree(HtmlTag.PRE); + addAnnotationInfo(typeElement, pre); + pre.addContent(modifiers); + LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_SIGNATURE, typeElement); + //Let's not link to ourselves in the signature. + linkInfo.linkToSelf = false; + Content className = new StringContent(utils.getSimpleName(typeElement)); + Content parameterLinks = getTypeParameterLinks(linkInfo); + if (configuration.linksource) { + addSrcLink(typeElement, className, pre); + pre.addContent(parameterLinks); + } else { + Content span = HtmlTree.SPAN(HtmlStyle.typeNameLabel, className); + span.addContent(parameterLinks); + pre.addContent(span); + } + if (!utils.isInterface(typeElement)) { + TypeMirror superclass = utils.getFirstVisibleSuperClass(typeElement); + if (superclass != null) { + pre.addContent(DocletConstants.NL); + pre.addContent("extends "); + Content link = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME, + superclass)); + pre.addContent(link); + } + } + List interfaces = typeElement.getInterfaces(); + if (!interfaces.isEmpty()) { + boolean isFirst = true; + for (TypeMirror type : interfaces) { + TypeElement tDoc = utils.asTypeElement(type); + if (!(utils.isPublic(tDoc) || utils.isLinkable(tDoc))) { + continue; + } + if (isFirst) { + pre.addContent(DocletConstants.NL); + pre.addContent(utils.isInterface(typeElement) ? "extends " : "implements "); + isFirst = false; + } else { + pre.addContent(", "); + } + Content link = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME, + type)); + pre.addContent(link); + } + } + classInfoTree.addContent(pre); + } + + /** + * {@inheritDoc} + */ + @Override + public void addClassDescription(Content classInfoTree) { + if(!configuration.nocomment) { + // generate documentation for the class. + if (!utils.getBody(typeElement).isEmpty()) { + addInlineComment(typeElement, classInfoTree); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addClassTagInfo(Content classInfoTree) { + if(!configuration.nocomment) { + // Print Information about all the tags here + addTagsInfo(typeElement, classInfoTree); + } + } + + /** + * Get the class hierarchy tree for the given class. + * + * @param type the class to print the hierarchy for + * @return a content tree for class inheritence + */ + private Content getClassInheritenceTree(TypeMirror type) { + TypeMirror sup; + HtmlTree classTreeUl = new HtmlTree(HtmlTag.UL); + classTreeUl.addStyle(HtmlStyle.inheritance); + Content liTree = null; + do { + sup = utils.getFirstVisibleSuperClass(type); + if (sup != null) { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.inheritance); + ul.addContent(getTreeForClassHelper(type)); + if (liTree != null) + ul.addContent(liTree); + Content li = HtmlTree.LI(ul); + liTree = li; + type = sup; + } else + classTreeUl.addContent(getTreeForClassHelper(type)); + } while (sup != null); + if (liTree != null) + classTreeUl.addContent(liTree); + return classTreeUl; + } + + /** + * Get the class helper tree for the given class. + * + * @param type the class to print the helper for + * @return a content tree for class helper + */ + private Content getTreeForClassHelper(TypeMirror type) { + Content li = new HtmlTree(HtmlTag.LI); + if (type.equals(typeElement.asType())) { + Content typeParameters = getTypeParameterLinks( + new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE, + typeElement)); + if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) { + li.addContent(utils.asTypeElement(type).getSimpleName().toString()); + li.addContent(typeParameters); + } else { + li.addContent(utils.asTypeElement(type).getQualifiedName().toString()); + li.addContent(typeParameters); + } + } else { + Content link = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS_TREE_PARENT, type) + .label(configuration.getClassName(utils.asTypeElement(type)))); + li.addContent(link); + } + return li; + } + + /** + * {@inheritDoc} + */ + @Override + public void addClassTree(Content classContentTree) { + if (!utils.isClass(typeElement)) { + return; + } + classContentTree.addContent(getClassInheritenceTree(typeElement.asType())); + } + + /** + * {@inheritDoc} + */ + @Override + public void addTypeParamInfo(Content classInfoTree) { + if (!utils.getTypeParamTrees(typeElement).isEmpty()) { + Content typeParam = (new ParamTaglet()).getTagletOutput(typeElement, + getTagletWriterInstance(false)); + Content dl = HtmlTree.DL(typeParam); + classInfoTree.addContent(dl); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addSubClassInfo(Content classInfoTree) { + if (utils.isClass(typeElement)) { + if (typeElement.getQualifiedName().toString().equals("java.lang.Object") || + typeElement.getQualifiedName().toString().equals("org.omg.CORBA.Object")) { + return; // Don't generate the list, too huge + } + Set subclasses = classtree.directSubClasses(typeElement, false); + if (!subclasses.isEmpty()) { + Content label = getResource( + "doclet.Subclasses"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUBCLASSES, + subclasses)); + classInfoTree.addContent(dl); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addSubInterfacesInfo(Content classInfoTree) { + if (utils.isInterface(typeElement)) { + Set subInterfaces = classtree.allSubClasses(typeElement, false); + if (!subInterfaces.isEmpty()) { + Content label = getResource( + "doclet.Subinterfaces"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUBINTERFACES, + subInterfaces)); + classInfoTree.addContent(dl); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addInterfaceUsageInfo (Content classInfoTree) { + if (!utils.isInterface(typeElement)) { + return; + } + if (typeElement.getQualifiedName().toString().equals("java.lang.Cloneable") || + typeElement.getQualifiedName().toString().equals("java.io.Serializable")) { + return; // Don't generate the list, too big + } + Set implcl = classtree.implementingClasses(typeElement); + if (!implcl.isEmpty()) { + Content label = getResource( + "doclet.Implementing_Classes"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_CLASSES, + implcl)); + classInfoTree.addContent(dl); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addImplementedInterfacesInfo(Content classInfoTree) { + SortedSet interfaces = new TreeSet<>(utils.makeTypeMirrorClassUseComparator()); + interfaces.addAll(utils.getAllInterfaces(typeElement)); + if (utils.isClass(typeElement) && !interfaces.isEmpty()) { + Content label = getResource( + "doclet.All_Implemented_Interfaces"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_INTERFACES, interfaces)); + classInfoTree.addContent(dl); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addSuperInterfacesInfo(Content classInfoTree) { + SortedSet interfaces = + new TreeSet<>(utils.makeTypeMirrorIndexUseComparator()); + interfaces.addAll(utils.getAllInterfaces(typeElement)); + + if (utils.isInterface(typeElement) && !interfaces.isEmpty()) { + Content label = getResource("doclet.All_Superinterfaces"); + Content dt = HtmlTree.DT(label); + Content dl = HtmlTree.DL(dt); + dl.addContent(getClassLinks(LinkInfoImpl.Kind.SUPER_INTERFACES, interfaces)); + classInfoTree.addContent(dl); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addNestedClassInfo(final Content classInfoTree) { + Element outerClass = typeElement.getEnclosingElement(); + if (outerClass == null) + return; + new SimpleElementVisitor8() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitType(TypeElement e, Void p) { + String label = utils.isInterface(e) + ? "doclet.Enclosing_Interface" + : "doclet.Enclosing_Class"; + Content dt = HtmlTree.DT(getResource(label)); + Content dl = HtmlTree.DL(dt); + Content dd = new HtmlTree(HtmlTag.DD); + dd.addContent(getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CLASS, e))); + dl.addContent(dd); + classInfoTree.addContent(dl); + return null; + } + }.visit(outerClass); + } + + /** + * {@inheritDoc} + */ + @Override + public void addFunctionalInterfaceInfo (Content classInfoTree) { + if (isFunctionalInterface()) { + Content dt = HtmlTree.DT(getResource("doclet.Functional_Interface")); + Content dl = HtmlTree.DL(dt); + Content dd = new HtmlTree(HtmlTag.DD); + dd.addContent(getResource("doclet.Functional_Interface_Message")); + dl.addContent(dd); + classInfoTree.addContent(dl); + } + } + + public boolean isFunctionalInterface() { + List annotationMirrors = ((Element) typeElement).getAnnotationMirrors(); + for (AnnotationMirror anno : annotationMirrors) { + if (utils.isFunctionalInterface(anno)) { + return true; + } + } + return false; + } + + + /** + * {@inheritDoc} + */ + @Override + public void addClassDeprecationInfo(Content classInfoTree) { + Content hr = new HtmlTree(HtmlTag.HR); + classInfoTree.addContent(hr); + List deprs = utils.getBlockTags(typeElement, DocTree.Kind.DEPRECATED); + if (utils.isDeprecated(typeElement)) { + Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase); + Content div = HtmlTree.DIV(HtmlStyle.block, deprLabel); + if (!deprs.isEmpty()) { + CommentHelper ch = utils.getCommentHelper(typeElement); + DocTree dt = deprs.get(0); + List commentTags = ch.getBody(configuration, dt); + if (!commentTags.isEmpty()) { + div.addContent(getSpace()); + addInlineDeprecatedComment(typeElement, deprs.get(0), div); + } + } + classInfoTree.addContent(div); + } + } + + /** + * Get links to the given classes. + * + * @param context the id of the context where the link will be printed + * @param list the list of classes + * @return a content tree for the class list + */ + private Content getClassLinks(LinkInfoImpl.Kind context, Collection list) { + Content dd = new HtmlTree(HtmlTag.DD); + boolean isFirst = true; + for (Object type : list) { + if (!isFirst) { + Content separator = new StringContent(", "); + dd.addContent(separator); + } else { + isFirst = false; + } + // TODO: should we simply split this method up to avoid instanceof ? + if (type instanceof TypeElement) { + Content link = getLink( + new LinkInfoImpl(configuration, context, (TypeElement)(type))); + dd.addContent(link); + } else { + Content link = getLink( + new LinkInfoImpl(configuration, context, ((TypeMirror)type))); + dd.addContent(link); + } + } + return dd; + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getNavLinkTree() { + Content treeLinkContent = getHyperLink(DocPaths.PACKAGE_TREE, + treeLabel, "", ""); + Content li = HtmlTree.LI(treeLinkContent); + return li; + } + + /** + * Add summary details to the navigation bar. + * + * @param subDiv the content tree to which the summary detail links will be added + */ + protected void addSummaryDetailLinks(Content subDiv) { + try { + Content div = HtmlTree.DIV(getNavSummaryLinks()); + div.addContent(getNavDetailLinks()); + subDiv.addContent(div); + } catch (Exception e) { + throw new DocletAbortException(e); + } + } + + /** + * Get summary links for navigation bar. + * + * @return the content tree for the navigation summary links + */ + protected Content getNavSummaryLinks() throws Exception { + Content li = HtmlTree.LI(summaryLabel); + li.addContent(getSpace()); + Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); + MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) + configuration.getBuilderFactory().getMemberSummaryBuilder(this); + for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.summarySet) { + Content liNav = new HtmlTree(HtmlTag.LI); + if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !utils.isEnum(typeElement)) { + continue; + } + if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && utils.isEnum(typeElement)) { + continue; + } + AbstractMemberWriter writer = + ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind)); + if (writer == null) { + liNav.addContent(getResource(VisibleMemberMap.Kind.getNavLinkLabels(kind))); + } else { + writer.addNavSummaryLink( + memberSummaryBuilder.members(kind), + memberSummaryBuilder.getVisibleMemberMap(kind), liNav); + } + if (kind != Kind.METHODS) { + addNavGap(liNav); + } + ulNav.addContent(liNav); + } + return ulNav; + } + + /** + * Get detail links for the navigation bar. + * + * @return the content tree for the detail links + * @throws java.lang.Exception + */ + protected Content getNavDetailLinks() throws Exception { + Content li = HtmlTree.LI(detailLabel); + li.addContent(getSpace()); + Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); + MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) + configuration.getBuilderFactory().getMemberSummaryBuilder(this); + for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.detailSet) { + Content liNav = new HtmlTree(HtmlTag.LI); + AbstractMemberWriter writer = + ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(kind)); + if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !utils.isEnum(typeElement)) { + continue; + } + if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && utils.isEnum(typeElement)) { + continue; + } + if (writer == null) { + liNav.addContent(getResource(VisibleMemberMap.Kind.getNavLinkLabels(kind))); + } else { + writer.addNavDetailLink(memberSummaryBuilder.members(kind), liNav); + } + if (kind != Kind.METHODS) { + addNavGap(liNav); + } + ulNav.addContent(liNav); + } + return ulNav; + } + + /** + * Add gap between navigation bar elements. + * + * @param liNav the content tree to which the gap will be added + */ + protected void addNavGap(Content liNav) { + liNav.addContent(getSpace()); + liNav.addContent("|"); + liNav.addContent(getSpace()); + } + + /** + * Return the TypeElement being documented. + * + * @return the TypeElement being documented. + */ + @Override + public TypeElement getTypeElement() { + return typeElement; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java new file mode 100644 index 00000000000..0b7aa5ec023 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java @@ -0,0 +1,747 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.net.*; +import java.util.*; + +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.util.DocTreePath; +import com.sun.tools.doclint.DocLint; + +import jdk.javadoc.doclet.Doclet; +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlVersion; +import jdk.javadoc.internal.doclets.toolkit.Configuration; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.WriterFactory; +import jdk.javadoc.internal.doclets.toolkit.util.DocFile; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.MessageRetriever; +import jdk.javadoc.internal.doclets.toolkit.util.Utils; + +import static javax.tools.Diagnostic.Kind.*; + +/** + * Configure the output based on the command line options. + *

          + * Also determine the length of the command line option. For example, + * for a option "-header" there will be a string argument associated, then the + * the length of option "-header" is two. But for option "-nohelp" no argument + * is needed so it's length is 1. + *

          + *

          + * Also do the error checking on the options used. For example it is illegal to + * use "-helpfile" option when already "-nohelp" option is used. + *

          + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert Field. + * @author Atul Dambalkar. + * @author Jamie Ho + * @author Bhavesh Patel (Modified) + */ +public class ConfigurationImpl extends Configuration { + + /** + * The build date. Note: For now, we will use + * a version number instead of a date. + */ + public static final String BUILD_DATE = System.getProperty("java.version"); + + /** + * Argument for command line option "-header". + */ + public String header = ""; + + /** + * Argument for command line option "-packagesheader". + */ + public String packagesheader = ""; + + /** + * Argument for command line option "-footer". + */ + public String footer = ""; + + /** + * Argument for command line option "-doctitle". + */ + public String doctitle = ""; + + /** + * Argument for command line option "-windowtitle". + */ + public String windowtitle = ""; + + /** + * Argument for command line option "-top". + */ + public String top = ""; + + /** + * Argument for command line option "-bottom". + */ + public String bottom = ""; + + /** + * Argument for command line option "-helpfile". + */ + public String helpfile = ""; + + /** + * Argument for command line option "-stylesheetfile". + */ + public String stylesheetfile = ""; + + /** + * Argument for command line option "-Xdocrootparent". + */ + public String docrootparent = ""; + + public boolean sortedMethodDetails = false; + + /** + * True if command line option "-nohelp" is used. Default value is false. + */ + public boolean nohelp = false; + + /** + * True if command line option "-splitindex" is used. Default value is + * false. + */ + public boolean splitindex = false; + + /** + * False if command line option "-noindex" is used. Default value is true. + */ + public boolean createindex = true; + + /** + * True if command line option "-use" is used. Default value is false. + */ + public boolean classuse = false; + + /** + * False if command line option "-notree" is used. Default value is true. + */ + public boolean createtree = true; + + /** + * True if command line option "-nodeprecated" is used. Default value is + * false. + */ + public boolean nodeprecatedlist = false; + + /** + * True if command line option "-nonavbar" is used. Default value is false. + */ + public boolean nonavbar = false; + + /** + * True if command line option "-nooverview" is used. Default value is + * false + */ + private boolean nooverview = false; + + /** + * The overview path specified with "-overview" flag. + */ + public String overviewpath = null; + + /** + * This is true if option "-overview" is used or option "-overview" is not + * used and number of packages is more than one. + */ + public boolean createoverview = false; + + /** + * This is the HTML version of the generated pages. HTML 4.01 is the default output version. + */ + public HtmlVersion htmlVersion = HtmlVersion.HTML4; + + /** + * Collected set of doclint options + */ + public Map doclintOpts = new LinkedHashMap<>(); + + /** + * Unique Resource Handler for this package. + */ + public final MessageRetriever standardmessage; + + /** + * First file to appear in the right-hand frame in the generated + * documentation. + */ + public DocPath topFile = DocPath.empty; + + /** + * The TypeElement for the class file getting generated. + */ + public TypeElement currentTypeElement = null; // Set this TypeElement in the ClassWriter. + + protected List memberSearchIndex = new ArrayList<>(); + + protected List packageSearchIndex = new ArrayList<>(); + + protected List tagSearchIndex = new ArrayList<>(); + + protected List typeSearchIndex = new ArrayList<>(); + + protected Map> tagSearchIndexMap = new HashMap<>(); + + protected Set tagSearchIndexKeys; + + /** + * Constructor. Initializes resource for the + * {@link com.sun.tools.doclets.internal.toolkit.util.MessageRetriever MessageRetriever}. + */ + public ConfigurationImpl() { + standardmessage = new MessageRetriever(this, + "jdk.javadoc.internal.doclets.formats.html.resources.standard"); + } + + private final String versionRBName = "jdk.javadoc.internal.tool.resources.version"; + private ResourceBundle versionRB; + + /** + * Return the build date for the doclet. + * @return the build date + */ + @Override + public String getDocletSpecificBuildDate() { + if (versionRB == null) { + try { + versionRB = ResourceBundle.getBundle(versionRBName, getLocale()); + } catch (MissingResourceException e) { + return BUILD_DATE; + } + } + + try { + return versionRB.getString("release"); + } catch (MissingResourceException e) { + return BUILD_DATE; + } + } + + protected boolean validateOptions() { + // check shared options + if (!generalValidOptions()) { + return false; + } + boolean helpfileSeen = false; + // otherwise look at our options + for (Doclet.Option opt : optionsProcessed) { + if (opt.matches("-helpfile")) { + if (nohelp == true) { + reporter.print(ERROR, getText("doclet.Option_conflict", + "-helpfile", "-nohelp")); + return false; + } + if (helpfileSeen) { + reporter.print(ERROR, getText("doclet.Option_reuse", + "-helpfile")); + return false; + } + helpfileSeen = true; + DocFile help = DocFile.createFileForInput(this, helpfile); + if (!help.exists()) { + reporter.print(ERROR, getText("doclet.File_not_found", helpfile)); + return false; + } + } else if (opt.matches("-nohelp")) { + if (helpfileSeen) { + reporter.print(ERROR, getText("doclet.Option_conflict", + "-nohelp", "-helpfile")); + return false; + } + } else if (opt.matches("-xdocrootparent")) { + try { + URL ignored = new URL(docrootparent); + } catch (MalformedURLException e) { + reporter.print(ERROR, getText("doclet.MalformedURL", docrootparent)); + return false; + } + } else if (opt.matches("-overview")) { + if (nooverview == true) { + reporter.print(ERROR, getText("doclet.Option_conflict", + "-overview", "-nooverview")); + return false; + } + } else if (opt.matches("-nooverview")) { + if (overviewpath != null) { + reporter.print(ERROR, getText("doclet.Option_conflict", + "-nooverview", "-overview")); + return false; + } + } else if (opt.matches("-splitindex")) { + if (createindex == false) { + reporter.print(ERROR, getText("doclet.Option_conflict", + "-splitindex", "-noindex")); + return false; + } + } else if (opt.matches("-noindex")) { + if (splitindex == true) { + reporter.print(ERROR, getText("doclet.Option_conflict", + "-noindex", "-splitindex")); + return false; + } + } else if (opt.matches("-xdoclint:")) { + String dopt = doclintOpts.get(opt); + if (dopt == null) { + continue; + } + if (dopt.contains("/")) { + reporter.print(ERROR, getText("doclet.Option_doclint_no_qualifiers")); + return false; + } + if (!DocLint.isValidOption(dopt)) { + reporter.print(ERROR, getText("doclet.Option_doclint_invalid_arg")); + return false; + } + } else if (opt.matches("-xdoclint/package:")) { + String dopt = doclintOpts.get(opt); + if (!DocLint.isValidOption(dopt)) { + reporter.print(ERROR, getText("doclet.Option_doclint_package_invalid_arg")); + return false; + } + } + } + return true; + } + + @Override + public boolean finishOptionSettings() { + if (!validateOptions()) { + return false; + } + if (!root.getSpecifiedElements().isEmpty()) { + Map map = new HashMap<>(); + PackageElement pkg; + List classes = new ArrayList<>(root.getIncludedClasses()); + for (TypeElement aClass : classes) { + pkg = utils.containingPackage(aClass); + if (!map.containsKey(utils.getPackageName(pkg))) { + map.put(utils.getPackageName(pkg), pkg); + } + } + } + setCreateOverview(); + setTopFile(root); + workArounds.initDocLint(doclintOpts.values(), tagletManager.getCustomTagNames(), + Utils.toLowerCase(htmlVersion.name())); + return true; + } + + /** + * Return true if the generated output is HTML5. + */ + public boolean isOutputHtml5() { + return htmlVersion == HtmlVersion.HTML5; + } + + /** + * Return true if the tag is allowed for this specific version of HTML. + */ + public boolean allowTag(HtmlTag htmlTag) { + return htmlTag.allowTag(this.htmlVersion); + } + + /** + * {@inheritDoc} + */ + @Override + public MessageRetriever getDocletSpecificMsg() { + return standardmessage; + } + + /** + * Decide the page which will appear first in the right-hand frame. It will + * be "overview-summary.html" if "-overview" option is used or no + * "-overview" but the number of packages is more than one. It will be + * "package-summary.html" of the respective package if there is only one + * package to document. It will be a class page(first in the sorted order), + * if only classes are provided on the command line. + * + * @param root Root of the program structure. + */ + protected void setTopFile(DocletEnvironment root) { + if (!checkForDeprecation(root)) { + return; + } + if (createoverview) { + topFile = DocPaths.OVERVIEW_SUMMARY; + } else { + if (packages.size() == 1 && packages.first().isUnnamed()) { + if (!root.getIncludedClasses().isEmpty()) { + List classes = new ArrayList<>(root.getIncludedClasses()); + TypeElement te = getValidClass(classes); + topFile = DocPath.forClass(utils, te); + } + } else if (!packages.isEmpty()) { + topFile = DocPath.forPackage(packages.first()).resolve(DocPaths.PACKAGE_SUMMARY); + } + } + } + + protected TypeElement getValidClass(List classes) { + if (!nodeprecated) { + return classes.get(0); + } + for (TypeElement te : classes) { + if (!utils.isDeprecated(te)) { + return te; + } + } + return null; + } + + protected boolean checkForDeprecation(DocletEnvironment root) { + for (TypeElement te : root.getIncludedClasses()) { + if (isGeneratedDoc(te)) { + return true; + } + } + return false; + } + + /** + * Generate "overview.html" page if option "-overview" is used or number of + * packages is more than one. Sets {@link #createoverview} field to true. + */ + protected void setCreateOverview() { + if ((overviewpath != null || packages.size() > 1) && !nooverview) { + createoverview = true; + } + } + + /** + * {@inheritDoc} + */ + @Override + public WriterFactory getWriterFactory() { + return new WriterFactoryImpl(this); + } + + /** + * {@inheritDoc} + */ + @Override + public Locale getLocale() { + if (locale == null) + return Locale.getDefault(); + return locale; + } + + /** + * Return the path of the overview file and null if it does not exist. + * + * @return the path of the overview file and null if it does not exist. + */ + public JavaFileObject getOverviewPath() { + if (overviewpath != null && getFileManager() instanceof StandardJavaFileManager) { + StandardJavaFileManager fm = (StandardJavaFileManager) getFileManager(); + return fm.getJavaFileObjects(overviewpath).iterator().next(); + } + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public JavaFileManager getFileManager() { + return root.getJavaFileManager(); + } + + @Override + public boolean showMessage(DocTreePath path, String key) { + return (path == null || workArounds.haveDocLint()); + } + + @Override + public boolean showMessage(Element e, String key) { + return (e == null || workArounds.haveDocLint()); + } + + @Override + public Content newContent() { + return new ContentBuilder(); + } + + protected void buildSearchTagIndex() { + for (SearchIndexItem sii : tagSearchIndex) { + String tagLabel = sii.getLabel(); + Character unicode = (tagLabel.length() == 0) + ? '*' + : Character.toUpperCase(tagLabel.charAt(0)); + List list = tagSearchIndexMap.get(unicode); + if (list == null) { + list = new ArrayList<>(); + tagSearchIndexMap.put(unicode, list); + } + list.add(sii); + } + tagSearchIndexKeys = tagSearchIndexMap.keySet(); + } + + @Override + public Set getSupportedOptions() { + Doclet.Option[] options = { + new Option(this, "bottom", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + bottom = args.next(); + return true; + } + }, + new Option(this, "charset", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + charset = args.next(); + return true; + } + }, + new Option(this, "doctitle", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + doctitle = args.next(); + return true; + } + }, + new Option(this, "footer", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + footer = args.next(); + return true; + } + }, + new Option(this, "header", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + header = args.next(); + return true; + } + }, + new Option(this, "helpfile", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + helpfile = args.next(); + return true; + } + }, + new Option(this, "html4") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + htmlVersion = HtmlVersion.HTML4; + return true; + } + }, + new Option(this, "html5") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + htmlVersion = HtmlVersion.HTML5; + return true; + } + }, + new Option(this, "nohelp") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + nohelp = true; + return true; + } + }, + new Option(this, "nodeprecatedlist") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + nodeprecatedlist = true; + return true; + } + }, + new Option(this, "noindex") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + createindex = false; + return true; + } + }, + new Option(this, "nonavbar") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + nonavbar = true; + return true; + } + }, + new Hidden(this, "nooverview") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + nooverview = true; + return true; + } + }, + new Option(this, "notree") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + createtree = false; + return true; + } + }, + new Hidden(this, "overview", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + overviewpath = args.next(); + return true; + } + }, + new Hidden(this, "packagesheader", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + packagesheader = args.next(); + return true; + } + }, + new Option(this, "splitindex") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + splitindex = true; + return true; + } + }, + new Option(this, "stylesheetfile", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + stylesheetfile = args.next(); + return true; + } + }, + new Option(this, "top", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + top = args.next(); + return true; + } + }, + new Option(this, "use") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + classuse = true; + return true; + } + }, + new Option(this, "windowtitle", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + windowtitle = args.next().replaceAll("\\<.*?>", ""); + return true; + } + }, + new XOption(this, "xdoclint") { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + doclintOpts.put(this, DocLint.XMSGS_OPTION); + return true; + } + }, + new XOption(this, "Xdocrootparent", 1) { + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + docrootparent = args.next(); + return true; + } + }, + new XOption(this, "doclet.xusage.xdoclint-extended.", "Xdoclint:", 0) { + @Override + public boolean matches(String option) { + String opt = option.startsWith("-") ? option.substring(1) : option; + return opt.toLowerCase().startsWith(getName().toLowerCase()); + } + + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + doclintOpts.put(this, opt.replace("-Xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX)); + return true; + } + }, + new XOption(this, "doclet.xusage.xdoclint-package.", "Xdoclint/package:", 0) { + @Override + public boolean matches(String option) { + String opt = option.startsWith("-") ? option.substring(1) : option; + return opt.toLowerCase().startsWith(getName().toLowerCase()); + } + + @Override + public boolean process(String opt, ListIterator args) { + optionsProcessed.add(this); + doclintOpts.put(this, opt.replace("-Xdoclint/package:", DocLint.XCHECK_PACKAGE)); + return true; + } + } + }; + Set oset = new TreeSet<>(); + oset.addAll(Arrays.asList(options)); + oset.addAll(super.getSupportedOptions()); + return oset; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java new file mode 100644 index 00000000000..2b993595998 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.Modifier; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocLink; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; + + +/** + * Write the Constants Summary Page in HTML format. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Jamie Ho + * @author Bhavesh Patel (Modified) + */ +public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements ConstantsSummaryWriter { + + /** + * The configuration used in this run of the standard doclet. + */ + ConfigurationImpl configuration; + + /** + * The current class being documented. + */ + private TypeElement currentTypeElement; + + private final String constantsTableSummary; + + private final List constantsTableHeader; + + /** + * The HTML tree for main tag. + */ + private HtmlTree mainTree = HtmlTree.MAIN(); + + /** + * The HTML tree for constant values summary. + */ + private HtmlTree summaryTree; + + /** + * Construct a ConstantsSummaryWriter. + * @param configuration the configuration used in this run + * of the standard doclet. + */ + public ConstantsSummaryWriterImpl(ConfigurationImpl configuration) + throws IOException { + super(configuration, DocPaths.CONSTANT_VALUES); + this.configuration = configuration; + constantsTableSummary = configuration.getText("doclet.Constants_Table_Summary", + configuration.getText("doclet.Constants_Summary")); + constantsTableHeader = new ArrayList<>(); + constantsTableHeader.add(getModifierTypeHeader()); + constantsTableHeader.add(configuration.getText("doclet.ConstantField")); + constantsTableHeader.add(configuration.getText("doclet.Value")); + } + + /** + * {@inheritDoc} + */ + public Content getHeader() { + String label = configuration.getText("doclet.Constants_Summary"); + HtmlTree bodyTree = getBody(true, getWindowTitle(label)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + return bodyTree; + } + + /** + * {@inheritDoc} + */ + public Content getContentsHeader() { + return new HtmlTree(HtmlTag.UL); + } + + /** + * {@inheritDoc} + */ + public void addLinkToPackageContent(PackageElement pkg, + Set printedPackageHeaders, Content contentListTree) { + //add link to summary + Content link; + if (pkg.isUnnamed()) { + link = getHyperLink(getDocLink( + SectionName.UNNAMED_PACKAGE_ANCHOR), + defaultPackageLabel, "", ""); + } else { + String parsedPackageName = utils.parsePackageName(pkg); + Content packageNameContent = getPackageLabel(parsedPackageName); + packageNameContent.addContent(".*"); + link = getHyperLink(DocLink.fragment(parsedPackageName), + packageNameContent, "", ""); + PackageElement abbrevPkg = utils.elementUtils.getPackageElement(parsedPackageName); + printedPackageHeaders.add(abbrevPkg); + } + contentListTree.addContent(HtmlTree.LI(link)); + } + + /** + * {@inheritDoc} + */ + public void addContentsList(Content contentTree, Content contentListTree) { + Content titleContent = getResource( + "doclet.Constants_Summary"); + Content pHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, titleContent); + Content div = HtmlTree.DIV(HtmlStyle.header, pHeading); + Content headingContent = getResource( + "doclet.Contents"); + Content heading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, true, + headingContent); + if (configuration.allowTag(HtmlTag.SECTION)) { + HtmlTree section = HtmlTree.SECTION(heading); + section.addContent(contentListTree); + div.addContent(section); + mainTree.addContent(div); + } else { + div.addContent(heading); + div.addContent(contentListTree); + contentTree.addContent(div); + } + } + + /** + * {@inheritDoc} + */ + public Content getConstantSummaries() { + HtmlTree summariesDiv = new HtmlTree(HtmlTag.DIV); + summariesDiv.addStyle(HtmlStyle.constantValuesContainer); + return summariesDiv; + } + + /** + * {@inheritDoc} + */ + public void addPackageName(PackageElement pkg, Content summariesTree, boolean first) { + Content pkgNameContent; + if (!first && configuration.allowTag(HtmlTag.SECTION)) { + summariesTree.addContent(summaryTree); + } + if (pkg.isUnnamed()) { + summariesTree.addContent(getMarkerAnchor( + SectionName.UNNAMED_PACKAGE_ANCHOR)); + pkgNameContent = defaultPackageLabel; + } else { + String parsedPackageName = utils.parsePackageName(pkg); + summariesTree.addContent(getMarkerAnchor(parsedPackageName)); + pkgNameContent = getPackageLabel(parsedPackageName); + } + Content headingContent = new StringContent(".*"); + Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, + pkgNameContent); + heading.addContent(headingContent); + if (configuration.allowTag(HtmlTag.SECTION)) { + summaryTree = HtmlTree.SECTION(heading); + } else { + summariesTree.addContent(heading); + } + } + + /** + * {@inheritDoc} + */ + public Content getClassConstantHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * {@inheritDoc} + */ + public void addClassConstant(Content summariesTree, Content classConstantTree) { + if (configuration.allowTag(HtmlTag.SECTION)) { + summaryTree.addContent(classConstantTree); + } else { + summariesTree.addContent(classConstantTree); + } + } + + /** + * Get the table caption and header for the constant summary table + * + * @param typeElement the TypeElement to be documented + * @return constant members header content + */ + public Content getConstantMembersHeader(TypeElement typeElement) { + //generate links backward only to public classes. + Content classlink = (utils.isPublic(typeElement) || utils.isProtected(typeElement)) ? + getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CONSTANT_SUMMARY, typeElement)) : + new StringContent(utils.getFullyQualifiedName(typeElement)); + + PackageElement enclosingPackage = utils.containingPackage(typeElement); + if (!enclosingPackage.isUnnamed()) { + Content cb = new ContentBuilder(); + cb.addContent(enclosingPackage.getQualifiedName().toString()); + cb.addContent("."); + cb.addContent(classlink); + return getClassName(cb); + } else { + return getClassName(classlink); + } + } + + /** + * Get the class name in the table caption and the table header. + * + * @param classStr the class name to print. + * @return the table caption and header + */ + protected Content getClassName(Content classStr) { + Content caption = getTableCaption(classStr); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.constantsSummary, caption) + : HtmlTree.TABLE(HtmlStyle.constantsSummary, constantsTableSummary, caption); + table.addContent(getSummaryTableHeader(constantsTableHeader, "col")); + return table; + } + + /** + * {@inheritDoc} + */ + public void addConstantMembers(TypeElement typeElement, Collection fields, + Content classConstantTree) { + currentTypeElement = typeElement; + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (VariableElement field : fields) { + HtmlTree tr = new HtmlTree(HtmlTag.TR); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + addConstantMember(field, tr); + tbody.addContent(tr); + altColor = !altColor; + } + Content table = getConstantMembersHeader(typeElement); + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + classConstantTree.addContent(li); + } + + /** + * Add the row for the constant summary table. + * + * @param member the field to be documented. + * @param trTree an htmltree object for the table row + */ + private void addConstantMember(VariableElement member, HtmlTree trTree) { + trTree.addContent(getTypeColumn(member)); + trTree.addContent(getNameColumn(member)); + trTree.addContent(getValue(member)); + } + + /** + * Get the type column for the constant summary table row. + * + * @param member the field to be documented. + * @return the type column of the constant table row + */ + private Content getTypeColumn(VariableElement member) { + Content anchor = getMarkerAnchor(currentTypeElement.getQualifiedName() + + "." + member.getSimpleName()); + Content tdType = HtmlTree.TD(HtmlStyle.colFirst, anchor); + Content code = new HtmlTree(HtmlTag.CODE); + for (Modifier mod : member.getModifiers()) { + Content modifier = new StringContent(mod.toString()); + code.addContent(modifier); + code.addContent(getSpace()); + } + Content type = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.CONSTANT_SUMMARY, member.asType())); + code.addContent(type); + tdType.addContent(code); + return tdType; + } + + /** + * Get the name column for the constant summary table row. + * + * @param member the field to be documented. + * @return the name column of the constant table row + */ + private Content getNameColumn(VariableElement member) { + Content nameContent = getDocLink(LinkInfoImpl.Kind.CONSTANT_SUMMARY, + member, member.getSimpleName().toString(), false); + Content code = HtmlTree.CODE(nameContent); + return HtmlTree.TD(code); + } + + /** + * Get the value column for the constant summary table row. + * + * @param member the field to be documented. + * @return the value column of the constant table row + */ + private Content getValue(VariableElement member) { + String value = utils.constantValueExpresion(member); + Content valueContent = new StringContent(value); + Content code = HtmlTree.CODE(valueContent); + return HtmlTree.TD(HtmlStyle.colLast, code); + } + + /** + * {@inheritDoc} + */ + public void addConstantSummaries(Content contentTree, Content summariesTree) { + if (configuration.allowTag(HtmlTag.SECTION) && summaryTree != null) { + summariesTree.addContent(summaryTree); + } + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(summariesTree); + contentTree.addContent(mainTree); + } else { + contentTree.addContent(summariesTree); + } + } + + /** + * {@inheritDoc} + */ + public void addFooter(Content contentTree) { + Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : contentTree; + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + contentTree.addContent(htmlTree); + } + } + + /** + * {@inheritDoc} + */ + public void printDocument(Content contentTree) throws IOException { + printHtmlDocument(null, true, contentTree); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java new file mode 100644 index 00000000000..c3f3a41e163 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java @@ -0,0 +1,354 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; +import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap; + + +/** + * Writes constructor documentation. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert Field + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class ConstructorWriterImpl extends AbstractExecutableMemberWriter + implements ConstructorWriter, MemberSummaryWriter { + + private boolean foundNonPubConstructor = false; + + /** + * Construct a new ConstructorWriterImpl. + * + * @param writer The writer for the class that the constructors belong to. + * @param typeElement the class being documented. + */ + public ConstructorWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) { + super(writer, typeElement); + + VisibleMemberMap visibleMemberMap = new VisibleMemberMap( + typeElement, + VisibleMemberMap.Kind.CONSTRUCTORS, configuration); + SortedSet constructors = visibleMemberMap.getMembersFor(typeElement); + for (Element constructor : constructors) { + if (utils.isProtected(constructor) || utils.isPrivate(constructor)) { + setFoundNonPubConstructor(true); + } + } + } + + /** + * Construct a new ConstructorWriterImpl. + * + * @param writer The writer for the class that the constructors belong to. + */ + public ConstructorWriterImpl(SubWriterHolderWriter writer) { + super(writer); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMemberSummaryHeader(TypeElement typeElement, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_CONSTRUCTOR_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, typeElement, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + writer.addMemberTree(memberSummaryTree, memberTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getConstructorDetailsTreeHeader(TypeElement typeElement, + Content memberDetailsTree) { + memberDetailsTree.addContent(HtmlConstants.START_OF_CONSTRUCTOR_DETAILS); + Content constructorDetailsTree = writer.getMemberTreeHeader(); + constructorDetailsTree.addContent(writer.getMarkerAnchor( + SectionName.CONSTRUCTOR_DETAIL)); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.constructorDetailsLabel); + constructorDetailsTree.addContent(heading); + return constructorDetailsTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getConstructorDocTreeHeader(ExecutableElement constructor, + Content constructorDetailsTree) { + String erasureAnchor; + if ((erasureAnchor = getErasureAnchor(constructor)) != null) { + constructorDetailsTree.addContent(writer.getMarkerAnchor((erasureAnchor))); + } + constructorDetailsTree.addContent( + writer.getMarkerAnchor(writer.getAnchor(constructor))); + Content constructorDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(name(constructor)); + constructorDocTree.addContent(heading); + return constructorDocTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getSignature(ExecutableElement constructor) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(constructor, pre); + int annotationLength = pre.charCount(); + addModifiers(constructor, pre); + if (configuration.linksource) { + Content constructorName = new StringContent(name(constructor)); + writer.addSrcLink(constructor, constructorName, pre); + } else { + addName(name(constructor), pre); + } + int indent = pre.charCount() - annotationLength; + addParameters(constructor, pre, indent); + addExceptions(constructor, pre, indent); + return pre; + } + + /** + * {@inheritDoc} + */ + @Override + public void setSummaryColumnStyle(HtmlTree tdTree) { + if (foundNonPubConstructor) + tdTree.addStyle(HtmlStyle.colLast); + else + tdTree.addStyle(HtmlStyle.colOne); + } + + /** + * {@inheritDoc} + */ + @Override + public void addDeprecated(ExecutableElement constructor, Content constructorDocTree) { + addDeprecatedInfo(constructor, constructorDocTree); + } + + /** + * {@inheritDoc} + */ + @Override + public void addComments(ExecutableElement constructor, Content constructorDocTree) { + addComment(constructor, constructorDocTree); + } + + /** + * {@inheritDoc} + */ + @Override + public void addTags(ExecutableElement constructor, Content constructorDocTree) { + writer.addTagsInfo(constructor, constructorDocTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getConstructorDetails(Content constructorDetailsTree) { + if (configuration.allowTag(HtmlTag.SECTION)) { + HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(constructorDetailsTree)); + return htmlTree; + } + return getMemberTree(constructorDetailsTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getConstructorDoc(Content constructorDocTree, + boolean isLastContent) { + return getMemberTree(constructorDocTree, isLastContent); + } + + /** + * Close the writer. + */ + @Override + public void close() throws IOException { + writer.close(); + } + + /** + * Let the writer know whether a non public constructor was found. + * + * @param foundNonPubConstructor true if we found a non public constructor. + */ + @Override + public void setFoundNonPubConstructor(boolean foundNonPubConstructor) { + this.foundNonPubConstructor = foundNonPubConstructor; + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Constructor_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + @Override + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Constructor_Summary"), + configuration.getText("doclet.constructors")); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getCaption() { + return configuration.getResource("doclet.Constructors"); + } + + /** + * {@inheritDoc} + */ + @Override + public List getSummaryTableHeader(Element member) { + List header = new ArrayList<>(); + if (foundNonPubConstructor) { + header.add(configuration.getText("doclet.Modifier")); + } + header.add(configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Constructor"), + configuration.getText("doclet.Description"))); + return header; + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryAnchor(TypeElement typeElement, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + SectionName.CONSTRUCTOR_SUMMARY)); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { + if (link) { + return writer.getHyperLink(SectionName.CONSTRUCTOR_SUMMARY, + writer.getResource("doclet.navConstructor")); + } else { + return writer.getResource("doclet.navConstructor"); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void addNavDetailLink(boolean link, Content liNav) { + if (link) { + liNav.addContent(writer.getHyperLink( + SectionName.CONSTRUCTOR_DETAIL, + writer.getResource("doclet.navConstructor"))); + } else { + liNav.addContent(writer.getResource("doclet.navConstructor")); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryType(Element member, Content tdSummaryType) { + if (foundNonPubConstructor) { + Content code = new HtmlTree(HtmlTag.CODE); + if (utils.isProtected(member)) { + code.addContent("protected "); + } else if (utils.isPrivate(member)) { + code.addContent("private "); + } else if (utils.isPublic(member)) { + code.addContent(writer.getSpace()); + } else { + code.addContent( + configuration.getText("doclet.Package_private")); + } + tdSummaryType.addContent(code); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java new file mode 100644 index 00000000000..6defcd7614d --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java @@ -0,0 +1,385 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + +import static jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder.*; + +/** + * Generate File to list all the deprecated classes and class members with the + * appropriate links. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @see java.util.List + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class DeprecatedListWriter extends SubWriterHolderWriter { + + private String getAnchorName(DeprElementKind kind) { + switch (kind) { + case PACKAGE: + return "package"; + case INTERFACE: + return "interface"; + case CLASS: + return "class"; + case ENUM: + return "enum"; + case EXCEPTION: + return "exception"; + case ERROR: + return "error"; + case ANNOTATION_TYPE: + return "annotation.type"; + case FIELD: + return "field"; + case METHOD: + return "method"; + case CONSTRUCTOR: + return "constructor"; + case ENUM_CONSTANT: + return "enum.constant"; + case ANNOTATION_TYPE_MEMBER: + return "annotation.type.member"; + default: + throw new AssertionError("unknown kind: " + kind); + } + } + + private String getHeadingKey(DeprElementKind kind) { + switch (kind) { + case PACKAGE: + return "doclet.Deprecated_Packages"; + case INTERFACE: + return "doclet.Deprecated_Interfaces"; + case CLASS: + return "doclet.Deprecated_Classes"; + case ENUM: + return "doclet.Deprecated_Enums"; + case EXCEPTION: + return "doclet.Deprecated_Exceptions"; + case ERROR: + return "doclet.Deprecated_Errors"; + case ANNOTATION_TYPE: + return "doclet.Deprecated_Annotation_Types"; + case FIELD: + return "doclet.Deprecated_Fields"; + case METHOD: + return "doclet.Deprecated_Methods"; + case CONSTRUCTOR: + return "doclet.Deprecated_Constructors"; + case ENUM_CONSTANT: + return "doclet.Deprecated_Enum_Constants"; + case ANNOTATION_TYPE_MEMBER: + return "doclet.Deprecated_Annotation_Type_Members"; + default: + throw new AssertionError("unknown kind: " + kind); + } + } + + private String getSummaryKey(DeprElementKind kind) { + switch (kind) { + case PACKAGE: + return "doclet.deprecated_packages"; + case INTERFACE: + return "doclet.deprecated_interfaces"; + case CLASS: + return "doclet.deprecated_classes"; + case ENUM: + return "doclet.deprecated_enums"; + case EXCEPTION: + return "doclet.deprecated_exceptions"; + case ERROR: + return "doclet.deprecated_errors"; + case ANNOTATION_TYPE: + return "doclet.deprecated_annotation_types"; + case FIELD: + return "doclet.deprecated_fields"; + case METHOD: + return "doclet.deprecated_methods"; + case CONSTRUCTOR: + return "doclet.deprecated_constructors"; + case ENUM_CONSTANT: + return "doclet.deprecated_enum_constants"; + case ANNOTATION_TYPE_MEMBER: + return "doclet.deprecated_annotation_type_members"; + default: + throw new AssertionError("unknown kind: " + kind); + } + } + + private String getHeaderKey(DeprElementKind kind) { + switch (kind) { + case PACKAGE: + return "doclet.Package"; + case INTERFACE: + return "doclet.Interface"; + case CLASS: + return "doclet.Class"; + case ENUM: + return "doclet.Enum"; + case EXCEPTION: + return "doclet.Exceptions"; + case ERROR: + return "doclet.Errors"; + case ANNOTATION_TYPE: + return "doclet.AnnotationType"; + case FIELD: + return "doclet.Field"; + case METHOD: + return "doclet.Method"; + case CONSTRUCTOR: + return "doclet.Constructor"; + case ENUM_CONSTANT: + return "doclet.Enum_Constant"; + case ANNOTATION_TYPE_MEMBER: + return "doclet.Annotation_Type_Member"; + default: + throw new AssertionError("unknown kind: " + kind); + } + } + + private EnumMap writerMap; + + private ConfigurationImpl configuration; + + /** + * Constructor. + * + * @param filename the file to be generated. + */ + + public DeprecatedListWriter(ConfigurationImpl configuration, + DocPath filename) throws IOException { + super(configuration, filename); + this.configuration = configuration; + NestedClassWriterImpl classW = new NestedClassWriterImpl(this); + writerMap = new EnumMap<>(DeprElementKind.class); + for (DeprElementKind kind : DeprElementKind.values()) { + switch (kind) { + case PACKAGE: + case INTERFACE: + case CLASS: + case ENUM: + case EXCEPTION: + case ERROR: + case ANNOTATION_TYPE: + writerMap.put(kind, classW); + break; + case FIELD: + writerMap.put(kind, new FieldWriterImpl(this)); + break; + case METHOD: + writerMap.put(kind, new MethodWriterImpl(this)); + break; + case CONSTRUCTOR: + writerMap.put(kind, new ConstructorWriterImpl(this)); + break; + case ENUM_CONSTANT: + writerMap.put(kind, new EnumConstantWriterImpl(this)); + break; + case ANNOTATION_TYPE_MEMBER: + writerMap.put(kind, new AnnotationTypeOptionalMemberWriterImpl(this, null)); + break; + default: + throw new AssertionError("unknown kind: " + kind); + } + } + } + + /** + * Get list of all the deprecated classes and members in all the Packages + * specified on the Command Line. + * Then instantiate DeprecatedListWriter and generate File. + * + * @param configuration the current configuration of the doclet. + */ + public static void generate(ConfigurationImpl configuration) { + DocPath filename = DocPaths.DEPRECATED_LIST; + try { + DeprecatedListWriter depr = + new DeprecatedListWriter(configuration, filename); + depr.generateDeprecatedListFile( + new DeprecatedAPIListBuilder(configuration)); + depr.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), filename); + throw new DocletAbortException(exc); + } + } + + /** + * Generate the deprecated API list. + * + * @param deprapi list of deprecated API built already. + */ + protected void generateDeprecatedListFile(DeprecatedAPIListBuilder deprapi) + throws IOException { + HtmlTree body = getHeader(); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN)) + ? HtmlTree.MAIN() + : body; + htmlTree.addContent(getContentsList(deprapi)); + String memberTableSummary; + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.contentContainer); + for (DeprElementKind kind : DeprElementKind.values()) { + if (deprapi.hasDocumentation(kind)) { + addAnchor(deprapi, kind, div); + memberTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText(getHeadingKey(kind)), + configuration.getText(getSummaryKey(kind))); + List memberTableHeader = new ArrayList<>(); + memberTableHeader.add(configuration.getText("doclet.0_and_1", + configuration.getText(getHeaderKey(kind)), + configuration.getText("doclet.Description"))); + if (kind == DeprElementKind.PACKAGE) + addPackageDeprecatedAPI(deprapi.getSet(kind), + getHeadingKey(kind), memberTableSummary, memberTableHeader, div); + else + writerMap.get(kind).addDeprecatedAPI(deprapi.getSet(kind), + getHeadingKey(kind), memberTableSummary, memberTableHeader, div); + } + } + if (configuration.allowTag(HtmlTag.MAIN)) { + htmlTree.addContent(div); + body.addContent(htmlTree); + } else { + body.addContent(div); + } + htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : body; + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(htmlTree); + } + printHtmlDocument(null, true, body); + } + + /** + * Add the index link. + * + * @param builder the deprecated list builder + * @param type the type of list being documented + * @param contentTree the content tree to which the index link will be added + */ + private void addIndexLink(DeprecatedAPIListBuilder builder, + DeprElementKind kind, Content contentTree) { + if (builder.hasDocumentation(kind)) { + Content li = HtmlTree.LI(getHyperLink(getAnchorName(kind), + getResource(getHeadingKey(kind)))); + contentTree.addContent(li); + } + } + + /** + * Get the contents list. + * + * @param deprapi the deprecated list builder + * @return a content tree for the contents list + */ + public Content getContentsList(DeprecatedAPIListBuilder deprapi) { + Content headContent = getResource("doclet.Deprecated_API"); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + Content headingContent = getResource("doclet.Contents"); + div.addContent(HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, true, + headingContent)); + Content ul = new HtmlTree(HtmlTag.UL); + for (DeprElementKind kind : DeprElementKind.values()) { + addIndexLink(deprapi, kind, ul); + } + div.addContent(ul); + return div; + } + + /** + * Add the anchor. + * + * @param builder the deprecated list builder + * @param type the type of list being documented + * @param htmlTree the content tree to which the anchor will be added + */ + private void addAnchor(DeprecatedAPIListBuilder builder, DeprElementKind kind, Content htmlTree) { + if (builder.hasDocumentation(kind)) { + htmlTree.addContent(getMarkerAnchor(getAnchorName(kind))); + } + } + + /** + * Get the header for the deprecated API Listing. + * + * @return a content tree for the header + */ + public HtmlTree getHeader() { + String title = configuration.getText("doclet.Window_Deprecated_List"); + HtmlTree bodyTree = getBody(true, getWindowTitle(title)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + return bodyTree; + } + + /** + * Get the deprecated label. + * + * @return a content tree for the deprecated label + */ + protected Content getNavLinkDeprecated() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, deprecatedLabel); + return li; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java new file mode 100644 index 00000000000..fc8bf385bb6 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import java.util.Arrays; +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.EnumConstantWriter; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; + +/** + * Writes enum constant documentation in HTML format. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Jamie Ho + * @author Bhavesh Patel (Modified) + */ +public class EnumConstantWriterImpl extends AbstractMemberWriter + implements EnumConstantWriter, MemberSummaryWriter { + + public EnumConstantWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) { + super(writer, typeElement); + } + + public EnumConstantWriterImpl(SubWriterHolderWriter writer) { + super(writer); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMemberSummaryHeader(TypeElement typeElement, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_ENUM_CONSTANT_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, typeElement, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + writer.addMemberTree(memberSummaryTree, memberTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getEnumConstantsDetailsTreeHeader(TypeElement typeElement, + Content memberDetailsTree) { + memberDetailsTree.addContent(HtmlConstants.START_OF_ENUM_CONSTANT_DETAILS); + Content enumConstantsDetailsTree = writer.getMemberTreeHeader(); + enumConstantsDetailsTree.addContent(writer.getMarkerAnchor( + SectionName.ENUM_CONSTANT_DETAIL)); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.enumConstantsDetailsLabel); + enumConstantsDetailsTree.addContent(heading); + return enumConstantsDetailsTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getEnumConstantsTreeHeader(VariableElement enumConstant, + Content enumConstantsDetailsTree) { + enumConstantsDetailsTree.addContent( + writer.getMarkerAnchor(name(enumConstant))); + Content enumConstantsTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(name(enumConstant)); + enumConstantsTree.addContent(heading); + return enumConstantsTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getSignature(VariableElement enumConstant) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(enumConstant, pre); + addModifiers(enumConstant, pre); + Content enumConstantLink = writer.getLink(new LinkInfoImpl( + configuration, LinkInfoImpl.Kind.MEMBER, enumConstant.asType())); + pre.addContent(enumConstantLink); + pre.addContent(" "); + if (configuration.linksource) { + Content enumConstantName = new StringContent(name(enumConstant)); + writer.addSrcLink(enumConstant, enumConstantName, pre); + } else { + addName(name(enumConstant), pre); + } + return pre; + } + + /** + * {@inheritDoc} + */ + @Override + public void addDeprecated(VariableElement enumConstant, Content enumConstantsTree) { + addDeprecatedInfo(enumConstant, enumConstantsTree); + } + + /** + * {@inheritDoc} + */ + @Override + public void addComments(VariableElement enumConstant, Content enumConstantsTree) { + addComment(enumConstant, enumConstantsTree); + } + + /** + * {@inheritDoc} + */ + @Override + public void addTags(VariableElement enumConstant, Content enumConstantsTree) { + writer.addTagsInfo(enumConstant, enumConstantsTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getEnumConstantsDetails(Content enumConstantsDetailsTree) { + if (configuration.allowTag(HtmlTag.SECTION)) { + HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(enumConstantsDetailsTree)); + return htmlTree; + } + return getMemberTree(enumConstantsDetailsTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getEnumConstants(Content enumConstantsTree, + boolean isLastContent) { + return getMemberTree(enumConstantsTree, isLastContent); + } + + /** + * {@inheritDoc} + */ + @Override + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Enum_Constant_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + @Override + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Enum_Constant_Summary"), + configuration.getText("doclet.enum_constants")); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getCaption() { + return configuration.getResource("doclet.Enum_Constants"); + } + + /** + * {@inheritDoc} + */ + @Override + public List getSummaryTableHeader(Element member) { + List header = Arrays.asList(configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Enum_Constant"), + configuration.getText("doclet.Description"))); + return header; + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryAnchor(TypeElement typeElement, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + SectionName.ENUM_CONSTANT_SUMMARY)); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member, + Content tdSummary) { + Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink, + writer.getDocLink(context, member, name(member), false)); + Content code = HtmlTree.CODE(memberLink); + tdSummary.addContent(code); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSummaryColumnStyle(HtmlTree tdTree) { + tdTree.addStyle(HtmlStyle.colOne); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) { + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryType(Element member, Content tdSummaryType) { + //Not applicable. + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getDeprecatedLink(Element member) { + String name = utils.getFullyQualifiedName(member) + "." + member.getSimpleName(); + return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, name); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { + if (link) { + if (typeElement == null) { + return writer.getHyperLink(SectionName.ENUM_CONSTANT_SUMMARY, + writer.getResource("doclet.navEnum")); + } else { + return writer.getHyperLink( + SectionName.ENUM_CONSTANTS_INHERITANCE, + configuration.getClassName(typeElement), writer.getResource("doclet.navEnum")); + } + } else { + return writer.getResource("doclet.navEnum"); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void addNavDetailLink(boolean link, Content liNav) { + if (link) { + liNav.addContent(writer.getHyperLink( + SectionName.ENUM_CONSTANT_DETAIL, + writer.getResource("doclet.navEnum"))); + } else { + liNav.addContent(writer.getResource("doclet.navEnum")); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java new file mode 100644 index 00000000000..b5e6c03b5f1 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.Arrays; +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.FieldWriter; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; + +/** + * Writes field documentation in HTML format. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert Field + * @author Atul M Dambalkar + * @author Jamie Ho (rewrite) + * @author Bhavesh Patel (Modified) + */ +public class FieldWriterImpl extends AbstractMemberWriter + implements FieldWriter, MemberSummaryWriter { + + public FieldWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) { + super(writer, typeElement); + } + + public FieldWriterImpl(SubWriterHolderWriter writer) { + super(writer); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMemberSummaryHeader(TypeElement typeElement, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_FIELD_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, typeElement, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + writer.addMemberTree(memberSummaryTree, memberTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getFieldDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) { + memberDetailsTree.addContent(HtmlConstants.START_OF_FIELD_DETAILS); + Content fieldDetailsTree = writer.getMemberTreeHeader(); + fieldDetailsTree.addContent(writer.getMarkerAnchor( + SectionName.FIELD_DETAIL)); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.fieldDetailsLabel); + fieldDetailsTree.addContent(heading); + return fieldDetailsTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getFieldDocTreeHeader(VariableElement field, Content fieldDetailsTree) { + fieldDetailsTree.addContent(writer.getMarkerAnchor(name(field))); + Content fieldTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(name(field)); + fieldTree.addContent(heading); + return fieldTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getSignature(VariableElement field) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(field, pre); + addModifiers(field, pre); + Content fieldlink = writer.getLink(new LinkInfoImpl( + configuration, LinkInfoImpl.Kind.MEMBER, field.asType())); + pre.addContent(fieldlink); + pre.addContent(" "); + if (configuration.linksource) { + Content fieldName = new StringContent(name(field)); + writer.addSrcLink(field, fieldName, pre); + } else { + addName(name(field), pre); + } + return pre; + } + + /** + * {@inheritDoc} + */ + @Override + public void addDeprecated(VariableElement field, Content fieldTree) { + addDeprecatedInfo(field, fieldTree); + } + + /** + * {@inheritDoc} + */ + @Override + public void addComments(VariableElement field, Content fieldTree) { + if (!utils.getBody(field).isEmpty()) { + writer.addInlineComment(field, fieldTree); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addTags(VariableElement field, Content fieldTree) { + writer.addTagsInfo(field, fieldTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getFieldDetails(Content fieldDetailsTree) { + if (configuration.allowTag(HtmlTag.SECTION)) { + HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(fieldDetailsTree)); + return htmlTree; + } + return getMemberTree(fieldDetailsTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getFieldDoc(Content fieldTree, + boolean isLastContent) { + return getMemberTree(fieldTree, isLastContent); + } + + /** + * Close the writer. + */ + @Override + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Field_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + @Override + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Field_Summary"), + configuration.getText("doclet.fields")); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getCaption() { + return configuration.getResource("doclet.Fields"); + } + + /** + * {@inheritDoc} + */ + @Override + public List getSummaryTableHeader(Element member) { + List header = Arrays.asList(writer.getModifierTypeHeader(), + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Field"), + configuration.getText("doclet.Description"))); + return header; + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryAnchor(TypeElement typeElement, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + SectionName.FIELD_SUMMARY)); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) { + inheritedTree.addContent(writer.getMarkerAnchor( + SectionName.FIELDS_INHERITANCE, configuration.getClassName(typeElement))); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + Content classLink = writer.getPreQualifiedClassLink( + LinkInfoImpl.Kind.MEMBER, typeElement, false); + Content label = new StringContent(utils.isClass(typeElement) + ? configuration.getText("doclet.Fields_Inherited_From_Class") + : configuration.getText("doclet.Fields_Inherited_From_Interface")); + Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING, + label); + labelHeading.addContent(writer.getSpace()); + labelHeading.addContent(classLink); + inheritedTree.addContent(labelHeading); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member, + Content tdSummary) { + Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink, + writer.getDocLink(context, typeElement , member, name(member), false)); + Content code = HtmlTree.CODE(memberLink); + tdSummary.addContent(code); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) { + linksTree.addContent( + writer.getDocLink(LinkInfoImpl.Kind.MEMBER, typeElement, member, + name(member), false)); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryType(Element member, Content tdSummaryType) { + addModifierAndType(member, member.asType(), tdSummaryType); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getDeprecatedLink(Element member) { + String name = utils.getFullyQualifiedName(member) + "." + member.getSimpleName(); + return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, name); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { + if (link) { + if (typeElement == null) { + return writer.getHyperLink( + SectionName.FIELD_SUMMARY, + writer.getResource("doclet.navField")); + } else { + return writer.getHyperLink( + SectionName.FIELDS_INHERITANCE, + configuration.getClassName(typeElement), writer.getResource("doclet.navField")); + } + } else { + return writer.getResource("doclet.navField"); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void addNavDetailLink(boolean link, Content liNav) { + if (link) { + liNav.addContent(writer.getHyperLink( + SectionName.FIELD_DETAIL, + writer.getResource("doclet.navField"))); + } else { + liNav.addContent(writer.getResource("doclet.navField")); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java new file mode 100644 index 00000000000..69be1be292e --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + + +/** + * Generate the documentation in the Html "frame" format in the browser. The + * generated documentation will have two or three frames depending upon the + * number of packages on the command line. In general there will be three frames + * in the output, a left-hand top frame will have a list of all packages with + * links to target left-hand bottom frame. The left-hand bottom frame will have + * the particular package contents or the all-classes list, where as the single + * right-hand frame will have overview or package summary or class file. Also + * take care of browsers which do not support Html frames. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + */ +public class FrameOutputWriter extends HtmlDocletWriter { + + /** + * Number of packages specified on the command line. + */ + int noOfPackages; + + /** + * Constructor to construct FrameOutputWriter object. + * + * @param configuration for this run + * @param filename File to be generated. + * @throws java.io.IOException + */ + public FrameOutputWriter(ConfigurationImpl configuration, DocPath filename) throws IOException { + super(configuration, filename); + noOfPackages = configuration.packages.size(); + } + + /** + * Construct FrameOutputWriter object and then use it to generate the Html + * file which will have the description of all the frames in the + * documentation. The name of the generated file is "index.html" which is + * the default first file for Html documents. + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration) { + FrameOutputWriter framegen; + DocPath filename = DocPath.empty; + try { + filename = DocPaths.INDEX; + framegen = new FrameOutputWriter(configuration, filename); + framegen.generateFrameFile(); + framegen.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), filename); + throw new DocletAbortException(exc); + } + } + + /** + * Generate the constants in the "index.html" file. Print the frame details + * as well as warning if browser is not supporting the Html frames. + */ + protected void generateFrameFile() throws IOException { + Content frame = getFrameDetails(); + HtmlTree body = new HtmlTree(HtmlTag.BODY); + if (configuration.allowTag(HtmlTag.MAIN)) { + HtmlTree main = HtmlTree.MAIN(frame); + body.addContent(main); + } else { + body.addContent(frame); + } + if (configuration.windowtitle.length() > 0) { + printFramesDocument(configuration.windowtitle, configuration, + body); + } else { + printFramesDocument(configuration.getText("doclet.Generated_Docs_Untitled"), + configuration, body); + } + } + + /** + * Get the frame sizes and their contents. + * + * @return a content tree for the frame details + */ + protected Content getFrameDetails() { + HtmlTree leftContainerDiv = new HtmlTree(HtmlTag.DIV); + HtmlTree rightContainerDiv = new HtmlTree(HtmlTag.DIV); + leftContainerDiv.addStyle(HtmlStyle.leftContainer); + rightContainerDiv.addStyle(HtmlStyle.rightContainer); + if (noOfPackages <= 1) { + addAllClassesFrameTag(leftContainerDiv); + } else if (noOfPackages > 1) { + addAllPackagesFrameTag(leftContainerDiv); + addAllClassesFrameTag(leftContainerDiv); + } + addClassFrameTag(rightContainerDiv); + HtmlTree mainContainer = HtmlTree.DIV(HtmlStyle.mainContainer, leftContainerDiv); + mainContainer.addContent(rightContainerDiv); + return mainContainer; + } + + /** + * Add the IFRAME tag for the frame that lists all packages. + * + * @param contentTree the content tree to which the information will be added + */ + private void addAllPackagesFrameTag(Content contentTree) { + HtmlTree frame = HtmlTree.IFRAME(DocPaths.OVERVIEW_FRAME.getPath(), + "packageListFrame", configuration.getText("doclet.All_Packages")); + HtmlTree leftTop = HtmlTree.DIV(HtmlStyle.leftTop, frame); + contentTree.addContent(leftTop); + } + + /** + * Add the IFRAME tag for the frame that lists all classes. + * + * @param contentTree the content tree to which the information will be added + */ + private void addAllClassesFrameTag(Content contentTree) { + HtmlTree frame = HtmlTree.IFRAME(DocPaths.ALLCLASSES_FRAME.getPath(), + "packageFrame", configuration.getText("doclet.All_classes_and_interfaces")); + HtmlTree leftBottom = HtmlTree.DIV(HtmlStyle.leftBottom, frame); + contentTree.addContent(leftBottom); + } + + /** + * Add the IFRAME tag for the frame that describes the class in detail. + * + * @param contentTree the content tree to which the information will be added + */ + private void addClassFrameTag(Content contentTree) { + HtmlTree frame = HtmlTree.IFRAME(configuration.topFile.getPath(), "classFrame", + configuration.getText("doclet.Package_class_and_interface_descriptions")); + frame.addStyle(HtmlStyle.rightIframe); + contentTree.addContent(frame); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java new file mode 100644 index 00000000000..784cabd3bc9 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java @@ -0,0 +1,449 @@ +/* + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + + +/** + * Generate the Help File for the generated API documentation. The help file + * contents are helpful for browsing the generated documentation. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + */ +public class HelpWriter extends HtmlDocletWriter { + + HtmlTree mainTree = HtmlTree.MAIN(); + + /** + * Constructor to construct HelpWriter object. + * @param filename File to be generated. + */ + public HelpWriter(ConfigurationImpl configuration, + DocPath filename) throws IOException { + super(configuration, filename); + } + + /** + * Construct the HelpWriter object and then use it to generate the help + * file. The name of the generated file is "help-doc.html". The help file + * will get generated if and only if "-helpfile" and "-nohelp" is not used + * on the command line. + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration) { + HelpWriter helpgen; + DocPath filename = DocPath.empty; + try { + filename = DocPaths.HELP_DOC; + helpgen = new HelpWriter(configuration, filename); + helpgen.generateHelpFile(); + helpgen.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), filename); + throw new DocletAbortException(exc); + } + } + + /** + * Generate the help file contents. + */ + protected void generateHelpFile() throws IOException { + String title = configuration.getText("doclet.Window_Help_title"); + HtmlTree body = getBody(true, getWindowTitle(title)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : body; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + body.addContent(htmlTree); + } + addHelpFileContents(body); + if (configuration.allowTag(HtmlTag.FOOTER)) { + htmlTree = HtmlTree.FOOTER(); + } + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(htmlTree); + } + printHtmlDocument(null, true, body); + } + + /** + * Add the help file contents from the resource file to the content tree. While adding the + * help file contents it also keeps track of user options. If "-notree" + * is used, then the "overview-tree.html" will not get added and hence + * help information also will not get added. + * + * @param contentTree the content tree to which the help file contents will be added + */ + protected void addHelpFileContents(Content contentTree) { + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, false, HtmlStyle.title, + getResource("doclet.Help_line_1")); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + Content line2 = HtmlTree.DIV(HtmlStyle.subTitle, + getResource("doclet.Help_line_2")); + div.addContent(line2); + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + } else { + contentTree.addContent(div); + } + HtmlTree htmlTree; + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + if (configuration.createoverview) { + Content overviewHeading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Overview")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(overviewHeading) + : HtmlTree.LI(HtmlStyle.blockList, overviewHeading); + Content line3 = getResource("doclet.Help_line_3", + getHyperLink(DocPaths.OVERVIEW_SUMMARY, + configuration.getText("doclet.Overview"))); + Content overviewPara = HtmlTree.P(line3); + htmlTree.addContent(overviewPara); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + } + Content packageHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Package")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(packageHead) + : HtmlTree.LI(HtmlStyle.blockList, packageHead); + Content line4 = getResource("doclet.Help_line_4"); + Content packagePara = HtmlTree.P(line4); + htmlTree.addContent(packagePara); + HtmlTree ulPackage = new HtmlTree(HtmlTag.UL); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Interfaces_Italic"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Classes"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Enums"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Exceptions"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.Errors"))); + ulPackage.addContent(HtmlTree.LI( + getResource("doclet.AnnotationTypes"))); + htmlTree.addContent(ulPackage); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + Content classHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_5")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(classHead) + : HtmlTree.LI(HtmlStyle.blockList, classHead); + Content line6 = getResource("doclet.Help_line_6"); + Content classPara = HtmlTree.P(line6); + htmlTree.addContent(classPara); + HtmlTree ul1 = new HtmlTree(HtmlTag.UL); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_7"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_8"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_9"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_10"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_11"))); + ul1.addContent(HtmlTree.LI( + getResource("doclet.Help_line_12"))); + htmlTree.addContent(ul1); + HtmlTree ul2 = new HtmlTree(HtmlTag.UL); + ul2.addContent(HtmlTree.LI( + getResource("doclet.Nested_Class_Summary"))); + ul2.addContent(HtmlTree.LI( + getResource("doclet.Field_Summary"))); + ul2.addContent(HtmlTree.LI( + getResource("doclet.Constructor_Summary"))); + ul2.addContent(HtmlTree.LI( + getResource("doclet.Method_Summary"))); + htmlTree.addContent(ul2); + HtmlTree ul3 = new HtmlTree(HtmlTag.UL); + ul3.addContent(HtmlTree.LI( + getResource("doclet.Field_Detail"))); + ul3.addContent(HtmlTree.LI( + getResource("doclet.Constructor_Detail"))); + ul3.addContent(HtmlTree.LI( + getResource("doclet.Method_Detail"))); + htmlTree.addContent(ul3); + Content line13 = getResource("doclet.Help_line_13"); + Content para = HtmlTree.P(line13); + htmlTree.addContent(para); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + //Annotation Types + Content aHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.AnnotationType")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(aHead) + : HtmlTree.LI(HtmlStyle.blockList, aHead); + Content aline1 = getResource("doclet.Help_annotation_type_line_1"); + Content aPara = HtmlTree.P(aline1); + htmlTree.addContent(aPara); + HtmlTree aul = new HtmlTree(HtmlTag.UL); + aul.addContent(HtmlTree.LI( + getResource("doclet.Help_annotation_type_line_2"))); + aul.addContent(HtmlTree.LI( + getResource("doclet.Help_annotation_type_line_3"))); + aul.addContent(HtmlTree.LI( + getResource("doclet.Annotation_Type_Required_Member_Summary"))); + aul.addContent(HtmlTree.LI( + getResource("doclet.Annotation_Type_Optional_Member_Summary"))); + aul.addContent(HtmlTree.LI( + getResource("doclet.Annotation_Type_Member_Detail"))); + htmlTree.addContent(aul); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + //Enums + Content enumHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Enum")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(enumHead) + : HtmlTree.LI(HtmlStyle.blockList, enumHead); + Content eline1 = getResource("doclet.Help_enum_line_1"); + Content enumPara = HtmlTree.P(eline1); + htmlTree.addContent(enumPara); + HtmlTree eul = new HtmlTree(HtmlTag.UL); + eul.addContent(HtmlTree.LI( + getResource("doclet.Help_enum_line_2"))); + eul.addContent(HtmlTree.LI( + getResource("doclet.Help_enum_line_3"))); + eul.addContent(HtmlTree.LI( + getResource("doclet.Enum_Constant_Summary"))); + eul.addContent(HtmlTree.LI( + getResource("doclet.Enum_Constant_Detail"))); + htmlTree.addContent(eul); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + if (configuration.classuse) { + Content useHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_14")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(useHead) + : HtmlTree.LI(HtmlStyle.blockList, useHead); + Content line15 = getResource("doclet.Help_line_15"); + Content usePara = HtmlTree.P(line15); + htmlTree.addContent(usePara); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + } + if (configuration.createtree) { + Content treeHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_16")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(treeHead) + : HtmlTree.LI(HtmlStyle.blockList, treeHead); + Content line17 = getResource("doclet.Help_line_17_with_tree_link", + getHyperLink(DocPaths.OVERVIEW_TREE, + configuration.getText("doclet.Class_Hierarchy")), + HtmlTree.CODE(new StringContent("java.lang.Object"))); + Content treePara = HtmlTree.P(line17); + htmlTree.addContent(treePara); + HtmlTree tul = new HtmlTree(HtmlTag.UL); + tul.addContent(HtmlTree.LI( + getResource("doclet.Help_line_18"))); + tul.addContent(HtmlTree.LI( + getResource("doclet.Help_line_19"))); + htmlTree.addContent(tul); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + } + if (!(configuration.nodeprecatedlist || + configuration.nodeprecated)) { + Content dHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Deprecated_API")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(dHead) + : HtmlTree.LI(HtmlStyle.blockList, dHead); + Content line20 = getResource("doclet.Help_line_20_with_deprecated_api_link", + getHyperLink(DocPaths.DEPRECATED_LIST, + configuration.getText("doclet.Deprecated_API"))); + Content dPara = HtmlTree.P(line20); + htmlTree.addContent(dPara); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + } + if (configuration.createindex) { + Content indexlink; + if (configuration.splitindex) { + indexlink = getHyperLink(DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1)), + configuration.getText("doclet.Index")); + } else { + indexlink = getHyperLink(DocPaths.INDEX_ALL, + configuration.getText("doclet.Index")); + } + Content indexHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_21")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(indexHead) + : HtmlTree.LI(HtmlStyle.blockList, indexHead); + Content line22 = getResource("doclet.Help_line_22", indexlink); + Content indexPara = HtmlTree.P(line22); + htmlTree.addContent(indexPara); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + } + Content prevHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_23")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(prevHead) + : HtmlTree.LI(HtmlStyle.blockList, prevHead); + Content line24 = getResource("doclet.Help_line_24"); + Content prevPara = HtmlTree.P(line24); + htmlTree.addContent(prevPara); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + Content frameHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Help_line_25")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(frameHead) + : HtmlTree.LI(HtmlStyle.blockList, frameHead); + Content line26 = getResource("doclet.Help_line_26"); + Content framePara = HtmlTree.P(line26); + htmlTree.addContent(framePara); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + Content allclassesHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.All_Classes")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(allclassesHead) + : HtmlTree.LI(HtmlStyle.blockList, allclassesHead); + Content line27 = getResource("doclet.Help_line_27", + getHyperLink(DocPaths.ALLCLASSES_NOFRAME, + configuration.getText("doclet.All_Classes"))); + Content allclassesPara = HtmlTree.P(line27); + htmlTree.addContent(allclassesPara); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + Content sHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Serialized_Form")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(sHead) + : HtmlTree.LI(HtmlStyle.blockList, sHead); + Content line28 = getResource("doclet.Help_line_28"); + Content serialPara = HtmlTree.P(line28); + htmlTree.addContent(serialPara); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + Content constHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + getResource("doclet.Constants_Summary")); + htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION(constHead) + : HtmlTree.LI(HtmlStyle.blockList, constHead); + Content line29 = getResource("doclet.Help_line_29", + getHyperLink(DocPaths.CONSTANT_VALUES, + configuration.getText("doclet.Constants_Summary"))); + Content constPara = HtmlTree.P(line29); + htmlTree.addContent(constPara); + if (configuration.allowTag(HtmlTag.SECTION)) { + ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree)); + } else { + ul.addContent(htmlTree); + } + Content divContent = HtmlTree.DIV(HtmlStyle.contentContainer, ul); + Content line30 = HtmlTree.SPAN(HtmlStyle.emphasizedPhrase, getResource("doclet.Help_line_30")); + divContent.addContent(line30); + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(divContent); + contentTree.addContent(mainTree); + } else { + contentTree.addContent(divContent); + } + } + + /** + * Get the help label. + * + * @return a content tree for the help label + */ + @Override + protected Content getNavLinkHelp() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, helpLabel); + return li; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java new file mode 100644 index 00000000000..b0f8ad9b418 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java @@ -0,0 +1,323 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.doclet.Doclet.Option; +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.doclet.Reporter; +import jdk.javadoc.internal.doclets.toolkit.AbstractDoclet; +import jdk.javadoc.internal.doclets.toolkit.Configuration; +import jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder; +import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; +import jdk.javadoc.internal.doclets.toolkit.util.DocFile; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.IndexBuilder; + +/** + * The class with "start" method, calls individual Writers. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Robert Field + * @author Jamie Ho + * + */ +public class HtmlDoclet extends AbstractDoclet { + + public HtmlDoclet() { + configuration = new ConfigurationImpl(); + } + + /** + * The global configuration information for this run. + */ + public final ConfigurationImpl configuration; + + + private static final DocPath DOCLET_RESOURCES = DocPath + .create("/jdk/javadoc/internal/doclets/formats/html/resources"); + + public void init(Locale locale, Reporter reporter) { + configuration.reporter = reporter; + configuration.locale = locale; + } + + /** + * The "start" method as required by Javadoc. + * + * @param root the root of the documentation tree. + * @see jdk.doclet.DocletEnvironment + * @return true if the doclet ran without encountering any errors. + */ + public boolean run(DocletEnvironment root) { + return startDoclet(root); + } + + /** + * Create the configuration instance. + * Override this method to use a different + * configuration. + */ + public Configuration configuration() { + return configuration; + } + + /** + * Start the generation of files. Call generate methods in the individual + * writers, which will in turn genrate the documentation files. Call the + * TreeWriter generation first to ensure the Class Hierarchy is built + * first and then can be used in the later generation. + * + * For new format. + * + * @see jdk.doclet.RootDoc + */ + protected void generateOtherFiles(DocletEnvironment root, ClassTree classtree) + throws Exception { + super.generateOtherFiles(root, classtree); + if (configuration.linksource) { + SourceToHTMLConverter.convertRoot(configuration, + root, DocPaths.SOURCE_OUTPUT); + } + + if (configuration.topFile.isEmpty()) { + configuration.standardmessage. + error("doclet.No_Non_Deprecated_Classes_To_Document"); + return; + } + boolean nodeprecated = configuration.nodeprecated; + performCopy(configuration.helpfile); + performCopy(configuration.stylesheetfile); + // do early to reduce memory footprint + if (configuration.classuse) { + ClassUseWriter.generate(configuration, classtree); + } + IndexBuilder indexbuilder = new IndexBuilder(configuration, nodeprecated); + + if (configuration.createtree) { + TreeWriter.generate(configuration, classtree); + } + if (configuration.createindex) { + configuration.buildSearchTagIndex(); + if (configuration.splitindex) { + SplitIndexWriter.generate(configuration, indexbuilder); + } else { + SingleIndexWriter.generate(configuration, indexbuilder); + } + } + + if (!(configuration.nodeprecatedlist || nodeprecated)) { + DeprecatedListWriter.generate(configuration); + } + + AllClassesFrameWriter.generate(configuration, + new IndexBuilder(configuration, nodeprecated, true)); + + FrameOutputWriter.generate(configuration); + + if (configuration.createoverview) { + PackageIndexWriter.generate(configuration); + } + if (configuration.helpfile.length() == 0 && + !configuration.nohelp) { + HelpWriter.generate(configuration); + } + // If a stylesheet file is not specified, copy the default stylesheet + // and replace newline with platform-specific newline. + DocFile f; + if (configuration.stylesheetfile.length() == 0) { + f = DocFile.createFileForOutput(configuration, DocPaths.STYLESHEET); + f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.STYLESHEET), false, true); + } + f = DocFile.createFileForOutput(configuration, DocPaths.JAVASCRIPT); + f.copyResource(DocPaths.RESOURCES.resolve(DocPaths.JAVASCRIPT), true, true); + if (configuration.createindex) { + f = DocFile.createFileForOutput(configuration, DocPaths.SEARCH_JS); + f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.SEARCH_JS), true, true); + + f = DocFile.createFileForOutput(configuration, DocPaths.RESOURCES.resolve(DocPaths.GLASS_IMG)); + f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.GLASS_IMG), true, false); + + f = DocFile.createFileForOutput(configuration, DocPaths.RESOURCES.resolve(DocPaths.X_IMG)); + f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.X_IMG), true, false); + copyJqueryFiles(); + } + } + + protected void copyJqueryFiles() { + List files = Arrays.asList( + "jquery-1.10.2.js", + "jquery-ui.js", + "jquery-ui.css", + "jquery-ui.min.js", + "jquery-ui.min.css", + "jquery-ui.structure.min.css", + "jquery-ui.structure.css", + "external/jquery/jquery.js", + "jszip/dist/jszip.js", + "jszip/dist/jszip.min.js", + "jszip-utils/dist/jszip-utils.js", + "jszip-utils/dist/jszip-utils.min.js", + "jszip-utils/dist/jszip-utils-ie.js", + "jszip-utils/dist/jszip-utils-ie.min.js", + "images/ui-bg_flat_0_aaaaaa_40x100.png", + "images/ui-icons_454545_256x240.png", + "images/ui-bg_glass_95_fef1ec_1x400.png", + "images/ui-bg_glass_75_dadada_1x400.png", + "images/ui-bg_highlight-soft_75_cccccc_1x100.png", + "images/ui-icons_888888_256x240.png", + "images/ui-icons_2e83ff_256x240.png", + "images/ui-bg_glass_65_ffffff_1x400.png", + "images/ui-icons_cd0a0a_256x240.png", + "images/ui-bg_glass_55_fbf9ee_1x400.png", + "images/ui-icons_222222_256x240.png", + "images/ui-bg_glass_75_e6e6e6_1x400.png", + "images/ui-bg_flat_75_ffffff_40x100.png"); + DocFile f; + for (String file : files) { + DocPath filePath = DocPaths.JQUERY_FILES.resolve(file); + f = DocFile.createFileForOutput(configuration, filePath); + f.copyResource(DOCLET_RESOURCES.resolve(filePath), true, false); + } + } + + /** + * {@inheritDoc} + */ + protected void generateClassFiles(SortedSet arr, ClassTree classtree) { + List list = new ArrayList<>(arr); + ListIterator iterator = list.listIterator(); + TypeElement klass = null; + while (iterator.hasNext()) { + TypeElement prev = iterator.hasPrevious() ? klass : null; + klass = iterator.next(); + TypeElement next = iterator.nextIndex() == list.size() + ? null : list.get(iterator.nextIndex()); + if (!(configuration.isGeneratedDoc(klass) && utils.isIncluded(klass))) { + continue; + } + try { + if (utils.isAnnotationType(klass)) { + AbstractBuilder annotationTypeBuilder = + configuration.getBuilderFactory() + .getAnnotationTypeBuilder(klass, + prev == null ? null : prev.asType(), + next == null ? null : next.asType()); + annotationTypeBuilder.build(); + } else { + AbstractBuilder classBuilder = + configuration.getBuilderFactory().getClassBuilder(klass, + prev, next, classtree); + classBuilder.build(); + } + } catch (IOException e) { + throw new DocletAbortException(e); + } catch (DocletAbortException de) { + throw de; + } catch (Exception e) { + e.printStackTrace(); + throw new DocletAbortException(e); + } + } + } + + + /** + * {@inheritDoc} + */ + protected void generatePackageFiles(ClassTree classtree) throws Exception { + Set packages = configuration.packages; + if (packages.size() > 1) { + PackageIndexFrameWriter.generate(configuration); + } + List pList = new ArrayList<>(packages); + PackageElement prev = null; + for (int i = 0 ; i < pList.size() ; i++) { + // if -nodeprecated option is set and the package is marked as + // deprecated, do not generate the package-summary.html, package-frame.html + // and package-tree.html pages for that package. + PackageElement pkg = pList.get(i); + if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) { + PackageFrameWriter.generate(configuration, pkg); + int nexti = i + 1; + PackageElement next = null; + if (nexti < pList.size()) { + next = pList.get(nexti); + // If the next package is unnamed package, skip 2 ahead if possible + if (next.isUnnamed() && ++nexti < pList.size()) { + next = pList.get(nexti); + } + } + AbstractBuilder packageSummaryBuilder = + configuration.getBuilderFactory().getPackageSummaryBuilder( + pkg, prev, next); + packageSummaryBuilder.build(); + if (configuration.createtree) { + PackageTreeWriter.generate(configuration, pkg, prev, next, + configuration.nodeprecated); + } + prev = pkg; + } + } + } + + public Set

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Robert Field + * @author Bhavesh Patel (Modified) + */ +public class HtmlDocletWriter extends HtmlDocWriter { + + /** + * Relative path from the file getting generated to the destination + * directory. For example, if the file getting generated is + * "java/lang/Object.html", then the path to the root is "../..". + * This string can be empty if the file getting generated is in + * the destination directory. + */ + public final DocPath pathToRoot; + + /** + * Platform-independent path from the current or the + * destination directory to the file getting generated. + * Used when creating the file. + */ + public final DocPath path; + + /** + * Name of the file getting generated. If the file getting generated is + * "java/lang/Object.html", then the filename is "Object.html". + */ + public final DocPath filename; + + /** + * The global configuration information for this run. + */ + public final ConfigurationImpl configuration; + + protected final Utils utils; + + /** + * To check whether annotation heading is printed or not. + */ + protected boolean printedAnnotationHeading = false; + + /** + * To check whether annotation field heading is printed or not. + */ + protected boolean printedAnnotationFieldHeading = false; + + /** + * To check whether the repeated annotations is documented or not. + */ + private boolean isAnnotationDocumented = false; + + /** + * To check whether the container annotations is documented or not. + */ + private boolean isContainerDocumented = false; + + HtmlTree fixedNavDiv = new HtmlTree(HtmlTag.DIV); + + /** + * Constructor to construct the HtmlStandardWriter object. + * + * @param path File to be generated. + */ + public HtmlDocletWriter(ConfigurationImpl configuration, DocPath path) + throws IOException { + super(configuration, path); + this.configuration = configuration; + this.utils = configuration.utils; + this.path = path; + this.pathToRoot = path.parent().invert(); + this.filename = path.basename(); + } + + /** + * Replace {@docRoot} tag used in options that accept HTML text, such + * as -header, -footer, -top and -bottom, and when converting a relative + * HREF where commentTagsToString inserts a {@docRoot} where one was + * missing. (Also see DocRootTaglet for {@docRoot} tags in doc + * comments.) + *

          + * Replace {@docRoot} tag in htmlstr with the relative path to the + * destination directory from the directory where the file is being + * written, looping to handle all such tags in htmlstr. + *

          + * For example, for "-d docs" and -header containing {@docRoot}, when + * the HTML page for source file p/C1.java is being generated, the + * {@docRoot} tag would be inserted into the header as "../", + * the relative path from docs/p/ to docs/ (the document root). + *

          + * Note: This doc comment was written with '&#064;' representing '@' + * to prevent the inline tag from being interpreted. + */ + public String replaceDocRootDir(String htmlstr) { + // Return if no inline tags exist + int index = htmlstr.indexOf("{@"); + if (index < 0) { + return htmlstr; + } + Matcher docrootMatcher = docrootPattern.matcher(htmlstr); + if (!docrootMatcher.find()) { + return htmlstr; + } + StringBuilder buf = new StringBuilder(); + int prevEnd = 0; + do { + int match = docrootMatcher.start(); + // append htmlstr up to start of next {@docroot} + buf.append(htmlstr.substring(prevEnd, match)); + prevEnd = docrootMatcher.end(); + if (configuration.docrootparent.length() > 0 && htmlstr.startsWith("/..", prevEnd)) { + // Insert the absolute link if {@docRoot} is followed by "/..". + buf.append(configuration.docrootparent); + prevEnd += 3; + } else { + // Insert relative path where {@docRoot} was located + buf.append(pathToRoot.isEmpty() ? "." : pathToRoot.getPath()); + } + // Append slash if next character is not a slash + if (prevEnd < htmlstr.length() && htmlstr.charAt(prevEnd) != '/') { + buf.append('/'); + } + } while (docrootMatcher.find()); + buf.append(htmlstr.substring(prevEnd)); + return buf.toString(); + } + //where: + // Note: {@docRoot} is not case sensitive when passed in w/command line option: + private static final Pattern docrootPattern = + Pattern.compile(Pattern.quote("{@docroot}"), Pattern.CASE_INSENSITIVE); + + /** + * Get the script to show or hide the All classes link. + * + * @param id id of the element to show or hide + * @return a content tree for the script + */ + public Content getAllClassesLinkScript(String id) { + HtmlTree script = HtmlTree.SCRIPT(); + String scriptCode = "" + DocletConstants.NL; + Content scriptContent = new RawHtml(scriptCode); + script.addContent(scriptContent); + Content div = HtmlTree.DIV(script); + Content div_noscript = HtmlTree.DIV(getResource("doclet.No_Script_Message")); + Content noScript = HtmlTree.NOSCRIPT(div_noscript); + div.addContent(noScript); + return div; + } + + /** + * Add method information. + * + * @param method the method to be documented + * @param dl the content tree to which the method information will be added + */ + private void addMethodInfo(ExecutableElement method, Content dl) { + TypeElement enclosing = utils.getEnclosingTypeElement(method); + List intfacs = enclosing.getInterfaces(); + ExecutableElement overriddenMethod = utils.overriddenMethod(method); + // Check whether there is any implementation or overridden info to be + // printed. If no overridden or implementation info needs to be + // printed, do not print this section. + if ((!intfacs.isEmpty() + && new ImplementedMethods(method, this.configuration).build().isEmpty() == false) + || overriddenMethod != null) { + MethodWriterImpl.addImplementsInfo(this, method, dl); + if (overriddenMethod != null) { + MethodWriterImpl.addOverridden(this, + utils.overriddenType(method), + overriddenMethod, + dl); + } + } + } + + /** + * Adds the tags information. + * + * @param e the Element for which the tags will be generated + * @param htmltree the documentation tree to which the tags will be added + */ + protected void addTagsInfo(Element e, Content htmltree) { + if (configuration.nocomment) { + return; + } + Content dl = new HtmlTree(HtmlTag.DL); + if (utils.isExecutableElement(e) && !utils.isConstructor(e)) { + addMethodInfo((ExecutableElement)e, dl); + } + Content output = new ContentBuilder(); + TagletWriter.genTagOutput(configuration.tagletManager, e, + configuration.tagletManager.getCustomTaglets(e), + getTagletWriterInstance(false), output); + dl.addContent(output); + htmltree.addContent(dl); + } + + /** + * Check whether there are any tags for Serialization Overview + * section to be printed. + * + * @param field the VariableElement object to check for tags. + * @return true if there are tags to be printed else return false. + */ + protected boolean hasSerializationOverviewTags(VariableElement field) { + Content output = new ContentBuilder(); + TagletWriter.genTagOutput(configuration.tagletManager, field, + configuration.tagletManager.getCustomTaglets(field), + getTagletWriterInstance(false), output); + return !output.isEmpty(); + } + + /** + * Returns a TagletWriter that knows how to write HTML. + * + * @return a TagletWriter that knows how to write HTML. + */ + public TagletWriter getTagletWriterInstance(boolean isFirstSentence) { + return new TagletWriterImpl(this, isFirstSentence); + } + + /** + * Get Package link, with target frame. + * + * @param pkg The link will be to the "package-summary.html" page for this package + * @param target name of the target frame + * @param label tag for the link + * @return a content for the target package link + */ + public Content getTargetPackageLink(PackageElement pkg, String target, + Content label) { + return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), label, "", target); + } + + + public void addClassesSummary(SortedSet classes, String label, + String tableSummary, List tableHeader, Content summaryContentTree) { + if (!classes.isEmpty()) { + Content caption = getTableCaption(new RawHtml(label)); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.typeSummary, caption) + : HtmlTree.TABLE(HtmlStyle.typeSummary, tableSummary, caption); + table.addContent(getSummaryTableHeader(tableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (TypeElement te : classes) { + if (!utils.isCoreClass(te) || + !configuration.isGeneratedDoc(te)) { + continue; + } + Content classContent = getLink(new LinkInfoImpl( + configuration, LinkInfoImpl.Kind.PACKAGE, te)); + Content tdClass = HtmlTree.TD(HtmlStyle.colFirst, classContent); + HtmlTree tr = HtmlTree.TR(tdClass); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD); + tdClassDescription.addStyle(HtmlStyle.colLast); + if (utils.isDeprecated(te)) { + tdClassDescription.addContent(deprecatedLabel); + List tags = utils.getDeprecatedTrees(te); + if (!tags.isEmpty()) { + addSummaryDeprecatedComment(te, tags.get(0), tdClassDescription); + } + } else { + addSummaryComment(te, tdClassDescription); + } + tr.addContent(tdClassDescription); + tbody.addContent(tr); + } + table.addContent(tbody); + summaryContentTree.addContent(table); + } + } + + /** + * Generates the HTML document tree and prints it out. + * + * @param metakeywords Array of String keywords for META tag. Each element + * of the array is assigned to a separate META tag. + * Pass in null for no array + * @param includeScript true if printing windowtitle script + * false for files that appear in the left-hand frames + * @param body the body htmltree to be included in the document + */ + public void printHtmlDocument(List metakeywords, boolean includeScript, + Content body) throws IOException { + Content htmlDocType = configuration.isOutputHtml5() + ? DocType.HTML5 + : DocType.TRANSITIONAL; + Content htmlComment = new Comment(configuration.getText("doclet.New_Page")); + Content head = new HtmlTree(HtmlTag.HEAD); + head.addContent(getGeneratedBy(!configuration.notimestamp)); + head.addContent(getTitle()); + Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, + (configuration.charset.length() > 0) ? + configuration.charset : HtmlConstants.HTML_DEFAULT_CHARSET); + head.addContent(meta); + if (!configuration.notimestamp) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + meta = HtmlTree.META(configuration.isOutputHtml5() + ? "dc.created" + : "date", dateFormat.format(new Date())); + head.addContent(meta); + } + if (metakeywords != null) { + for (String metakeyword : metakeywords) { + meta = HtmlTree.META("keywords", metakeyword); + head.addContent(meta); + } + } + addStyleSheetProperties(head); + addScriptProperties(head); + Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), + head, body); + Content htmlDocument = new HtmlDocument(htmlDocType, + htmlComment, htmlTree); + write(htmlDocument); + } + + /** + * Get the window title. + * + * @param title the title string to construct the complete window title + * @return the window title string + */ + public String getWindowTitle(String title) { + if (configuration.windowtitle.length() > 0) { + title += " (" + configuration.windowtitle + ")"; + } + return title; + } + + /** + * Get user specified header and the footer. + * + * @param header if true print the user provided header else print the + * user provided footer. + */ + public Content getUserHeaderFooter(boolean header) { + String content; + if (header) { + content = replaceDocRootDir(configuration.header); + } else { + if (configuration.footer.length() != 0) { + content = replaceDocRootDir(configuration.footer); + } else { + content = replaceDocRootDir(configuration.header); + } + } + Content rawContent = new RawHtml(content); + return rawContent; + } + + /** + * Adds the user specified top. + * + * @param htmlTree the content tree to which user specified top will be added + */ + public void addTop(Content htmlTree) { + Content top = new RawHtml(replaceDocRootDir(configuration.top)); + fixedNavDiv.addContent(top); + } + + /** + * Adds the user specified bottom. + * + * @param htmlTree the content tree to which user specified bottom will be added + */ + public void addBottom(Content htmlTree) { + Content bottom = new RawHtml(replaceDocRootDir(configuration.bottom)); + Content small = HtmlTree.SMALL(bottom); + Content p = HtmlTree.P(HtmlStyle.legalCopy, small); + htmlTree.addContent(p); + } + + /** + * Adds the navigation bar for the Html page at the top and and the bottom. + * + * @param header If true print navigation bar at the top of the page else + * @param htmlTree the HtmlTree to which the nav links will be added + */ + protected void addNavLinks(boolean header, Content htmlTree) { + if (!configuration.nonavbar) { + Content tree = (configuration.allowTag(HtmlTag.NAV)) + ? HtmlTree.NAV() + : htmlTree; + String allClassesId = "allclasses_"; + HtmlTree navDiv = new HtmlTree(HtmlTag.DIV); + fixedNavDiv.addStyle(HtmlStyle.fixedNav); + Content skipNavLinks = configuration.getResource("doclet.Skip_navigation_links"); + if (header) { + fixedNavDiv.addContent(HtmlConstants.START_OF_TOP_NAVBAR); + navDiv.addStyle(HtmlStyle.topNav); + allClassesId += "navbar_top"; + Content a = getMarkerAnchor(SectionName.NAVBAR_TOP); + //WCAG - Hyperlinks should contain text or an image with alt text - for AT tools + navDiv.addContent(a); + Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink( + getDocLink(SectionName.SKIP_NAVBAR_TOP), skipNavLinks, + skipNavLinks.toString(), "")); + navDiv.addContent(skipLinkContent); + } else { + tree.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR); + navDiv.addStyle(HtmlStyle.bottomNav); + allClassesId += "navbar_bottom"; + Content a = getMarkerAnchor(SectionName.NAVBAR_BOTTOM); + navDiv.addContent(a); + Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink( + getDocLink(SectionName.SKIP_NAVBAR_BOTTOM), skipNavLinks, + skipNavLinks.toString(), "")); + navDiv.addContent(skipLinkContent); + } + if (header) { + navDiv.addContent(getMarkerAnchor(SectionName.NAVBAR_TOP_FIRSTROW)); + } else { + navDiv.addContent(getMarkerAnchor(SectionName.NAVBAR_BOTTOM_FIRSTROW)); + } + HtmlTree navList = new HtmlTree(HtmlTag.UL); + navList.addStyle(HtmlStyle.navList); + navList.addAttr(HtmlAttr.TITLE, + configuration.getText("doclet.Navigation")); + if (configuration.createoverview) { + navList.addContent(getNavLinkContents()); + } + if (configuration.packages.size() == 1) { + navList.addContent(getNavLinkPackage(configuration.packages.first())); + } else if (!configuration.packages.isEmpty()) { + navList.addContent(getNavLinkPackage()); + } + navList.addContent(getNavLinkClass()); + if(configuration.classuse) { + navList.addContent(getNavLinkClassUse()); + } + if(configuration.createtree) { + navList.addContent(getNavLinkTree()); + } + if(!(configuration.nodeprecated || + configuration.nodeprecatedlist)) { + navList.addContent(getNavLinkDeprecated()); + } + if(configuration.createindex) { + navList.addContent(getNavLinkIndex()); + } + if (!configuration.nohelp) { + navList.addContent(getNavLinkHelp()); + } + navDiv.addContent(navList); + Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, getUserHeaderFooter(header)); + navDiv.addContent(aboutDiv); + if (header) { + fixedNavDiv.addContent(navDiv); + } else { + tree.addContent(navDiv); + } + Content ulNav = HtmlTree.UL(HtmlStyle.navList, getNavLinkPrevious()); + ulNav.addContent(getNavLinkNext()); + Content subDiv = HtmlTree.DIV(HtmlStyle.subNav, ulNav); + Content ulFrames = HtmlTree.UL(HtmlStyle.navList, getNavShowLists()); + ulFrames.addContent(getNavHideLists(filename)); + subDiv.addContent(ulFrames); + HtmlTree ulAllClasses = HtmlTree.UL(HtmlStyle.navList, getNavLinkClassIndex()); + ulAllClasses.addAttr(HtmlAttr.ID, allClassesId); + subDiv.addContent(ulAllClasses); + if (header && configuration.createindex) { + HtmlTree inputText = HtmlTree.INPUT("text", "search"); + HtmlTree inputReset = HtmlTree.INPUT("reset", "reset"); + Content searchTxt = configuration.getResource("doclet.search"); + searchTxt.addContent(getSpace()); + HtmlTree liInput = HtmlTree.LI(HtmlTree.SPAN(searchTxt)); + liInput.addContent(inputText); + liInput.addContent(inputReset); + HtmlTree ulSearch = HtmlTree.UL(HtmlStyle.navListSearch, liInput); + subDiv.addContent(ulSearch); + } + subDiv.addContent(getAllClassesLinkScript(allClassesId)); + addSummaryDetailLinks(subDiv); + if (header) { + subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_TOP)); + fixedNavDiv.addContent(subDiv); + fixedNavDiv.addContent(HtmlConstants.END_OF_TOP_NAVBAR); + tree.addContent(fixedNavDiv); + } else { + subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_BOTTOM)); + tree.addContent(subDiv); + tree.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR); + } + if (configuration.allowTag(HtmlTag.NAV)) { + htmlTree.addContent(tree); + } + } + } + + /** + * Get the word "NEXT" to indicate that no link is available. Override + * this method to customize next link. + * + * @return a content tree for the link + */ + protected Content getNavLinkNext() { + return getNavLinkNext(null); + } + + /** + * Get the word "PREV" to indicate that no link is available. Override + * this method to customize prev link. + * + * @return a content tree for the link + */ + protected Content getNavLinkPrevious() { + return getNavLinkPrevious(null); + } + + /** + * Do nothing. This is the default method. + */ + protected void addSummaryDetailLinks(Content navDiv) { + } + + /** + * Get link to the "overview-summary.html" page. + * + * @return a content tree for the link + */ + protected Content getNavLinkContents() { + Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_SUMMARY), + overviewLabel, "", ""); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get link to the "package-summary.html" page for the package passed. + * + * @param pkg Package to which link will be generated + * @return a content tree for the link + */ + protected Content getNavLinkPackage(PackageElement pkg) { + Content linkContent = getPackageLink(pkg, packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get the word "Package" , to indicate that link is not available here. + * + * @return a content tree for the link + */ + protected Content getNavLinkPackage() { + Content li = HtmlTree.LI(packageLabel); + return li; + } + + /** + * Get the word "Use", to indicate that link is not available. + * + * @return a content tree for the link + */ + protected Content getNavLinkClassUse() { + Content li = HtmlTree.LI(useLabel); + return li; + } + + /** + * Get link for previous file. + * + * @param prev File name for the prev link + * @return a content tree for the link + */ + public Content getNavLinkPrevious(DocPath prev) { + Content li; + if (prev != null) { + li = HtmlTree.LI(getHyperLink(prev, prevLabel, "", "")); + } + else + li = HtmlTree.LI(prevLabel); + return li; + } + + /** + * Get link for next file. If next is null, just print the label + * without linking it anywhere. + * + * @param next File name for the next link + * @return a content tree for the link + */ + public Content getNavLinkNext(DocPath next) { + Content li; + if (next != null) { + li = HtmlTree.LI(getHyperLink(next, nextLabel, "", "")); + } + else + li = HtmlTree.LI(nextLabel); + return li; + } + + /** + * Get "FRAMES" link, to switch to the frame version of the output. + * + * @param link File to be linked, "index.html" + * @return a content tree for the link + */ + protected Content getNavShowLists(DocPath link) { + DocLink dl = new DocLink(link, path.getPath(), null); + Content framesContent = getHyperLink(dl, framesLabel, "", "_top"); + Content li = HtmlTree.LI(framesContent); + return li; + } + + /** + * Get "FRAMES" link, to switch to the frame version of the output. + * + * @return a content tree for the link + */ + protected Content getNavShowLists() { + return getNavShowLists(pathToRoot.resolve(DocPaths.INDEX)); + } + + /** + * Get "NO FRAMES" link, to switch to the non-frame version of the output. + * + * @param link File to be linked + * @return a content tree for the link + */ + protected Content getNavHideLists(DocPath link) { + Content noFramesContent = getHyperLink(link, noframesLabel, "", "_top"); + Content li = HtmlTree.LI(noFramesContent); + return li; + } + + /** + * Get "Tree" link in the navigation bar. If there is only one package + * specified on the command line, then the "Tree" link will be to the + * only "package-tree.html" file otherwise it will be to the + * "overview-tree.html" file. + * + * @return a content tree for the link + */ + protected Content getNavLinkTree() { + List packages = new ArrayList<>(utils.getSpecifiedPackages()); + DocPath docPath = packages.size() == 1 && utils.getSpecifiedClasses().isEmpty() + ? pathString(packages.get(0), DocPaths.PACKAGE_TREE) + : pathToRoot.resolve(DocPaths.OVERVIEW_TREE); + return HtmlTree.LI(getHyperLink(docPath, treeLabel, "", "")); + } + + /** + * Get the overview tree link for the main tree. + * + * @param label the label for the link + * @return a content tree for the link + */ + protected Content getNavLinkMainTree(String label) { + Content mainTreeContent = getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), + new StringContent(label)); + Content li = HtmlTree.LI(mainTreeContent); + return li; + } + + /** + * Get the word "Class", to indicate that class link is not available. + * + * @return a content tree for the link + */ + protected Content getNavLinkClass() { + Content li = HtmlTree.LI(classLabel); + return li; + } + + /** + * Get "Deprecated" API link in the navigation bar. + * + * @return a content tree for the link + */ + protected Content getNavLinkDeprecated() { + Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST), + deprecatedLabel, "", ""); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get link for generated index. If the user has used "-splitindex" + * command line option, then link to file "index-files/index-1.html" is + * generated otherwise link to file "index-all.html" is generated. + * + * @return a content tree for the link + */ + protected Content getNavLinkClassIndex() { + Content allClassesContent = getHyperLink(pathToRoot.resolve( + DocPaths.ALLCLASSES_NOFRAME), + allclassesLabel, "", ""); + Content li = HtmlTree.LI(allClassesContent); + return li; + } + + /** + * Get link for generated class index. + * + * @return a content tree for the link + */ + protected Content getNavLinkIndex() { + Content linkContent = getHyperLink(pathToRoot.resolve( + (configuration.splitindex + ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1)) + : DocPaths.INDEX_ALL)), + indexLabel, "", ""); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get help file link. If user has provided a help file, then generate a + * link to the user given file, which is already copied to current or + * destination directory. + * + * @return a content tree for the link + */ + protected Content getNavLinkHelp() { + String helpfile = configuration.helpfile; + DocPath helpfilenm; + if (helpfile.isEmpty()) { + helpfilenm = DocPaths.HELP_DOC; + } else { + DocFile file = DocFile.createFileForInput(configuration, helpfile); + helpfilenm = DocPath.create(file.getName()); + } + Content linkContent = getHyperLink(pathToRoot.resolve(helpfilenm), + helpLabel, "", ""); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get summary table header. + * + * @param header the header for the table + * @param scope the scope of the headers + * @return a content tree for the header + */ + public Content getSummaryTableHeader(List header, String scope) { + Content tr = new HtmlTree(HtmlTag.TR); + final int size = header.size(); + Content tableHeader; + if (size == 1) { + tableHeader = new StringContent(header.get(0)); + tr.addContent(HtmlTree.TH(HtmlStyle.colOne, scope, tableHeader)); + return tr; + } + for (int i = 0; i < size; i++) { + tableHeader = new StringContent(header.get(i)); + if(i == 0) + tr.addContent(HtmlTree.TH(HtmlStyle.colFirst, scope, tableHeader)); + else if(i == (size - 1)) + tr.addContent(HtmlTree.TH(HtmlStyle.colLast, scope, tableHeader)); + else + tr.addContent(HtmlTree.TH(scope, tableHeader)); + } + return tr; + } + + /** + * Get table caption. + * + * @param rawText the caption for the table which could be raw Html + * @return a content tree for the caption + */ + public Content getTableCaption(Content title) { + Content captionSpan = HtmlTree.SPAN(title); + Content space = getSpace(); + Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space); + Content caption = HtmlTree.CAPTION(captionSpan); + caption.addContent(tabSpan); + return caption; + } + + /** + * Get the marker anchor which will be added to the documentation tree. + * + * @param anchorName the anchor name attribute + * @return a content tree for the marker anchor + */ + public Content getMarkerAnchor(String anchorName) { + return getMarkerAnchor(getName(anchorName), null); + } + + /** + * Get the marker anchor which will be added to the documentation tree. + * + * @param sectionName the section name anchor attribute for page + * @return a content tree for the marker anchor + */ + public Content getMarkerAnchor(SectionName sectionName) { + return getMarkerAnchor(sectionName.getName(), null); + } + + /** + * Get the marker anchor which will be added to the documentation tree. + * + * @param sectionName the section name anchor attribute for page + * @param anchorName the anchor name combined with section name attribute for the page + * @return a content tree for the marker anchor + */ + public Content getMarkerAnchor(SectionName sectionName, String anchorName) { + return getMarkerAnchor(sectionName.getName() + getName(anchorName), null); + } + + /** + * Get the marker anchor which will be added to the documentation tree. + * + * @param anchorName the anchor name or id attribute + * @param anchorContent the content that should be added to the anchor + * @return a content tree for the marker anchor + */ + public Content getMarkerAnchor(String anchorName, Content anchorContent) { + if (anchorContent == null) + anchorContent = new Comment(" "); + Content markerAnchor = HtmlTree.A(configuration.htmlVersion, anchorName, anchorContent); + return markerAnchor; + } + + /** + * Returns a packagename content. + * + * @param packageElement the package to check + * @return package name content + */ + public Content getPackageName(PackageElement packageElement) { + return packageElement == null || packageElement.isUnnamed() + ? defaultPackageLabel + : getPackageLabel(packageElement.getQualifiedName().toString()); + } + + /** + * Returns a package name label. + * + * @param packageName the package name + * @return the package name content + */ + public Content getPackageLabel(String packageName) { + return new StringContent(packageName); + } + + /** + * Add package deprecation information to the documentation tree + * + * @param deprPkgs list of deprecated packages + * @param headingKey the caption for the deprecated package table + * @param tableSummary the summary for the deprecated package table + * @param tableHeader table headers for the deprecated package table + * @param contentTree the content tree to which the deprecated package table will be added + */ + protected void addPackageDeprecatedAPI(SortedSet deprPkgs, String headingKey, + String tableSummary, List tableHeader, Content contentTree) { + if (deprPkgs.size() > 0) { + Content caption = getTableCaption(configuration.getResource(headingKey)); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption) + : HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption); + table.addContent(getSummaryTableHeader(tableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (Element e : deprPkgs) { + PackageElement pkg = (PackageElement) e; + HtmlTree td = HtmlTree.TD(HtmlStyle.colOne, + getPackageLink(pkg, getPackageName(pkg))); + List tags = utils.getDeprecatedTrees(pkg); + if (!tags.isEmpty()) { + addInlineDeprecatedComment(pkg, tags.get(0), td); + } + HtmlTree tr = HtmlTree.TR(td); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + tbody.addContent(tr); + } + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + Content ul = HtmlTree.UL(HtmlStyle.blockList, li); + contentTree.addContent(ul); + } + } + + /** + * Return the path to the class page for a typeElement. + * + * @param te TypeElement for which the path is requested. + * @param name Name of the file(doesn't include path). + */ + protected DocPath pathString(TypeElement te, DocPath name) { + return pathString(utils.containingPackage(te), name); + } + + /** + * Return path to the given file name in the given package. So if the name + * passed is "Object.html" and the name of the package is "java.lang", and + * if the relative path is "../.." then returned string will be + * "../../java/lang/Object.html" + * + * @param packageElement Package in which the file name is assumed to be. + * @param name File name, to which path string is. + */ + protected DocPath pathString(PackageElement packageElement, DocPath name) { + return pathToRoot.resolve(DocPath.forPackage(packageElement).resolve(name)); + } + + /** + * Given a package, return the name to be used in HTML anchor tag. + * @param packageElement the package. + * @return the name to be used in HTML anchor tag. + */ + public String getPackageAnchorName(PackageElement packageElement) { + return packageElement == null || packageElement.isUnnamed() + ? SectionName.UNNAMED_PACKAGE_ANCHOR.getName() + : utils.getPackageName(packageElement); + } + + /** + * Return the link to the given package. + * + * @param packageElement the package to link to. + * @param label the label for the link. + * @return a content tree for the package link. + */ + public Content getPackageLink(PackageElement packageElement, String label) { + return getPackageLink(packageElement, new StringContent(label)); + } + + public Content getPackageLink(PackageElement packageElement) { + StringContent content = packageElement.isUnnamed() + ? new StringContent() + : new StringContent(utils.getPackageName(packageElement)); + return getPackageLink(packageElement, content); + } + + /** + * Return the link to the given package. + * + * @param packageElement the package to link to. + * @param label the label for the link. + * @return a content tree for the package link. + */ + public Content getPackageLink(PackageElement packageElement, Content label) { + boolean included = packageElement != null && utils.isIncluded(packageElement); + if (!included) { + for (PackageElement p : configuration.packages) { + if (p.equals(packageElement)) { + included = true; + break; + } + } + } + if (included || packageElement == null) { + return getHyperLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY), + label); + } else { + DocLink crossPkgLink = getCrossPackageLink(utils.getPackageName(packageElement)); + if (crossPkgLink != null) { + return getHyperLink(crossPkgLink, label); + } else { + return label; + } + } + } + + public Content interfaceName(TypeElement typeElement, boolean qual) { + Content name = new StringContent((qual) + ? typeElement.getQualifiedName().toString() + : utils.getSimpleName(typeElement)); + return (utils.isInterface(typeElement)) ? HtmlTree.SPAN(HtmlStyle.interfaceName, name) : name; + } + + /** + * Add the link to the content tree. + * + * @param typeElement program element typeElement for which the link will be added + * @param label label for the link + * @param htmltree the content tree to which the link will be added + */ + public void addSrcLink(Element typeElement, Content label, Content htmltree) { + if (typeElement == null) { + return; + } + TypeElement te = utils.getEnclosingTypeElement(typeElement); + if (te == null) { + // must be a typeElement since in has no containing class. + te = (TypeElement) typeElement; + } + DocPath href = pathToRoot + .resolve(DocPaths.SOURCE_OUTPUT) + .resolve(DocPath.forClass(utils, te)); + Content linkContent = getHyperLink(href + .fragment(SourceToHTMLConverter.getAnchorName(utils, typeElement)), label, "", ""); + htmltree.addContent(linkContent); + } + + /** + * Return the link to the given class. + * + * @param linkInfo the information about the link. + * + * @return the link for the given class. + */ + public Content getLink(LinkInfoImpl linkInfo) { + LinkFactoryImpl factory = new LinkFactoryImpl(this); + return factory.getLink(linkInfo); + } + + /** + * Return the type parameters for the given class. + * + * @param linkInfo the information about the link. + * @return the type for the given class. + */ + public Content getTypeParameterLinks(LinkInfoImpl linkInfo) { + LinkFactoryImpl factory = new LinkFactoryImpl(this); + return factory.getTypeParameterLinks(linkInfo, false); + } + + /************************************************************* + * Return a class cross link to external class documentation. + * The name must be fully qualified to determine which package + * the class is in. The -link option does not allow users to + * link to external classes in the "default" package. + * + * @param qualifiedClassName the qualified name of the external class. + * @param refMemName the name of the member being referenced. This should + * be null or empty string if no member is being referenced. + * @param label the label for the external link. + * @param strong true if the link should be strong. + * @param style the style of the link. + * @param code true if the label should be code font. + */ + public Content getCrossClassLink(String qualifiedClassName, String refMemName, + Content label, boolean strong, String style, + boolean code) { + String className = ""; + String packageName = qualifiedClassName == null ? "" : qualifiedClassName; + int periodIndex; + while ((periodIndex = packageName.lastIndexOf('.')) != -1) { + className = packageName.substring(periodIndex + 1, packageName.length()) + + (className.length() > 0 ? "." + className : ""); + Content defaultLabel = new StringContent(className); + if (code) + defaultLabel = HtmlTree.CODE(defaultLabel); + packageName = packageName.substring(0, periodIndex); + if (getCrossPackageLink(packageName) != null) { + /* + The package exists in external documentation, so link to the external + class (assuming that it exists). This is definitely a limitation of + the -link option. There are ways to determine if an external package + exists, but no way to determine if the external class exists. We just + have to assume that it does. + */ + DocLink link = configuration.extern.getExternalLink(packageName, pathToRoot, + className + ".html", refMemName); + return getHyperLink(link, + (label == null) || label.isEmpty() ? defaultLabel : label, + strong, style, + configuration.getText("doclet.Href_Class_Or_Interface_Title", packageName), + ""); + } + } + return null; + } + + public boolean isClassLinkable(TypeElement typeElement) { + if (utils.isIncluded(typeElement)) { + return configuration.isGeneratedDoc(typeElement); + } + return configuration.extern.isExternal(typeElement); + } + + public DocLink getCrossPackageLink(String pkgName) { + return configuration.extern.getExternalLink(pkgName, pathToRoot, + DocPaths.PACKAGE_SUMMARY.getPath()); + } + + /** + * Get the class link. + * + * @param context the id of the context where the link will be added + * @param element to link to + * @return a content tree for the link + */ + public Content getQualifiedClassLink(LinkInfoImpl.Kind context, Element element) { + LinkInfoImpl linkInfoImpl = new LinkInfoImpl(configuration, context, (TypeElement)element); + return getLink(linkInfoImpl.label(utils.getFullyQualifiedName(element))); + } + + /** + * Add the class link. + * + * @param context the id of the context where the link will be added + * @param typeElement to link to + * @param contentTree the content tree to which the link will be added + */ + public void addPreQualifiedClassLink(LinkInfoImpl.Kind context, TypeElement typeElement, Content contentTree) { + addPreQualifiedClassLink(context, typeElement, false, contentTree); + } + + /** + * Retrieve the class link with the package portion of the label in + * plain text. If the qualifier is excluded, it will not be included in the + * link label. + * + * @param typeElement the class to link to. + * @param isStrong true if the link should be strong. + * @return the link with the package portion of the label in plain text. + */ + public Content getPreQualifiedClassLink(LinkInfoImpl.Kind context, + TypeElement typeElement, boolean isStrong) { + ContentBuilder classlink = new ContentBuilder(); + PackageElement pkg = utils.containingPackage(typeElement); + if (pkg != null && ! configuration.shouldExcludeQualifier(pkg.getSimpleName().toString())) { + classlink.addContent(getEnclosingPackageName(typeElement)); + } + classlink.addContent(getLink(new LinkInfoImpl(configuration, + context, typeElement).label(utils.getSimpleName(typeElement)).strong(isStrong))); + return classlink; + } + + /** + * Add the class link with the package portion of the label in + * plain text. If the qualifier is excluded, it will not be included in the + * link label. + * + * @param context the id of the context where the link will be added + * @param typeElement the class to link to + * @param isStrong true if the link should be strong + * @param contentTree the content tree to which the link with be added + */ + public void addPreQualifiedClassLink(LinkInfoImpl.Kind context, + TypeElement typeElement, boolean isStrong, Content contentTree) { + PackageElement pkg = utils.containingPackage(typeElement); + if(pkg != null && ! configuration.shouldExcludeQualifier(pkg.getSimpleName().toString())) { + contentTree.addContent(getEnclosingPackageName(typeElement)); + } + LinkInfoImpl linkinfo = new LinkInfoImpl(configuration, context, typeElement) + .label(utils.getSimpleName(typeElement)) + .strong(isStrong); + Content link = getLink(linkinfo); + contentTree.addContent(link); + } + + /** + * Add the class link, with only class name as the strong link and prefixing + * plain package name. + * + * @param context the id of the context where the link will be added + * @param typeElement the class to link to + * @param contentTree the content tree to which the link with be added + */ + public void addPreQualifiedStrongClassLink(LinkInfoImpl.Kind context, TypeElement typeElement, Content contentTree) { + addPreQualifiedClassLink(context, typeElement, true, contentTree); + } + + /** + * Get the link for the given member. + * + * @param context the id of the context where the link will be added + * @param element the member being linked to + * @param label the label for the link + * @return a content tree for the element link + */ + public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label) { + return getDocLink(context, utils.getEnclosingTypeElement(element), element, + new StringContent(label)); + } + + /** + * Return the link for the given member. + * + * @param context the id of the context where the link will be printed. + * @param element the member being linked to. + * @param label the label for the link. + * @param strong true if the link should be strong. + * @return the link for the given member. + */ + public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label, + boolean strong) { + return getDocLink(context, utils.getEnclosingTypeElement(element), element, label, strong); + } + + /** + * Return the link for the given member. + * + * @param context the id of the context where the link will be printed. + * @param typeElement the typeElement that we should link to. This is not + necessarily equal to element.containingClass(). We may be + inheriting comments. + * @param element the member being linked to. + * @param label the label for the link. + * @param strong true if the link should be strong. + * @return the link for the given member. + */ + public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, + String label, boolean strong) { + return getDocLink(context, typeElement, element, label, strong, false); + } + + public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, + Content label, boolean strong) { + return getDocLink(context, typeElement, element, label, strong, false); + } + + /** + * Return the link for the given member. + * + * @param context the id of the context where the link will be printed. + * @param typeElement the typeElement that we should link to. This is not + necessarily equal to element.containingClass(). We may be + inheriting comments. + * @param element the member being linked to. + * @param label the label for the link. + * @param strong true if the link should be strong. + * @param isProperty true if the element parameter is a JavaFX property. + * @return the link for the given member. + */ + public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, + String label, boolean strong, boolean isProperty) { + return getDocLink(context, typeElement, element, new StringContent(check(label)), strong, isProperty); + } + + String check(String s) { + if (s.matches(".*[&<>].*")) { + throw new IllegalArgumentException(s); + } + return s; + } + + public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, + Content label, boolean strong, boolean isProperty) { + if (! (utils.isIncluded(element) || utils.isLinkable(typeElement))) { + return label; + } else if (utils.isExecutableElement(element)) { + ExecutableElement ee = (ExecutableElement)element; + return getLink(new LinkInfoImpl(configuration, context, typeElement) + .label(label) + .where(getName(getAnchor(ee, isProperty))) + .strong(strong)); + } else if (utils.isVariableElement(element) || utils.isTypeElement(element)) { + return getLink(new LinkInfoImpl(configuration, context, typeElement) + .label(label) + .where(getName(element.getSimpleName().toString())) + .strong(strong)); + } else { + return label; + } + } + + /** + * Return the link for the given member. + * + * @param context the id of the context where the link will be added + * @param typeElement the typeElement that we should link to. This is not + necessarily equal to element.containingClass(). We may be + inheriting comments + * @param element the member being linked to + * @param label the label for the link + * @return the link for the given member + */ + public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, + Content label) { + if (! (utils.isIncluded(element) || utils.isLinkable(typeElement))) { + return label; + } else if (utils.isExecutableElement(element)) { + ExecutableElement emd = (ExecutableElement) element; + return getLink(new LinkInfoImpl(configuration, context, typeElement) + .label(label) + .where(getName(getAnchor(emd)))); + } else if (utils.isVariableElement(element) || utils.isTypeElement(element)) { + return getLink(new LinkInfoImpl(configuration, context, typeElement) + .label(label).where(getName(element.getSimpleName().toString()))); + } else { + return label; + } + } + + public String getAnchor(ExecutableElement executableElement) { + return getAnchor(executableElement, false); + } + + public String getAnchor(ExecutableElement executableElement, boolean isProperty) { + if (isProperty) { + return executableElement.getSimpleName().toString(); + } + String signature = utils.signature(executableElement); + StringBuilder signatureParsed = new StringBuilder(); + int counter = 0; + for (int i = 0; i < signature.length(); i++) { + char c = signature.charAt(i); + if (c == '<') { + counter++; + } else if (c == '>') { + counter--; + } else if (counter == 0) { + signatureParsed.append(c); + } + } + return utils.getSimpleName(executableElement) + signatureParsed.toString(); + } + + public Content seeTagToContent(Element element, DocTree see) { + + Kind kind = see.getKind(); + if (!(kind == LINK || kind == SEE || kind == LINK_PLAIN)) { + return new ContentBuilder(); + } + + CommentHelper ch = utils.getCommentHelper(element); + String tagName = ch.getTagName(see); + String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see))); + // Check if @see is an href or "string" + if (seetext.startsWith("<") || seetext.startsWith("\"")) { + return new RawHtml(seetext); + } + boolean isLinkPlain = kind == LINK_PLAIN; + Content label = plainOrCode(isLinkPlain, new RawHtml(ch.getLabel(configuration, see))); + + //The text from the @see tag. We will output this text when a label is not specified. + Content text = plainOrCode(kind == LINK_PLAIN, new RawHtml(seetext)); + + TypeElement refClass = ch.getReferencedClass(configuration, see); + String refClassName = ch.getReferencedClassName(configuration, see); + Element refMem = ch.getReferencedMember(configuration, see); + String refMemName = ch.getReferencedMemberName(see); + + if (refMemName == null && refMem != null) { + refMemName = refMem.toString(); + } + if (refClass == null) { + //@see is not referencing an included class + PackageElement refPackage = ch.getReferencedPackage(configuration, see); + if (refPackage != null && utils.isIncluded(refPackage)) { + //@see is referencing an included package + if (label.isEmpty()) + label = plainOrCode(isLinkPlain, + new StringContent(refPackage.getQualifiedName().toString())); + return getPackageLink(refPackage, label); + } else { + // @see is not referencing an included class or package. Check for cross links. + Content classCrossLink; + DocLink packageCrossLink = getCrossPackageLink(refClassName); + if (packageCrossLink != null) { + // Package cross link found + return getHyperLink(packageCrossLink, + (label.isEmpty() ? text : label)); + } else if ((classCrossLink = getCrossClassLink(refClassName, + refMemName, label, false, "", !isLinkPlain)) != null) { + // Class cross link found (possibly to a member in the class) + return classCrossLink; + } else { + // No cross link found so print warning + configuration.getDocletSpecificMsg().warning(ch.getDocTreePath(see), + "doclet.see.class_or_package_not_found", + "@" + tagName, + seetext); + return (label.isEmpty() ? text: label); + } + } + } else if (refMemName == null) { + // Must be a class reference since refClass is not null and refMemName is null. + if (label.isEmpty()) { + /* + * it seems to me this is the right thing to do, but it causes comparator failures. + */ + if (!configuration.backwardCompatibility) { + StringContent content = utils.isEnclosingPackageIncluded(refClass) + ? new StringContent(utils.getSimpleName(refClass)) + : new StringContent(utils.getFullyQualifiedName(refClass)); + label = plainOrCode(isLinkPlain, content); + } else { + label = plainOrCode(isLinkPlain, + new StringContent(utils.getSimpleName(refClass))); + } + + } + return getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, refClass) + .label(label)); + } else if (refMem == null) { + // Must be a member reference since refClass is not null and refMemName is not null. + // However, refMem is null, so this referenced member does not exist. + return (label.isEmpty() ? text: label); + } else { + // Must be a member reference since refClass is not null and refMemName is not null. + // refMem is not null, so this @see tag must be referencing a valid member. + TypeElement containing = utils.getEnclosingTypeElement(refMem); + if (ch.getText(see).trim().startsWith("#") && + ! (utils.isPublic(containing) || utils.isLinkable(containing))) { + // Since the link is relative and the holder is not even being + // documented, this must be an inherited link. Redirect it. + // The current class either overrides the referenced member or + // inherits it automatically. + if (this instanceof ClassWriterImpl) { + containing = ((ClassWriterImpl) this).getTypeElement(); + } else if (!utils.isPublic(containing)) { + configuration.getDocletSpecificMsg().warning( + ch.getDocTreePath(see), "doclet.see.class_or_package_not_accessible", + tagName, utils.getFullyQualifiedName(containing)); + } else { + configuration.getDocletSpecificMsg().warning( + ch.getDocTreePath(see), "doclet.see.class_or_package_not_found", + tagName, seetext); + } + } + if (configuration.currentTypeElement != containing) { + refMemName = (utils.isConstructor(refMem)) + ? refMemName + : utils.getSimpleName(containing) + "." + refMemName; + } + if (utils.isExecutableElement(refMem)) { + if (refMemName.indexOf('(') < 0) { + refMemName += utils.makeSignature((ExecutableElement)refMem, true); + } + } + + text = plainOrCode(kind == LINK_PLAIN, new StringContent(refMemName)); + + return getDocLink(LinkInfoImpl.Kind.SEE_TAG, containing, + refMem, (label.isEmpty() ? text: label), false); + } + } + + private Content plainOrCode(boolean plain, Content body) { + return (plain || body.isEmpty()) ? body : HtmlTree.CODE(body); + } + + /** + * Add the inline comment. + * + * @param element the Element for which the inline comment will be added + * @param tag the inline tag to be added + * @param htmltree the content tree to which the comment will be added + */ + public void addInlineComment(Element element, DocTree tag, Content htmltree) { + CommentHelper ch = utils.getCommentHelper(element); + List description = ch.getDescription(configuration, tag); + addCommentTags(element, tag, description, false, false, htmltree); + } + + /** + * Add the inline deprecated comment. + * + * @param e the Element for which the inline deprecated comment will be added + * @param tag the inline tag to be added + * @param htmltree the content tree to which the comment will be added + */ + public void addInlineDeprecatedComment(Element e, DocTree tag, Content htmltree) { + CommentHelper ch = utils.getCommentHelper(e); + addCommentTags(e, ch.getBody(configuration, tag), true, false, htmltree); + } + + /** + * Adds the summary content. + * + * @param element the Element for which the summary will be generated + * @param htmltree the documentation tree to which the summary will be added + */ + public void addSummaryComment(Element element, Content htmltree) { + addSummaryComment(element, utils.getFirstSentenceTrees(element), htmltree); + } + + /** + * Adds the summary content. + * + * @param element the Element for which the summary will be generated + * @param firstSentenceTags the first sentence tags for the doc + * @param htmltree the documentation tree to which the summary will be added + */ + public void addSummaryComment(Element element, List firstSentenceTags, Content htmltree) { + addCommentTags(element, firstSentenceTags, false, true, htmltree); + } + + public void addSummaryDeprecatedComment(Element element, DocTree tag, Content htmltree) { + CommentHelper ch = utils.getCommentHelper(element); + List body = ch.getBody(configuration, tag); + addCommentTags(element, ch.getFirstSentenceTrees(configuration, body), true, true, htmltree); + } + + /** + * Adds the inline comment. + * + * @param element the Element for which the inline comments will be generated + * @param htmltree the documentation tree to which the inline comments will be added + */ + public void addInlineComment(Element element, Content htmltree) { + addCommentTags(element, utils.getBody(element), false, false, htmltree); + } + + /** + * Adds the comment tags. + * + * @param element the Element for which the comment tags will be generated + * @param tags the first sentence tags for the doc + * @param depr true if it is deprecated + * @param first true if the first sentence tags should be added + * @param htmltree the documentation tree to which the comment tags will be added + */ + private void addCommentTags(Element element, List tags, boolean depr, + boolean first, Content htmltree) { + addCommentTags(element, null, tags, depr, first, htmltree); + } + + /** + * Adds the comment tags. + * + * @param element for which the comment tags will be generated + * @param holderTag the block tag context for the inline tags + * @param tags the first sentence tags for the doc + * @param depr true if it is deprecated + * @param first true if the first sentence tags should be added + * @param htmltree the documentation tree to which the comment tags will be added + */ + private void addCommentTags(Element element, DocTree holderTag, List tags, boolean depr, + boolean first, Content htmltree) { + if(configuration.nocomment){ + return; + } + Content div; + Content result = commentTagsToContent(null, element, tags, first); + if (depr) { + Content italic = HtmlTree.SPAN(HtmlStyle.deprecationComment, result); + div = HtmlTree.DIV(HtmlStyle.block, italic); + htmltree.addContent(div); + } + else { + div = HtmlTree.DIV(HtmlStyle.block, result); + htmltree.addContent(div); + } + if (tags.isEmpty()) { + htmltree.addContent(getSpace()); + } + } + + boolean ignoreNonInlineTag(DocTree dtree) { + Name name = null; + if (dtree.getKind() == Kind.START_ELEMENT) { + StartElementTree setree = (StartElementTree)dtree; + name = setree.getName(); + } else if (dtree.getKind() == Kind.END_ELEMENT) { + EndElementTree eetree = (EndElementTree)dtree; + name = eetree.getName(); + } + + if (name != null) { + com.sun.tools.doclint.HtmlTag htmlTag = com.sun.tools.doclint.HtmlTag.get(name); + if (htmlTag != null && + htmlTag.blockType != com.sun.tools.doclint.HtmlTag.BlockType.INLINE) { + return true; + } + } + return false; + } + + boolean isAllWhiteSpace(String body) { + for (int i = 0 ; i < body.length(); i++) { + if (!Character.isWhitespace(body.charAt(i))) + return false; + } + return true; + } + + /** + * Converts inline tags and text to text strings, expanding the + * inline tags along the way. Called wherever text can contain + * an inline tag, such as in comments or in free-form text arguments + * to non-inline tags. + * + * @param holderTag specific tag where comment resides + * @param element specific element where comment resides + * @param tags array of text tags and inline tags (often alternating) + present in the text of interest for this element + * @param isFirstSentence true if text is first sentence + * @return a Content object + */ + public Content commentTagsToContent(DocTree holderTag, Element element, + List tags, boolean isFirstSentence) { + + final Content result = new ContentBuilder() { + @Override + public void addContent(String text) { + super.addContent(utils.normalizeNewlines(text)); + } + }; + CommentHelper ch = utils.getCommentHelper(element); + // Array of all possible inline tags for this javadoc run + configuration.tagletManager.checkTags(utils, element, tags, true); + for (ListIterator iterator = tags.listIterator(); iterator.hasNext();) { + DocTree tag = iterator.next(); + // zap block tags + if (isFirstSentence && ignoreNonInlineTag(tag)) + continue; + + if (isFirstSentence && iterator.nextIndex() == tags.size() && + (tag.getKind() == TEXT && isAllWhiteSpace(ch.getText(tag)))) + continue; + + boolean allDone = new SimpleDocTreeVisitor() { + // notify the next DocTree handler to take necessary action + boolean commentRemoved = false; + + private boolean isLast(DocTree node) { + return node.equals(tags.get(tags.size() - 1)); + } + + private boolean isFirst(DocTree node) { + return node.equals(tags.get(0)); + } + + private boolean inAnAtag() { + if (utils.isStartElement(tag)) { + StartElementTree st = (StartElementTree)tag; + Name name = st.getName(); + if (name != null) { + com.sun.tools.doclint.HtmlTag htag = + com.sun.tools.doclint.HtmlTag.get(name); + return htag != null && htag.equals(com.sun.tools.doclint.HtmlTag.A); + } + } + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitAttribute(AttributeTree node, Content c) { + StringBuilder sb = new StringBuilder(SPACER).append(node.getName()); + if (node.getValueKind() == ValueKind.EMPTY) { + result.addContent(sb.toString()); + return false; + } + sb.append("="); + String quote; + switch (node.getValueKind()) { + case DOUBLE: + quote = "\""; + break; + case SINGLE: + quote = "\'"; + break; + default: + quote = ""; + break; + } + sb.append(quote); + result.addContent(sb.toString()); + Content docRootContent = new ContentBuilder(); + + for (DocTree dt : node.getValue()) { + if (utils.isText(dt) && inAnAtag()) { + String text = ((TextTree) dt).getBody(); + if (text.startsWith("/..") && !configuration.docrootparent.isEmpty()) { + result.addContent(configuration.docrootparent); + docRootContent = new ContentBuilder(); + text = textCleanup(text.substring(3), isLast(node)); + } else { + if (!docRootContent.isEmpty()) { + docRootContent = copyDocRootContent(docRootContent); + } else { + text = redirectRelativeLinks(element, (TextTree) dt); + } + text = textCleanup(text, isLast(node)); + } + result.addContent(text); + } else { + docRootContent = copyDocRootContent(docRootContent); + dt.accept(this, docRootContent); + } + } + copyDocRootContent(docRootContent); + result.addContent(quote); + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitComment(CommentTree node, Content c) { + if (isFirstSentence && isFirst(node)) { + commentRemoved = true; + return this.visit(iterator.next(), c); + } + result.addContent(new RawHtml(node.getBody())); + return false; + } + + private Content copyDocRootContent(Content content) { + if (!content.isEmpty()) { + result.addContent(content); + return new ContentBuilder(); + } + return content; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitDocRoot(DocRootTree node, Content c) { + Content docRootContent = TagletWriter.getInlineTagOutput(element, + configuration.tagletManager, + holderTag, + node, + getTagletWriterInstance(isFirstSentence)); + if (c != null) { + c.addContent(docRootContent); + } else { + result.addContent(docRootContent); + } + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitEndElement(EndElementTree node, Content c) { + RawHtml rawHtml = new RawHtml(""); + result.addContent(rawHtml); + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitEntity(EntityTree node, Content c) { + result.addContent(new RawHtml(node.toString())); + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitErroneous(ErroneousTree node, Content c) { + configuration.getDocletSpecificMsg().warning(ch.getDocTreePath(node), + "doclet.tag.invalid_usage", node); + result.addContent(new RawHtml(node.toString())); + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitInheritDoc(InheritDocTree node, Content c) { + Content output = TagletWriter.getInlineTagOutput(element, + configuration.tagletManager, holderTag, + tag, getTagletWriterInstance(isFirstSentence)); + result.addContent(output); + // if we obtained the first sentence successfully, nothing more to do + return (isFirstSentence && !output.isEmpty()); + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitIndex(IndexTree node, Content p) { + Content output = TagletWriter.getInlineTagOutput(element, + configuration.tagletManager, holderTag, tag, + getTagletWriterInstance(isFirstSentence)); + if (output != null) { + result.addContent(output); + } + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitLink(LinkTree node, Content c) { + // we need to pass the DocTreeImpl here, so ignore node + result.addContent(seeTagToContent(element, tag)); + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitLiteral(LiteralTree node, Content c) { + String s = node.getBody().toString(); + Content content = new StringContent(utils.normalizeNewlines(s)); + if (node.getKind() == CODE) + content = HtmlTree.CODE(content); + result.addContent(content); + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitSee(SeeTree node, Content c) { + // we need to pass the DocTreeImpl here, so ignore node + result.addContent(seeTagToContent(element, tag)); + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitStartElement(StartElementTree node, Content c) { + String text = "<" + node.getName(); + text = utils.normalizeNewlines(text); + RawHtml rawHtml = new RawHtml(text); + result.addContent(rawHtml); + + for (DocTree dt : node.getAttributes()) { + dt.accept(this, null); + } + result.addContent(new RawHtml(node.isSelfClosing() ? "/>" : ">")); + return false; + } + + private String textCleanup(String text, boolean isLast) { + return textCleanup(text, isLast, false); + } + + private String textCleanup(String text, boolean isLast, boolean trimLeader) { + if (trimLeader) { + text = removeLeadingWhitespace(text); + } + if (isFirstSentence && isLast) { + text = removeTrailingWhitespace(text); + } + text = utils.replaceTabs(text); + text = utils.normalizeNewlines(text); + return text; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Boolean visitText(TextTree node, Content c) { + String text = node.getBody(); + text = textCleanup(text, isLast(node), commentRemoved); + commentRemoved = false; + result.addContent(new RawHtml(text)); + return false; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + protected Boolean defaultAction(DocTree node, Content c) { + Content output = TagletWriter.getInlineTagOutput(element, + configuration.tagletManager, holderTag, tag, + getTagletWriterInstance(isFirstSentence)); + if (output != null) { + result.addContent(output); + } + return false; + } + + }.visit(tag, null); + if (allDone) + break; + } + return result; + } + + private String removeTrailingWhitespace(String text) { + char[] buf = text.toCharArray(); + for (int i = buf.length - 1; i > 0 ; i--) { + if (!Character.isWhitespace(buf[i])) + return text.substring(0, i + 1); + } + return text; + } + + private String removeLeadingWhitespace(String text) { + char[] buf = text.toCharArray(); + for (int i = 0; i < buf.length; i++) { + if (!Character.isWhitespace(buf[i])) { + return text.substring(i); + } + } + return text; + } + + /** + * Return true if relative links should not be redirected. + * + * @return Return true if a relative link should not be redirected. + */ + private boolean shouldNotRedirectRelativeLinks() { + return this instanceof AnnotationTypeWriter || + this instanceof ClassWriter || + this instanceof PackageSummaryWriter; + } + + /** + * Suppose a piece of documentation has a relative link. When you copy + * that documentation to another place such as the index or class-use page, + * that relative link will no longer work. We should redirect those links + * so that they will work again. + *

          + * Here is the algorithm used to fix the link: + *

          + * {@literal => docRoot + + } + *

          + * For example, suppose DocletEnvironment has this link: + * {@literal The package Page } + *

          + * If this link appeared in the index, we would redirect + * the link like this: + * + * {@literal The package Page} + * + * @param element the Element object whose documentation is being written. + * @param text the text being written. + * + * @return the text, with all the relative links redirected to work. + */ + private String redirectRelativeLinks(Element element, TextTree tt) { + String text = tt.getBody(); + if (element == null || utils.isOverviewElement(element) || shouldNotRedirectRelativeLinks()) { + return text; + } + + DocPath redirectPathFromRoot = new SimpleElementVisitor9() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public DocPath visitType(TypeElement e, Void p) { + return DocPath.forPackage(utils.containingPackage(e)); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public DocPath visitPackage(PackageElement e, Void p) { + return DocPath.forPackage(e); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public DocPath visitVariable(VariableElement e, Void p) { + return DocPath.forPackage(utils.containingPackage(e)); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public DocPath visitExecutable(ExecutableElement e, Void p) { + return DocPath.forPackage(utils.containingPackage(e)); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected DocPath defaultAction(Element e, Void p) { + return null; + } + }.visit(element); + if (redirectPathFromRoot == null) { + return text; + } + String lower = Utils.toLowerCase(text); + if (!(lower.startsWith("mailto:") + || lower.startsWith("http:") + || lower.startsWith("https:") + || lower.startsWith("file:"))) { + text = "{@" + (new DocRootTaglet()).getName() + "}/" + + redirectPathFromRoot.resolve(text).getPath(); + text = replaceDocRootDir(text); + } + return text; + } + + static final Set blockTags = new HashSet<>(); + static { + for (HtmlTag t: HtmlTag.values()) { + if (t.blockType == HtmlTag.BlockType.BLOCK) + blockTags.add(t.value); + } + } + + /** + * Add a link to the stylesheet file. + * + * @param head the content tree to which the files will be added + */ + public void addStyleSheetProperties(Content head) { + String stylesheetfile = configuration.stylesheetfile; + DocPath stylesheet; + if (stylesheetfile.isEmpty()) { + stylesheet = DocPaths.STYLESHEET; + } else { + DocFile file = DocFile.createFileForInput(configuration, stylesheetfile); + stylesheet = DocPath.create(file.getName()); + } + HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", + pathToRoot.resolve(stylesheet).getPath(), + "Style"); + head.addContent(link); + if (configuration.createindex) { + HtmlTree jq_link = HtmlTree.LINK("stylesheet", "text/css", + pathToRoot.resolve(DocPaths.JQUERY_FILES.resolve(DocPaths.JQUERY_STYLESHEET_FILE)).getPath(), + "Style"); + head.addContent(jq_link); + } + } + + /** + * Add a link to the JavaScript file. + * + * @param head the content tree to which the files will be added + */ + public void addScriptProperties(Content head) { + HtmlTree javascript = HtmlTree.SCRIPT(pathToRoot.resolve(DocPaths.JAVASCRIPT).getPath()); + head.addContent(javascript); + if (configuration.createindex) { + if (pathToRoot != null && script != null) { + String path = pathToRoot.isEmpty() ? "." : pathToRoot.getPath(); + script.addContent(new RawHtml("var pathtoroot = \"" + path + "/\";loadScripts(document, \'script\');")); + } + addJQueryFile(head, DocPaths.JSZIP_MIN); + addJQueryFile(head, DocPaths.JSZIPUTILS_MIN); + head.addContent(new RawHtml("")); + addJQueryFile(head, DocPaths.JQUERY_JS_1_10); + addJQueryFile(head, DocPaths.JQUERY_JS); + } + } + + /** + * Add a link to the JQuery javascript file. + * + * @param head the content tree to which the files will be added + * @param filePath the DocPath of the file that needs to be added + */ + private void addJQueryFile(Content head, DocPath filePath) { + HtmlTree jqyeryScriptFile = HtmlTree.SCRIPT( + pathToRoot.resolve(DocPaths.JQUERY_FILES.resolve(filePath)).getPath()); + head.addContent(jqyeryScriptFile); + } + + /** + * According to + * The Java™ Language Specification, + * all the outer classes and static nested classes are core classes. + */ + public boolean isCoreClass(TypeElement typeElement) { + return utils.getEnclosingTypeElement(typeElement) == null || utils.isStatic(typeElement); + } + + /** + * Adds the annotation types for the given packageElement. + * + * @param packageElement the package to write annotations for. + * @param htmltree the documentation tree to which the annotation info will be + * added + */ + public void addAnnotationInfo(PackageElement packageElement, Content htmltree) { + addAnnotationInfo(packageElement, packageElement.getAnnotationMirrors(), htmltree); + } + + /** + * Add the annotation types of the executable receiver. + * + * @param method the executable to write the receiver annotations for. + * @param descList list of annotation description. + * @param htmltree the documentation tree to which the annotation info will be + * added + */ + public void addReceiverAnnotationInfo(ExecutableElement method, List descList, + Content htmltree) { + addAnnotationInfo(0, method, descList, false, htmltree); + } + + /* + * this is a hack to delay dealing with Annotations in the writers, the assumption + * is that all necessary checks have been made to get here. + */ + public void addReceiverAnnotationInfo(ExecutableElement method, TypeMirror rcvrTypeMirror, + List annotationMirrors, Content htmltree) { + TypeMirror rcvrType = method.getReceiverType(); + List annotationMirrors1 = rcvrType.getAnnotationMirrors(); + addAnnotationInfo(0, method, annotationMirrors1, false, htmltree); + } + + /** + * Adds the annotatation types for the given element. + * + * @param element the package to write annotations for + * @param htmltree the content tree to which the annotation types will be added + */ + public void addAnnotationInfo(Element element, Content htmltree) { + addAnnotationInfo(element, element.getAnnotationMirrors(), htmltree); + } + + /** + * Add the annotatation types for the given element and parameter. + * + * @param indent the number of spaces to indent the parameters. + * @param element the element to write annotations for. + * @param param the parameter to write annotations for. + * @param tree the content tree to which the annotation types will be added + */ + public boolean addAnnotationInfo(int indent, Element element, VariableElement param, + Content tree) { + return addAnnotationInfo(indent, element, param.getAnnotationMirrors(), false, tree); + } + + /** + * Adds the annotatation types for the given Element. + * + * @param element the element to write annotations for. + * @param descList the array of {@link AnnotationDesc}. + * @param htmltree the documentation tree to which the annotation info will be + * added + */ + private void addAnnotationInfo(Element element, List descList, + Content htmltree) { + addAnnotationInfo(0, element, descList, true, htmltree); + } + + /** + * Adds the annotation types for the given element. + * + * @param indent the number of extra spaces to indent the annotations. + * @param element the element to write annotations for. + * @param descList the array of {@link AnnotationDesc}. + * @param htmltree the documentation tree to which the annotation info will be + * added + */ + private boolean addAnnotationInfo(int indent, Element element, + List descList, boolean lineBreak, Content htmltree) { + List annotations = getAnnotations(indent, descList, lineBreak); + String sep = ""; + if (annotations.isEmpty()) { + return false; + } + for (Content annotation: annotations) { + htmltree.addContent(sep); + htmltree.addContent(annotation); + if (!lineBreak) { + sep = " "; + } + } + return true; + } + + /** + * Return the string representations of the annotation types for + * the given doc. + * + * @param indent the number of extra spaces to indent the annotations. + * @param descList the array of {@link AnnotationDesc}. + * @param linkBreak if true, add new line between each member value. + * @return an array of strings representing the annotations being + * documented. + */ + private List getAnnotations(int indent, List descList, boolean linkBreak) { + return getAnnotations(indent, descList, linkBreak, true); + } + + private List getAnnotations(int indent, AnnotationMirror amirror, boolean linkBreak) { + List descList = new ArrayList<>(); + descList.add(amirror); + return getAnnotations(indent, descList, linkBreak, true); + } + + /** + * Return the string representations of the annotation types for + * the given doc. + * + * A {@code null} {@code elementType} indicates that all the + * annotations should be returned without any filtering. + * + * @param indent the number of extra spaces to indent the annotations. + * @param descList the array of {@link AnnotationDesc}. + * @param linkBreak if true, add new line between each member value. + * @param isJava5DeclarationLocation + * @return an array of strings representing the annotations being + * documented. + */ + public List getAnnotations(int indent, List descList, + boolean linkBreak, boolean isJava5DeclarationLocation) { + List results = new ArrayList<>(); + ContentBuilder annotation; + for (AnnotationMirror aDesc : descList) { + TypeElement annotationElement = (TypeElement)aDesc.getAnnotationType().asElement(); + // If an annotation is not documented, do not add it to the list. If + // the annotation is of a repeatable type, and if it is not documented + // and also if its container annotation is not documented, do not add it + // to the list. If an annotation of a repeatable type is not documented + // but its container is documented, it will be added to the list. + if (!utils.isDocumentedAnnotation(annotationElement) && + (!isAnnotationDocumented && !isContainerDocumented)) { + continue; + } + /* TODO: check logic here to correctly handle declaration + * and type annotations. + if (utils.isDeclarationAnnotation(annotationElement, isJava5DeclarationLocation)) { + continue; + }*/ + annotation = new ContentBuilder(); + isAnnotationDocumented = false; + LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.ANNOTATION, annotationElement); + Map pairs = aDesc.getElementValues(); + // If the annotation is synthesized, do not print the container. + if (utils.configuration.workArounds.isSynthesized(aDesc)) { + for (ExecutableElement ee : pairs.keySet()) { + AnnotationValue annotationValue = pairs.get(ee); + List annotationTypeValues = new ArrayList<>(); + + new SimpleAnnotationValueVisitor9>() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitArray(List vals, List p) { + p.addAll(vals); + return null; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Void defaultAction(Object o, List p) { + p.add(annotationValue); + return null; + } + }.visit(annotationValue, annotationTypeValues); + + String sep = ""; + for (AnnotationValue av : annotationTypeValues) { + annotation.addContent(sep); + annotation.addContent(annotationValueToContent(av)); + sep = " "; + } + } + } else if (isAnnotationArray(pairs)) { + // If the container has 1 or more value defined and if the + // repeatable type annotation is not documented, do not print + // the container. + if (pairs.size() == 1 && isAnnotationDocumented) { + List annotationTypeValues = new ArrayList<>(); + for (AnnotationValue a : pairs.values()) { + new SimpleAnnotationValueVisitor9>() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitArray(List vals, List annotationTypeValues) { + for (AnnotationValue av : vals) { + annotationTypeValues.add(av); + } + return null; + } + }.visit(a, annotationTypeValues); + } + String sep = ""; + for (AnnotationValue av : annotationTypeValues) { + annotation.addContent(sep); + annotation.addContent(annotationValueToContent(av)); + sep = " "; + } + } + // If the container has 1 or more value defined and if the + // repeatable type annotation is not documented, print the container. + else { + addAnnotations(annotationElement, linkInfo, annotation, pairs, + indent, false); + } + } + else { + addAnnotations(annotationElement, linkInfo, annotation, pairs, + indent, linkBreak); + } + annotation.addContent(linkBreak ? DocletConstants.NL : ""); + results.add(annotation); + } + return results; + } + + /** + * Add annotation to the annotation string. + * + * @param annotationDoc the annotation being documented + * @param linkInfo the information about the link + * @param annotation the annotation string to which the annotation will be added + * @param pairs annotation type element and value pairs + * @param indent the number of extra spaces to indent the annotations. + * @param linkBreak if true, add new line between each member value + */ + private void addAnnotations(TypeElement annotationDoc, LinkInfoImpl linkInfo, + ContentBuilder annotation, Mapmap, + int indent, boolean linkBreak) { + linkInfo.label = new StringContent("@" + annotationDoc.getSimpleName().toString()); + annotation.addContent(getLink(linkInfo)); + if (!map.isEmpty()) { + annotation.addContent("("); + boolean isFirst = true; + for (ExecutableElement element : map.keySet()) { + if (isFirst) { + isFirst = false; + } else { + annotation.addContent(","); + if (linkBreak) { + annotation.addContent(DocletConstants.NL); + int spaces = annotationDoc.getSimpleName().toString().length() + 2; + for (int k = 0; k < (spaces + indent); k++) { + annotation.addContent(" "); + } + } + } + annotation.addContent(getDocLink(LinkInfoImpl.Kind.ANNOTATION, + element, element.getSimpleName().toString(), false)); + annotation.addContent("="); + AnnotationValue annotationValue = map.get(element); + List annotationTypeValues = new ArrayList<>(); + new SimpleAnnotationValueVisitor9() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitArray(List vals, AnnotationValue p) { + annotationTypeValues.addAll(vals); + return null; + } + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Void defaultAction(Object o, AnnotationValue p) { + annotationTypeValues.add(p); + return null; + } + }.visit(annotationValue, annotationValue); + annotation.addContent(annotationTypeValues.size() == 1 ? "" : "{"); + String sep = ""; + for (AnnotationValue av : annotationTypeValues) { + annotation.addContent(sep); + annotation.addContent(annotationValueToContent(av)); + sep = ","; + } + annotation.addContent(annotationTypeValues.size() == 1 ? "" : "}"); + isContainerDocumented = false; + } + annotation.addContent(")"); + } + } + + /** + * Check if the annotation contains an array of annotation as a value. This + * check is to verify if a repeatable type annotation is present or not. + * + * @param pairs annotation type element and value pairs + * + * @return true if the annotation contains an array of annotation as a value. + */ + private boolean isAnnotationArray(Map pairs) { + AnnotationValue annotationValue; + for (ExecutableElement ee : pairs.keySet()) { + annotationValue = pairs.get(ee); + boolean rvalue = new SimpleAnnotationValueVisitor9() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Boolean visitArray(List vals, Void p) { + if (vals.size() > 1) { + if (vals.get(0) instanceof AnnotationMirror) { + isContainerDocumented = true; + return new SimpleAnnotationValueVisitor9() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Boolean visitAnnotation(AnnotationMirror a, Void p) { + isContainerDocumented = true; + Element asElement = a.getAnnotationType().asElement(); + if (utils.isDocumentedAnnotation((TypeElement)asElement)) { + isAnnotationDocumented = true; + } + return true; + } + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Boolean defaultAction(Object o, Void p) { + return false; + } + }.visit(vals.get(0)); + } + } + return false; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Boolean defaultAction(Object o, Void p) { + return false; + } + }.visit(annotationValue); + if (rvalue) { + return true; + } + } + return false; + } + + private Content annotationValueToContent(AnnotationValue annotationValue) { + return new SimpleAnnotationValueVisitor9() { + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Content visitType(TypeMirror t, Void p) { + return new SimpleTypeVisitor9() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Content visitDeclared(DeclaredType t, Void p) { + LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.ANNOTATION, t); + String name = utils.isIncluded(t.asElement()) + ? t.asElement().getSimpleName().toString() + : utils.getFullyQualifiedName(t.asElement()); + linkInfo.label = new StringContent(name + utils.getDimension(t) + ".class"); + return getLink(linkInfo); + } + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Content defaultAction(TypeMirror e, Void p) { + return new StringContent(t + utils.getDimension(t) + ".class"); + } + }.visit(t); + } + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Content visitAnnotation(AnnotationMirror a, Void p) { + List list = getAnnotations(0, a, false); + ContentBuilder buf = new ContentBuilder(); + for (Content c : list) { + buf.addContent(c); + } + return buf; + } + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Content visitEnumConstant(VariableElement c, Void p) { + return getDocLink(LinkInfoImpl.Kind.ANNOTATION, + c, c.getSimpleName().toString(), false); + } + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Content visitArray(List vals, Void p) { + ContentBuilder buf = new ContentBuilder(); + String sep = ""; + for (AnnotationValue av : vals) { + buf.addContent(sep); + buf.addContent(visit(av)); + sep = " "; + } + return buf; + } + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Content defaultAction(Object o, Void p) { + return new StringContent(annotationValue.toString()); + } + }.visit(annotationValue); + } + + /** + * Return the configuration for this doclet. + * + * @return the configuration for this doclet. + */ + public Configuration configuration() { + return configuration; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java new file mode 100644 index 00000000000..5421c278411 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.util.*; + +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; + +import com.sun.source.doctree.DocTree; + +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter; +import jdk.javadoc.internal.doclets.toolkit.taglets.TagletWriter; +import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; + +/** + * Generate serialized form for serializable fields. + * Documentation denoted by the tags serial and + * serialField is processed. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Joe Fialli + * @author Bhavesh Patel (Modified) + */ +public class HtmlSerialFieldWriter extends FieldWriterImpl + implements SerializedFormWriter.SerialFieldWriter { + + public HtmlSerialFieldWriter(SubWriterHolderWriter writer, TypeElement typeElement) { + super(writer, typeElement); + } + + public SortedSet members(TypeElement te) { + return utils.serializableFields(te); + } + + /** + * Return the header for serializable fields section. + * + * @return a content tree for the header + */ + public Content getSerializableFieldsHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * Return the header for serializable fields content section. + * + * @param isLastContent true if the cotent being documented is the last content. + * @return a content tree for the header + */ + public Content getFieldsContentHeader(boolean isLastContent) { + HtmlTree li = new HtmlTree(HtmlTag.LI); + if (isLastContent) + li.addStyle(HtmlStyle.blockListLast); + else + li.addStyle(HtmlStyle.blockList); + return li; + } + + /** + * Add serializable fields. + * + * @param heading the heading for the section + * @param serializableFieldsTree the tree to be added to the serializable fileds + * content tree + * @return a content tree for the serializable fields content + */ + public Content getSerializableFields(String heading, Content serializableFieldsTree) { + HtmlTree li = new HtmlTree(HtmlTag.LI); + li.addStyle(HtmlStyle.blockList); + if (serializableFieldsTree.isValid()) { + Content headingContent = new StringContent(heading); + Content serialHeading = HtmlTree.HEADING(HtmlConstants.SERIALIZED_MEMBER_HEADING, + headingContent); + li.addContent(serialHeading); + li.addContent(serializableFieldsTree); + } + return li; + } + + /** + * Add the member header. + * + * @param fieldType the class document to be listed + * @param fieldTypeStr the string for the field type to be documented + * @param fieldDimensions the dimensions of the field string to be added + * @param fieldName name of the field to be added + * @param contentTree the content tree to which the member header will be added + */ + public void addMemberHeader(TypeElement fieldType, String fieldTypeStr, + String fieldDimensions, String fieldName, Content contentTree) { + Content nameContent = new RawHtml(fieldName); + Content heading = HtmlTree.HEADING(HtmlConstants.MEMBER_HEADING, nameContent); + contentTree.addContent(heading); + Content pre = new HtmlTree(HtmlTag.PRE); + if (fieldType == null) { + pre.addContent(fieldTypeStr); + } else { + Content fieldContent = writer.getLink(new LinkInfoImpl( + configuration, LinkInfoImpl.Kind.SERIAL_MEMBER, fieldType)); + pre.addContent(fieldContent); + } + pre.addContent(fieldDimensions + " "); + pre.addContent(fieldName); + contentTree.addContent(pre); + } + + /** + * Add the deprecated information for this member. + * + * @param field the field to document. + * @param contentTree the tree to which the deprecated info will be added + */ + public void addMemberDeprecatedInfo(VariableElement field, Content contentTree) { + addDeprecatedInfo(field, contentTree); + } + + /** + * Add the description text for this member. + * + * @param field the field to document. + * @param contentTree the tree to which the deprecated info will be added + */ + public void addMemberDescription(VariableElement field, Content contentTree) { + if (!utils.getBody(field).isEmpty()) { + writer.addInlineComment(field, contentTree); + } + List tags = utils.getBlockTags(field, DocTree.Kind.SERIAL); + if (!tags.isEmpty()) { + writer.addInlineComment(field, tags.get(0), contentTree); + } + } + + /** + * Add the description text for this member represented by the tag. + * + * @param serialFieldTag the field to document (represented by tag) + * @param contentTree the tree to which the deprecated info will be added + */ + public void addMemberDescription(VariableElement field, DocTree serialFieldTag, Content contentTree) { + CommentHelper ch = utils.getCommentHelper(field); + List description = ch.getDescription(configuration, serialFieldTag); + if (!description.isEmpty()) { + Content serialFieldContent = new RawHtml(ch.getText(description)); + Content div = HtmlTree.DIV(HtmlStyle.block, serialFieldContent); + contentTree.addContent(div); + } + } + + /** + * Add the tag information for this member. + * + * @param field the field to document. + * @param contentTree the tree to which the member tags info will be added + */ + public void addMemberTags(VariableElement field, Content contentTree) { + Content tagContent = new ContentBuilder(); + TagletWriter.genTagOutput(configuration.tagletManager, field, + configuration.tagletManager.getCustomTaglets(field), + writer.getTagletWriterInstance(false), tagContent); + Content dlTags = new HtmlTree(HtmlTag.DL); + dlTags.addContent(tagContent); + contentTree.addContent(dlTags); // TODO: what if empty? + } + + /** + * Check to see if overview details should be printed. If + * nocomment option set or if there is no text to be printed + * for deprecation info, comment or tags, do not print overview details. + * + * @param field the field to check overview details for. + * @return true if overview details need to be printed + */ + public boolean shouldPrintOverview(VariableElement field) { + if (!configuration.nocomment) { + if(!utils.getBody(field).isEmpty() || + writer.hasSerializationOverviewTags(field)) + return true; + } + if (utils.isDeprecated(field)) + return true; + return false; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java new file mode 100644 index 00000000000..ca58a2e4dea --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter; +import jdk.javadoc.internal.doclets.toolkit.taglets.TagletManager; +import jdk.javadoc.internal.doclets.toolkit.taglets.TagletWriter; + + +/** + * Generate serialized form for Serializable/Externalizable methods. + * Documentation denoted by the serialData tag is processed. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Joe Fialli + * @author Bhavesh Patel (Modified) + */ +public class HtmlSerialMethodWriter extends MethodWriterImpl implements + SerializedFormWriter.SerialMethodWriter{ + + public HtmlSerialMethodWriter(SubWriterHolderWriter writer, TypeElement typeElement) { + super(writer, typeElement); + } + + /** + * Return the header for serializable methods section. + * + * @return a content tree for the header + */ + public Content getSerializableMethodsHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * Return the header for serializable methods content section. + * + * @param isLastContent true if the cotent being documented is the last content. + * @return a content tree for the header + */ + public Content getMethodsContentHeader(boolean isLastContent) { + HtmlTree li = new HtmlTree(HtmlTag.LI); + if (isLastContent) + li.addStyle(HtmlStyle.blockListLast); + else + li.addStyle(HtmlStyle.blockList); + return li; + } + + /** + * Add serializable methods. + * + * @param heading the heading for the section + * @param serializableMethodContent the tree to be added to the serializable methods + * content tree + * @return a content tree for the serializable methods content + */ + public Content getSerializableMethods(String heading, Content serializableMethodContent) { + Content headingContent = new StringContent(heading); + Content serialHeading = HtmlTree.HEADING(HtmlConstants.SERIALIZED_MEMBER_HEADING, + headingContent); + Content li = HtmlTree.LI(HtmlStyle.blockList, serialHeading); + li.addContent(serializableMethodContent); + return li; + } + + /** + * Return the no customization message. + * + * @param msg the message to be displayed + * @return no customization message content + */ + public Content getNoCustomizationMsg(String msg) { + Content noCustomizationMsg = new StringContent(msg); + return noCustomizationMsg; + } + + /** + * Add the member header. + * + * @param member the method document to be listed + * @param methodsContentTree the content tree to which the member header will be added + */ + public void addMemberHeader(ExecutableElement member, Content methodsContentTree) { + methodsContentTree.addContent(getHead(member)); + methodsContentTree.addContent(getSignature(member)); + } + + /** + * Add the deprecated information for this member. + * + * @param member the method to document. + * @param methodsContentTree the tree to which the deprecated info will be added + */ + public void addDeprecatedMemberInfo(ExecutableElement member, Content methodsContentTree) { + addDeprecatedInfo(member, methodsContentTree); + } + + /** + * Add the description text for this member. + * + * @param member the method to document. + * @param methodsContentTree the tree to which the deprecated info will be added + */ + public void addMemberDescription(ExecutableElement member, Content methodsContentTree) { + addComment(member, methodsContentTree); + } + + /** + * Add the tag information for this member. + * + * @param member the method to document. + * @param methodsContentTree the tree to which the member tags info will be added + */ + public void addMemberTags(ExecutableElement member, Content methodsContentTree) { + Content tagContent = new ContentBuilder(); + TagletManager tagletManager = + configuration.tagletManager; + TagletWriter.genTagOutput(tagletManager, member, + tagletManager.getSerializedFormTaglets(), + writer.getTagletWriterInstance(false), tagContent); + Content dlTags = new HtmlTree(HtmlTag.DL); + dlTags.addContent(tagContent); + methodsContentTree.addContent(dlTags); + if (name(member).compareTo("writeExternal") == 0 + && utils.getSerialDataTrees(member).isEmpty()) { + serialWarning(member, "doclet.MissingSerialDataTag", + utils.getFullyQualifiedName(member.getEnclosingElement()), name(member)); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java new file mode 100644 index 00000000000..dbb476920be --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.util.List; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.toolkit.Configuration; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.Utils; +import jdk.javadoc.internal.doclets.toolkit.util.links.LinkFactory; +import jdk.javadoc.internal.doclets.toolkit.util.links.LinkInfo; + +import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER_TYPE_PARAMS; + +/** + * A factory that returns a link given the information about it. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Jamie Ho + */ +public class LinkFactoryImpl extends LinkFactory { + + private final HtmlDocletWriter m_writer; + + public LinkFactoryImpl(HtmlDocletWriter writer) { + m_writer = writer; + } + + /** + * {@inheritDoc} + */ + @Override + protected Content newContent() { + return new ContentBuilder(); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getClassLink(LinkInfo linkInfo) { + Configuration configuration = m_writer.configuration; + Utils utils = configuration.utils; + LinkInfoImpl classLinkInfo = (LinkInfoImpl) linkInfo; + boolean noLabel = linkInfo.label == null || linkInfo.label.isEmpty(); + TypeElement typeElement = classLinkInfo.typeElement; + // Create a tool tip if we are linking to a class or interface. Don't + // create one if we are linking to a member. + String title = ""; + if (classLinkInfo.where == null || classLinkInfo.where.length() == 0) { + boolean isTypeLink = classLinkInfo.type != null && + utils.isTypeVariable(utils.getComponentType(classLinkInfo.type)); + title = getClassToolTip(typeElement, isTypeLink); + } + Content label = classLinkInfo.getClassLinkLabel(m_writer.configuration); + + Content link = new ContentBuilder(); + if (utils.isIncluded(typeElement)) { + if (configuration.isGeneratedDoc(typeElement)) { + DocPath filename = getPath(classLinkInfo); + if (linkInfo.linkToSelf || + !(DocPath.forName(utils, typeElement)).equals(m_writer.filename)) { + link.addContent(m_writer.getHyperLink( + filename.fragment(classLinkInfo.where), + label, + classLinkInfo.isStrong, classLinkInfo.styleName, + title, classLinkInfo.target)); + if (noLabel && !classLinkInfo.excludeTypeParameterLinks) { + link.addContent(getTypeParameterLinks(linkInfo)); + } + return link; + } + } + } else { + Content crossLink = m_writer.getCrossClassLink( + typeElement.getQualifiedName().toString(), classLinkInfo.where, + label, classLinkInfo.isStrong, classLinkInfo.styleName, + true); + if (crossLink != null) { + link.addContent(crossLink); + if (noLabel && !classLinkInfo.excludeTypeParameterLinks) { + link.addContent(getTypeParameterLinks(linkInfo)); + } + return link; + } + } + // Can't link so just write label. + link.addContent(label); + if (noLabel && !classLinkInfo.excludeTypeParameterLinks) { + link.addContent(getTypeParameterLinks(linkInfo)); + } + return link; + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getTypeParameterLink(LinkInfo linkInfo, TypeMirror typeParam) { + LinkInfoImpl typeLinkInfo = new LinkInfoImpl(m_writer.configuration, + ((LinkInfoImpl) linkInfo).getContext(), typeParam); + typeLinkInfo.excludeTypeBounds = linkInfo.excludeTypeBounds; + typeLinkInfo.excludeTypeParameterLinks = linkInfo.excludeTypeParameterLinks; + typeLinkInfo.linkToSelf = linkInfo.linkToSelf; + typeLinkInfo.isJava5DeclarationLocation = false; + return getLink(typeLinkInfo); + } + + @Override + protected Content getTypeAnnotationLink(LinkInfo linkInfo, AnnotationMirror annotation) { + throw new RuntimeException("Not implemented yet!"); + } + + @Override + public Content getTypeAnnotationLinks(LinkInfo linkInfo) { + Utils utils = ((LinkInfoImpl)linkInfo).utils; + ContentBuilder links = new ContentBuilder(); + List annotations; + if (utils.isAnnotated(linkInfo.type)) { + annotations = linkInfo.type.getAnnotationMirrors(); + } else if (utils.isTypeVariable(linkInfo.type)) { + // TODO: use the context for now, and special case for Receiver_Types, + // which takes the default case. + switch (((LinkInfoImpl)linkInfo).context) { + case MEMBER_TYPE_PARAMS: + case EXECUTABLE_MEMBER_PARAM: + case CLASS_SIGNATURE: + Element element = utils.typeUtils.asElement(linkInfo.type); + annotations = element.getAnnotationMirrors(); + break; + default: + annotations = linkInfo.type.getAnnotationMirrors(); + break; + } + + } else { + return links; + } + + if (annotations.isEmpty()) + return links; + + List annos = m_writer.getAnnotations(0, annotations, false, linkInfo.isJava5DeclarationLocation); + + boolean isFirst = true; + for (Content anno : annos) { + if (!isFirst) { + links.addContent(" "); + } + links.addContent(anno); + isFirst = false; + } + if (!annos.isEmpty()) { + links.addContent(" "); + } + + return links; + } + + /** + * Given a class, return the appropriate tool tip. + * + * @param typeElement the class to get the tool tip for. + * @return the tool tip for the appropriate class. + */ + private String getClassToolTip(TypeElement typeElement, boolean isTypeLink) { + Configuration configuration = m_writer.configuration; + Utils utils = configuration.utils; + if (isTypeLink) { + return configuration.getText("doclet.Href_Type_Param_Title", + utils.getSimpleName(typeElement)); + } else if (utils.isInterface(typeElement)){ + return configuration.getText("doclet.Href_Interface_Title", + utils.getPackageName(utils.containingPackage(typeElement))); + } else if (utils.isAnnotationType(typeElement)) { + return configuration.getText("doclet.Href_Annotation_Title", + utils.getPackageName(utils.containingPackage(typeElement))); + } else if (utils.isEnum(typeElement)) { + return configuration.getText("doclet.Href_Enum_Title", + utils.getPackageName(utils.containingPackage(typeElement))); + } else { + return configuration.getText("doclet.Href_Class_Title", + utils.getPackageName(utils.containingPackage(typeElement))); + } + } + + /** + * Return path to the given file name in the given package. So if the name + * passed is "Object.html" and the name of the package is "java.lang", and + * if the relative path is "../.." then returned string will be + * "../../java/lang/Object.html" + * + * @param linkInfo the information about the link. + */ + private DocPath getPath(LinkInfoImpl linkInfo) { + if (linkInfo.context == LinkInfoImpl.Kind.PACKAGE_FRAME) { + //Not really necessary to do this but we want to be consistent + //with 1.4.2 output. + return DocPath.forName(linkInfo.utils, linkInfo.typeElement); + } + return m_writer.pathToRoot.resolve(DocPath.forClass(linkInfo.utils, linkInfo.typeElement)); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java new file mode 100644 index 00000000000..01cd9508a1a --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.Utils; +import jdk.javadoc.internal.doclets.toolkit.util.links.LinkInfo; + + +/** + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class LinkInfoImpl extends LinkInfo { + + public enum Kind { + DEFAULT, + + /** + * Indicate that the link appears in a class list. + */ + ALL_CLASSES_FRAME, + + /** + * Indicate that the link appears in a class documentation. + */ + CLASS, + + /** + * Indicate that the link appears in member documentation. + */ + MEMBER, + + /** + * Indicate that the link appears in class use documentation. + */ + CLASS_USE, + + /** + * Indicate that the link appears in index documentation. + */ + INDEX, + + /** + * Indicate that the link appears in constant value summary. + */ + CONSTANT_SUMMARY, + + /** + * Indicate that the link appears in serialized form documentation. + */ + SERIALIZED_FORM, + + /** + * Indicate that the link appears in serial member documentation. + */ + SERIAL_MEMBER, + + /** + * Indicate that the link appears in package documentation. + */ + PACKAGE, + + /** + * Indicate that the link appears in see tag documentation. + */ + SEE_TAG, + + /** + * Indicate that the link appears in value tag documentation. + */ + VALUE_TAG, + + /** + * Indicate that the link appears in tree documentation. + */ + TREE, + + /** + * Indicate that the link appears in a class list. + */ + PACKAGE_FRAME, + + /** + * The header in the class documentation. + */ + CLASS_HEADER, + + /** + * The signature in the class documentation. + */ + CLASS_SIGNATURE, + + /** + * The return type of a method. + */ + RETURN_TYPE, + + /** + * The return type of a method in a member summary. + */ + SUMMARY_RETURN_TYPE, + + /** + * The type of a method/constructor parameter. + */ + EXECUTABLE_MEMBER_PARAM, + + /** + * Super interface links. + */ + SUPER_INTERFACES, + + /** + * Implemented interface links. + */ + IMPLEMENTED_INTERFACES, + + /** + * Implemented class links. + */ + IMPLEMENTED_CLASSES, + + /** + * Subinterface links. + */ + SUBINTERFACES, + + /** + * Subclasses links. + */ + SUBCLASSES, + + /** + * The signature in the class documentation (implements/extends portion). + */ + CLASS_SIGNATURE_PARENT_NAME, + + /** + * The header for method documentation copied from parent. + */ + EXECUTABLE_ELEMENT_COPY, + + /** + * Method "specified by" link. + */ + METHOD_SPECIFIED_BY, + + /** + * Method "overrides" link. + */ + METHOD_OVERRIDES, + + /** + * Annotation link. + */ + ANNOTATION, + + /** + * The header for field documentation copied from parent. + */ + VARIABLE_ELEMENT_COPY, + + /** + * The parent nodes in the class tree. + */ + CLASS_TREE_PARENT, + + /** + * The type parameters of a method or constructor. + */ + MEMBER_TYPE_PARAMS, + + /** + * Indicate that the link appears in class use documentation. + */ + CLASS_USE_HEADER, + + /** + * The header for property documentation copied from parent. + */ + PROPERTY_COPY, + + /** + * A receiver type + */ + RECEIVER_TYPE + } + + public final ConfigurationImpl configuration; + + /** + * The location of the link. + */ + public Kind context = Kind.DEFAULT; + + /** + * The value of the marker #. + */ + public String where = ""; + + /** + * String style of text defined in style sheet. + */ + public String styleName = ""; + + /** + * The value of the target. + */ + public String target = ""; + public final Utils utils; + /** + * Construct a LinkInfo object. + * + * @param configuration the configuration data for the doclet + * @param context the context of the link. + * @param ee the member to link to. + */ + public LinkInfoImpl(ConfigurationImpl configuration, Kind context, ExecutableElement ee) { + this.configuration = configuration; + this.utils = configuration.utils; + this.executableElement = ee; + setContext(context); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content newContent() { + return new ContentBuilder(); + } + + /** + * Construct a LinkInfo object. + * + * @param configuration the configuration data for the doclet + * @param context the context of the link. + * @param typeElement the class to link to. + */ + public LinkInfoImpl(ConfigurationImpl configuration, Kind context, TypeElement typeElement) { + this.configuration = configuration; + this.utils = configuration.utils; + this.typeElement = typeElement; + setContext(context); + } + + /** + * Construct a LinkInfo object. + * + * @param configuration the configuration data for the doclet + * @param context the context of the link. + * @param type the class to link to. + */ + public LinkInfoImpl(ConfigurationImpl configuration, Kind context, TypeMirror type) { + this.configuration = configuration; + this.utils = configuration.utils; + this.type = type; + setContext(context); + } + + /** + * Set the label for the link. + * @param label plain-text label for the link + */ + public LinkInfoImpl label(String label) { + this.label = new StringContent(label); + return this; + } + + /** + * Set the label for the link. + */ + public LinkInfoImpl label(Content label) { + this.label = label; + return this; + } + + /** + * Set whether or not the link should be strong. + */ + public LinkInfoImpl strong(boolean strong) { + this.isStrong = strong; + return this; + } + + /** + * Set the style to be used for the link. + * @param styleName String style of text defined in style sheet. + */ + public LinkInfoImpl styleName(String styleName) { + this.styleName = styleName; + return this; + } + + /** + * Set the target to be used for the link. + * @param styleName String style of text defined in style sheet. + */ + public LinkInfoImpl target(String target) { + this.target = target; + return this; + } + + /** + * Set whether or not this is a link to a varargs parameter. + */ + public LinkInfoImpl varargs(boolean varargs) { + this.isVarArg = varargs; + return this; + } + + /** + * Set the fragment specifier for the link. + */ + public LinkInfoImpl where(String where) { + this.where = where; + return this; + } + + /** + * {@inheritDoc} + */ + public Kind getContext() { + return context; + } + + /** + * {@inheritDoc} + * + * This method sets the link attributes to the appropriate values + * based on the context. + * + * @param c the context id to set. + */ + public final void setContext(Kind c) { + //NOTE: Put context specific link code here. + switch (c) { + case ALL_CLASSES_FRAME: + case PACKAGE_FRAME: + case IMPLEMENTED_CLASSES: + case SUBCLASSES: + case EXECUTABLE_ELEMENT_COPY: + case VARIABLE_ELEMENT_COPY: + case PROPERTY_COPY: + case CLASS_USE_HEADER: + includeTypeInClassLinkLabel = false; + break; + + case ANNOTATION: + excludeTypeParameterLinks = true; + excludeTypeBounds = true; + break; + + case IMPLEMENTED_INTERFACES: + case SUPER_INTERFACES: + case SUBINTERFACES: + case CLASS_TREE_PARENT: + case TREE: + case CLASS_SIGNATURE_PARENT_NAME: + excludeTypeParameterLinks = true; + excludeTypeBounds = true; + includeTypeInClassLinkLabel = false; + includeTypeAsSepLink = true; + break; + + case PACKAGE: + case CLASS_USE: + case CLASS_HEADER: + case CLASS_SIGNATURE: + case RECEIVER_TYPE: + excludeTypeParameterLinks = true; + includeTypeAsSepLink = true; + includeTypeInClassLinkLabel = false; + break; + + case MEMBER_TYPE_PARAMS: + includeTypeAsSepLink = true; + includeTypeInClassLinkLabel = false; + break; + + case RETURN_TYPE: + case SUMMARY_RETURN_TYPE: + excludeTypeBounds = true; + break; + case EXECUTABLE_MEMBER_PARAM: + excludeTypeBounds = true; + break; + } + context = c; + if (type != null && + utils.isTypeVariable(type) && + utils.isExecutableElement(utils.asTypeElement(type).getEnclosingElement())) { + excludeTypeParameterLinks = true; + } + } + + /** + * Return true if this link is linkable and false if we can't link to the + * desired place. + * + * @return true if this link is linkable and false if we can't link to the + * desired place. + */ + @Override + public boolean isLinkable() { + return configuration.utils.isLinkable(typeElement); + } + + @Override + public String toString() { + return "LinkInfoImpl{" + + "context=" + context + + ", where=" + where + + ", styleName=" + styleName + + ", target=" + target + + super.toString() + '}'; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkOutputImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkOutputImpl.java new file mode 100644 index 00000000000..f13d7e9a282 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkOutputImpl.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import jdk.javadoc.internal.doclets.toolkit.util.links.LinkOutput; + +/** + * Stores output of a link. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Jamie Ho + */ +public class LinkOutputImpl implements LinkOutput { + + /** + * The output of the link. + */ + public StringBuilder output; + + /** + * Construct a new LinkOutputImpl. + */ + public LinkOutputImpl() { + output = new StringBuilder(); + } + + /** + * {@inheritDoc} + */ + public void append(Object o) { + output.append(o instanceof String ? + (String) o : ((LinkOutputImpl)o).toString()); + } + + /** + * {@inheritDoc} + */ + public void insert(int offset, Object o) { + output.insert(offset, o.toString()); + } + + /** + * {@inheritDoc} + */ + public String toString() { + return output.toString(); + } + +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java new file mode 100644 index 00000000000..40b00cdd1fd --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java @@ -0,0 +1,457 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import java.util.Arrays; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; +import jdk.javadoc.internal.doclets.toolkit.MethodWriter; +import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods; +import jdk.javadoc.internal.doclets.toolkit.util.Utils; + +/** + * Writes method documentation in HTML format. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert Field + * @author Atul M Dambalkar + * @author Jamie Ho (rewrite) + * @author Bhavesh Patel (Modified) + */ +public class MethodWriterImpl extends AbstractExecutableMemberWriter + implements MethodWriter, MemberSummaryWriter { + + /** + * Construct a new MethodWriterImpl. + * + * @param writer the writer for the class that the methods belong to. + * @param typeElement the class being documented. + */ + public MethodWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) { + super(writer, typeElement); + } + + /** + * Construct a new MethodWriterImpl. + * + * @param writer The writer for the class that the methods belong to. + */ + public MethodWriterImpl(SubWriterHolderWriter writer) { + super(writer); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_METHOD_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, typeElement, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + writer.addMemberTree(memberSummaryTree, memberTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMethodDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) { + memberDetailsTree.addContent(HtmlConstants.START_OF_METHOD_DETAILS); + Content methodDetailsTree = writer.getMemberTreeHeader(); + methodDetailsTree.addContent(writer.getMarkerAnchor( + SectionName.METHOD_DETAIL)); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.methodDetailsLabel); + methodDetailsTree.addContent(heading); + return methodDetailsTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMethodDocTreeHeader(ExecutableElement method, Content methodDetailsTree) { + String erasureAnchor; + if ((erasureAnchor = getErasureAnchor(method)) != null) { + methodDetailsTree.addContent(writer.getMarkerAnchor((erasureAnchor))); + } + methodDetailsTree.addContent( + writer.getMarkerAnchor(writer.getAnchor(method))); + Content methodDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(name(method)); + methodDocTree.addContent(heading); + return methodDocTree; + } + + /** + * Get the signature for the given method. + * + * @param method the method being documented. + * @return a content object for the signature + */ + @Override + public Content getSignature(ExecutableElement method) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(method, pre); + int annotationLength = pre.charCount(); + addModifiers(method, pre); + addTypeParameters(method, pre); + addReturnType(method, pre); + if (configuration.linksource) { + Content methodName = new StringContent(name(method)); + writer.addSrcLink(method, methodName, pre); + } else { + addName(name(method), pre); + } + int indent = pre.charCount() - annotationLength; + addParameters(method, pre, indent); + addExceptions(method, pre, indent); + return pre; + } + + /** + * {@inheritDoc} + */ + @Override + public void addDeprecated(ExecutableElement method, Content methodDocTree) { + addDeprecatedInfo(method, methodDocTree); + } + + /** + * {@inheritDoc} + */ + @Override + public void addComments(TypeMirror holderType, ExecutableElement method, Content methodDocTree) { + TypeElement holder = utils.asTypeElement(holderType); + if (!utils.getBody(method).isEmpty()) { + if (holder.equals(typeElement) || + !(utils.isPublic(holder) || + utils.isLinkable(holder))) { + writer.addInlineComment(method, methodDocTree); + } else { + Content link = + writer.getDocLink(LinkInfoImpl.Kind.EXECUTABLE_ELEMENT_COPY, + holder, method, + utils.isIncluded(holder) + ? utils.getSimpleName(holder) + : utils.getFullyQualifiedName(holder), + false); + Content codelLink = HtmlTree.CODE(link); + Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel, + utils.isClass(holder) + ? writer.descfrmClassLabel + : writer.descfrmInterfaceLabel); + descfrmLabel.addContent(writer.getSpace()); + descfrmLabel.addContent(codelLink); + methodDocTree.addContent(HtmlTree.DIV(HtmlStyle.block, descfrmLabel)); + writer.addInlineComment(method, methodDocTree); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addTags(ExecutableElement method, Content methodDocTree) { + writer.addTagsInfo(method, methodDocTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMethodDetails(Content methodDetailsTree) { + if (configuration.allowTag(HtmlTag.SECTION)) { + HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(methodDetailsTree)); + return htmlTree; + } + return getMemberTree(methodDetailsTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMethodDoc(Content methodDocTree, + boolean isLastContent) { + return getMemberTree(methodDocTree, isLastContent); + } + + /** + * Close the writer. + */ + @Override + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Method_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + @Override + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Method_Summary"), + configuration.getText("doclet.methods")); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getCaption() { + return configuration.getResource("doclet.Methods"); + } + + /** + * {@inheritDoc} + */ + @Override + public List getSummaryTableHeader(Element member) { + List header = Arrays.asList(writer.getModifierTypeHeader(), + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Method"), + configuration.getText("doclet.Description"))); + return header; + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryAnchor(TypeElement typeElement, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + SectionName.METHOD_SUMMARY)); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) { + inheritedTree.addContent(writer.getMarkerAnchor( + SectionName.METHODS_INHERITANCE, configuration.getClassName(typeElement))); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + Content classLink = writer.getPreQualifiedClassLink( + LinkInfoImpl.Kind.MEMBER, typeElement, false); + Content label = new StringContent(utils.isClass(typeElement) + ? configuration.getText("doclet.Methods_Inherited_From_Class") + : configuration.getText("doclet.Methods_Inherited_From_Interface")); + Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING, + label); + labelHeading.addContent(writer.getSpace()); + labelHeading.addContent(classLink); + inheritedTree.addContent(labelHeading); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryType(Element member, Content tdSummaryType) { + ExecutableElement meth = (ExecutableElement)member; + addModifierAndType(meth, utils.getReturnType(meth), tdSummaryType); + } + + /** + * {@inheritDoc} + */ + protected static void addOverridden(HtmlDocletWriter writer, + TypeMirror overriddenType, ExecutableElement method, Content dl) { + if (writer.configuration.nocomment) { + return; + } + Utils utils = writer.configuration().utils; + TypeElement holder = utils.getEnclosingTypeElement(method); + if (!(utils.isPublic(holder) || + utils.isLinkable(holder))) { + //This is an implementation detail that should not be documented. + return; + } + if (utils.isIncluded(holder) && ! utils.isIncluded(method)) { + //The class is included but the method is not. That means that it + //is not visible so don't document this. + return; + } + Content label = writer.overridesLabel; + LinkInfoImpl.Kind context = LinkInfoImpl.Kind.METHOD_OVERRIDES; + + if (method != null) { + if (utils.isAbstract(holder) && utils.isAbstract(method)){ + //Abstract method is implemented from abstract class, + //not overridden + label = writer.specifiedByLabel; + context = LinkInfoImpl.Kind.METHOD_SPECIFIED_BY; + } + Content dt = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.overrideSpecifyLabel, label)); + dl.addContent(dt); + Content overriddenTypeLink = + writer.getLink(new LinkInfoImpl(writer.configuration, context, overriddenType)); + Content codeOverridenTypeLink = HtmlTree.CODE(overriddenTypeLink); + String name = method.getSimpleName().toString(); + Content methlink = writer.getLink( + new LinkInfoImpl(writer.configuration, LinkInfoImpl.Kind.MEMBER, + holder) + .where(writer.getName(writer.getAnchor(method))).label(name)); + Content codeMethLink = HtmlTree.CODE(methlink); + Content dd = HtmlTree.DD(codeMethLink); + dd.addContent(writer.getSpace()); + dd.addContent(writer.getResource("doclet.in_class")); + dd.addContent(writer.getSpace()); + dd.addContent(codeOverridenTypeLink); + dl.addContent(dd); + } + } + + /** + * {@inheritDoc} + */ + protected static void addImplementsInfo(HtmlDocletWriter writer, + ExecutableElement method, Content dl) { + if (writer.configuration.nocomment) { + return; + } + Utils utils = writer.utils; + ImplementedMethods implementedMethodsFinder = + new ImplementedMethods(method, writer.configuration); + SortedSet implementedMethods = + new TreeSet<>(utils.makeOverrideUseComparator()); + implementedMethods.addAll(implementedMethodsFinder.build()); + for (ExecutableElement implementedMeth : implementedMethods) { + TypeMirror intfac = implementedMethodsFinder.getMethodHolder(implementedMeth); + intfac = utils.getDeclaredType(utils.getEnclosingTypeElement(method), intfac); + Content intfaclink = writer.getLink(new LinkInfoImpl( + writer.configuration, LinkInfoImpl.Kind.METHOD_SPECIFIED_BY, intfac)); + Content codeIntfacLink = HtmlTree.CODE(intfaclink); + Content dt = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.overrideSpecifyLabel, writer.specifiedByLabel)); + dl.addContent(dt); + Content methlink = writer.getDocLink( + LinkInfoImpl.Kind.MEMBER, implementedMeth, + implementedMeth.getSimpleName().toString(), false); + Content codeMethLink = HtmlTree.CODE(methlink); + Content dd = HtmlTree.DD(codeMethLink); + dd.addContent(writer.getSpace()); + dd.addContent(writer.getResource("doclet.in_interface")); + dd.addContent(writer.getSpace()); + dd.addContent(codeIntfacLink); + dl.addContent(dd); + } + } + + /** + * Add the return type. + * + * @param method the method being documented. + * @param htmltree the content tree to which the return type will be added + */ + protected void addReturnType(ExecutableElement method, Content htmltree) { + TypeMirror type = utils.getReturnType(method); + if (type != null) { + Content linkContent = writer.getLink( + new LinkInfoImpl(configuration, LinkInfoImpl.Kind.RETURN_TYPE, type)); + htmltree.addContent(linkContent); + htmltree.addContent(writer.getSpace()); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { + if (link) { + if (typeElement == null) { + return writer.getHyperLink( + SectionName.METHOD_SUMMARY, + writer.getResource("doclet.navMethod")); + } else { + return writer.getHyperLink( + SectionName.METHODS_INHERITANCE, + configuration.getClassName(typeElement), writer.getResource("doclet.navMethod")); + } + } else { + return writer.getResource("doclet.navMethod"); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void addNavDetailLink(boolean link, Content liNav) { + if (link) { + liNav.addContent(writer.getHyperLink( + SectionName.METHOD_DETAIL, writer.getResource("doclet.navMethod"))); + } else { + liNav.addContent(writer.getResource("doclet.navMethod")); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java new file mode 100644 index 00000000000..c0828b8d5e2 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import java.util.Arrays; +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; + +/** + * Writes nested class documentation in HTML format. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert Field + * @author Atul M Dambalkar + * @author Jamie Ho (rewrite) + * @author Bhavesh Patel (Modified) + */ +public class NestedClassWriterImpl extends AbstractMemberWriter + implements MemberSummaryWriter { + + public NestedClassWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) { + super(writer, typeElement); + } + + public NestedClassWriterImpl(SubWriterHolderWriter writer) { + super(writer); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMemberSummaryHeader(TypeElement typeElement, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_NESTED_CLASS_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, typeElement, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + writer.addMemberTree(memberSummaryTree, memberTree); + } + + /** + * Close the writer. + */ + @Override + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Nested_Class_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + @Override + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Nested_Class_Summary"), + configuration.getText("doclet.nested_classes")); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getCaption() { + return configuration.getResource("doclet.Nested_Classes"); + } + + /** + * {@inheritDoc} + */ + @Override + public List getSummaryTableHeader(Element member) { + if (utils.isInterface(member)) { + return Arrays.asList(writer.getModifierTypeHeader(), + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Interface"), + configuration.getText("doclet.Description"))); + + } else { + return Arrays.asList(writer.getModifierTypeHeader(), + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Class"), + configuration.getText("doclet.Description"))); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryAnchor(TypeElement typeElement, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + SectionName.NESTED_CLASS_SUMMARY)); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) { + inheritedTree.addContent(writer.getMarkerAnchor( + SectionName.NESTED_CLASSES_INHERITANCE, + utils.getFullyQualifiedName(typeElement))); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + Content classLink = writer.getPreQualifiedClassLink( + LinkInfoImpl.Kind.MEMBER, typeElement, false); + Content label = new StringContent(utils.isInterface(typeElement) + ? configuration.getText("doclet.Nested_Classes_Interface_Inherited_From_Interface") + : configuration.getText("doclet.Nested_Classes_Interfaces_Inherited_From_Class")); + Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING, + label); + labelHeading.addContent(writer.getSpace()); + labelHeading.addContent(classLink); + inheritedTree.addContent(labelHeading); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member, + Content tdSummary) { + Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink, + writer.getLink(new LinkInfoImpl(configuration, context, (TypeElement)member))); + Content code = HtmlTree.CODE(memberLink); + tdSummary.addContent(code); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) { + linksTree.addContent( + writer.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, + (TypeElement)member))); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryType(Element member, Content tdSummaryType) { + addModifierAndType(member, null, tdSummaryType); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getDeprecatedLink(Element member) { + return writer.getQualifiedClassLink(LinkInfoImpl.Kind.MEMBER, member); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { + if (link) { + if (typeElement == null) { + return writer.getHyperLink( + SectionName.NESTED_CLASS_SUMMARY, + writer.getResource("doclet.navNested")); + } else { + return writer.getHyperLink( + SectionName.NESTED_CLASSES_INHERITANCE, + utils.getFullyQualifiedName(typeElement), writer.getResource("doclet.navNested")); + } + } else { + return writer.getResource("doclet.navNested"); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void addNavDetailLink(boolean link, Content liNav) { + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageFrameWriter.java new file mode 100644 index 00000000000..4925b55d00b --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageFrameWriter.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Configuration; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + + +/** + * Class to generate file for each package contents in the left-hand bottom + * frame. This will list all the Class Kinds in the package. A click on any + * class-kind will update the right-hand frame with the clicked class-kind page. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class PackageFrameWriter extends HtmlDocletWriter { + + /** + * The package being documented. + */ + private PackageElement packageElement; + + /** + * The classes to be documented. Use this to filter out classes + * that will not be documented. + */ + private SortedSet documentedClasses; + + /** + * Constructor to construct PackageFrameWriter object and to generate + * "package-frame.html" file in the respective package directory. + * For example for package "java.lang" this will generate file + * "package-frame.html" file in the "java/lang" directory. It will also + * create "java/lang" directory in the current or the destination directory + * if it doesn't exist. + * + * @param configuration the configuration of the doclet. + * @param packageElement PackageElement under consideration. + */ + public PackageFrameWriter(ConfigurationImpl configuration, PackageElement packageElement) + throws IOException { + super(configuration, DocPath.forPackage(packageElement).resolve(DocPaths.PACKAGE_FRAME)); + this.packageElement = packageElement; + if (utils.getSpecifiedPackages().isEmpty()) { + documentedClasses = new TreeSet<>(utils.makeGeneralPurposeComparator()); + documentedClasses.addAll(configuration.root.getIncludedClasses()); + } + } + + /** + * Generate a package summary page for the left-hand bottom frame. Construct + * the PackageFrameWriter object and then uses it generate the file. + * + * @param configuration the current configuration of the doclet. + * @param packageElement The package for which "pacakge-frame.html" is to be generated. + */ + public static void generate(ConfigurationImpl configuration, PackageElement packageElement) { + PackageFrameWriter packgen; + try { + packgen = new PackageFrameWriter(configuration, packageElement); + String pkgName = configuration.utils.getPackageName(packageElement); + HtmlTree body = packgen.getBody(false, packgen.getWindowTitle(pkgName)); + Content pkgNameContent = new StringContent(pkgName); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN)) + ? HtmlTree.MAIN() + : body; + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, HtmlStyle.bar, + packgen.getTargetPackageLink(packageElement, "classFrame", pkgNameContent)); + htmlTree.addContent(heading); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.indexContainer); + packgen.addClassListing(div); + htmlTree.addContent(div); + if (configuration.allowTag(HtmlTag.MAIN)) { + body.addContent(htmlTree); + } + packgen.printHtmlDocument( + configuration.metakeywords.getMetaKeywords(packageElement), false, body); + packgen.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), DocPaths.PACKAGE_FRAME.getPath()); + throw new DocletAbortException(exc); + } + } + + /** + * Add class listing for all the classes in this package. Divide class + * listing as per the class kind and generate separate listing for + * Classes, Interfaces, Exceptions and Errors. + * + * @param contentTree the content tree to which the listing will be added + */ + protected void addClassListing(HtmlTree contentTree) { + Configuration config = configuration; + if (utils.isIncluded(packageElement)) { + addClassKindListing(utils.getInterfaces(packageElement), + getResource("doclet.Interfaces"), contentTree); + addClassKindListing(utils.getOrdinaryClasses(packageElement), + getResource("doclet.Classes"), contentTree); + addClassKindListing(utils.getEnums(packageElement), + getResource("doclet.Enums"), contentTree); + addClassKindListing(utils.getExceptions(packageElement), + getResource("doclet.Exceptions"), contentTree); + addClassKindListing(utils.getErrors(packageElement), + getResource("doclet.Errors"), contentTree); + addClassKindListing(utils.getAnnotationTypes(packageElement), + getResource("doclet.AnnotationTypes"), contentTree); + } else { + addClassKindListing(config.typeElementCatalog.interfaces(packageElement), + getResource("doclet.Interfaces"), contentTree); + addClassKindListing(config.typeElementCatalog.ordinaryClasses(packageElement), + getResource("doclet.Classes"), contentTree); + addClassKindListing(config.typeElementCatalog.enums(packageElement), + getResource("doclet.Enums"), contentTree); + addClassKindListing(config.typeElementCatalog.exceptions(packageElement), + getResource("doclet.Exceptions"), contentTree); + addClassKindListing(config.typeElementCatalog.errors(packageElement), + getResource("doclet.Errors"), contentTree); + addClassKindListing(config.typeElementCatalog.annotationTypes(packageElement), + getResource("doclet.AnnotationTypes"), contentTree); + } + } + + /** + * Add specific class kind listing. Also add label to the listing. + * + * @param arr Array of specific class kinds, namely Class or Interface or Exception or Error + * @param labelContent content tree of the label to be added + * @param contentTree the content tree to which the class kind listing will be added + */ + protected void addClassKindListing(Iterable list, Content labelContent, + HtmlTree contentTree) { + SortedSet tset = utils.filterOutPrivateClasses(list, configuration.javafx); + if(!tset.isEmpty()) { + boolean printedHeader = false; + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.SECTION() + : contentTree; + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.setTitle(labelContent); + for (TypeElement typeElement : tset) { + if (documentedClasses != null && !documentedClasses.contains(typeElement)) { + continue; + } + if (!utils.isCoreClass(typeElement) || !configuration.isGeneratedDoc(typeElement)) { + continue; + } + if (!printedHeader) { + Content heading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, + true, labelContent); + htmlTree.addContent(heading); + printedHeader = true; + } + Content arr_i_name = new StringContent(utils.getSimpleName(typeElement)); + if (utils.isInterface(typeElement)) + arr_i_name = HtmlTree.SPAN(HtmlStyle.interfaceName, arr_i_name); + Content link = getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.PACKAGE_FRAME, typeElement).label(arr_i_name).target("classFrame")); + Content li = HtmlTree.LI(link); + ul.addContent(li); + } + htmlTree.addContent(ul); + if (configuration.allowTag(HtmlTag.SECTION)) { + contentTree.addContent(htmlTree); + } + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java new file mode 100644 index 00000000000..064a93ce9d2 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.IOException; +import java.util.Collection; + +import javax.lang.model.element.PackageElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + + +/** + * Generate the package index for the left-hand frame in the generated output. + * A click on the package name in this frame will update the page in the bottom + * left hand frame with the listing of contents of the clicked package. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + */ +public class PackageIndexFrameWriter extends AbstractPackageIndexWriter { + + /** + * Construct the PackageIndexFrameWriter object. + * + * @param filename Name of the package index file to be generated. + */ + public PackageIndexFrameWriter(ConfigurationImpl configuration, + DocPath filename) throws IOException { + super(configuration, filename); + } + + /** + * Generate the package index file named "overview-frame.html". + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration) { + PackageIndexFrameWriter packgen; + DocPath filename = DocPaths.OVERVIEW_FRAME; + try { + packgen = new PackageIndexFrameWriter(configuration, filename); + packgen.buildPackageIndexFile("doclet.Window_Overview", false); + packgen.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), filename); + throw new DocletAbortException(exc); + } + } + + /** + * {@inheritDoc} + */ + protected void addPackagesList(Collection packages, String text, + String tableSummary, Content body) { + Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, + packagesLabel); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN)) + ? HtmlTree.MAIN(HtmlStyle.indexContainer, heading) + : HtmlTree.DIV(HtmlStyle.indexContainer, heading); + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.setTitle(packagesLabel); + for (PackageElement aPackage : packages) { + // Do not list the package if -nodeprecated option is set and the + // package is marked as deprecated. + if (aPackage != null && + (!(configuration.nodeprecated && utils.isDeprecated(aPackage)))) { + ul.addContent(getPackage(aPackage)); + } + } + htmlTree.addContent(ul); + body.addContent(htmlTree); + } + + /** + * Returns each package name as a separate link. + * + * @param pe PackageElement + * @return content for the package link + */ + protected Content getPackage(PackageElement pe) { + Content packageLinkContent; + Content packageLabel; + if (pe.isUnnamed()) { + packageLabel = new StringContent(""); + packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME, + packageLabel, "", "packageFrame"); + } else { + packageLabel = getPackageLabel(pe.getQualifiedName().toString()); + packageLinkContent = getHyperLink(pathString(pe, + DocPaths.PACKAGE_FRAME), packageLabel, "", + "packageFrame"); + } + Content li = HtmlTree.LI(packageLinkContent); + return li; + } + + /** + * {@inheritDoc} + */ + protected void addNavigationBarHeader(Content body) { + Content headerContent; + if (configuration.packagesheader.length() > 0) { + headerContent = new RawHtml(replaceDocRootDir(configuration.packagesheader)); + } else { + headerContent = new RawHtml(replaceDocRootDir(configuration.header)); + } + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.bar, headerContent); + body.addContent(heading); + } + + /** + * Do nothing as there is no overview information in this page. + */ + protected void addOverviewHeader(Content body) { + } + + /** + * Adds "All Classes" link for the top of the left-hand frame page to the + * documentation tree. + * + * @param ul the Content object to which the "All Classes" link should be added + */ + protected void addAllClassesLink(Content ul) { + Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME, + allclassesLabel, "", "packageFrame"); + Content li = HtmlTree.LI(linkContent); + ul.addContent(li); + } + + /** + * {@inheritDoc} + */ + protected void addNavigationBarFooter(Content body) { + Content p = HtmlTree.P(getSpace()); + body.addContent(p); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java new file mode 100644 index 00000000000..c9a3a987038 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.PackageElement; + +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.Group; + +/** + * Generate the package index page "overview-summary.html" for the right-hand + * frame. A click on the package name on this page will update the same frame + * with the "package-summary.html" file for the clicked package. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class PackageIndexWriter extends AbstractPackageIndexWriter { + + /** + * Root of the program structure. Used for "overview" documentation. + */ + private DocletEnvironment root; + + /** + * Map representing the group of packages as specified on the command line. + * + * @see Group + */ + private Map> groupPackageMap; + + /** + * List to store the order groups as specified on the command line. + */ + private List groupList; + + /** + * HTML tree for main tag. + */ + private HtmlTree htmlTree = HtmlTree.MAIN(); + + /** + * Construct the PackageIndexWriter. Also constructs the grouping + * information as provided on the command line by "-group" option. Stores + * the order of groups specified by the user. + * + * @see Group + */ + public PackageIndexWriter(ConfigurationImpl configuration, DocPath filename) throws IOException { + super(configuration, filename); + this.root = configuration.root; + groupPackageMap = configuration.group.groupPackages(packages); + groupList = configuration.group.getGroupList(); + } + + /** + * Generate the package index page for the right-hand frame. + * + * @param configuration the current configuration of the doclet. + */ + public static void generate(ConfigurationImpl configuration) { + PackageIndexWriter packgen; + DocPath filename = DocPaths.OVERVIEW_SUMMARY; + try { + packgen = new PackageIndexWriter(configuration, filename); + packgen.buildPackageIndexFile("doclet.Window_Overview_Summary", true); + packgen.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), filename); + throw new DocletAbortException(exc); + } + } + + /** + * Depending upon the grouping information and their titles, add + * separate table indices for each package group. + * + * @param body the documentation tree to which the index will be added + */ + protected void addIndex(Content body) { + for (String groupname : groupList) { + SortedSet list = groupPackageMap.get(groupname); + if (list != null && !list.isEmpty()) { + addIndexContents(list, + groupname, configuration.getText("doclet.Member_Table_Summary", + groupname, configuration.getText("doclet.packages")), body); + } + } + } + + /** + * {@inheritDoc} + */ + protected void addPackagesList(Collection packages, String text, + String tableSummary, Content body) { + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.overviewSummary, getTableCaption(new RawHtml(text))) + : HtmlTree.TABLE(HtmlStyle.overviewSummary, tableSummary, getTableCaption(new RawHtml(text))); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + addPackagesList(packages, tbody); + table.addContent(tbody); + Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table); + if (configuration.allowTag(HtmlTag.MAIN)) { + htmlTree.addContent(div); + } else { + body.addContent(div); + } + } + + /** + * Adds list of packages in the index table. Generate link to each package. + * + * @param packages Packages to which link is to be generated + * @param tbody the documentation tree to which the list will be added + */ + protected void addPackagesList(Collection packages, Content tbody) { + boolean altColor = true; + for (PackageElement pkg : packages) { + if (!pkg.isUnnamed()) { + if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) { + Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg)); + Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, packageLinkContent); + HtmlTree tdSummary = new HtmlTree(HtmlTag.TD); + tdSummary.addStyle(HtmlStyle.colLast); + addSummaryComment(pkg, tdSummary); + HtmlTree tr = HtmlTree.TR(tdPackage); + tr.addContent(tdSummary); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + tbody.addContent(tr); + } + } + altColor = !altColor; + } + } + + /** + * Adds the overview summary comment for this documentation. Add one line + * summary at the top of the page and generate a link to the description, + * which is added at the end of this page. + * + * @param body the documentation tree to which the overview header will be added + */ + protected void addOverviewHeader(Content body) { + addConfigurationTitle(body); + if (!utils.getBody(configuration.overviewElement).isEmpty()) { + HtmlTree subTitleDiv = new HtmlTree(HtmlTag.DIV); + subTitleDiv.addStyle(HtmlStyle.subTitle); + addSummaryComment(configuration.overviewElement, subTitleDiv); + Content div = HtmlTree.DIV(HtmlStyle.header, subTitleDiv); + Content see = seeLabel; + see.addContent(" "); + Content descPara = HtmlTree.P(see); + Content descLink = getHyperLink(getDocLink( + SectionName.OVERVIEW_DESCRIPTION), + descriptionLabel, "", ""); + descPara.addContent(descLink); + div.addContent(descPara); + if (configuration.allowTag(HtmlTag.MAIN)) { + htmlTree.addContent(div); + } else { + body.addContent(div); + } + } + } + + /** + * Adds the overview comment as provided in the file specified by the + * "-overview" option on the command line. + * + * @param htmltree the documentation tree to which the overview comment will + * be added + */ + protected void addOverviewComment(Content htmltree) { + if (!utils.getBody(configuration.overviewElement).isEmpty()) { + htmltree.addContent(getMarkerAnchor(SectionName.OVERVIEW_DESCRIPTION)); + addInlineComment(configuration.overviewElement, htmltree); + } + } + + /** + * Adds the tag information as provided in the file specified by the + * "-overview" option on the command line. + * + * @param body the documentation tree to which the overview will be added + */ + protected void addOverview(Content body) throws IOException { + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.contentContainer); + addOverviewComment(div); + if (configuration.allowTag(HtmlTag.MAIN)) { + htmlTree.addContent(div); + body.addContent(htmlTree); + } else { + body.addContent(div); + } + } + + /** + * Adds the top text (from the -top option), the upper + * navigation bar, and then the title (from the"-title" + * option), at the top of page. + * + * @param body the documentation tree to which the navigation bar header will be added + */ + protected void addNavigationBarHeader(Content body) { + Content htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : body; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + body.addContent(htmlTree); + } + } + + /** + * Adds the lower navigation bar and the bottom text + * (from the -bottom option) at the bottom of page. + * + * @param body the documentation tree to which the navigation bar footer will be added + */ + protected void addNavigationBarFooter(Content body) { + Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : body; + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(htmlTree); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java new file mode 100644 index 00000000000..9dac9a3bf18 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import javax.lang.model.element.PackageElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + + +/** + * Class to generate Tree page for a package. The name of the file generated is + * "package-tree.html" and it is generated in the respective package directory. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class PackageTreeWriter extends AbstractTreeWriter { + + /** + * Package for which tree is to be generated. + */ + protected PackageElement packageElement; + + /** + * The previous package name in the alpha-order list. + */ + protected PackageElement prev; + + /** + * The next package name in the alpha-order list. + */ + protected PackageElement next; + + /** + * Constructor. + * @param configuration the configuration + * @param path the docpath to generate files into + * @param packageElement the current package + * @param prev the previous package + * @param next the next package + * @throws IOException + * @throws DocletAbortException + */ + public PackageTreeWriter(ConfigurationImpl configuration, + DocPath path, + PackageElement packageElement, + PackageElement prev, PackageElement next) + throws IOException { + super(configuration, path, + new ClassTree(configuration.typeElementCatalog.allClasses(packageElement), configuration)); + this.packageElement = packageElement; + this.prev = prev; + this.next = next; + } + + /** + * Construct a PackageTreeWriter object and then use it to generate the + * package tree page. + * + * @param configuration the configuration for this run. + * @param pkg Package for which tree file is to be generated. + * @param prev Previous package in the alpha-ordered list. + * @param next Next package in the alpha-ordered list. + * @param noDeprecated If true, do not generate any information for + * deprecated classe or interfaces. + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration, + PackageElement pkg, PackageElement prev, + PackageElement next, boolean noDeprecated) { + PackageTreeWriter packgen; + DocPath path = DocPath.forPackage(pkg).resolve(DocPaths.PACKAGE_TREE); + try { + packgen = new PackageTreeWriter(configuration, path, pkg, + prev, next); + packgen.generatePackageTreeFile(); + packgen.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), path.getPath()); + throw new DocletAbortException(exc); + } + } + + /** + * Generate a separate tree file for each package. + * @throws java.io.IOException + */ + protected void generatePackageTreeFile() throws IOException { + HtmlTree body = getPackageTreeHeader(); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN)) + ? HtmlTree.MAIN() + : body; + Content headContent = getResource("doclet.Hierarchy_For_Package", + utils.getPackageName(packageElement)); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, false, + HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + if (configuration.packages.size() > 1) { + addLinkToMainTree(div); + } + htmlTree.addContent(div); + HtmlTree divTree = new HtmlTree(HtmlTag.DIV); + divTree.addStyle(HtmlStyle.contentContainer); + addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", divTree); + addTree(classtree.baseInterfaces(), "doclet.Interface_Hierarchy", divTree); + addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree); + addTree(classtree.baseEnums(), "doclet.Enum_Hierarchy", divTree, true); + htmlTree.addContent(divTree); + if (configuration.allowTag(HtmlTag.MAIN)) { + body.addContent(htmlTree); + } + HtmlTree tree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : body; + addNavLinks(false, tree); + addBottom(tree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(tree); + } + printHtmlDocument(null, true, body); + } + + /** + * Get the package tree header. + * + * @return a content tree for the header + */ + protected HtmlTree getPackageTreeHeader() { + String packageName = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement); + String title = packageName + " " + configuration.getText("doclet.Window_Class_Hierarchy"); + HtmlTree bodyTree = getBody(true, getWindowTitle(title)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + return bodyTree; + } + + /** + * Add a link to the tree for all the packages. + * + * @param div the content tree to which the link will be added + */ + protected void addLinkToMainTree(Content div) { + Content span = HtmlTree.SPAN(HtmlStyle.packageHierarchyLabel, + getResource("doclet.Package_Hierarchies")); + div.addContent(span); + HtmlTree ul = new HtmlTree (HtmlTag.UL); + ul.addStyle(HtmlStyle.horizontal); + ul.addContent(getNavLinkMainTree(configuration.getText("doclet.All_Packages"))); + div.addContent(ul); + } + + /** + * Get link for the previous package tree file. + * + * @return a content tree for the link + */ + protected Content getNavLinkPrevious() { + if (prev == null) { + return getNavLinkPrevious(null); + } else { + DocPath path = DocPath.relativePath(packageElement, prev); + return getNavLinkPrevious(path.resolve(DocPaths.PACKAGE_TREE)); + } + } + + /** + * Get link for the next package tree file. + * + * @return a content tree for the link + */ + protected Content getNavLinkNext() { + if (next == null) { + return getNavLinkNext(null); + } else { + DocPath path = DocPath.relativePath(packageElement, next); + return getNavLinkNext(path.resolve(DocPaths.PACKAGE_TREE)); + } + } + + /** + * Get link to the package summary page for the package of this tree. + * + * @return a content tree for the package link + */ + protected Content getNavLinkPackage() { + Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY, + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java new file mode 100644 index 00000000000..3763e725892 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + +/** + * Generate package usage information. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert G. Field + * @author Bhavesh Patel (Modified) + */ +public class PackageUseWriter extends SubWriterHolderWriter { + + final PackageElement packageElement; + final SortedMap> usingPackageToUsedClasses = new TreeMap<>(); + protected HtmlTree mainTree = HtmlTree.MAIN(); + + /** + * Constructor. + * + * @param filename the file to be generated. + * @throws IOException + * @throws DocletAbortException + */ + public PackageUseWriter(ConfigurationImpl configuration, + ClassUseMapper mapper, DocPath filename, + PackageElement pkgElement) throws IOException { + super(configuration, DocPath.forPackage(pkgElement).resolve(filename)); + this.packageElement = pkgElement; + + // by examining all classes in this package, find what packages + // use these classes - produce a map between using package and + // used classes. + for (TypeElement usedClass : utils.getEnclosedTypeElements(pkgElement)) { + Set usingClasses = mapper.classToClass.get(usedClass); + if (usingClasses != null) { + for (TypeElement usingClass : usingClasses) { + PackageElement usingPackage = utils.containingPackage(usingClass); + Set usedClasses = usingPackageToUsedClasses + .get(utils.getPackageName(usingPackage)); + if (usedClasses == null) { + usedClasses = new TreeSet<>(utils.makeGeneralPurposeComparator()); + usingPackageToUsedClasses.put(utils.getPackageName(usingPackage), + usedClasses); + } + usedClasses.add(usedClass); + } + } + } + } + + /** + * Generate a class page. + * + * @param configuration the current configuration of the doclet. + * @param mapper the mapping of the class usage. + * @param pkgElement the package being documented. + */ + public static void generate(ConfigurationImpl configuration, + ClassUseMapper mapper, PackageElement pkgElement) { + PackageUseWriter pkgusegen; + DocPath filename = DocPaths.PACKAGE_USE; + try { + pkgusegen = new PackageUseWriter(configuration, mapper, filename, pkgElement); + pkgusegen.generatePackageUseFile(); + pkgusegen.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), filename); + throw new DocletAbortException(exc); + } + } + + /** + * Generate the package use list. + */ + protected void generatePackageUseFile() throws IOException { + HtmlTree body = getPackageUseHeader(); + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.contentContainer); + if (usingPackageToUsedClasses.isEmpty()) { + div.addContent(getResource("doclet.ClassUse_No.usage.of.0", utils.getPackageName(packageElement))); + } else { + addPackageUse(div); + } + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + body.addContent(mainTree); + } else { + body.addContent(div); + } + HtmlTree tree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : body; + addNavLinks(false, tree); + addBottom(tree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(tree); + } + printHtmlDocument(null, true, body); + } + + /** + * Add the package use information. + * + * @param contentTree the content tree to which the package use information will be added + */ + protected void addPackageUse(Content contentTree) throws IOException { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + if (configuration.packages.size() > 1) { + addPackageList(ul); + } + addClassList(ul); + contentTree.addContent(ul); + } + + /** + * Add the list of packages that use the given package. + * + * @param contentTree the content tree to which the package list will be added + */ + protected void addPackageList(Content contentTree) throws IOException { + Content caption = getTableCaption(configuration.getResource( + "doclet.ClassUse_Packages.that.use.0", + getPackageLink(packageElement, utils.getPackageName(packageElement)))); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) + : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption); + table.addContent(getSummaryTableHeader(packageTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (String pkgname: usingPackageToUsedClasses.keySet()) { + PackageElement pkg = utils.elementUtils.getPackageElement(pkgname); + HtmlTree tr = new HtmlTree(HtmlTag.TR); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + addPackageUse(pkg, tr); + tbody.addContent(tr); + } + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + contentTree.addContent(li); + } + + /** + * Add the list of classes that use the given package. + * + * @param contentTree the content tree to which the class list will be added + */ + protected void addClassList(Content contentTree) throws IOException { + List classTableHeader = Arrays.asList( + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Class"), + configuration.getText("doclet.Description"))); + for (String packageName : usingPackageToUsedClasses.keySet()) { + PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName); + HtmlTree li = new HtmlTree(HtmlTag.LI); + li.addStyle(HtmlStyle.blockList); + if (usingPackage != null) { + li.addContent(getMarkerAnchor(utils.getPackageName(usingPackage))); + } + String tableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.classes")); + Content caption = getTableCaption(configuration.getResource( + "doclet.ClassUse_Classes.in.0.used.by.1", + getPackageLink(packageElement, utils.getPackageName(packageElement)), + getPackageLink(usingPackage, utils.getPackageName(usingPackage)))); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.useSummary, caption) + : HtmlTree.TABLE(HtmlStyle.useSummary, tableSummary, caption); + table.addContent(getSummaryTableHeader(classTableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = true; + for (TypeElement te : usingPackageToUsedClasses.get(packageName)) { + HtmlTree tr = new HtmlTree(HtmlTag.TR); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + altColor = !altColor; + addClassRow(te, usingPackage, tr); + tbody.addContent(tr); + } + table.addContent(tbody); + li.addContent(table); + contentTree.addContent(li); + } + } + + /** + * Add a row for the class that uses the given package. + * + * @param usedClass the class that uses the given package + * @param pkg the package to which the class belongs + * @param contentTree the content tree to which the row will be added + */ + protected void addClassRow(TypeElement usedClass, PackageElement pkg, + Content contentTree) { + DocPath dp = pathString(usedClass, + DocPaths.CLASS_USE.resolve(DocPath.forName(utils, usedClass))); + StringContent stringContent = new StringContent(utils.getSimpleName(usedClass)); + Content td = HtmlTree.TD(HtmlStyle.colOne, + getHyperLink(dp.fragment(getPackageAnchorName(pkg)), stringContent)); + addIndexComment(usedClass, td); + contentTree.addContent(td); + } + + /** + * Add the package use information. + * + * @param pkg the package that used the given package + * @param contentTree the content tree to which the information will be added + */ + protected void addPackageUse(PackageElement pkg, Content contentTree) throws IOException { + Content tdFirst = HtmlTree.TD(HtmlStyle.colFirst, + getHyperLink(utils.getPackageName(pkg), + new StringContent(utils.getPackageName(pkg)))); + contentTree.addContent(tdFirst); + HtmlTree tdLast = new HtmlTree(HtmlTag.TD); + tdLast.addStyle(HtmlStyle.colLast); + if (pkg != null && !pkg.isUnnamed()) { + addSummaryComment(pkg, tdLast); + } else { + tdLast.addContent(getSpace()); + } + contentTree.addContent(tdLast); + } + + /** + * Get the header for the package use listing. + * + * @return a content tree representing the package use header + */ + protected HtmlTree getPackageUseHeader() { + String packageText = configuration.getText("doclet.Package"); + String name = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement); + String title = configuration.getText("doclet.Window_ClassUse_Header", packageText, name); + HtmlTree bodyTree = getBody(true, getWindowTitle(title)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + ContentBuilder headContent = new ContentBuilder(); + headContent.addContent(getResource("doclet.ClassUse_Title", packageText)); + headContent.addContent(new HtmlTree(HtmlTag.BR)); + headContent.addContent(name); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + } else { + bodyTree.addContent(div); + } + return bodyTree; + } + + /** + * Get this package link. + * + * @return a content tree for the package link + */ + protected Content getNavLinkPackage() { + Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY, + packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get the use link. + * + * @return a content tree for the use link + */ + protected Content getNavLinkClassUse() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, useLabel); + return li; + } + + /** + * Get the tree link. + * + * @return a content tree for the tree link + */ + protected Content getNavLinkTree() { + Content linkContent = getHyperLink(DocPaths.PACKAGE_TREE, + treeLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java new file mode 100644 index 00000000000..8689b0f76e8 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java @@ -0,0 +1,377 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; + +import com.sun.source.doctree.DocTree; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter; +import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; + +/** + * Class to generate file for each package contents in the right-hand + * frame. This will list all the Class Kinds in the package. A click on any + * class-kind will update the frame with the clicked class-kind page. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class PackageWriterImpl extends HtmlDocletWriter + implements PackageSummaryWriter { + + /** + * The prev package name in the alpha-order list. + */ + protected PackageElement prev; + + /** + * The next package name in the alpha-order list. + */ + protected PackageElement next; + + /** + * The package being documented. + */ + protected PackageElement packageElement; + + /** + * The HTML tree for main tag. + */ + protected HtmlTree mainTree = HtmlTree.MAIN(); + + /** + * The HTML tree for section tag. + */ + protected HtmlTree sectionTree = HtmlTree.SECTION(); + + /** + * Constructor to construct PackageWriter object and to generate + * "package-summary.html" file in the respective package directory. + * For example for package "java.lang" this will generate file + * "package-summary.html" file in the "java/lang" directory. It will also + * create "java/lang" directory in the current or the destination directory + * if it doesn't exist. + * + * @param configuration the configuration of the doclet. + * @param packageElement PackageElement under consideration. + * @param prev Previous package in the sorted array. + * @param next Next package in the sorted array. + */ + public PackageWriterImpl(ConfigurationImpl configuration, + PackageElement packageElement, PackageElement prev, PackageElement next) + throws IOException { + super(configuration, DocPath + .forPackage(packageElement) + .resolve(DocPaths.PACKAGE_SUMMARY)); + this.prev = prev; + this.next = next; + this.packageElement = packageElement; + } + + /** + * {@inheritDoc} + */ + public Content getPackageHeader(String heading) { + HtmlTree bodyTree = getBody(true, getWindowTitle(utils.getPackageName(packageElement))); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.header); + Content annotationContent = new HtmlTree(HtmlTag.P); + addAnnotationInfo(packageElement, annotationContent); + div.addContent(annotationContent); + Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, packageLabel); + tHeading.addContent(getSpace()); + Content packageHead = new StringContent(heading); + tHeading.addContent(packageHead); + div.addContent(tHeading); + addDeprecationInfo(div); + if (!utils.getBody(packageElement).isEmpty() && !configuration.nocomment) { + HtmlTree docSummaryDiv = new HtmlTree(HtmlTag.DIV); + docSummaryDiv.addStyle(HtmlStyle.docSummary); + addSummaryComment(packageElement, docSummaryDiv); + div.addContent(docSummaryDiv); + Content space = getSpace(); + Content descLink = getHyperLink(getDocLink( + SectionName.PACKAGE_DESCRIPTION), + descriptionLabel, "", ""); + Content descPara = new HtmlTree(HtmlTag.P, seeLabel, space, descLink); + div.addContent(descPara); + } + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + } else { + bodyTree.addContent(div); + } + return bodyTree; + } + + /** + * {@inheritDoc} + */ + public Content getContentHeader() { + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.contentContainer); + return div; + } + + /** + * Add the package deprecation information to the documentation tree. + * + * @param div the content tree to which the deprecation information will be added + */ + public void addDeprecationInfo(Content div) { + List deprs = utils.getBlockTags(packageElement, DocTree.Kind.DEPRECATED); + if (utils.isDeprecated(packageElement)) { + CommentHelper ch = utils.getCommentHelper(packageElement); + HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV); + deprDiv.addStyle(HtmlStyle.deprecatedContent); + Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase); + deprDiv.addContent(deprPhrase); + if (!deprs.isEmpty()) { + List commentTags = ch.getDescription(configuration, deprs.get(0)); + if (!commentTags.isEmpty()) { + addInlineDeprecatedComment(packageElement, deprs.get(0), deprDiv); + } + } + div.addContent(deprDiv); + } + } + + /** + * {@inheritDoc} + */ + public Content getSummaryHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * {@inheritDoc} + */ + public void addClassesSummary(SortedSet classes, String label, + String tableSummary, List tableHeader, Content summaryContentTree) { + if(!classes.isEmpty()) { + Content caption = getTableCaption(new RawHtml(label)); + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.typeSummary, caption) + : HtmlTree.TABLE(HtmlStyle.typeSummary, tableSummary, caption); + table.addContent(getSummaryTableHeader(tableHeader, "col")); + Content tbody = new HtmlTree(HtmlTag.TBODY); + boolean altColor = false; + for (TypeElement klass : classes) { + altColor = !altColor; + if (!utils.isCoreClass(klass) || + !configuration.isGeneratedDoc(klass)) { + continue; + } + Content classContent = getLink(new LinkInfoImpl( + configuration, LinkInfoImpl.Kind.PACKAGE, klass)); + Content tdClass = HtmlTree.TD(HtmlStyle.colFirst, classContent); + HtmlTree tr = HtmlTree.TR(tdClass); + tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor); + + HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD); + tdClassDescription.addStyle(HtmlStyle.colLast); + if (utils.isDeprecated(klass)) { + tdClassDescription.addContent(deprecatedLabel); + List tags = utils.getDeprecatedTrees(klass); + if (!tags.isEmpty()) { + addSummaryDeprecatedComment(klass, tags.get(0), tdClassDescription); + } + } else { + addSummaryComment(klass, tdClassDescription); + } + tr.addContent(tdClassDescription); + tbody.addContent(tr); + } + table.addContent(tbody); + Content li = HtmlTree.LI(HtmlStyle.blockList, table); + summaryContentTree.addContent(li); + } + } + + /** + * {@inheritDoc} + */ + public void addPackageDescription(Content packageContentTree) { + if (!utils.getBody(packageElement).isEmpty()) { + packageContentTree.addContent( + getMarkerAnchor(SectionName.PACKAGE_DESCRIPTION)); + Content h2Content = new StringContent( + configuration.getText("doclet.Package_Description", + packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement))); + Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, h2Content); + if (configuration.allowTag(HtmlTag.SECTION)) { + sectionTree.addContent(heading); + addInlineComment(packageElement, sectionTree); + } else { + packageContentTree.addContent(heading); + addInlineComment(packageElement, packageContentTree); + } + } + } + + /** + * {@inheritDoc} + */ + public void addPackageTags(Content packageContentTree) { + Content htmlTree = (configuration.allowTag(HtmlTag.SECTION)) + ? sectionTree + : packageContentTree; + addTagsInfo(packageElement, htmlTree); + } + + /** + * {@inheritDoc} + */ + public void addPackageContent(Content contentTree, Content packageContentTree) { + if (configuration.allowTag(HtmlTag.MAIN)) { + packageContentTree.addContent(sectionTree); + mainTree.addContent(packageContentTree); + contentTree.addContent(mainTree); + } else { + contentTree.addContent(packageContentTree); + } + } + + /** + * {@inheritDoc} + */ + public void addPackageFooter(Content contentTree) { + Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : contentTree; + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + contentTree.addContent(htmlTree); + } + } + + /** + * {@inheritDoc} + */ + public void printDocument(Content contentTree) throws IOException { + printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement), + true, contentTree); + } + + /** + * Get "Use" link for this pacakge in the navigation bar. + * + * @return a content tree for the class use link + */ + protected Content getNavLinkClassUse() { + Content useLink = getHyperLink(DocPaths.PACKAGE_USE, + useLabel, "", ""); + Content li = HtmlTree.LI(useLink); + return li; + } + + /** + * Get "PREV PACKAGE" link in the navigation bar. + * + * @return a content tree for the previous link + */ + public Content getNavLinkPrevious() { + Content li; + if (prev == null) { + li = HtmlTree.LI(prevpackageLabel); + } else { + DocPath path = DocPath.relativePath(packageElement, prev); + li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.PACKAGE_SUMMARY), + prevpackageLabel, "", "")); + } + return li; + } + + /** + * Get "NEXT PACKAGE" link in the navigation bar. + * + * @return a content tree for the next link + */ + public Content getNavLinkNext() { + Content li; + if (next == null) { + li = HtmlTree.LI(nextpackageLabel); + } else { + DocPath path = DocPath.relativePath(packageElement, next); + li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.PACKAGE_SUMMARY), + nextpackageLabel, "", "")); + } + return li; + } + + /** + * Get "Tree" link in the navigation bar. This will be link to the package + * tree file. + * + * @return a content tree for the tree link + */ + protected Content getNavLinkTree() { + Content useLink = getHyperLink(DocPaths.PACKAGE_TREE, + treeLabel, "", ""); + Content li = HtmlTree.LI(useLink); + return li; + } + + /** + * Highlight "Package" in the navigation bar, as this is the package page. + * + * @return a content tree for the package link + */ + protected Content getNavLinkPackage() { + Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, packageLabel); + return li; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java new file mode 100644 index 00000000000..3a1eebc23cf --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java @@ -0,0 +1,369 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import java.util.Arrays; +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; +import jdk.javadoc.internal.doclets.toolkit.PropertyWriter; + + +/** + * Writes property documentation in HTML format. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Robert Field + * @author Atul M Dambalkar + * @author Jamie Ho (rewrite) + * @author Bhavesh Patel (Modified) + */ +public class PropertyWriterImpl extends AbstractMemberWriter + implements PropertyWriter, MemberSummaryWriter { + + public PropertyWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) { + super(writer, typeElement); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getMemberSummaryHeader(TypeElement typeElement, + Content memberSummaryTree) { + memberSummaryTree.addContent(HtmlConstants.START_OF_PROPERTY_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, typeElement, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + writer.addMemberTree(memberSummaryTree, memberTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getPropertyDetailsTreeHeader(TypeElement typeElement, + Content memberDetailsTree) { + memberDetailsTree.addContent(HtmlConstants.START_OF_PROPERTY_DETAILS); + Content propertyDetailsTree = writer.getMemberTreeHeader(); + propertyDetailsTree.addContent(writer.getMarkerAnchor( + SectionName.PROPERTY_DETAIL)); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.propertyDetailsLabel); + propertyDetailsTree.addContent(heading); + return propertyDetailsTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getPropertyDocTreeHeader(ExecutableElement property, + Content propertyDetailsTree) { + propertyDetailsTree.addContent( + writer.getMarkerAnchor(name(property))); + Content propertyDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(utils.getPropertyLabel(name(property))); + propertyDocTree.addContent(heading); + return propertyDocTree; + } + + /** + * {@inheritDoc} + */ + @Override + public Content getSignature(ExecutableElement property) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(property, pre); + addModifiers(property, pre); + Content propertylink = writer.getLink(new LinkInfoImpl( + configuration, LinkInfoImpl.Kind.MEMBER, + utils.getReturnType(property))); + pre.addContent(propertylink); + pre.addContent(" "); + if (configuration.linksource) { + Content propertyName = new StringContent(name(property)); + writer.addSrcLink(property, propertyName, pre); + } else { + addName(name(property), pre); + } + return pre; + } + + /** + * {@inheritDoc} + */ + @Override + public void addDeprecated(ExecutableElement property, Content propertyDocTree) { + } + + /** + * {@inheritDoc} + */ + @Override + public void addComments(ExecutableElement property, Content propertyDocTree) { + TypeElement holder = (TypeElement)property.getEnclosingElement(); + if (!utils.getBody(property).isEmpty()) { + if (holder.equals(typeElement) || + (!utils.isPublic(holder) || utils.isLinkable(holder))) { + writer.addInlineComment(property, propertyDocTree); + } else { + Content link = + writer.getDocLink(LinkInfoImpl.Kind.PROPERTY_COPY, + holder, property, + utils.isIncluded(holder) + ? holder.toString() : utils.getFullyQualifiedName(holder), + false); + Content codeLink = HtmlTree.CODE(link); + Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel, + utils.isClass(holder) + ? writer.descfrmClassLabel + : writer.descfrmInterfaceLabel); + descfrmLabel.addContent(writer.getSpace()); + descfrmLabel.addContent(codeLink); + propertyDocTree.addContent(HtmlTree.DIV(HtmlStyle.block, descfrmLabel)); + writer.addInlineComment(property, propertyDocTree); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addTags(ExecutableElement property, Content propertyDocTree) { + writer.addTagsInfo(property, propertyDocTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getPropertyDetails(Content propertyDetailsTree) { + if (configuration.allowTag(HtmlTag.SECTION)) { + HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(propertyDetailsTree)); + return htmlTree; + } + return getMemberTree(propertyDetailsTree); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getPropertyDoc(Content propertyDocTree, + boolean isLastContent) { + return getMemberTree(propertyDocTree, isLastContent); + } + + /** + * Close the writer. + */ + @Override + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Property_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + @Override + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Property_Summary"), + configuration.getText("doclet.properties")); + } + + /** + * {@inheritDoc} + */ + @Override + public Content getCaption() { + return configuration.getResource("doclet.Properties"); + } + + /** + * {@inheritDoc} + */ + @Override + public List getSummaryTableHeader(Element member) { + List header = Arrays.asList(configuration.getText("doclet.Type"), + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Property"), + configuration.getText("doclet.Description"))); + return header; + } + + /** + * {@inheritDoc} + */ + @Override + public void addSummaryAnchor(TypeElement typeElement, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + SectionName.PROPERTY_SUMMARY)); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) { + inheritedTree.addContent(writer.getMarkerAnchor( + SectionName.PROPERTIES_INHERITANCE, + configuration.getClassName(typeElement))); + } + + /** + * {@inheritDoc} + */ + @Override + public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) { + Content classLink = writer.getPreQualifiedClassLink( + LinkInfoImpl.Kind.MEMBER, typeElement, false); + Content label = new StringContent( + utils.isClass(typeElement) + ? configuration.getText("doclet.Properties_Inherited_From_Class") + : configuration.getText("doclet.Properties_Inherited_From_Interface")); + Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING, + label); + labelHeading.addContent(writer.getSpace()); + labelHeading.addContent(classLink); + inheritedTree.addContent(labelHeading); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member, + Content tdSummary) { + Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink, + writer.getDocLink(context, typeElement, + member, + utils.getPropertyLabel(name(member)), + false, + true)); + + Content code = HtmlTree.CODE(memberLink); + tdSummary.addContent(code); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) { + String mname = name(member); + Content content = writer.getDocLink(LinkInfoImpl.Kind.MEMBER, typeElement, member, + utils.isProperty(mname) ? utils.getPropertyName(mname) : mname, + false, true); + linksTree.addContent(content); + } + + /** + * {@inheritDoc} + */ + @Override + protected void addSummaryType(Element member, Content tdSummaryType) { + addModifierAndType(member, utils.getReturnType((ExecutableElement)member), tdSummaryType); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getDeprecatedLink(Element member) { + return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, + utils.getFullyQualifiedName(member)); + } + + /** + * {@inheritDoc} + */ + @Override + protected Content getNavSummaryLink(TypeElement typeElement, boolean link) { + if (link) { + if (typeElement == null) { + return writer.getHyperLink( + SectionName.PROPERTY_SUMMARY, + writer.getResource("doclet.navProperty")); + } else { + return writer.getHyperLink( + SectionName.PROPERTIES_INHERITANCE, + configuration.getClassName(typeElement), writer.getResource("doclet.navProperty")); + } + } else { + return writer.getResource("doclet.navProperty"); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void addNavDetailLink(boolean link, Content liNav) { + if (link) { + liNav.addContent(writer.getHyperLink( + SectionName.PROPERTY_DETAIL, + writer.getResource("doclet.navProperty"))); + } else { + liNav.addContent(writer.getResource("doclet.navProperty")); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchIndexItem.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchIndexItem.java new file mode 100644 index 00000000000..d260a9b5538 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchIndexItem.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +/** + * Index item for search. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class SearchIndexItem { + + private String label = ""; + private String url = ""; + private String category = ""; + private String containingPackage = ""; + private String containingClass = ""; + private String holder = ""; + private String description = ""; + + public void setLabel(String l) { + label = l; + } + + public String getLabel() { + return label; + } + + public void setUrl(String u) { + url = u; + } + + public String getUrl() { + return url; + } + + public void setContainingPackage(String p) { + containingPackage = p; + } + + public void setContainingClass(String c) { + containingClass = c; + } + + public void setCategory(String c) { + category = c; + } + + public void setHolder(String h) { + holder = h; + } + + public String getHolder() { + return holder; + } + + public void setDescription(String d) { + description = d; + } + + public String getDescription() { + return description; + } + + public String toString() { + StringBuilder item = new StringBuilder(""); + if (category.equals("Packages")) { + item.append("{") + .append("\"l\":\"").append(label).append("\"") + .append("}"); + } else if (category.equals("Types")) { + item.append("{") + .append("\"p\":\"").append(containingPackage).append("\",") + .append("\"l\":\"").append(label).append("\"") + .append("}"); + } else if (category.equals("Members")) { + item.append("{") + .append("\"p\":\"").append(containingPackage).append("\",") + .append("\"c\":\"").append(containingClass).append("\",") + .append("\"l\":\"").append(label).append("\""); + if (!url.equals("")) { + item.append(",\"url\":\"").append(url).append("\""); + } + item.append("}"); + } else { + item.append("{") + .append("\"l\":\"").append(label).append("\",") + .append("\"h\":\"").append(holder).append("\","); + if (!description.equals("")) { + item.append("\"d\":\"").append(description).append("\","); + } + item.append("\"u\":\"").append(url).append("\"") + .append("}"); + } + return item.toString(); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java new file mode 100644 index 00000000000..a9ff3e50311 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +/** + * Enum representing various section names of generated API documentation. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public enum SectionName { + + ANNOTATION_TYPE_ELEMENT_DETAIL("annotation.type.element.detail"), + ANNOTATION_TYPE_FIELD_DETAIL("annotation.type.field.detail"), + ANNOTATION_TYPE_FIELD_SUMMARY("annotation.type.field.summary"), + ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY("annotation.type.optional.element.summary"), + ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY("annotation.type.required.element.summary"), + CONSTRUCTOR_DETAIL("constructor.detail"), + CONSTRUCTOR_SUMMARY("constructor.summary"), + ENUM_CONSTANT_DETAIL("enum.constant.detail"), + ENUM_CONSTANTS_INHERITANCE("enum.constants.inherited.from.class."), + ENUM_CONSTANT_SUMMARY("enum.constant.summary"), + FIELD_DETAIL("field.detail"), + FIELDS_INHERITANCE("fields.inherited.from.class."), + FIELD_SUMMARY("field.summary"), + METHOD_DETAIL("method.detail"), + METHODS_INHERITANCE("methods.inherited.from.class."), + METHOD_SUMMARY("method.summary"), + NAVBAR_BOTTOM("navbar.bottom"), + NAVBAR_BOTTOM_FIRSTROW("navbar.bottom.firstrow"), + NAVBAR_TOP("navbar.top"), + NAVBAR_TOP_FIRSTROW("navbar.top.firstrow"), + NESTED_CLASSES_INHERITANCE("nested.classes.inherited.from.class."), + NESTED_CLASS_SUMMARY("nested.class.summary"), + OVERVIEW_DESCRIPTION("overview.description"), + PACKAGE_DESCRIPTION("package.description"), + PROPERTY_DETAIL("property.detail"), + PROPERTIES_INHERITANCE("properties.inherited.from.class."), + PROPERTY_SUMMARY("property.summary"), + SKIP_NAVBAR_BOTTOM("skip.navbar.bottom"), + SKIP_NAVBAR_TOP("skip.navbar.top"), + UNNAMED_PACKAGE_ANCHOR("unnamed.package"); + + private final String value; + + SectionName(String sName) { + this.value = sName; + } + + public String getName() { + return this.value; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java new file mode 100644 index 00000000000..764810f3902 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java @@ -0,0 +1,301 @@ +/* + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter; +import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter.SerialFieldWriter; +import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter.SerialMethodWriter; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + +/** + * Generate the Serialized Form Information Page. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + */ +public class SerializedFormWriterImpl extends SubWriterHolderWriter + implements SerializedFormWriter { + + Set visibleClasses; + + /** + * HTML tree for main tag. + */ + private HtmlTree mainTree = HtmlTree.MAIN(); + + /** + * @param configuration the configuration data for the doclet + * @throws IOException + * @throws DocletAbortException + */ + public SerializedFormWriterImpl(ConfigurationImpl configuration) + throws IOException { + super(configuration, DocPaths.SERIALIZED_FORM); + visibleClasses = configuration.root.getIncludedClasses(); + } + + /** + * Get the given header. + * + * @param header the header to write + * @return the body content tree + */ + public Content getHeader(String header) { + HtmlTree bodyTree = getBody(true, getWindowTitle(header)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + Content h1Content = new StringContent(header); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true, + HtmlStyle.title, h1Content); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(div); + } else { + bodyTree.addContent(div); + } + return bodyTree; + } + + /** + * Get the serialized form summaries header. + * + * @return the serialized form summary header tree + */ + public Content getSerializedSummariesHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * Get the package serialized form header. + * + * @return the package serialized form header tree + */ + public Content getPackageSerializedHeader() { + HtmlTree htmlTree; + if (configuration.allowTag(HtmlTag.SECTION)) { + htmlTree = HtmlTree.SECTION(); + } else { + htmlTree = new HtmlTree(HtmlTag.LI); + htmlTree.addStyle(HtmlStyle.blockList); + } + return htmlTree; + } + + /** + * Get the given package header. + * + * @param packageName the package header to write + * @return a content tree for the package header + */ + public Content getPackageHeader(String packageName) { + Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, + packageLabel); + heading.addContent(getSpace()); + heading.addContent(packageName); + return heading; + } + + /** + * Get the serialized class header. + * + * @return a content tree for the serialized class header + */ + public Content getClassSerializedHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * Checks if a class is generated and is visible. + * + * @param typeElement the class being processed. + * @return true if the class, that is being processed, is generated and is visible. + */ + public boolean isVisibleClass(TypeElement typeElement) { + return visibleClasses.contains(typeElement) && configuration.isGeneratedDoc(typeElement); + } + + /** + * Get the serializable class heading. + * + * @param typeElement the class being processed + * @return a content tree for the class header + */ + public Content getClassHeader(TypeElement typeElement) { + Content classLink = (isVisibleClass(typeElement)) + ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, typeElement) + .label(configuration.getClassName(typeElement))) + : new StringContent(utils.getFullyQualifiedName(typeElement)); + Content li = HtmlTree.LI(HtmlStyle.blockList, getMarkerAnchor( + utils.getFullyQualifiedName(typeElement))); + Content superClassLink = typeElement.getSuperclass() != null + ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.SERIALIZED_FORM, + typeElement.getSuperclass())) + : null; + + //Print the heading. + Content className = superClassLink == null ? + configuration.getResource( + "doclet.Class_0_implements_serializable", classLink) : + configuration.getResource( + "doclet.Class_0_extends_implements_serializable", classLink, + superClassLink); + li.addContent(HtmlTree.HEADING(HtmlConstants.SERIALIZED_MEMBER_HEADING, + className)); + return li; + } + + /** + * Get the serial UID info header. + * + * @return a content tree for the serial uid info header + */ + public Content getSerialUIDInfoHeader() { + HtmlTree dl = new HtmlTree(HtmlTag.DL); + dl.addStyle(HtmlStyle.nameValue); + return dl; + } + + /** + * Adds the serial UID info. + * + * @param header the header that will show up before the UID. + * @param serialUID the serial UID to print. + * @param serialUidTree the serial UID content tree to which the serial UID + * content will be added + */ + public void addSerialUIDInfo(String header, String serialUID, + Content serialUidTree) { + Content headerContent = new StringContent(header); + serialUidTree.addContent(HtmlTree.DT(headerContent)); + Content serialContent = new StringContent(serialUID); + serialUidTree.addContent(HtmlTree.DD(serialContent)); + } + + /** + * Get the class serialize content header. + * + * @return a content tree for the class serialize content header + */ + public Content getClassContentHeader() { + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.blockList); + return ul; + } + + /** + * Get the serialized content tree section. + * + * @param serializedTreeContent the serialized content tree to be added + * @return a div content tree + */ + public Content getSerializedContent(Content serializedTreeContent) { + HtmlTree divContent = HtmlTree.DIV(HtmlStyle.serializedFormContainer, + serializedTreeContent); + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(divContent); + return mainTree; + } else { + return divContent; + } + } + + /** + * {@inheritDoc} + */ + public void addPackageSerializedTree(Content serializedSummariesTree, + Content packageSerializedTree) { + serializedSummariesTree.addContent((configuration.allowTag(HtmlTag.SECTION)) + ? HtmlTree.LI(HtmlStyle.blockList, packageSerializedTree) + : packageSerializedTree); + } + + /** + * Add the footer. + * + * @param serializedTree the serialized tree to be added + */ + public void addFooter(Content serializedTree) { + Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER)) + ? HtmlTree.FOOTER() + : serializedTree; + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + serializedTree.addContent(htmlTree); + } + } + + /** + * {@inheritDoc} + */ + public void printDocument(Content serializedTree) throws IOException { + printHtmlDocument(null, true, serializedTree); + } + + /** + * Return an instance of a SerialFieldWriter. + * + * @return an instance of a SerialFieldWriter. + */ + public SerialFieldWriter getSerialFieldWriter(TypeElement typeElement) { + return new HtmlSerialFieldWriter(this, typeElement); + } + + /** + * Return an instance of a SerialMethodWriter. + * + * @return an instance of a SerialMethodWriter. + */ + public SerialMethodWriter getSerialMethodWriter(TypeElement typeElement) { + return new HtmlSerialMethodWriter(this, typeElement); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java new file mode 100644 index 00000000000..81189d6ee61 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.IndexBuilder; + + +/** + * Generate only one index file for all the Member Names with Indexing in + * Unicode Order. The name of the generated file is "index-all.html" and it is + * generated in current or the destination directory. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @see java.lang.Character + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class SingleIndexWriter extends AbstractIndexWriter { + + private Set elements; + + /** + * Construct the SingleIndexWriter with filename "index-all.html" and the + * {@link IndexBuilder} + * + * @param filename Name of the index file to be generated. + * @param indexbuilder Unicode based Index from {@link IndexBuilder} + */ + public SingleIndexWriter(ConfigurationImpl configuration, + DocPath filename, + IndexBuilder indexbuilder) throws IOException { + super(configuration, filename, indexbuilder); + } + + /** + * Generate single index file, for all Unicode characters. + * + * @param indexbuilder IndexBuilder built by {@link IndexBuilder} + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration, + IndexBuilder indexbuilder) { + SingleIndexWriter indexgen; + DocPath filename = DocPaths.INDEX_ALL; + try { + indexgen = new SingleIndexWriter(configuration, + filename, indexbuilder); + indexgen.generateIndexFile(); + indexgen.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), filename); + throw new DocletAbortException(exc); + } + } + + /** + * Generate the contents of each index file, with Header, Footer, + * Member Field, Method and Constructor Description. + */ + protected void generateIndexFile() throws IOException { + String title = configuration.getText("doclet.Window_Single_Index"); + HtmlTree body = getBody(true, getWindowTitle(title)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : body; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + body.addContent(htmlTree); + } + HtmlTree divTree = new HtmlTree(HtmlTag.DIV); + divTree.addStyle(HtmlStyle.contentContainer); + elements = new TreeSet<>(indexbuilder.getIndexMap().keySet()); + elements.addAll(configuration.tagSearchIndexKeys); + addLinksForIndexes(divTree); + for (Character unicode : elements) { + if (configuration.tagSearchIndexMap.get(unicode) == null) { + addContents(unicode, indexbuilder.getMemberList(unicode), divTree); + } else if (indexbuilder.getMemberList(unicode) == null) { + addSearchContents(unicode, configuration.tagSearchIndexMap.get(unicode), divTree); + } else { + addContents(unicode, indexbuilder.getMemberList(unicode), + configuration.tagSearchIndexMap.get(unicode), divTree); + } + } + addLinksForIndexes(divTree); + body.addContent((configuration.allowTag(HtmlTag.MAIN)) + ? HtmlTree.MAIN(divTree) + : divTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + htmlTree = HtmlTree.FOOTER(); + } + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(htmlTree); + } + createSearchIndexFiles(); + printHtmlDocument(null, true, body); + } + + /** + * Add links for all the Index Files per unicode character. + * + * @param contentTree the content tree to which the links for indexes will be added + */ + protected void addLinksForIndexes(Content contentTree) { + for (Object ch : elements) { + String unicode = ch.toString(); + contentTree.addContent( + getHyperLink(getNameForIndex(unicode), + new StringContent(unicode))); + contentTree.addContent(getSpace()); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java new file mode 100644 index 00000000000..0396188d8be --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; + +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.tools.FileObject; + +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.internal.doclets.formats.html.markup.DocType; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocFile; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; +import jdk.javadoc.internal.doclets.toolkit.util.Utils; + +/** + * Converts Java Source Code to HTML. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Jamie Ho + * @author Bhavesh Patel (Modified) + */ +public class SourceToHTMLConverter { + + /** + * The number of trailing blank lines at the end of the page. + * This is inserted so that anchors at the bottom of small pages + * can be reached. + */ + private static final int NUM_BLANK_LINES = 60; + + /** + * New line to be added to the documentation. + */ + private static final String NEW_LINE = DocletConstants.NL; + + private final ConfigurationImpl configuration; + private final Utils utils; + + private final DocletEnvironment rootDoc; + + private DocPath outputdir; + + /** + * Relative path from the documentation root to the file that is being + * generated. + */ + private DocPath relativePath = DocPath.empty; + + private SourceToHTMLConverter(ConfigurationImpl configuration, DocletEnvironment rd, + DocPath outputdir) { + this.configuration = configuration; + this.utils = configuration.utils; + this.rootDoc = rd; + this.outputdir = outputdir; + } + + /** + * Translate the TypeElements in the given DocletEnvironment to HTML representation. + * + * @param configuration the configuration. + * @param root the DocletEnvironment to convert. + * @param outputdir the name of the directory to output to. + */ + public static void convertRoot(ConfigurationImpl configuration, DocletEnvironment root, + DocPath outputdir) { + new SourceToHTMLConverter(configuration, root, outputdir).generate(); + } + + void generate() { + if (rootDoc == null || outputdir == null) { + return; + } + for (PackageElement pkg : utils.getSpecifiedPackages()) { + // If -nodeprecated option is set and the package is marked as deprecated, + // do not convert the package files to HTML. + if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) + convertPackage(pkg, outputdir); + } + for (TypeElement te : utils.getSpecifiedClasses()) { + // If -nodeprecated option is set and the class is marked as deprecated + // or the containing package is deprecated, do not convert the + // package files to HTML. + if (!(configuration.nodeprecated && + (utils.isDeprecated(te) || utils.isDeprecated(utils.containingPackage(te))))) + convertClass(te, outputdir); + } + } + + /** + * Convert the Classes in the given Package to an HTML. + * + * @param pkg the Package to convert. + * @param outputdir the name of the directory to output to. + */ + public void convertPackage(PackageElement pkg, DocPath outputdir) { + if (pkg == null) { + return; + } + for (Element te : utils.getAllClasses(pkg)) { + // If -nodeprecated option is set and the class is marked as deprecated, + // do not convert the package files to HTML. We do not check for + // containing package deprecation since it is already check in + // the calling method above. + if (!(configuration.nodeprecated && utils.isDeprecated(te))) + convertClass((TypeElement)te, outputdir); + } + } + + /** + * Convert the given Class to an HTML. + * + * @param te the class to convert. + * @param outputdir the name of the directory to output to. + */ + public void convertClass(TypeElement te, DocPath outputdir) { + if (te == null) { + return; + } + try { + FileObject fo = utils.getFileObject(te); + if (fo == null) + return; + Reader r = fo.openReader(true); + int lineno = 1; + String line; + relativePath = DocPaths.SOURCE_OUTPUT + .resolve(DocPath.forPackage(utils, te)) + .invert(); + Content body = getHeader(); + Content pre = new HtmlTree(HtmlTag.PRE); + try (LineNumberReader reader = new LineNumberReader(r)) { + while ((line = reader.readLine()) != null) { + addLineNo(pre, lineno); + addLine(pre, line, lineno); + lineno++; + } + } + addBlankLines(pre); + Content div = HtmlTree.DIV(HtmlStyle.sourceContainer, pre); + body.addContent((configuration.allowTag(HtmlTag.MAIN)) ? HtmlTree.MAIN(div) : div); + writeToFile(body, outputdir.resolve(DocPath.forClass(utils, te))); + } catch (IOException e) { + throw new DocletAbortException(e); + } + } + + /** + * Write the output to the file. + * + * @param body the documentation content to be written to the file. + * @param path the path for the file. + */ + private void writeToFile(Content body, DocPath path) throws IOException { + Content htmlDocType = configuration.isOutputHtml5() + ? DocType.HTML5 + : DocType.TRANSITIONAL; + Content head = new HtmlTree(HtmlTag.HEAD); + head.addContent(HtmlTree.TITLE(new StringContent( + configuration.getText("doclet.Window_Source_title")))); + head.addContent(getStyleSheetProperties()); + Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), + head, body); + Content htmlDocument = new HtmlDocument(htmlDocType, htmlTree); + configuration.message.notice("doclet.Generating_0", path.getPath()); + DocFile df = DocFile.createFileForOutput(configuration, path); + try (Writer w = df.openWriter()) { + htmlDocument.write(w, true); + } + + } + + /** + * Returns a link to the stylesheet file. + * + * @return an HtmlTree for the lINK tag which provides the stylesheet location + */ + public HtmlTree getStyleSheetProperties() { + String filename = configuration.stylesheetfile; + DocPath stylesheet; + if (filename.length() > 0) { + DocFile file = DocFile.createFileForInput(configuration, filename); + stylesheet = DocPath.create(file.getName()); + } else { + stylesheet = DocPaths.STYLESHEET; + } + DocPath p = relativePath.resolve(stylesheet); + HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", p.getPath(), "Style"); + return link; + } + + /** + * Get the header. + * + * @return the header content for the HTML file + */ + private static Content getHeader() { + return new HtmlTree(HtmlTag.BODY); + } + + /** + * Add the line numbers for the source code. + * + * @param pre the content tree to which the line number will be added + * @param lineno The line number + */ + private static void addLineNo(Content pre, int lineno) { + HtmlTree span = new HtmlTree(HtmlTag.SPAN); + span.addStyle(HtmlStyle.sourceLineNo); + if (lineno < 10) { + span.addContent("00" + Integer.toString(lineno)); + } else if (lineno < 100) { + span.addContent("0" + Integer.toString(lineno)); + } else { + span.addContent(Integer.toString(lineno)); + } + pre.addContent(span); + } + + /** + * Add a line from source to the HTML file that is generated. + * + * @param pre the content tree to which the line will be added. + * @param line the string to format. + * @param currentLineNo the current number. + */ + private void addLine(Content pre, String line, int currentLineNo) { + if (line != null) { + Content anchor = HtmlTree.A(configuration.htmlVersion, + "line." + Integer.toString(currentLineNo), + new StringContent(utils.replaceTabs(line))); + pre.addContent(anchor); + pre.addContent(NEW_LINE); + } + } + + /** + * Add trailing blank lines at the end of the page. + * + * @param pre the content tree to which the blank lines will be added. + */ + private static void addBlankLines(Content pre) { + for (int i = 0; i < NUM_BLANK_LINES; i++) { + pre.addContent(NEW_LINE); + } + } + + /** + * Given a Doc, return an anchor name for it. + * + * @param d the Doc to check. + * @return the name of the anchor. + */ + public static String getAnchorName(Utils utils, Element e) { + return "line." + utils.getLineNumber(e); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java new file mode 100644 index 00000000000..f73407cd5e2 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.ListIterator; +import java.util.Set; +import java.util.TreeSet; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.IndexBuilder; + + +/** + * Generate Separate Index Files for all the member names with Indexing in + * Unicode Order. This will create "index-files" directory in the current or + * destination directory and will generate separate file for each unicode index. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @see java.lang.Character + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class SplitIndexWriter extends AbstractIndexWriter { + + /** + * Previous unicode character index in the built index. + */ + protected int prev; + + /** + * Next unicode character in the built index. + */ + protected int next; + + private List indexElements; + + /** + * Construct the SplitIndexWriter. Uses path to this file and relative path + * from this file. + * + * @param path Path to the file which is getting generated. + * @param indexbuilder Unicode based Index from {@link IndexBuilder} + */ + public SplitIndexWriter(ConfigurationImpl configuration, + DocPath path, + IndexBuilder indexbuilder, + Collection elements, + int prev, int next) throws IOException { + super(configuration, path, indexbuilder); + this.indexElements = new ArrayList<>(elements); + this.prev = prev; + this.next = next; + } + + /** + * Generate separate index files, for each Unicode character, listing all + * the members starting with the particular unicode character. + * + * @param indexbuilder IndexBuilder built by {@link IndexBuilder} + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration, + IndexBuilder indexbuilder) { + SplitIndexWriter indexgen; + DocPath filename = DocPath.empty; + DocPath path = DocPaths.INDEX_FILES; + try { + Set keys = new TreeSet<>(indexbuilder.getIndexMap().keySet()); + keys.addAll(configuration.tagSearchIndexKeys); + ListIterator li = new ArrayList<>(keys).listIterator(); + while (li.hasNext()) { + Object ch = li.next(); + filename = DocPaths.indexN(li.nextIndex()); + indexgen = new SplitIndexWriter(configuration, + path.resolve(filename), + indexbuilder, keys, li.previousIndex(), li.nextIndex()); + indexgen.generateIndexFile((Character) ch); + if (!li.hasNext()) { + indexgen.createSearchIndexFiles(); + } + indexgen.close(); + } + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), filename.getPath()); + throw new DocletAbortException(exc); + } + } + + /** + * Generate the contents of each index file, with Header, Footer, + * Member Field, Method and Constructor Description. + * + * @param unicode Unicode character referring to the character for the + * index. + */ + protected void generateIndexFile(Character unicode) throws IOException { + String title = configuration.getText("doclet.Window_Split_Index", + unicode.toString()); + HtmlTree body = getBody(true, getWindowTitle(title)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : body; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + body.addContent(htmlTree); + } + HtmlTree divTree = new HtmlTree(HtmlTag.DIV); + divTree.addStyle(HtmlStyle.contentContainer); + addLinksForIndexes(divTree); + if (configuration.tagSearchIndexMap.get(unicode) == null) { + addContents(unicode, indexbuilder.getMemberList(unicode), divTree); + } else if (indexbuilder.getMemberList(unicode) == null) { + addSearchContents(unicode, configuration.tagSearchIndexMap.get(unicode), divTree); + } else { + addContents(unicode, indexbuilder.getMemberList(unicode), + configuration.tagSearchIndexMap.get(unicode), divTree); + } + addLinksForIndexes(divTree); + body.addContent((configuration.allowTag(HtmlTag.MAIN)) ? HtmlTree.MAIN(divTree) : divTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + htmlTree = HtmlTree.FOOTER(); + } + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(htmlTree); + } + printHtmlDocument(null, true, body); + } + + /** + * Add links for all the Index Files per unicode character. + * + * @param contentTree the content tree to which the links for indexes will be added + */ + protected void addLinksForIndexes(Content contentTree) { + for (int i = 0; i < indexElements.size(); i++) { + int j = i + 1; + contentTree.addContent(getHyperLink(DocPaths.indexN(j), + new StringContent(indexElements.get(i).toString()))); + contentTree.addContent(getSpace()); + } + } + + /** + * Get link to the previous unicode character. + * + * @return a content tree for the link + */ + public Content getNavLinkPrevious() { + Content prevletterLabel = getResource("doclet.Prev_Letter"); + if (prev == -1) { + return HtmlTree.LI(prevletterLabel); + } + else { + Content prevLink = getHyperLink(DocPaths.indexN(prev), + prevletterLabel); + return HtmlTree.LI(prevLink); + } + } + + /** + * Get link to the next unicode character. + * + * @return a content tree for the link + */ + public Content getNavLinkNext() { + Content nextletterLabel = getResource("doclet.Next_Letter"); + if (next == -1) { + return HtmlTree.LI(nextletterLabel); + } + else { + Content nextLink = getHyperLink(DocPaths.indexN(next), + nextletterLabel); + return HtmlTree.LI(nextLink); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java new file mode 100644 index 00000000000..11888eb26db --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +import com.sun.source.doctree.DocTree; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.MethodTypes; + +/** + * This abstract class exists to provide functionality needed in the + * the formatting of member information. Since AbstractSubWriter and its + * subclasses control this, they would be the logical place to put this. + * However, because each member type has its own subclass, subclassing + * can not be used effectively to change formatting. The concrete + * class subclass of this class can be subclassed to change formatting. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @see AbstractMemberWriter + * @see ClassWriterImpl + * + * @author Robert Field + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public abstract class SubWriterHolderWriter extends HtmlDocletWriter { + + /** + * The HTML tree for main tag. + */ + protected HtmlTree mainTree = HtmlTree.MAIN(); + + public SubWriterHolderWriter(ConfigurationImpl configuration, DocPath filename) + throws IOException { + super(configuration, filename); + } + + /** + * Add the summary header. + * + * @param mw the writer for the member being documented + * @param typeElement the te to be documented + * @param memberTree the content tree to which the summary header will be added + */ + public void addSummaryHeader(AbstractMemberWriter mw, TypeElement typeElement, + Content memberTree) { + mw.addSummaryAnchor(typeElement, memberTree); + mw.addSummaryLabel(memberTree); + } + + /** + * Get the summary table. + * + * @param mw the writer for the member being documented + * @param typeElement the te to be documented + * @param tableContents list of summary table contents + * @param showTabs true if the table needs to show tabs + * @return the content tree for the summary table + */ + public Content getSummaryTableTree(AbstractMemberWriter mw, TypeElement typeElement, + List tableContents, boolean showTabs) { + Content caption; + if (showTabs) { + caption = getTableCaption(mw.methodTypes); + generateMethodTypesScript(mw.typeMap, mw.methodTypes); + } + else { + caption = getTableCaption(mw.getCaption()); + } + Content table = (configuration.isOutputHtml5()) + ? HtmlTree.TABLE(HtmlStyle.memberSummary, caption) + : HtmlTree.TABLE(HtmlStyle.memberSummary, mw.getTableSummary(), caption); + table.addContent(getSummaryTableHeader(mw.getSummaryTableHeader(typeElement), "col")); + for (Content tableContent : tableContents) { + table.addContent(tableContent); + } + return table; + } + + /** + * Get the summary table caption. + * + * @param methodTypes set comprising of method types to show as table caption + * @return the caption for the summary table + */ + public Content getTableCaption(Set methodTypes) { + Content tabbedCaption = new HtmlTree(HtmlTag.CAPTION); + for (MethodTypes type : methodTypes) { + Content captionSpan; + Content span; + if (type.isDefaultTab()) { + captionSpan = HtmlTree.SPAN(configuration.getResource(type.resourceKey())); + span = HtmlTree.SPAN(type.tabId(), + HtmlStyle.activeTableTab, captionSpan); + } else { + captionSpan = HtmlTree.SPAN(getMethodTypeLinks(type)); + span = HtmlTree.SPAN(type.tabId(), + HtmlStyle.tableTab, captionSpan); + } + Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, getSpace()); + span.addContent(tabSpan); + tabbedCaption.addContent(span); + } + return tabbedCaption; + } + + /** + * Get the method type links for the table caption. + * + * @param methodType the method type to be displayed as link + * @return the content tree for the method type link + */ + public Content getMethodTypeLinks(MethodTypes methodType) { + String jsShow = "javascript:show(" + methodType.value() +");"; + HtmlTree link = HtmlTree.A(jsShow, configuration.getResource(methodType.resourceKey())); + return link; + } + + /** + * Add the inherited summary header. + * + * @param mw the writer for the member being documented + * @param typeElement the te to be documented + * @param inheritedTree the content tree to which the inherited summary header will be added + */ + public void addInheritedSummaryHeader(AbstractMemberWriter mw, TypeElement typeElement, + Content inheritedTree) { + mw.addInheritedSummaryAnchor(typeElement, inheritedTree); + mw.addInheritedSummaryLabel(typeElement, inheritedTree); + } + + /** + * Add the index comment. + * + * @param member the member being documented + * @param contentTree the content tree to which the comment will be added + */ + protected void addIndexComment(Element member, Content contentTree) { + List tags = utils.getFirstSentenceTrees(member); + addIndexComment(member, tags, contentTree); + } + + /** + * Add the index comment. + * + * @param member the member being documented + * @param firstSentenceTags the first sentence tags for the member to be documented + * @param tdSummary the content tree to which the comment will be added + */ + protected void addIndexComment(Element member, List firstSentenceTags, + Content tdSummary) { + List deprs = utils.getBlockTags(member, DocTree.Kind.DEPRECATED); + Content div; + if (utils.isDeprecated(member)) { + Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase); + div = HtmlTree.DIV(HtmlStyle.block, deprLabel); + div.addContent(getSpace()); + if (!deprs.isEmpty()) { + addInlineDeprecatedComment(member, deprs.get(0), div); + } + tdSummary.addContent(div); + return; + } else { + Element te = member.getEnclosingElement(); + if (te != null && utils.isTypeElement(te) && utils.isDeprecated(te)) { + Content deprLabel = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, deprecatedPhrase); + div = HtmlTree.DIV(HtmlStyle.block, deprLabel); + div.addContent(getSpace()); + tdSummary.addContent(div); + } + } + addSummaryComment(member, firstSentenceTags, tdSummary); + } + + /** + * Add the summary type for the member. + * + * @param mw the writer for the member being documented + * @param member the member to be documented + * @param tdSummaryType the content tree to which the type will be added + */ + public void addSummaryType(AbstractMemberWriter mw, Element member, Content tdSummaryType) { + mw.addSummaryType(member, tdSummaryType); + } + + /** + * Add the summary link for the member. + * + * @param mw the writer for the member being documented + * @param member the member to be documented + * @param contentTree the content tree to which the link will be added + */ + public void addSummaryLinkComment(AbstractMemberWriter mw, Element member, Content contentTree) { + List tags = utils.getFirstSentenceTrees(member); + addSummaryLinkComment(mw, member, tags, contentTree); + } + + /** + * Add the summary link comment. + * + * @param mw the writer for the member being documented + * @param member the member being documented + * @param firstSentenceTags the first sentence tags for the member to be documented + * @param tdSummary the content tree to which the comment will be added + */ + public void addSummaryLinkComment(AbstractMemberWriter mw, + Element member, List firstSentenceTags, Content tdSummary) { + addIndexComment(member, firstSentenceTags, tdSummary); + } + + /** + * Add the inherited member summary. + * + * @param mw the writer for the member being documented + * @param typeElement the class being documented + * @param member the member being documented + * @param isFirst true if its the first link being documented + * @param linksTree the content tree to which the summary will be added + */ + public void addInheritedMemberSummary(AbstractMemberWriter mw, TypeElement typeElement, + Element member, boolean isFirst, Content linksTree) { + if (! isFirst) { + linksTree.addContent(", "); + } + mw.addInheritedSummaryLink(typeElement, member, linksTree); + } + + /** + * Get the document content header tree + * + * @return a content tree the document content header + */ + public Content getContentHeader() { + HtmlTree div = new HtmlTree(HtmlTag.DIV); + div.addStyle(HtmlStyle.contentContainer); + return div; + } + + /** + * Add the class content tree. + * + * @param contentTree content tree to which the class content will be added + * @param classContentTree class content tree which will be added to the content tree + */ + public void addClassContentTree(Content contentTree, Content classContentTree) { + if (configuration.allowTag(HtmlTag.MAIN)) { + mainTree.addContent(classContentTree); + contentTree.addContent(mainTree); + } else { + contentTree.addContent(classContentTree); + } + } + + /** + * Add the annotation content tree. + * + * @param contentTree content tree to which the annotation content will be added + * @param annotationContentTree annotation content tree which will be added to the content tree + */ + public void addAnnotationContentTree(Content contentTree, Content annotationContentTree) { + addClassContentTree(contentTree, annotationContentTree); + } + + /** + * Get the member header tree + * + * @return a content tree the member header + */ + public Content getMemberTreeHeader() { + HtmlTree li = new HtmlTree(HtmlTag.LI); + li.addStyle(HtmlStyle.blockList); + return li; + } + + /** + * Add the member tree. + * + * @param memberSummaryTree the content tree representing the member summary + * @param memberTree the content tree representing the member + */ + public void addMemberTree(Content memberSummaryTree, Content memberTree) { + if (configuration.allowTag(HtmlTag.SECTION)) { + HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(memberTree)); + memberSummaryTree.addContent(htmlTree); + } else { + memberSummaryTree.addContent(getMemberTree(memberTree)); + } + } + + /** + * Get the member tree + * + * @param contentTree the tree used to generate the complete member tree + * @return a content tree for the member + */ + public Content getMemberTree(Content contentTree) { + Content ul = HtmlTree.UL(HtmlStyle.blockList, contentTree); + return ul; + } + + /** + * Get the member summary tree + * + * @param contentTree the tree used to generate the member summary tree + * @return a content tree for the member summary + */ + public Content getMemberSummaryTree(Content contentTree) { + return getMemberTree(HtmlStyle.summary, contentTree); + } + + /** + * Get the member details tree + * + * @param contentTree the tree used to generate the member details tree + * @return a content tree for the member details + */ + public Content getMemberDetailsTree(Content contentTree) { + return getMemberTree(HtmlStyle.details, contentTree); + } + + /** + * Get the member tree + * + * @param style the style class to be added to the content tree + * @param contentTree the tree used to generate the complete member tree + */ + public Content getMemberTree(HtmlStyle style, Content contentTree) { + Content div = HtmlTree.DIV(style, getMemberTree(contentTree)); + return div; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java new file mode 100644 index 00000000000..1ae644233b2 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.util.List; +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.SimpleElementVisitor9; + +import com.sun.source.doctree.DocTree; +import com.sun.source.doctree.IndexTree; +import com.sun.tools.javac.util.DefinedBy; + +import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Configuration; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.builders.SerializedFormBuilder; +import jdk.javadoc.internal.doclets.toolkit.taglets.TagletWriter; +import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; +import jdk.javadoc.internal.doclets.toolkit.util.DocLink; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; +import jdk.javadoc.internal.doclets.toolkit.util.MessageRetriever; +import jdk.javadoc.internal.doclets.toolkit.util.Utils; + +/** + * The taglet writer that writes HTML. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Jamie Ho + * @author Bhavesh Patel (Modified) + */ + +public class TagletWriterImpl extends TagletWriter { + + private final HtmlDocletWriter htmlWriter; + private final ConfigurationImpl configuration; + private final Utils utils; + + public TagletWriterImpl(HtmlDocletWriter htmlWriter, boolean isFirstSentence) { + super(isFirstSentence); + this.htmlWriter = htmlWriter; + configuration = htmlWriter.configuration; + this.utils = configuration.utils; + } + + /** + * {@inheritDoc} + */ + public Content getOutputInstance() { + return new ContentBuilder(); + } + + /** + * {@inheritDoc} + */ + protected Content codeTagOutput(Element element, DocTree tag) { + CommentHelper ch = utils.getCommentHelper(element); + String str = utils.normalizeNewlines(ch.getText(tag)); + StringContent content = new StringContent(str); + Content result = HtmlTree.CODE(content); + return result; + } + + protected Content indexTagOutput(Element element, DocTree tag) { + CommentHelper ch = utils.getCommentHelper(element); + IndexTree itt = (IndexTree)tag; + + String tagText = ch.getText(itt.getSearchTerm()); + if (tagText.charAt(0) == '"' && tagText.charAt(tagText.length() - 1) == '"') { + tagText = tagText.substring(1, tagText.length() - 1); + } + String desc = ch.getText(itt.getDescription()); + + String anchorName = htmlWriter.getName(tagText); + Content result = HtmlTree.A_ID(anchorName, new StringContent(tagText)); + if (configuration.createindex && !tagText.isEmpty()) { + SearchIndexItem si = new SearchIndexItem(); + si.setLabel(tagText); + si.setDescription(desc); + new SimpleElementVisitor9() { + @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL) + public Void visitPackage(PackageElement e, Void p) { + si.setUrl(DocPath.forPackage(e).getPath() + + "/" + DocPaths.PACKAGE_SUMMARY.getPath() + "#" + anchorName); + si.setHolder(utils.getSimpleName(element)); + return null; + } + + @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL) + public Void visitType(TypeElement e, Void p) { + si.setUrl(DocPath.forClass(utils, e).getPath() + "#" + anchorName); + si.setHolder(utils.getFullyQualifiedName(e)); + return null; + } + + @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL) + public Void visitVariable(VariableElement e, Void p) { + TypeElement te = utils.getEnclosingTypeElement(e); + si.setUrl(DocPath.forClass(utils, te).getPath() + "#" + anchorName); + si.setHolder(utils.getFullyQualifiedName(e) + "." + utils.getSimpleName(e)); + return null; + } + + @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL) + protected Void defaultAction(Element e, Void p) { + TypeElement te = utils.getEnclosingTypeElement(e); + si.setUrl(DocPath.forClass(utils, te).getPath() + "#" + anchorName); + si.setHolder(utils.getFullyQualifiedName(e)); + return null; + } + }.visit(element); + si.setCategory(configuration.getResource("doclet.SearchTags").toString()); + configuration.tagSearchIndex.add(si); + } + return result; + } + + /** + * {@inheritDoc} + */ + public Content getDocRootOutput() { + String path; + if (htmlWriter.pathToRoot.isEmpty()) + path = "."; + else + path = htmlWriter.pathToRoot.getPath(); + return new StringContent(path); + } + + /** + * {@inheritDoc} + */ + public Content deprecatedTagOutput(Element element) { + ContentBuilder result = new ContentBuilder(); + CommentHelper ch = utils.getCommentHelper(element); + List deprs = utils.getBlockTags(element, DocTree.Kind.DEPRECATED); + if (utils.isTypeElement(element)) { + if (utils.isDeprecated(element)) { + result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel, + new StringContent(configuration.getText("doclet.Deprecated")))); + result.addContent(RawHtml.nbsp); + if (!deprs.isEmpty()) { + List commentTags = ch.getDescription(configuration, deprs.get(0)); + if (!commentTags.isEmpty()) { + result.addContent(commentTagsToOutput(null, element, commentTags, false)); + } + } + } + } else { + if (utils.isDeprecated(element)) { + result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel, + new StringContent(configuration.getText("doclet.Deprecated")))); + result.addContent(RawHtml.nbsp); + if (!deprs.isEmpty()) { + List bodyTags = ch.getBody(configuration, deprs.get(0)); + Content body = commentTagsToOutput(null, element, bodyTags, false); + if (!body.isEmpty()) + result.addContent(HtmlTree.SPAN(HtmlStyle.deprecationComment, body)); + } + } else { + if (utils.isDeprecated(utils.getEnclosingTypeElement(element))) { + result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel, + new StringContent(configuration.getText("doclet.Deprecated")))); + result.addContent(RawHtml.nbsp); + } + } + } + return result; + } + + /** + * {@inheritDoc} + */ + protected Content literalTagOutput(Element element, DocTree tag) { + CommentHelper ch = utils.getCommentHelper(element); + Content result = new StringContent(utils.normalizeNewlines(ch.getText(tag))); + return result; + } + + /** + * {@inheritDoc} + */ + public MessageRetriever getMsgRetriever() { + return configuration.message; + } + + /** + * {@inheritDoc} + */ + public Content getParamHeader(String header) { + HtmlTree result = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.paramLabel, + new StringContent(header))); + return result; + } + + /** + * {@inheritDoc} + */ + public Content paramTagOutput(Element element, DocTree paramTag, String paramName) { + ContentBuilder body = new ContentBuilder(); + CommentHelper ch = utils.getCommentHelper(element); + body.addContent(HtmlTree.CODE(new RawHtml(paramName))); + body.addContent(" - "); + List description = ch.getDescription(configuration, paramTag); + body.addContent(htmlWriter.commentTagsToContent(paramTag, element, description, false)); + HtmlTree result = HtmlTree.DD(body); + return result; + } + + /** + * {@inheritDoc} + */ + public Content propertyTagOutput(Element element, DocTree tag, String prefix) { + Content body = new ContentBuilder(); + CommentHelper ch = utils.getCommentHelper(element); + body.addContent(new RawHtml(prefix)); + body.addContent(" "); + body.addContent(HtmlTree.CODE(new RawHtml(ch.getText(tag)))); + body.addContent("."); + Content result = HtmlTree.P(body); + return result; + } + + /** + * {@inheritDoc} + */ + public Content returnTagOutput(Element element, DocTree returnTag) { + ContentBuilder result = new ContentBuilder(); + CommentHelper ch = utils.getCommentHelper(element); + result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.returnLabel, + new StringContent(configuration.getText("doclet.Returns"))))); + result.addContent(HtmlTree.DD(htmlWriter.commentTagsToContent( + returnTag, element, ch.getDescription(configuration, returnTag), false))); + return result; + } + + /** + * {@inheritDoc} + */ + public Content seeTagOutput(Element holder, List seeTags) { + ContentBuilder body = new ContentBuilder(); + if (!seeTags.isEmpty()) { + for (DocTree dt : seeTags) { + appendSeparatorIfNotEmpty(body); + body.addContent(htmlWriter.seeTagToContent(holder, dt)); + } + } + if (utils.isVariableElement(holder) && ((VariableElement)holder).getConstantValue() != null && + htmlWriter instanceof ClassWriterImpl) { + //Automatically add link to constant values page for constant fields. + appendSeparatorIfNotEmpty(body); + DocPath constantsPath = + htmlWriter.pathToRoot.resolve(DocPaths.CONSTANT_VALUES); + String whichConstant = + ((ClassWriterImpl) htmlWriter).getTypeElement().getQualifiedName() + "." + + utils.getSimpleName(holder); + DocLink link = constantsPath.fragment(whichConstant); + body.addContent(htmlWriter.getHyperLink(link, + new StringContent(configuration.getText("doclet.Constants_Summary")))); + } + if (utils.isClass(holder) && utils.isSerializable((TypeElement)holder)) { + //Automatically add link to serialized form page for serializable classes. + if (SerializedFormBuilder.serialInclude(utils, holder) && + SerializedFormBuilder.serialInclude(utils, utils.containingPackage(holder))) { + appendSeparatorIfNotEmpty(body); + DocPath serialPath = htmlWriter.pathToRoot.resolve(DocPaths.SERIALIZED_FORM); + DocLink link = serialPath.fragment(utils.getFullyQualifiedName(holder)); + body.addContent(htmlWriter.getHyperLink(link, + new StringContent(configuration.getText("doclet.Serialized_Form")))); + } + } + if (body.isEmpty()) + return body; + + ContentBuilder result = new ContentBuilder(); + result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.seeLabel, + new StringContent(configuration.getText("doclet.See_Also"))))); + result.addContent(HtmlTree.DD(body)); + return result; + + } + + private void appendSeparatorIfNotEmpty(ContentBuilder body) { + if (!body.isEmpty()) { + body.addContent(", "); + body.addContent(DocletConstants.NL); + } + } + + /** + * {@inheritDoc} + */ + public Content simpleTagOutput(Element element, List simpleTags, String header) { + CommentHelper ch = utils.getCommentHelper(element); + ContentBuilder result = new ContentBuilder(); + result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.simpleTagLabel, new RawHtml(header)))); + ContentBuilder body = new ContentBuilder(); + boolean many = false; + for (DocTree simpleTag : simpleTags) { + if (many) { + body.addContent(", "); + } + List bodyTags = ch.getBody(configuration, simpleTag); + body.addContent(htmlWriter.commentTagsToContent(simpleTag, element, bodyTags, false)); + many = true; + } + result.addContent(HtmlTree.DD(body)); + return result; + } + + /** + * {@inheritDoc} + */ + public Content simpleTagOutput(Element element, DocTree simpleTag, String header) { + ContentBuilder result = new ContentBuilder(); + result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.simpleTagLabel, new RawHtml(header)))); + CommentHelper ch = utils.getCommentHelper(element); + List description = ch.getDescription(configuration, simpleTag); + Content body = htmlWriter.commentTagsToContent(simpleTag, element, description, false); + result.addContent(HtmlTree.DD(body)); + return result; + } + + /** + * {@inheritDoc} + */ + public Content getThrowsHeader() { + HtmlTree result = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.throwsLabel, + new StringContent(configuration.getText("doclet.Throws")))); + return result; + } + + /** + * {@inheritDoc} + */ + public Content throwsTagOutput(Element element, DocTree throwsTag) { + ContentBuilder body = new ContentBuilder(); + CommentHelper ch = utils.getCommentHelper(element); + Element exception = ch.getException(configuration, throwsTag); + Content excName; + if (exception == null) { + excName = new RawHtml(ch.getExceptionName(throwsTag).toString()); + } else if (exception.asType() == null) { + excName = new RawHtml(utils.getFullyQualifiedName(exception)); + } else { + LinkInfoImpl link = new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, + exception.asType()); + link.excludeTypeBounds = true; + excName = htmlWriter.getLink(link); + } + body.addContent(HtmlTree.CODE(excName)); + List description = ch.getDescription(configuration, throwsTag); + Content desc = htmlWriter.commentTagsToContent(throwsTag, element, description, false); + if (desc != null && !desc.isEmpty()) { + body.addContent(" - "); + body.addContent(desc); + } + HtmlTree result = HtmlTree.DD(body); + return result; + } + + /** + * {@inheritDoc} + */ + public Content throwsTagOutput(TypeMirror throwsType) { + HtmlTree result = HtmlTree.DD(HtmlTree.CODE(htmlWriter.getLink( + new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, throwsType)))); + return result; + } + + /** + * {@inheritDoc} + */ + public Content valueTagOutput(VariableElement field, String constantVal, boolean includeLink) { + return includeLink ? + htmlWriter.getDocLink(LinkInfoImpl.Kind.VALUE_TAG, field, + constantVal, false) : new RawHtml(constantVal); + } + + /** + * {@inheritDoc} + */ + public Content commentTagsToOutput(DocTree holderTag, List tags) { + return commentTagsToOutput(holderTag, null, tags, false); + } + + /** + * {@inheritDoc} + */ + public Content commentTagsToOutput(Element holder, List tags) { + return commentTagsToOutput(null, holder, tags, false); + } + + /** + * {@inheritDoc} + */ + public Content commentTagsToOutput(DocTree holderTag, + Element holder, List tags, boolean isFirstSentence) { + return htmlWriter.commentTagsToContent(holderTag, holder, + tags, isFirstSentence); + } + + /** + * {@inheritDoc} + */ + public Configuration configuration() { + return configuration; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java new file mode 100644 index 00000000000..0987cc2d825 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.IOException; +import java.util.SortedSet; + +import javax.lang.model.element.PackageElement; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + +/** + * Generate Class Hierarchy page for all the Classes in this run. Use + * ClassTree for building the Tree. The name of + * the generated file is "overview-tree.html" and it is generated in the + * current or the destination directory. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class TreeWriter extends AbstractTreeWriter { + + /** + * Packages in this run. + */ + SortedSet packages; + + /** + * True if there are no packages specified on the command line, + * False otherwise. + */ + private boolean classesonly; + + /** + * Constructor to construct TreeWriter object. + * + * @param configuration the current configuration of the doclet. + * @param filename String filename + * @param classtree the tree being built. + */ + public TreeWriter(ConfigurationImpl configuration, + DocPath filename, ClassTree classtree) throws IOException { + super(configuration, filename, classtree); + packages = configuration.packages; + classesonly = packages.isEmpty(); + } + + /** + * Create a TreeWriter object and use it to generate the + * "overview-tree.html" file. + * + * @param classtree the class tree being documented. + * @throws DocletAbortException + */ + public static void generate(ConfigurationImpl configuration, + ClassTree classtree) { + TreeWriter treegen; + DocPath filename = DocPaths.OVERVIEW_TREE; + try { + treegen = new TreeWriter(configuration, filename, classtree); + treegen.generateTreeFile(); + treegen.close(); + } catch (IOException exc) { + configuration.standardmessage.error( + "doclet.exception_encountered", + exc.toString(), filename); + throw new DocletAbortException(exc); + } + } + + /** + * Generate the interface hierarchy and class hierarchy. + */ + public void generateTreeFile() throws IOException { + HtmlTree body = getTreeHeader(); + Content headContent = getResource("doclet.Hierarchy_For_All_Packages"); + Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, false, + HtmlStyle.title, headContent); + Content div = HtmlTree.DIV(HtmlStyle.header, heading); + addPackageTreeLinks(div); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.MAIN)) + ? HtmlTree.MAIN() + : body; + htmlTree.addContent(div); + HtmlTree divTree = new HtmlTree(HtmlTag.DIV); + divTree.addStyle(HtmlStyle.contentContainer); + addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", divTree); + addTree(classtree.baseInterfaces(), "doclet.Interface_Hierarchy", divTree); + addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree); + addTree(classtree.baseEnums(), "doclet.Enum_Hierarchy", divTree, true); + htmlTree.addContent(divTree); + if (configuration.allowTag(HtmlTag.MAIN)) { + body.addContent(htmlTree); + } + if (configuration.allowTag(HtmlTag.FOOTER)) { + htmlTree = HtmlTree.FOOTER(); + } else { + htmlTree = body; + } + addNavLinks(false, htmlTree); + addBottom(htmlTree); + if (configuration.allowTag(HtmlTag.FOOTER)) { + body.addContent(htmlTree); + } + printHtmlDocument(null, true, body); + } + + /** + * Add the links to all the package tree files. + * + * @param contentTree the content tree to which the links will be added + */ + protected void addPackageTreeLinks(Content contentTree) { + //Do nothing if only unnamed package is used + if (isUnnamedPackage()) { + return; + } + if (!classesonly) { + Content span = HtmlTree.SPAN(HtmlStyle.packageHierarchyLabel, + getResource("doclet.Package_Hierarchies")); + contentTree.addContent(span); + HtmlTree ul = new HtmlTree(HtmlTag.UL); + ul.addStyle(HtmlStyle.horizontal); + int i = 0; + for (PackageElement pkg : packages) { + // If the package name length is 0 or if -nodeprecated option + // is set and the package is marked as deprecated, do not include + // the page in the list of package hierarchies. + if (pkg.isUnnamed() || + (configuration.nodeprecated && utils.isDeprecated(pkg))) { + i++; + continue; + } + DocPath link = pathString(pkg, DocPaths.PACKAGE_TREE); + Content li = HtmlTree.LI(getHyperLink(link, + new StringContent(utils.getPackageName(pkg)))); + if (i < packages.size() - 1) { + li.addContent(", "); + } + ul.addContent(li); + i++; + } + contentTree.addContent(ul); + } + } + + /** + * Get the tree header. + * + * @return a content tree for the tree header + */ + protected HtmlTree getTreeHeader() { + String title = configuration.getText("doclet.Window_Class_Hierarchy"); + HtmlTree bodyTree = getBody(true, getWindowTitle(title)); + HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER)) + ? HtmlTree.HEADER() + : bodyTree; + addTop(htmlTree); + addNavLinks(true, htmlTree); + if (configuration.allowTag(HtmlTag.HEADER)) { + bodyTree.addContent(htmlTree); + } + return bodyTree; + } + + private boolean isUnnamedPackage() { + return packages.size() == 1 && packages.first().isUnnamed(); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java new file mode 100644 index 00000000000..cce4052b9b3 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html; + +import java.io.IOException; + +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter; +import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter; +import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter; +import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter; +import jdk.javadoc.internal.doclets.toolkit.ClassWriter; +import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter; +import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; +import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter; +import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter; +import jdk.javadoc.internal.doclets.toolkit.WriterFactory; +import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; +import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap; + +import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind.*; + +/** + * The factory that returns HTML writers. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Jamie Ho + */ +public class WriterFactoryImpl implements WriterFactory { + + private final ConfigurationImpl configuration; + public WriterFactoryImpl(ConfigurationImpl configuration) { + this.configuration = configuration; + } + + /** + * {@inheritDoc} + */ + @Override + public ConstantsSummaryWriter getConstantsSummaryWriter() throws Exception { + return new ConstantsSummaryWriterImpl(configuration); + } + + /** + * {@inheritDoc} + */ + @Override + public PackageSummaryWriter getPackageSummaryWriter(PackageElement packageElement, + PackageElement prevPkg, PackageElement nextPkg) throws Exception { + return new PackageWriterImpl(configuration, packageElement, prevPkg, nextPkg); + } + + /** + * {@inheritDoc} + */ + @Override + public ClassWriter getClassWriter(TypeElement typeElement, TypeElement prevClass, + TypeElement nextClass, ClassTree classTree) throws IOException { + return new ClassWriterImpl(configuration, typeElement, prevClass, nextClass, classTree); + } + + /** + * {@inheritDoc} + */ + @Override + public AnnotationTypeWriter getAnnotationTypeWriter(TypeElement annotationType, + TypeMirror prevType, TypeMirror nextType) throws Exception { + return new AnnotationTypeWriterImpl(configuration, annotationType, prevType, nextType); + } + + /** + * {@inheritDoc} + */ + @Override + public AnnotationTypeFieldWriter + getAnnotationTypeFieldWriter(AnnotationTypeWriter annotationTypeWriter) throws Exception { + TypeElement te = annotationTypeWriter.getAnnotationTypeElement(); + return new AnnotationTypeFieldWriterImpl( + (SubWriterHolderWriter) annotationTypeWriter, te); + } + + /** + * {@inheritDoc} + */ + @Override + public AnnotationTypeOptionalMemberWriter + getAnnotationTypeOptionalMemberWriter( + AnnotationTypeWriter annotationTypeWriter) throws Exception { + TypeElement te = annotationTypeWriter.getAnnotationTypeElement(); + return new AnnotationTypeOptionalMemberWriterImpl( + (SubWriterHolderWriter) annotationTypeWriter, te); + } + + /** + * {@inheritDoc} + */ + @Override + public AnnotationTypeRequiredMemberWriter + getAnnotationTypeRequiredMemberWriter(AnnotationTypeWriter annotationTypeWriter) throws Exception { + TypeElement te = annotationTypeWriter.getAnnotationTypeElement(); + return new AnnotationTypeRequiredMemberWriterImpl( + (SubWriterHolderWriter) annotationTypeWriter, te); + } + + /** + * {@inheritDoc} + */ + @Override + public EnumConstantWriterImpl getEnumConstantWriter(ClassWriter classWriter) + throws Exception { + return new EnumConstantWriterImpl((SubWriterHolderWriter) classWriter, + classWriter.getTypeElement()); + } + + /** + * {@inheritDoc} + */ + @Override + public FieldWriterImpl getFieldWriter(ClassWriter classWriter) + throws Exception { + return new FieldWriterImpl((SubWriterHolderWriter) classWriter, classWriter.getTypeElement()); + } + + /** + * {@inheritDoc} + */ + @Override + public PropertyWriterImpl getPropertyWriter(ClassWriter classWriter) + throws Exception { + return new PropertyWriterImpl((SubWriterHolderWriter) classWriter, + classWriter.getTypeElement()); + } + + /** + * {@inheritDoc} + */ + @Override + public MethodWriterImpl getMethodWriter(ClassWriter classWriter) + throws Exception { + return new MethodWriterImpl((SubWriterHolderWriter) classWriter, classWriter.getTypeElement()); + } + + /** + * {@inheritDoc} + */ + @Override + public ConstructorWriterImpl getConstructorWriter(ClassWriter classWriter) + throws Exception { + return new ConstructorWriterImpl((SubWriterHolderWriter) classWriter, + classWriter.getTypeElement()); + } + + /** + * {@inheritDoc} + */ + @Override + public MemberSummaryWriter getMemberSummaryWriter( + ClassWriter classWriter, VisibleMemberMap.Kind memberType) + throws Exception { + switch (memberType) { + case CONSTRUCTORS: + return getConstructorWriter(classWriter); + case ENUM_CONSTANTS: + return getEnumConstantWriter(classWriter); + case FIELDS: + return getFieldWriter(classWriter); + case PROPERTIES: + return getPropertyWriter(classWriter); + case INNER_CLASSES: + return new NestedClassWriterImpl((SubWriterHolderWriter) + classWriter, classWriter.getTypeElement()); + case METHODS: + return getMethodWriter(classWriter); + default: + return null; + } + } + + /** + * {@inheritDoc} + */ + @Override + public MemberSummaryWriter getMemberSummaryWriter( + AnnotationTypeWriter annotationTypeWriter, VisibleMemberMap.Kind memberType) + throws Exception { + switch (memberType) { + case ANNOTATION_TYPE_FIELDS: + return (AnnotationTypeFieldWriterImpl) + getAnnotationTypeFieldWriter(annotationTypeWriter); + case ANNOTATION_TYPE_MEMBER_OPTIONAL: + return (AnnotationTypeOptionalMemberWriterImpl) + getAnnotationTypeOptionalMemberWriter(annotationTypeWriter); + case ANNOTATION_TYPE_MEMBER_REQUIRED: + return (AnnotationTypeRequiredMemberWriterImpl) + getAnnotationTypeRequiredMemberWriter(annotationTypeWriter); + default: + return null; + } + } + + /** + * {@inheritDoc} + */ + @Override + public SerializedFormWriter getSerializedFormWriter() throws Exception { + return new SerializedFormWriterImpl(configuration); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java new file mode 100644 index 00000000000..0adfc088106 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import java.io.IOException; +import java.io.Writer; + +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; + +/** + * Class for generating a comment for HTML pages of javadoc output. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public class Comment extends Content { + + private String commentText; + + /** + * Constructor to construct a Comment object. + * + * @param comment comment text for the comment + */ + public Comment(String comment) { + commentText = nullCheck(comment); + } + + /** + * This method is not supported by the class. + * + * @param content content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(Content content) { + throw new DocletAbortException("not supported"); + } + + /** + * This method is not supported by the class. + * + * @param stringContent string content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(String stringContent) { + throw new DocletAbortException("not supported"); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return commentText.isEmpty(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean write(Writer out, boolean atNewline) throws IOException { + if (!atNewline) + out.write(DocletConstants.NL); + out.write("" + DocletConstants.NL); + return true; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java new file mode 100644 index 00000000000..64ceef82473 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import jdk.javadoc.internal.doclets.toolkit.Content; + +/** + * A sequence of Content nodes. + */ +public class ContentBuilder extends Content { + protected List contents = Collections.emptyList(); + + @Override + public void addContent(Content content) { + nullCheck(content); + ensureMutableContents(); + if (content instanceof ContentBuilder) { + contents.addAll(((ContentBuilder) content).contents); + } else + contents.add(content); + } + + @Override + public void addContent(String text) { + if (text.isEmpty()) + return; + ensureMutableContents(); + Content c = contents.isEmpty() ? null : contents.get(contents.size() - 1); + StringContent sc; + if (c != null && c instanceof StringContent) { + sc = (StringContent) c; + } else { + contents.add(sc = new StringContent()); + } + sc.addContent(text); + } + + @Override + public boolean write(Writer writer, boolean atNewline) throws IOException { + for (Content content: contents) { + atNewline = content.write(writer, atNewline); + } + return atNewline; + } + + @Override + public boolean isEmpty() { + for (Content content: contents) { + if (!content.isEmpty()) + return false; + } + return true; + } + + @Override + public int charCount() { + int n = 0; + for (Content c : contents) + n += c.charCount(); + return n; + } + + private void ensureMutableContents() { + if (contents.isEmpty()) + contents = new ArrayList<>(); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java new file mode 100644 index 00000000000..469ee40743f --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import java.io.IOException; +import java.io.Writer; + +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; + +/** + * Class for generating document type for HTML pages of javadoc output. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public class DocType extends Content { + + private String docType; + + public static final DocType TRANSITIONAL = + new DocType("Transitional", "http://www.w3.org/TR/html4/loose.dtd"); + + public static final DocType HTML5 = new DocType(); + + /** + * Constructor to construct a DocType object. + * + * @param type the doctype to be added + * @param dtd the dtd of the doctype + */ + private DocType(String type, String dtd) { + docType = "" + DocletConstants.NL; + } + + /** + * Constructor to construct a DocType object. + */ + private DocType() { + docType = "" + DocletConstants.NL; + } + + /** + * This method is not supported by the class. + * + * @param content content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(Content content) { + throw new DocletAbortException("not supported"); + } + + /** + * This method is not supported by the class. + * + * @param stringContent string content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(String stringContent) { + throw new DocletAbortException("not supported"); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return (docType.length() == 0); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean write(Writer out, boolean atNewline) throws IOException { + out.write(docType); + return true; // guaranteed by constructor + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlAttr.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlAttr.java new file mode 100644 index 00000000000..69ae2aa5c0e --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlAttr.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import jdk.javadoc.internal.doclets.toolkit.util.Utils; + +/** + * Enum representing HTML tag attributes. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public enum HtmlAttr { + ALT, + CLASS, + CLEAR, + COLS, + CONTENT, + DISABLED, + HREF, + HTTP_EQUIV("http-equiv"), + ID, + LANG, + NAME, + ONLOAD, + REL, + ROLE, + ROWS, + SCOPE, + SCROLLING, + SRC, + SUMMARY, + TARGET, + TITLE, + TYPE, + VALUE, + WIDTH; + + private final String value; + + public enum Role { + + BANNER, + CONTENTINFO, + MAIN, + NAVIGATION, + REGION; + + private final String role; + + Role() { + role = Utils.toLowerCase(name()); + } + + public String toString() { + return role; + } + } + + HtmlAttr() { + this.value = Utils.toLowerCase(name()); + } + + HtmlAttr(String name) { + this.value = name; + } + + public String toString() { + return value; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java new file mode 100644 index 00000000000..b1e03e3e49b --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import jdk.javadoc.internal.doclets.toolkit.Content; + +/** + * Stores constants for Html Doclet. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public class HtmlConstants { + + /** + * Marker to identify start of top navigation bar. + */ + public static final Content START_OF_TOP_NAVBAR = + new Comment("========= START OF TOP NAVBAR ======="); + + /** + * Marker to identify start of bottom navigation bar. + */ + public static final Content START_OF_BOTTOM_NAVBAR = + new Comment("======= START OF BOTTOM NAVBAR ======"); + + /** + * Marker to identify end of top navigation bar. + */ + public static final Content END_OF_TOP_NAVBAR = + new Comment("========= END OF TOP NAVBAR ========="); + + /** + * Marker to identify end of bottom navigation bar. + */ + public static final Content END_OF_BOTTOM_NAVBAR = + new Comment("======== END OF BOTTOM NAVBAR ======="); + + /** + * Marker to identify start of class data. + */ + public static final Content START_OF_CLASS_DATA = + new Comment("======== START OF CLASS DATA ========"); + + /** + * Marker to identify end of class data. + */ + public static final Content END_OF_CLASS_DATA = + new Comment("========= END OF CLASS DATA ========="); + + /** + * Marker to identify start of nested class summary. + */ + public static final Content START_OF_NESTED_CLASS_SUMMARY = + new Comment("======== NESTED CLASS SUMMARY ========"); + + /** + * Marker to identify start of annotation type optional member summary. + */ + public static final Content START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY = + new Comment("=========== ANNOTATION TYPE OPTIONAL MEMBER SUMMARY ==========="); + + /** + * Marker to identify start of annotation type required member summary. + */ + public static final Content START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY = + new Comment("=========== ANNOTATION TYPE REQUIRED MEMBER SUMMARY ==========="); + + /** + * Marker to identify start of annotation type required member summary. + */ + public static final Content START_OF_ANNOTATION_TYPE_FIELD_SUMMARY = + new Comment("=========== ANNOTATION TYPE FIELD SUMMARY ==========="); + + /** + * Marker to identify start of constructor summary. + */ + public static final Content START_OF_CONSTRUCTOR_SUMMARY = + new Comment("======== CONSTRUCTOR SUMMARY ========"); + + /** + * Marker to identify start of enum constants summary. + */ + public static final Content START_OF_ENUM_CONSTANT_SUMMARY = + new Comment("=========== ENUM CONSTANT SUMMARY ==========="); + + /** + * Marker to identify start of field summary. + */ + public static final Content START_OF_FIELD_SUMMARY = + new Comment("=========== FIELD SUMMARY ==========="); + + /** + * Marker to identify start of properties summary. + */ + public static final Content START_OF_PROPERTY_SUMMARY = + new Comment("=========== PROPERTY SUMMARY ==========="); + + /** + * Marker to identify start of method summary. + */ + public static final Content START_OF_METHOD_SUMMARY = + new Comment("========== METHOD SUMMARY ==========="); + + /** + * Marker to identify start of annotation type details. + */ + public static final Content START_OF_ANNOTATION_TYPE_DETAILS = + new Comment("============ ANNOTATION TYPE MEMBER DETAIL ==========="); + + /** + * Marker to identify start of annotation type field details. + */ + public static final Content START_OF_ANNOTATION_TYPE_FIELD_DETAILS = + new Comment("============ ANNOTATION TYPE FIELD DETAIL ==========="); + + /** + * Marker to identify start of method details. + */ + public static final Content START_OF_METHOD_DETAILS = + new Comment("============ METHOD DETAIL =========="); + + /** + * Marker to identify start of field details. + */ + public static final Content START_OF_FIELD_DETAILS = + new Comment("============ FIELD DETAIL ==========="); + + /** + * Marker to identify start of property details. + */ + public static final Content START_OF_PROPERTY_DETAILS = + new Comment("============ PROPERTY DETAIL ==========="); + + /** + * Marker to identify start of constructor details. + */ + public static final Content START_OF_CONSTRUCTOR_DETAILS = + new Comment("========= CONSTRUCTOR DETAIL ========"); + + /** + * Marker to identify start of enum constants details. + */ + public static final Content START_OF_ENUM_CONSTANT_DETAILS = + new Comment("============ ENUM CONSTANT DETAIL ==========="); + + /** + * Html tag for the page title heading. + */ + public static final HtmlTag TITLE_HEADING = HtmlTag.H1; + + /** + * Html tag for the class page title heading. + */ + public static final HtmlTag CLASS_PAGE_HEADING = HtmlTag.H2; + + /** + * Html tag for the content heading. + */ + public static final HtmlTag CONTENT_HEADING = HtmlTag.H2; + + /** + * Html tag for the package name heading. + */ + public static final HtmlTag PACKAGE_HEADING = HtmlTag.H2; + + /** + * Html tag for the member summary heading. + */ + public static final HtmlTag SUMMARY_HEADING = HtmlTag.H3; + + /** + * Html tag for the inherited member summary heading. + */ + public static final HtmlTag INHERITED_SUMMARY_HEADING = HtmlTag.H3; + + /** + * Html tag for the member details heading. + */ + public static final HtmlTag DETAILS_HEADING = HtmlTag.H3; + + /** + * Html tag for the serialized member heading. + */ + public static final HtmlTag SERIALIZED_MEMBER_HEADING = HtmlTag.H3; + + /** + * Html tag for the member heading. + */ + public static final HtmlTag MEMBER_HEADING = HtmlTag.H4; + + /** + * Default charset for HTML. + */ + public static final String HTML_DEFAULT_CHARSET = "utf-8"; +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java new file mode 100644 index 00000000000..d7aec841525 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java @@ -0,0 +1,361 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import java.io.*; +import java.util.*; + +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; + +import jdk.javadoc.internal.doclets.formats.html.ConfigurationImpl; +import jdk.javadoc.internal.doclets.formats.html.SectionName; +import jdk.javadoc.internal.doclets.toolkit.Configuration; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocFile; +import jdk.javadoc.internal.doclets.toolkit.util.DocLink; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; + + +/** + * Class for the Html Format Code Generation specific to JavaDoc. + * This Class contains methods related to the Html Code Generation which + * are used by the Sub-Classes in the package jdk.javadoc.internal.tool.standard. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Robert Field + */ +public abstract class HtmlDocWriter extends HtmlWriter { + + public static final String CONTENT_TYPE = "text/html"; + + DocPath pathToRoot; + + /** + * Constructor. Initializes the destination file name through the super + * class HtmlWriter. + * + * @param filename String file name. + */ + public HtmlDocWriter(Configuration configuration, DocPath filename) + throws IOException { + super(configuration, filename); + this.pathToRoot = filename.parent().invert(); + configuration.message.notice("doclet.Generating_0", + DocFile.createFileForOutput(configuration, filename).getPath()); + } + + /** + * Accessor for configuration. + */ + public abstract Configuration configuration(); + + public Content getHyperLink(DocPath link, String label) { + return getHyperLink(link, new StringContent(label), false, "", "", ""); + } + + /** + * Get Html Hyper Link Content. + * + * @param where Position of the link in the file. Character '#' is not + * needed. + * @param label Tag for the link. + * @return a content tree for the hyper link + */ + public Content getHyperLink(String where, + Content label) { + return getHyperLink(getDocLink(where), label, "", ""); + } + + /** + * Get Html Hyper Link Content. + * + * @param sectionName The section name to which the link will be created. + * @param label Tag for the link. + * @return a content tree for the hyper link + */ + public Content getHyperLink(SectionName sectionName, + Content label) { + return getHyperLink(getDocLink(sectionName), label, "", ""); + } + + /** + * Get Html Hyper Link Content. + * + * @param sectionName The section name combined with where to which the link + * will be created. + * @param where The fragment combined with sectionName to which the link + * will be created. + * @param label Tag for the link. + * @return a content tree for the hyper link + */ + public Content getHyperLink(SectionName sectionName, String where, + Content label) { + return getHyperLink(getDocLink(sectionName, where), label, "", ""); + } + + /** + * Get the link. + * + * @param where Position of the link in the file. + * @return a DocLink object for the hyper link + */ + public DocLink getDocLink(String where) { + return DocLink.fragment(getName(where)); + } + + /** + * Get the link. + * + * @param sectionName The section name to which the link will be created. + * @return a DocLink object for the hyper link + */ + public DocLink getDocLink(SectionName sectionName) { + return DocLink.fragment(sectionName.getName()); + } + + /** + * Get the link. + * + * @param sectionName The section name combined with where to which the link + * will be created. + * @param where The fragment combined with sectionName to which the link + * will be created. + * @return a DocLink object for the hyper link + */ + public DocLink getDocLink(SectionName sectionName, String where) { + return DocLink.fragment(sectionName.getName() + getName(where)); + } + + /** + * Convert the name to a valid HTML name. + * + * @param name the name that needs to be converted to valid HTML name. + * @return a valid HTML name string. + */ + public String getName(String name) { + StringBuilder sb = new StringBuilder(); + char ch; + /* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions + * that the name/id should begin with a letter followed by other valid characters. + * The HTML 5 spec (draft) is more permissive on names/ids where the only restriction + * is that it should be at least one character long and should not contain spaces. + * The spec draft is @ http://www.w3.org/html/wg/drafts/html/master/dom.html#the-id-attribute. + * + * For HTML 4, we need to check for non-characters at the beginning of the name and + * substitute it accordingly, "_" and "$" can appear at the beginning of a member name. + * The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z". + */ + for (int i = 0; i < name.length(); i++) { + ch = name.charAt(i); + switch (ch) { + case '(': + case ')': + case '<': + case '>': + case ',': + sb.append('-'); + break; + case ' ': + case '[': + break; + case ']': + sb.append(":A"); + break; + // Any appearance of $ needs to be substituted with ":D" and not with hyphen + // since a field name "P$$ and a method P(), both valid member names, can end + // up as "P--". A member name beginning with $ needs to be substituted with + // "Z:Z:D". + case '$': + if (i == 0) + sb.append("Z:Z"); + sb.append(":D"); + break; + // A member name beginning with _ needs to be prefixed with "Z:Z" since valid anchor + // names can only begin with a letter. + case '_': + if (i == 0) + sb.append("Z:Z"); + sb.append(ch); + break; + default: + sb.append(ch); + } + } + return sb.toString(); + } + + /** + * Get Html hyperlink. + * + * @param link path of the file. + * @param label Tag for the link. + * @return a content tree for the hyper link + */ + public Content getHyperLink(DocPath link, Content label) { + return getHyperLink(link, label, "", ""); + } + + public Content getHyperLink(DocLink link, Content label) { + return getHyperLink(link, label, "", ""); + } + + public Content getHyperLink(DocPath link, + Content label, boolean strong, + String stylename, String title, String target) { + return getHyperLink(new DocLink(link), label, strong, + stylename, title, target); + } + + public Content getHyperLink(DocLink link, + Content label, boolean strong, + String stylename, String title, String target) { + Content body = label; + if (strong) { + body = HtmlTree.SPAN(HtmlStyle.typeNameLink, body); + } + if (stylename != null && stylename.length() != 0) { + HtmlTree t = new HtmlTree(HtmlTag.FONT, body); + t.addAttr(HtmlAttr.CLASS, stylename); + body = t; + } + HtmlTree l = HtmlTree.A(link.toString(), body); + if (title != null && title.length() != 0) { + l.addAttr(HtmlAttr.TITLE, title); + } + if (target != null && target.length() != 0) { + l.addAttr(HtmlAttr.TARGET, target); + } + return l; + } + + /** + * Get Html Hyper Link. + * + * @param link String name of the file. + * @param label Tag for the link. + * @param title String that describes the link's content for accessibility. + * @param target Target frame. + * @return a content tree for the hyper link. + */ + public Content getHyperLink(DocPath link, Content label, String title, String target) { + return getHyperLink(new DocLink(link), label, title, target); + } + + public Content getHyperLink(DocLink link, Content label, String title, String target) { + HtmlTree anchor = HtmlTree.A(link.toString(), label); + if (title != null && title.length() != 0) { + anchor.addAttr(HtmlAttr.TITLE, title); + } + if (target != null && target.length() != 0) { + anchor.addAttr(HtmlAttr.TARGET, target); + } + return anchor; + } + + /** + * Get the enclosed name of the package + * + * @param te TypeElement + * @return the name + */ + public String getEnclosingPackageName(TypeElement te) { + + PackageElement encl = configuration.utils.containingPackage(te); + return (encl.isUnnamed()) ? "" : (encl.getQualifiedName() + "."); + } + + public boolean getMemberDetailsListPrinted() { + return memberDetailsListPrinted; + } + + /** + * Print the frames version of the Html file header. + * Called only when generating an HTML frames file. + * + * @param title Title of this HTML document + * @param configuration the configuration object + * @param body the body content tree to be added to the HTML document + */ + public void printFramesDocument(String title, ConfigurationImpl configuration, + HtmlTree body) throws IOException { + Content htmlDocType = configuration.isOutputHtml5() + ? DocType.HTML5 + : DocType.TRANSITIONAL; + Content htmlComment = new Comment(configuration.getText("doclet.New_Page")); + Content head = new HtmlTree(HtmlTag.HEAD); + head.addContent(getGeneratedBy(!configuration.notimestamp)); + Content windowTitle = HtmlTree.TITLE(new StringContent(title)); + head.addContent(windowTitle); + Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, + (configuration.charset.length() > 0) ? + configuration.charset : HtmlConstants.HTML_DEFAULT_CHARSET); + head.addContent(meta); + head.addContent(getStyleSheetProperties(configuration)); + head.addContent(getFramesJavaScript()); + Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), + head, body); + Content htmlDocument = new HtmlDocument(htmlDocType, + htmlComment, htmlTree); + write(htmlDocument); + } + + /** + * Returns a link to the stylesheet file. + * + * @return an HtmlTree for the lINK tag which provides the stylesheet location + */ + public HtmlTree getStyleSheetProperties(ConfigurationImpl configuration) { + String stylesheetfile = configuration.stylesheetfile; + DocPath stylesheet; + if (stylesheetfile.isEmpty()) { + stylesheet = DocPaths.STYLESHEET; + } else { + DocFile file = DocFile.createFileForInput(configuration, stylesheetfile); + stylesheet = DocPath.create(file.getName()); + } + HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", + pathToRoot.resolve(stylesheet).getPath(), + "Style"); + return link; + } + + protected Comment getGeneratedBy(boolean timestamp) { + String text = "Generated by javadoc"; // marker string, deliberately not localized + if (timestamp) { + Calendar calendar = new GregorianCalendar(TimeZone.getDefault()); + Date today = calendar.getTime(); + text += " ("+ configuration.getDocletSpecificBuildDate() + ") on " + today; + } + return new Comment(text); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java new file mode 100644 index 00000000000..8f995c7c772 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import java.io.IOException; +import java.io.Writer; +import java.util.*; + +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; + +/** + * Class for generating an HTML document for javadoc output. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public class HtmlDocument extends Content { + + private List docContent = Collections.emptyList(); + + /** + * Constructor to construct an HTML document. + * + * @param docType document type for the HTML document + * @param docComment comment for the document + * @param htmlTree HTML tree of the document + */ + public HtmlDocument(Content docType, Content docComment, Content htmlTree) { + docContent = new ArrayList<>(); + addContent(nullCheck(docType)); + addContent(nullCheck(docComment)); + addContent(nullCheck(htmlTree)); + } + + /** + * Constructor to construct an HTML document. + * + * @param docType document type for the HTML document + * @param htmlTree HTML tree of the document + */ + public HtmlDocument(Content docType, Content htmlTree) { + docContent = new ArrayList<>(); + addContent(nullCheck(docType)); + addContent(nullCheck(htmlTree)); + } + + /** + * Adds content for the HTML document. + * + * @param htmlContent html content to be added + */ + public final void addContent(Content htmlContent) { + if (htmlContent.isValid()) + docContent.add(htmlContent); + } + + /** + * This method is not supported by the class. + * + * @param stringContent string content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(String stringContent) { + throw new DocletAbortException("not supported"); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return (docContent.isEmpty()); + } + + /** + * {@inheritDoc} + */ + public boolean write(Writer out, boolean atNewline) throws IOException { + for (Content c : docContent) + atNewline = c.write(out, atNewline); + return atNewline; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java new file mode 100644 index 00000000000..ccaf4769276 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +/** + * Enum representing HTML styles. The name map to values in the CSS file. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public enum HtmlStyle { + aboutLanguage, + activeTableTab, + altColor, + bar, + block, + blockList, + blockListLast, + bottomNav, + circle, + classUseContainer, + colFirst, + colLast, + colOne, + constantsSummary, + constantValuesContainer, + contentContainer, + deprecatedContent, + deprecatedLabel, + deprecatedSummary, + deprecationComment, + description, + descfrmTypeLabel, + details, + docSummary, + emphasizedPhrase, + fixedNav, + header, + horizontal, + footer, + indexContainer, + indexNav, + inheritance, + interfaceName, + leftContainer, + leftTop, + leftBottom, + legalCopy, + mainContainer, + memberNameLabel, + memberNameLink, + memberSummary, + nameValue, + navBarCell1Rev, + navList, + navListSearch, + overrideSpecifyLabel, + overviewSummary, + packageHierarchyLabel, + paramLabel, + returnLabel, + rightContainer, + rightIframe, + rowColor, + searchTagLink, + seeLabel, + serializedFormContainer, + simpleTagLabel, + skipNav, + sourceContainer, + sourceLineNo, + subNav, + subNavList, + subTitle, + summary, + tabEnd, + tableTab, + throwsLabel, + title, + topNav, + typeNameLabel, + typeNameLink, + typeSummary, + useSummary +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTag.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTag.java new file mode 100644 index 00000000000..3bc64ea959f --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTag.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import jdk.javadoc.internal.doclets.toolkit.util.Utils; + +/** + * Enum representing HTML tags. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public enum HtmlTag { + A(BlockType.INLINE, EndTag.END), + BLOCKQUOTE, + BODY(BlockType.OTHER, EndTag.END), + BR(BlockType.INLINE, EndTag.NOEND), + CAPTION, + CENTER(HtmlVersion.HTML4), + CODE(BlockType.INLINE, EndTag.END), + DD, + DIR(HtmlVersion.HTML4), + DIV, + DL, + DT, + EM(BlockType.INLINE, EndTag.END), + FONT(HtmlVersion.HTML4, BlockType.INLINE, EndTag.END), + FOOTER(HtmlVersion.HTML5), + H1, + H2, + H3, + H4, + H5, + H6, + HEAD(BlockType.OTHER, EndTag.END), + HEADER(HtmlVersion.HTML5), + HR(BlockType.BLOCK, EndTag.NOEND), + HTML(BlockType.OTHER, EndTag.END), + I(BlockType.INLINE, EndTag.END), + IFRAME(BlockType.OTHER, EndTag.END), + IMG(BlockType.INLINE, EndTag.NOEND), + INPUT(BlockType.BLOCK, EndTag.NOEND), + LI, + LISTING, + LINK(BlockType.OTHER, EndTag.NOEND), + MAIN(HtmlVersion.HTML5), + MENU, + META(BlockType.OTHER, EndTag.NOEND), + NAV(HtmlVersion.HTML5), + NOSCRIPT(BlockType.OTHER, EndTag.END), + OL, + P, + PRE, + SCRIPT(BlockType.OTHER, EndTag.END), + SECTION(HtmlVersion.HTML5), + SMALL(BlockType.INLINE, EndTag.END), + SPAN(BlockType.INLINE, EndTag.END), + STRONG(BlockType.INLINE, EndTag.END), + SUB(BlockType.INLINE, EndTag.END), + TABLE, + TBODY, + TD, + TH, + TITLE(BlockType.OTHER, EndTag.END), + TR, + TT(HtmlVersion.HTML4, BlockType.INLINE, EndTag.END), + UL; + + public final BlockType blockType; + public final EndTag endTag; + public final String value; + public final HtmlVersion htmlVersion; + + /** + * Enum representing the type of HTML element. + */ + public static enum BlockType { + BLOCK, + INLINE, + OTHER + } + + /** + * Enum representing HTML end tag requirement. + */ + public static enum EndTag { + END, + NOEND + } + + HtmlTag() { + this(HtmlVersion.ALL, BlockType.BLOCK, EndTag.END); + } + + HtmlTag(HtmlVersion htmlVersion) { + this(htmlVersion, BlockType.BLOCK, EndTag.END); + } + + HtmlTag(BlockType blockType, EndTag endTag ) { + this(HtmlVersion.ALL, blockType, endTag); + } + + HtmlTag(HtmlVersion htmlVersion, BlockType blockType, EndTag endTag ) { + this.htmlVersion = htmlVersion; + this.blockType = blockType; + this.endTag = endTag; + this.value = Utils.toLowerCase(name()); + } + + /** + * Returns true if the end tag is required. This is specific to the standard + * doclet and does not exactly resemble the W3C specifications. + * + * @return true if end tag needs to be displayed else return false + */ + public boolean endTagRequired() { + return (endTag == EndTag.END); + } + + /** + * Returns true if the tag is allowed in the output HTML version of this javadoc run. + * + * @param htmlVer the output HTML version for this javadoc run + * @return true if the tag is allowed + */ + public boolean allowTag(HtmlVersion htmlVer) { + return (this.htmlVersion == HtmlVersion.ALL || this.htmlVersion == htmlVer); + } + + public String toString() { + return value; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java new file mode 100644 index 00000000000..93b9071dcf7 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java @@ -0,0 +1,978 @@ +/* + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr.Role; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; + +/** + * Class for generating HTML tree for javadoc output. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public class HtmlTree extends Content { + + private HtmlTag htmlTag; + private Map attrs = Collections.emptyMap(); + private List content = Collections.emptyList(); + public static final Content EMPTY = new StringContent(""); + + /** + * Constructor to construct HtmlTree object. + * + * @param tag HTML tag for the HtmlTree object + */ + public HtmlTree(HtmlTag tag) { + htmlTag = nullCheck(tag); + } + + /** + * Constructor to construct HtmlTree object. + * + * @param tag HTML tag for the HtmlTree object + * @param contents contents to be added to the tree + */ + public HtmlTree(HtmlTag tag, Content... contents) { + this(tag); + for (Content content: contents) + addContent(content); + } + + /** + * Adds an attribute for the HTML tag. + * + * @param attrName name of the attribute + * @param attrValue value of the attribute + */ + public void addAttr(HtmlAttr attrName, String attrValue) { + if (attrs.isEmpty()) + attrs = new LinkedHashMap<>(3); + attrs.put(nullCheck(attrName), escapeHtmlChars(attrValue)); + } + + public void setTitle(Content body) { + addAttr(HtmlAttr.TITLE, stripHtml(body)); + } + + public void setRole(Role role) { + addAttr(HtmlAttr.ROLE, role.toString()); + } + + /** + * Adds a style for the HTML tag. + * + * @param style style to be added + */ + public void addStyle(HtmlStyle style) { + addAttr(HtmlAttr.CLASS, style.toString()); + } + + /** + * Adds content for the HTML tag. + * + * @param tagContent tag content to be added + */ + public void addContent(Content tagContent) { + if (tagContent instanceof ContentBuilder) { + for (Content content: ((ContentBuilder)tagContent).contents) { + addContent(content); + } + } + else if (tagContent == HtmlTree.EMPTY || tagContent.isValid()) { + if (content.isEmpty()) + content = new ArrayList<>(); + content.add(tagContent); + } + } + + /** + * This method adds a string content to the htmltree. If the last content member + * added is a StringContent, append the string to that StringContent or else + * create a new StringContent and add it to the html tree. + * + * @param stringContent string content that needs to be added + */ + public void addContent(String stringContent) { + if (!content.isEmpty()) { + Content lastContent = content.get(content.size() - 1); + if (lastContent instanceof StringContent) + lastContent.addContent(stringContent); + else + addContent(new StringContent(stringContent)); + } + else + addContent(new StringContent(stringContent)); + } + + public int charCount() { + int n = 0; + for (Content c : content) + n += c.charCount(); + return n; + } + + /** + * Given a string, escape all special html characters and + * return the result. + * + * @param s The string to check. + * @return the original string with all of the HTML characters escaped. + */ + private static String escapeHtmlChars(String s) { + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + // only start building a new string if we need to + case '<': case '>': case '&': + StringBuilder sb = new StringBuilder(s.substring(0, i)); + for ( ; i < s.length(); i++) { + ch = s.charAt(i); + switch (ch) { + case '<': sb.append("<"); break; + case '>': sb.append(">"); break; + case '&': sb.append("&"); break; + default: sb.append(ch); break; + } + } + return sb.toString(); + } + } + return s; + } + + /** + * A set of ASCII URI characters to be left unencoded. + */ + public static final BitSet NONENCODING_CHARS = new BitSet(256); + + static { + // alphabetic characters + for (int i = 'a'; i <= 'z'; i++) { + NONENCODING_CHARS.set(i); + } + for (int i = 'A'; i <= 'Z'; i++) { + NONENCODING_CHARS.set(i); + } + // numeric characters + for (int i = '0'; i <= '9'; i++) { + NONENCODING_CHARS.set(i); + } + // Reserved characters as per RFC 3986. These are set of delimiting characters. + String noEnc = ":/?#[]@!$&'()*+,;="; + // Unreserved characters as per RFC 3986 which should not be percent encoded. + noEnc += "-._~"; + for (int i = 0; i < noEnc.length(); i++) { + NONENCODING_CHARS.set(noEnc.charAt(i)); + } + } + + private static String encodeURL(String url) { + StringBuilder sb = new StringBuilder(); + for (byte c : url.getBytes(Charset.forName("UTF-8"))) { + if (NONENCODING_CHARS.get(c & 0xFF)) { + sb.append((char) c); + } else { + sb.append(String.format("%%%02X", c & 0xFF)); + } + } + return sb.toString(); + } + + /** + * Generates an HTML anchor tag. + * + * @param ref reference url for the anchor tag + * @param body content for the anchor tag + * @return an HtmlTree object + */ + public static HtmlTree A(String ref, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.A, nullCheck(body)); + htmltree.addAttr(HtmlAttr.HREF, encodeURL(ref)); + return htmltree; + } + + /** + * Generates an HTML anchor tag with an id or a name attribute and content. + * + * @param htmlVersion the version of the generated HTML + * @param attr name or id attribute for the anchor tag + * @param body content for the anchor tag + * @return an HtmlTree object + */ + public static HtmlTree A(HtmlVersion htmlVersion, String attr, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.A); + htmltree.addAttr((htmlVersion == HtmlVersion.HTML4) + ? HtmlAttr.NAME + : HtmlAttr.ID, + nullCheck(attr)); + htmltree.addContent(nullCheck(body)); + return htmltree; + } + + /** + * Generates an HTML anchor tag with id attribute and a body. + * + * @param id id for the anchor tag + * @param body body for the anchor tag + * @return an HtmlTree object + */ + public static HtmlTree A_ID(String id, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.A); + htmltree.addAttr(HtmlAttr.ID, nullCheck(id)); + htmltree.addContent(nullCheck(body)); + return htmltree; + } + + /** + * Generates a CAPTION tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the CAPTION tag + */ + public static HtmlTree CAPTION(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.CAPTION, nullCheck(body)); + return htmltree; + } + + /** + * Generates a CODE tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the CODE tag + */ + public static HtmlTree CODE(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.CODE, nullCheck(body)); + return htmltree; + } + + /** + * Generates a DD tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the DD tag + */ + public static HtmlTree DD(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.DD, nullCheck(body)); + return htmltree; + } + + /** + * Generates a DL tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the DL tag + */ + public static HtmlTree DL(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.DL, nullCheck(body)); + return htmltree; + } + + /** + * Generates a DIV tag with the style class attributes. It also encloses + * a content. + * + * @param styleClass stylesheet class for the tag + * @param body content for the tag + * @return an HtmlTree object for the DIV tag + */ + public static HtmlTree DIV(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.DIV, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a DIV tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the DIV tag + */ + public static HtmlTree DIV(Content body) { + return DIV(null, body); + } + + /** + * Generates a DT tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the DT tag + */ + public static HtmlTree DT(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.DT, nullCheck(body)); + return htmltree; + } + + /** + * Generates a FOOTER tag with role attribute. + * + * @return an HtmlTree object for the FOOTER tag + */ + public static HtmlTree FOOTER() { + HtmlTree htmltree = new HtmlTree(HtmlTag.FOOTER); + htmltree.setRole(Role.CONTENTINFO); + return htmltree; + } + + /** + * Generates a HEADER tag with role attribute. + * + * @return an HtmlTree object for the HEADER tag + */ + public static HtmlTree HEADER() { + HtmlTree htmltree = new HtmlTree(HtmlTag.HEADER); + htmltree.setRole(Role.BANNER); + return htmltree; + } + + /** + * Generates a heading tag (h1 to h6) with the title and style class attributes. It also encloses + * a content. + * + * @param headingTag the heading tag to be generated + * @param printTitle true if title for the tag needs to be printed else false + * @param styleClass stylesheet class for the tag + * @param body content for the tag + * @return an HtmlTree object for the tag + */ + public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle, + HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(headingTag, nullCheck(body)); + if (printTitle) + htmltree.setTitle(body); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a heading tag (h1 to h6) with style class attribute. It also encloses + * a content. + * + * @param headingTag the heading tag to be generated + * @param styleClass stylesheet class for the tag + * @param body content for the tag + * @return an HtmlTree object for the tag + */ + public static HtmlTree HEADING(HtmlTag headingTag, HtmlStyle styleClass, Content body) { + return HEADING(headingTag, false, styleClass, body); + } + + /** + * Generates a heading tag (h1 to h6) with the title attribute. It also encloses + * a content. + * + * @param headingTag the heading tag to be generated + * @param printTitle true if the title for the tag needs to be printed else false + * @param body content for the tag + * @return an HtmlTree object for the tag + */ + public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle, Content body) { + return HEADING(headingTag, printTitle, null, body); + } + + /** + * Generates a heading tag (h1 to h6) with some content. + * + * @param headingTag the heading tag to be generated + * @param body content for the tag + * @return an HtmlTree object for the tag + */ + public static HtmlTree HEADING(HtmlTag headingTag, Content body) { + return HEADING(headingTag, false, null, body); + } + + /** + * Generates an HTML tag with lang attribute. It also adds head and body + * content to the HTML tree. + * + * @param lang language for the HTML document + * @param head head for the HTML tag + * @param body body for the HTML tag + * @return an HtmlTree object for the HTML tag + */ + public static HtmlTree HTML(String lang, Content head, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.HTML, nullCheck(head), nullCheck(body)); + htmltree.addAttr(HtmlAttr.LANG, nullCheck(lang)); + return htmltree; + } + + /** + * Generates a IFRAME tag. + * + * @param src the url of the document to be shown in the frame + * @param name specifies the name of the frame + * @param title the title for the frame + * @return an HtmlTree object for the IFRAME tag + */ + public static HtmlTree IFRAME(String src, String name, String title) { + HtmlTree htmltree = new HtmlTree(HtmlTag.IFRAME); + htmltree.addAttr(HtmlAttr.SRC, nullCheck(src)); + htmltree.addAttr(HtmlAttr.NAME, nullCheck(name)); + htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title)); + return htmltree; + } + + /** + * Generates a INPUT tag with some id. + * + * @param type the type of input + * @param id id for the tag + * @return an HtmlTree object for the INPUT tag + */ + public static HtmlTree INPUT(String type, String id) { + HtmlTree htmltree = new HtmlTree(HtmlTag.INPUT); + htmltree.addAttr(HtmlAttr.TYPE, nullCheck(type)); + htmltree.addAttr(HtmlAttr.ID, nullCheck(id)); + htmltree.addAttr(HtmlAttr.VALUE, " "); + htmltree.addAttr(HtmlAttr.DISABLED, "disabled"); + return htmltree; + } + + /** + * Generates a LI tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the LI tag + */ + public static HtmlTree LI(Content body) { + return LI(null, body); + } + + /** + * Generates a LI tag with some content. + * + * @param styleClass style for the tag + * @param body content for the tag + * @return an HtmlTree object for the LI tag + */ + public static HtmlTree LI(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.LI, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a LINK tag with the rel, type, href and title attributes. + * + * @param rel relevance of the link + * @param type type of link + * @param href the path for the link + * @param title title for the link + * @return an HtmlTree object for the LINK tag + */ + public static HtmlTree LINK(String rel, String type, String href, String title) { + HtmlTree htmltree = new HtmlTree(HtmlTag.LINK); + htmltree.addAttr(HtmlAttr.REL, nullCheck(rel)); + htmltree.addAttr(HtmlAttr.TYPE, nullCheck(type)); + htmltree.addAttr(HtmlAttr.HREF, nullCheck(href)); + htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title)); + return htmltree; + } + + /** + * Generates a MAIN tag with role attribute. + * + * @return an HtmlTree object for the MAIN tag + */ + public static HtmlTree MAIN() { + HtmlTree htmltree = new HtmlTree(HtmlTag.MAIN); + htmltree.setRole(Role.MAIN); + return htmltree; + } + + /** + * Generates a MAIN tag with role attribute and some content. + * + * @param body content of the MAIN tag + * @return an HtmlTree object for the MAIN tag + */ + public static HtmlTree MAIN(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.MAIN, nullCheck(body)); + htmltree.setRole(Role.MAIN); + return htmltree; + } + + /** + * Generates a MAIN tag with role attribute, style attribute and some content. + * + * @param styleClass style of the MAIN tag + * @param body content of the MAIN tag + * @return an HtmlTree object for the MAIN tag + */ + public static HtmlTree MAIN(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = HtmlTree.MAIN(body); + if (styleClass != null) { + htmltree.addStyle(styleClass); + } + return htmltree; + } + + /** + * Generates a META tag with the http-equiv, content and charset attributes. + * + * @param httpEquiv http equiv attribute for the META tag + * @param content type of content + * @param charSet character set used + * @return an HtmlTree object for the META tag + */ + public static HtmlTree META(String httpEquiv, String content, String charSet) { + HtmlTree htmltree = new HtmlTree(HtmlTag.META); + String contentCharset = content + "; charset=" + charSet; + htmltree.addAttr(HtmlAttr.HTTP_EQUIV, nullCheck(httpEquiv)); + htmltree.addAttr(HtmlAttr.CONTENT, contentCharset); + return htmltree; + } + + /** + * Generates a META tag with the name and content attributes. + * + * @param name name attribute + * @param content type of content + * @return an HtmlTree object for the META tag + */ + public static HtmlTree META(String name, String content) { + HtmlTree htmltree = new HtmlTree(HtmlTag.META); + htmltree.addAttr(HtmlAttr.NAME, nullCheck(name)); + htmltree.addAttr(HtmlAttr.CONTENT, nullCheck(content)); + return htmltree; + } + + /** + * Generates a NAV tag with the role attribute. + * + * @return an HtmlTree object for the NAV tag + */ + public static HtmlTree NAV() { + HtmlTree htmltree = new HtmlTree(HtmlTag.NAV); + htmltree.setRole(Role.NAVIGATION); + return htmltree; + } + + /** + * Generates a NOSCRIPT tag with some content. + * + * @param body content of the noscript tag + * @return an HtmlTree object for the NOSCRIPT tag + */ + public static HtmlTree NOSCRIPT(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.NOSCRIPT, nullCheck(body)); + return htmltree; + } + + /** + * Generates a P tag with some content. + * + * @param body content of the Paragraph tag + * @return an HtmlTree object for the P tag + */ + public static HtmlTree P(Content body) { + return P(null, body); + } + + /** + * Generates a P tag with some content. + * + * @param styleClass style of the Paragraph tag + * @param body content of the Paragraph tag + * @return an HtmlTree object for the P tag + */ + public static HtmlTree P(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.P, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a SCRIPT tag with the type and src attributes. + * + * @param type type of link + * @param src the path for the script + * @return an HtmlTree object for the SCRIPT tag + */ + public static HtmlTree SCRIPT(String src) { + HtmlTree htmltree = HtmlTree.SCRIPT(); + htmltree.addAttr(HtmlAttr.SRC, nullCheck(src)); + return htmltree; + } + + /** + * Generates a SCRIPT tag with the type attribute. + * + * @return an HtmlTree object for the SCRIPT tag + */ + public static HtmlTree SCRIPT() { + HtmlTree htmltree = new HtmlTree(HtmlTag.SCRIPT); + htmltree.addAttr(HtmlAttr.TYPE, "text/javascript"); + return htmltree; + } + + /** + * Generates a SECTION tag with role attribute. + * + * @return an HtmlTree object for the SECTION tag + */ + public static HtmlTree SECTION() { + HtmlTree htmltree = new HtmlTree(HtmlTag.SECTION); + htmltree.setRole(Role.REGION); + return htmltree; + } + + /** + * Generates a SECTION tag with role attribute and some content. + * + * @param body content of the section tag + * @return an HtmlTree object for the SECTION tag + */ + public static HtmlTree SECTION(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.SECTION, nullCheck(body)); + htmltree.setRole(Role.REGION); + return htmltree; + } + + /** + * Generates a SMALL tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the SMALL tag + */ + public static HtmlTree SMALL(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.SMALL, nullCheck(body)); + return htmltree; + } + + /** + * Generates a SPAN tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the SPAN tag + */ + public static HtmlTree SPAN(Content body) { + return SPAN(null, body); + } + + /** + * Generates a SPAN tag with style class attribute and some content. + * + * @param styleClass style class for the tag + * @param body content for the tag + * @return an HtmlTree object for the SPAN tag + */ + public static HtmlTree SPAN(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a SPAN tag with id and style class attributes. It also encloses + * a content. + * + * @param id the id for the tag + * @param styleClass stylesheet class for the tag + * @param body content for the tag + * @return an HtmlTree object for the SPAN tag + */ + public static HtmlTree SPAN(String id, HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body)); + htmltree.addAttr(HtmlAttr.ID, nullCheck(id)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a Table tag with style class and summary attributes and some content. + * + * @param styleClass style of the table + * @param summary summary for the table + * @param body content for the table + * @return an HtmlTree object for the TABLE tag + */ + public static HtmlTree TABLE(HtmlStyle styleClass, String summary, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary)); + return htmltree; + } + + /** + * Generates a Table tag with style class attribute and some content. + * + * @param styleClass style of the table + * @param body content for the table + * @return an HtmlTree object for the TABLE tag + */ + public static HtmlTree TABLE(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body)); + if (styleClass != null) { + htmltree.addStyle(styleClass); + } + return htmltree; + } + + /** + * Generates a TD tag with style class attribute and some content. + * + * @param styleClass style for the tag + * @param body content for the tag + * @return an HtmlTree object for the TD tag + */ + public static HtmlTree TD(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TD, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + return htmltree; + } + + /** + * Generates a TD tag for an HTML table with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the TD tag + */ + public static HtmlTree TD(Content body) { + return TD(null, body); + } + + /** + * Generates a TH tag with style class and scope attributes and some content. + * + * @param styleClass style for the tag + * @param scope scope of the tag + * @param body content for the tag + * @return an HtmlTree object for the TH tag + */ + public static HtmlTree TH(HtmlStyle styleClass, String scope, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TH, nullCheck(body)); + if (styleClass != null) + htmltree.addStyle(styleClass); + htmltree.addAttr(HtmlAttr.SCOPE, nullCheck(scope)); + return htmltree; + } + + /** + * Generates a TH tag with scope attribute and some content. + * + * @param scope scope of the tag + * @param body content for the tag + * @return an HtmlTree object for the TH tag + */ + public static HtmlTree TH(String scope, Content body) { + return TH(null, scope, body); + } + + /** + * Generates a TITLE tag with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the TITLE tag + */ + public static HtmlTree TITLE(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TITLE, nullCheck(body)); + return htmltree; + } + + /** + * Generates a TR tag for an HTML table with some content. + * + * @param body content for the tag + * @return an HtmlTree object for the TR tag + */ + public static HtmlTree TR(Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.TR, nullCheck(body)); + return htmltree; + } + + /** + * Generates a UL tag with the style class attribute and some content. + * + * @param styleClass style for the tag + * @param body content for the tag + * @return an HtmlTree object for the UL tag + */ + public static HtmlTree UL(HtmlStyle styleClass, Content body) { + HtmlTree htmltree = new HtmlTree(HtmlTag.UL, nullCheck(body)); + htmltree.addStyle(nullCheck(styleClass)); + return htmltree; + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return (!hasContent() && !hasAttrs()); + } + + /** + * Returns true if the HTML tree has content. + * + * @return true if the HTML tree has content else return false + */ + public boolean hasContent() { + return (!content.isEmpty()); + } + + /** + * Returns true if the HTML tree has attributes. + * + * @return true if the HTML tree has attributes else return false + */ + public boolean hasAttrs() { + return (!attrs.isEmpty()); + } + + /** + * Returns true if the HTML tree has a specific attribute. + * + * @param attrName name of the attribute to check within the HTML tree + * @return true if the HTML tree has the specified attribute else return false + */ + public boolean hasAttr(HtmlAttr attrName) { + return (attrs.containsKey(attrName)); + } + + /** + * Returns true if the HTML tree is valid. This check is more specific to + * standard doclet and not exactly similar to W3C specifications. But it + * ensures HTML validation. + * + * @return true if the HTML tree is valid + */ + public boolean isValid() { + switch (htmlTag) { + case A : + return (hasAttr(HtmlAttr.NAME) || hasAttr(HtmlAttr.ID) || (hasAttr(HtmlAttr.HREF) && hasContent())); + case BR : + return (!hasContent() && (!hasAttrs() || hasAttr(HtmlAttr.CLEAR))); + case IFRAME : + return (hasAttr(HtmlAttr.SRC) && !hasContent()); + case HR : + case INPUT: + return (!hasContent()); + case IMG : + return (hasAttr(HtmlAttr.SRC) && hasAttr(HtmlAttr.ALT) && !hasContent()); + case LINK : + return (hasAttr(HtmlAttr.HREF) && !hasContent()); + case META : + return (hasAttr(HtmlAttr.CONTENT) && !hasContent()); + case SCRIPT : + return ((hasAttr(HtmlAttr.TYPE) && hasAttr(HtmlAttr.SRC) && !hasContent()) || + (hasAttr(HtmlAttr.TYPE) && hasContent())); + default : + return hasContent(); + } + } + + /** + * Returns true if the element is an inline element. + * + * @return true if the HTML tag is an inline element + */ + public boolean isInline() { + return (htmlTag.blockType == HtmlTag.BlockType.INLINE); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean write(Writer out, boolean atNewline) throws IOException { + if (!isInline() && !atNewline) + out.write(DocletConstants.NL); + String tagString = htmlTag.toString(); + out.write("<"); + out.write(tagString); + Iterator iterator = attrs.keySet().iterator(); + HtmlAttr key; + String value; + while (iterator.hasNext()) { + key = iterator.next(); + value = attrs.get(key); + out.write(" "); + out.write(key.toString()); + if (!value.isEmpty()) { + out.write("=\""); + out.write(value); + out.write("\""); + } + } + out.write(">"); + boolean nl = false; + for (Content c : content) + nl = c.write(out, nl); + if (htmlTag.endTagRequired()) { + out.write(""); + } + if (!isInline()) { + out.write(DocletConstants.NL); + return true; + } else { + return false; + } + } + + /** + * Given a Content node, strips all html characters and + * return the result. + * + * @param body The content node to check. + * @return the plain text from the content node + * + */ + private static String stripHtml(Content body) { + String rawString = body.toString(); + // remove HTML tags + rawString = rawString.replaceAll("\\<.*?>", " "); + // consolidate multiple spaces between a word to a single space + rawString = rawString.replaceAll("\\b\\s{2,}\\b", " "); + // remove extra whitespaces + return rawString.trim(); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlVersion.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlVersion.java new file mode 100644 index 00000000000..c3b3e6ded5e --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlVersion.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +/** + * Enum representing the version of HTML generated by javadoc. + * + * @author Bhavesh Patel + */ +public enum HtmlVersion { + HTML4, + HTML5, + ALL +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java new file mode 100644 index 00000000000..589f342ef79 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java @@ -0,0 +1,515 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import java.io.*; +import java.util.*; + +import jdk.javadoc.internal.doclets.toolkit.Configuration; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocFile; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; +import jdk.javadoc.internal.doclets.toolkit.util.MethodTypes; + + +/** + * Class for the Html format code generation. + * Initializes PrintWriter with FileWriter, to enable print + * related methods to generate the code to the named File through FileWriter. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) + */ +public class HtmlWriter { + + /** + * The window title of this file + */ + protected String winTitle; + + /** + * The configuration + */ + protected Configuration configuration; + + /** + * The flag to indicate whether a member details list is printed or not. + */ + protected boolean memberDetailsListPrinted; + + /** + * Header for tables displaying packages and description.. + */ + protected final List packageTableHeader; + + /** + * Summary for use tables displaying class and package use. + */ + protected final String useTableSummary; + + /** + * Column header for class docs displaying Modifier and Type header. + */ + protected final String modifierTypeHeader; + + public final Content overviewLabel; + + public final Content defaultPackageLabel; + + public final Content packageLabel; + + public final Content useLabel; + + public final Content prevLabel; + + public final Content nextLabel; + + public final Content prevclassLabel; + + public final Content nextclassLabel; + + public final Content summaryLabel; + + public final Content detailLabel; + + public final Content framesLabel; + + public final Content noframesLabel; + + public final Content treeLabel; + + public final Content classLabel; + + public final Content deprecatedLabel; + + public final Content deprecatedPhrase; + + public final Content allclassesLabel; + + public final Content allpackagesLabel; + + public final Content indexLabel; + + public final Content helpLabel; + + public final Content seeLabel; + + public final Content descriptionLabel; + + public final Content prevpackageLabel; + + public final Content nextpackageLabel; + + public final Content packagesLabel; + + public final Content methodDetailsLabel; + + public final Content annotationTypeDetailsLabel; + + public final Content fieldDetailsLabel; + + public final Content propertyDetailsLabel; + + public final Content constructorDetailsLabel; + + public final Content enumConstantsDetailsLabel; + + public final Content specifiedByLabel; + + public final Content overridesLabel; + + public final Content descfrmClassLabel; + + public final Content descfrmInterfaceLabel; + + private final Writer writer; + + protected Content script; + + + /** + * Constructor. + * + * @param path The directory path to be created for this file + * or null if none to be created. + * @exception IOException Exception raised by the FileWriter is passed on + * to next level. + * @exception UnsupportedEncodingException Exception raised by the + * OutputStreamWriter is passed on to next level. + */ + public HtmlWriter(Configuration configuration, DocPath path) + throws IOException, UnsupportedEncodingException { + writer = DocFile.createFileForOutput(configuration, path).openWriter(); + this.configuration = configuration; + this.memberDetailsListPrinted = false; + packageTableHeader = new ArrayList<>(); + packageTableHeader.add(configuration.getText("doclet.Package")); + packageTableHeader.add(configuration.getText("doclet.Description")); + useTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.packages")); + modifierTypeHeader = configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Modifier"), + configuration.getText("doclet.Type")); + overviewLabel = getResource("doclet.Overview"); + defaultPackageLabel = new StringContent(DocletConstants.DEFAULT_PACKAGE_NAME); + packageLabel = getResource("doclet.Package"); + useLabel = getResource("doclet.navClassUse"); + prevLabel = getResource("doclet.Prev"); + nextLabel = getResource("doclet.Next"); + prevclassLabel = getNonBreakResource("doclet.Prev_Class"); + nextclassLabel = getNonBreakResource("doclet.Next_Class"); + summaryLabel = getResource("doclet.Summary"); + detailLabel = getResource("doclet.Detail"); + framesLabel = getResource("doclet.Frames"); + noframesLabel = getNonBreakResource("doclet.No_Frames"); + treeLabel = getResource("doclet.Tree"); + classLabel = getResource("doclet.Class"); + deprecatedLabel = getResource("doclet.navDeprecated"); + deprecatedPhrase = getResource("doclet.Deprecated"); + allclassesLabel = getNonBreakResource("doclet.All_Classes"); + allpackagesLabel = getNonBreakResource("doclet.All_Packages"); + indexLabel = getResource("doclet.Index"); + helpLabel = getResource("doclet.Help"); + seeLabel = getResource("doclet.See"); + descriptionLabel = getResource("doclet.Description"); + prevpackageLabel = getNonBreakResource("doclet.Prev_Package"); + nextpackageLabel = getNonBreakResource("doclet.Next_Package"); + packagesLabel = getResource("doclet.Packages"); + methodDetailsLabel = getResource("doclet.Method_Detail"); + annotationTypeDetailsLabel = getResource("doclet.Annotation_Type_Member_Detail"); + fieldDetailsLabel = getResource("doclet.Field_Detail"); + propertyDetailsLabel = getResource("doclet.Property_Detail"); + constructorDetailsLabel = getResource("doclet.Constructor_Detail"); + enumConstantsDetailsLabel = getResource("doclet.Enum_Constant_Detail"); + specifiedByLabel = getResource("doclet.Specified_By"); + overridesLabel = getResource("doclet.Overrides"); + descfrmClassLabel = getResource("doclet.Description_From_Class"); + descfrmInterfaceLabel = getResource("doclet.Description_From_Interface"); + } + + public void write(Content c) throws IOException { + c.write(writer, true); + } + + public void close() throws IOException { + writer.close(); + } + + /** + * Get the configuration string as a content. + * + * @param key the key to look for in the configuration file + * @return a content tree for the text + */ + public Content getResource(String key) { + return configuration.getResource(key); + } + + /** + * Get the configuration string as a content, replacing spaces + * with non-breaking spaces. + * + * @param key the key to look for in the configuration file + * @return a content tree for the text + */ + public Content getNonBreakResource(String key) { + String text = configuration.getText(key); + Content c = configuration.newContent(); + int start = 0; + int p; + while ((p = text.indexOf(" ", start)) != -1) { + c.addContent(text.substring(start, p)); + c.addContent(RawHtml.nbsp); + start = p + 1; + } + c.addContent(text.substring(start)); + return c; + } + + /** + * Get the configuration string as a content. + * + * @param key the key to look for in the configuration file + * @param o string or content argument added to configuration text + * @return a content tree for the text + */ + public Content getResource(String key, Object o) { + return configuration.getResource(key, o); + } + + /** + * Get the configuration string as a content. + * + * @param key the key to look for in the configuration file + * @param o1 string or content argument added to configuration text + * @param o2 string or content argument added to configuration text + * @return a content tree for the text + */ + public Content getResource(String key, Object o0, Object o1) { + return configuration.getResource(key, o0, o1); + } + + /** + * Returns an HtmlTree for the SCRIPT tag. + * + * @return an HtmlTree for the SCRIPT tag + */ + protected HtmlTree getWinTitleScript(){ + HtmlTree script = HtmlTree.SCRIPT(); + if(winTitle != null && winTitle.length() > 0) { + String scriptCode = "" + DocletConstants.NL; + RawHtml scriptContent = new RawHtml(scriptCode); + script.addContent(scriptContent); + } + return script; + } + + /** + * Returns a String with escaped special JavaScript characters. + * + * @param s String that needs to be escaped + * @return a valid escaped JavaScript string + */ + private static String escapeJavaScriptChars(String s) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + case '\b': + sb.append("\\b"); + break; + case '\t': + sb.append("\\t"); + break; + case '\n': + sb.append("\\n"); + break; + case '\f': + sb.append("\\f"); + break; + case '\r': + sb.append("\\r"); + break; + case '"': + sb.append("\\\""); + break; + case '\'': + sb.append("\\\'"); + break; + case '\\': + sb.append("\\\\"); + break; + default: + if (ch < 32 || ch >= 127) { + sb.append(String.format("\\u%04X", (int)ch)); + } else { + sb.append(ch); + } + break; + } + } + return sb.toString(); + } + + /** + * Returns a content tree for the SCRIPT tag for the main page(index.html). + * + * @return a content for the SCRIPT tag + */ + protected Content getFramesJavaScript() { + HtmlTree script = HtmlTree.SCRIPT(); + String scriptCode = DocletConstants.NL + + " targetPage = \"\" + window.location.search;" + DocletConstants.NL + + " if (targetPage != \"\" && targetPage != \"undefined\")" + DocletConstants.NL + + " targetPage = targetPage.substring(1);" + DocletConstants.NL + + " if (targetPage.indexOf(\":\") != -1 || (targetPage != \"\" && !validURL(targetPage)))" + DocletConstants.NL + + " targetPage = \"undefined\";" + DocletConstants.NL + + " function validURL(url) {" + DocletConstants.NL + + " try {" + DocletConstants.NL + + " url = decodeURIComponent(url);" + DocletConstants.NL + + " }" + DocletConstants.NL + + " catch (error) {" + DocletConstants.NL + + " return false;" + DocletConstants.NL + + " }" + DocletConstants.NL + + " var pos = url.indexOf(\".html\");" + DocletConstants.NL + + " if (pos == -1 || pos != url.length - 5)" + DocletConstants.NL + + " return false;" + DocletConstants.NL + + " var allowNumber = false;" + DocletConstants.NL + + " var allowSep = false;" + DocletConstants.NL + + " var seenDot = false;" + DocletConstants.NL + + " for (var i = 0; i < url.length - 5; i++) {" + DocletConstants.NL + + " var ch = url.charAt(i);" + DocletConstants.NL + + " if ('a' <= ch && ch <= 'z' ||" + DocletConstants.NL + + " 'A' <= ch && ch <= 'Z' ||" + DocletConstants.NL + + " ch == '$' ||" + DocletConstants.NL + + " ch == '_' ||" + DocletConstants.NL + + " ch.charCodeAt(0) > 127) {" + DocletConstants.NL + + " allowNumber = true;" + DocletConstants.NL + + " allowSep = true;" + DocletConstants.NL + + " } else if ('0' <= ch && ch <= '9'" + DocletConstants.NL + + " || ch == '-') {" + DocletConstants.NL + + " if (!allowNumber)" + DocletConstants.NL + + " return false;" + DocletConstants.NL + + " } else if (ch == '/' || ch == '.') {" + DocletConstants.NL + + " if (!allowSep)" + DocletConstants.NL + + " return false;" + DocletConstants.NL + + " allowNumber = false;" + DocletConstants.NL + + " allowSep = false;" + DocletConstants.NL + + " if (ch == '.')" + DocletConstants.NL + + " seenDot = true;" + DocletConstants.NL + + " if (ch == '/' && seenDot)" + DocletConstants.NL + + " return false;" + DocletConstants.NL + + " } else {" + DocletConstants.NL + + " return false;"+ DocletConstants.NL + + " }" + DocletConstants.NL + + " }" + DocletConstants.NL + + " return true;" + DocletConstants.NL + + " }" + DocletConstants.NL; + RawHtml scriptContent = new RawHtml(scriptCode); + script.addContent(scriptContent); + return script; + } + + /** + * Returns an HtmlTree for the BODY tag. + * + * @param includeScript set true if printing windowtitle script + * @param title title for the window + * @return an HtmlTree for the BODY tag + */ + public HtmlTree getBody(boolean includeScript, String title) { + HtmlTree body = new HtmlTree(HtmlTag.BODY); + // Set window title string which is later printed + this.winTitle = title; + // Don't print windowtitle script for overview-frame, allclasses-frame + // and package-frame + if (includeScript) { + this.script = getWinTitleScript(); + body.addContent(script); + Content noScript = HtmlTree.NOSCRIPT( + HtmlTree.DIV(getResource("doclet.No_Script_Message"))); + body.addContent(noScript); + } + return body; + } + + /** + * Generated javascript variables for the document. + * + * @param typeMap map comprising of method and type relationship + * @param methodTypes set comprising of all methods types for this class + */ + public void generateMethodTypesScript(Map typeMap, + Set methodTypes) { + String sep = ""; + StringBuilder vars = new StringBuilder("var methods = {"); + for (Map.Entry entry : typeMap.entrySet()) { + vars.append(sep); + sep = ","; + vars.append("\"") + .append(entry.getKey()) + .append("\":") + .append(entry.getValue()); + } + vars.append("};").append(DocletConstants.NL); + sep = ""; + vars.append("var tabs = {"); + for (MethodTypes entry : methodTypes) { + vars.append(sep); + sep = ","; + vars.append(entry.value()) + .append(":") + .append("[") + .append("\"") + .append(entry.tabId()) + .append("\"") + .append(sep) + .append("\"") + .append(configuration.getText(entry.resourceKey())) + .append("\"]"); + } + vars.append("};") + .append(DocletConstants.NL); + addStyles(HtmlStyle.altColor, vars); + addStyles(HtmlStyle.rowColor, vars); + addStyles(HtmlStyle.tableTab, vars); + addStyles(HtmlStyle.activeTableTab, vars); + script.addContent(new RawHtml(vars.toString())); + } + + /** + * Adds javascript style variables to the document. + * + * @param style style to be added as a javascript variable + * @param vars variable string to which the style variable will be added + */ + public void addStyles(HtmlStyle style, StringBuilder vars) { + vars.append("var ").append(style).append(" = \"").append(style) + .append("\";").append(DocletConstants.NL); + } + + /** + * Returns an HtmlTree for the TITLE tag. + * + * @return an HtmlTree for the TITLE tag + */ + public HtmlTree getTitle() { + HtmlTree title = HtmlTree.TITLE(new StringContent(winTitle)); + return title; + } + + public String codeText(String text) { + return "" + text + ""; + } + + /** + * Return "&nbsp;", non-breaking space. + */ + public Content getSpace() { + return RawHtml.nbsp; + } + + /* + * Returns a header for Modifier and Type column of a table. + */ + public String getModifierTypeHeader() { + return modifierTypeHeader; + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java new file mode 100644 index 00000000000..fe425dd743a --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import java.io.IOException; +import java.io.Writer; + +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; + +/** + * Class for generating raw HTML content to be added to HTML pages of javadoc output. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public class RawHtml extends Content { + + private String rawHtmlContent; + + public static final Content nbsp = new RawHtml(" "); + + /** + * Constructor to construct a RawHtml object. + * + * @param rawHtml raw HTML text to be added + */ + public RawHtml(String rawHtml) { + rawHtmlContent = nullCheck(rawHtml); + } + + /** + * This method is not supported by the class. + * + * @param content content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(Content content) { + throw new DocletAbortException("not supported"); + } + + /** + * This method is not supported by the class. + * + * @param stringContent string content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + public void addContent(String stringContent) { + throw new DocletAbortException("not supported"); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return rawHtmlContent.isEmpty(); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return rawHtmlContent; + } + + private enum State { TEXT, ENTITY, TAG, STRING } + + @Override + public int charCount() { + return charCount(rawHtmlContent); + } + + static int charCount(String htmlText) { + State state = State.TEXT; + int count = 0; + for (int i = 0; i < htmlText.length(); i++) { + char c = htmlText.charAt(i); + switch (state) { + case TEXT: + switch (c) { + case '<': + state = State.TAG; + break; + case '&': + state = State.ENTITY; + count++; + break; + default: + count++; + } + break; + + case ENTITY: + if (!Character.isLetterOrDigit(c)) + state = State.TEXT; + break; + + case TAG: + switch (c) { + case '"': + state = State.STRING; + break; + case '>': + state = State.TEXT; + break; + } + break; + + case STRING: + switch (c) { + case '"': + state = State.TAG; + break; + } + } + } + return count; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean write(Writer out, boolean atNewline) throws IOException { + out.write(rawHtmlContent); + return rawHtmlContent.endsWith(DocletConstants.NL); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java new file mode 100644 index 00000000000..6b7c7dde2ed --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; + +import java.io.IOException; +import java.io.Writer; + +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException; +import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; + +/** + * Class for generating string content for HTML tags of javadoc output. + * + *

          This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public class StringContent extends Content { + + private StringBuilder stringContent; + + /** + * Constructor to construct StringContent object. + */ + public StringContent() { + stringContent = new StringBuilder(); + } + + /** + * Constructor to construct StringContent object with some initial content. + * + * @param initialContent initial content for the object + */ + public StringContent(String initialContent) { + stringContent = new StringBuilder(); + appendChars(initialContent); + } + + /** + * This method is not supported by the class. + * + * @param content content that needs to be added + * @throws DocletAbortException this method will always throw a + * DocletAbortException because it + * is not supported. + */ + @Override + public void addContent(Content content) { + throw new DocletAbortException("not supported"); + } + + /** + * Adds content for the StringContent object. The method escapes + * HTML characters for the string content that is added. + * + * @param strContent string content to be added + */ + @Override + public void addContent(String strContent) { + appendChars(strContent); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isEmpty() { + return (stringContent.length() == 0); + } + + @Override + public int charCount() { + return RawHtml.charCount(stringContent.toString()); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return stringContent.toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean write(Writer out, boolean atNewline) throws IOException { + String s = stringContent.toString(); + out.write(s); + return s.endsWith(DocletConstants.NL); + } + + private void appendChars(String s) { + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + case '<': stringContent.append("<"); break; + case '>': stringContent.append(">"); break; + case '&': stringContent.append("&"); break; + default: stringContent.append(ch); break; + } + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/package-info.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/package-info.java new file mode 100644 index 00000000000..41069a3939c --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/package-info.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 package contains classes that write HTML markup tags. + +

          This is NOT part of any supported API. + If you write code that depends on this, you do so at your own risk. + This code and its internal interfaces are subject to change or + deletion without notice. + */ + +package jdk.javadoc.internal.doclets.formats.html.markup; diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/package-info.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/package-info.java new file mode 100644 index 00000000000..6219b40bdc2 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/package-info.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 is the default HTML doclet provided with the JDK. + * + *

          + * This is NOT part of any supported API. If you write code that depends on this, you do so at + * your own risk. This code and its internal interfaces are subject to change or deletion without + * notice. + */ +package jdk.javadoc.internal.doclets.formats.html; diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/glass.png b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/glass.png new file mode 100644 index 00000000000..a7f591f467a Binary files /dev/null and b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/glass.png differ diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/external/jquery/jquery.js b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/external/jquery/jquery.js new file mode 100644 index 00000000000..c5c648255c1 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/external/jquery/jquery.js @@ -0,0 +1,9789 @@ +/*! + * jQuery JavaScript Library v1.10.2 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03T13:48Z + */ +(function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.2", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.10.2 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent.attachEvent && parent !== parent.top ) { + parent.attachEvent( "onbeforeunload", function() { + setDocument(); + }); + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "

          "; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; + } + }); +} + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
          a"; + + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; + a = div.getElementsByTagName("a")[ 0 ]; + if ( !a || !a.style || !all.length ) { + return support; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
          t
          "; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior. + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
          "; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})({}); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + data = null, + i = 0, + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + return tabindex ? + parseInt( tabindex, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = { + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }; + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = ret.push( cur ); + break; + } + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
          ", "
          " ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
          " ], + tr: [ 2, "", "
          " ], + col: [ 2, "", "
          " ], + td: [ 3, "", "
          " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
          ", "
          " ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
          " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each(function() { + if ( isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("\n" + + ""); + } + + void html5NegatedOutput() { + // Negated test for overview-frame page + checkOutput("overview-frame.html", false, + "", + "\n" + + "
            \n" + + "
          • All Classes
          • ", + "
            \n" + + "

            Packages

            "); + + // Negated test for allclasses-frame page + checkOutput("allclasses-frame.html", false, + "", + "\n" + + "
              \n" + + "
            • "); + + // Negated test for allclasses-noframe page + checkOutput("allclasses-noframe.html", false, + "", + "\n" + + "
                \n" + + "
              • "); + + // Negated test for overview-summary page + checkOutput("overview-summary.html", false, + "", + "\n" + + "\n" + + "", + "
          \n" + + "
          ", + "\n" + + "
          \n" + + ""); + + // Negated test for package-frame page + checkOutput("pkg/package-frame.html", false, + "", + "\n" + + "

          pkg

          "); + + // Negated test for package-summary page + checkOutput("pkg/package-summary.html", false, + "", + "\n" + + "\n" + + "", + "", + "
          ", + "
          ", + "
          ", + "
          ", + "
          "); + + // Negated test for package-tree page + checkOutput("pkg/package-tree.html", false, + "", + "\n" + + "\n" + + ""); + + // Negated test for package-use page + checkOutput("pkg1/package-use.html", false, + "", + "\n" + + "\n" + + "", + "
          "); + + // Negated test for constant-values page + checkOutput("constant-values.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "
          ", + "
          "); + + // Negated test for deprecated-list page + checkOutput("deprecated-list.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "
          \n" + + "

          Deprecated API

          \n" + + "

          Contents

          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          "); + + // Negated test for serialized-form page + checkOutput("serialized-form.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "
          ", + "
        • \n" + + "

          Package pkg

          "); + + // Negated test for overview-tree page + checkOutput("overview-tree.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "
        • \n" + + "
          ", + "
          \n" + + "

          Class Hierarchy

          ", + "\n" + + "

          Interface Hierarchy

          ", + "\n" + + "

          Enum Hierarchy

          "); + + // Negated test for index-all page + checkOutput("index-all.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "
          \n" + + "
          "); + + // Negated test for src-html page + checkOutput("src-html/pkg/AnotherClass.html", false, + "", + "\n" + + "
          "); + + // Negated test for help-doc page + checkOutput("help-doc.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "
          \n" + + "
          ", + "
            \n" + + "
          • \n" + + "

            Overview

            ", + "
          • \n" + + "

            Package

            ", + "
          • \n" + + "

            Class/Interface

            "); + + // Negated test for a regular class page and members (nested class, field, constructore and method) + checkOutput("pkg/AnotherClass.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "
            ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
            \n" + + "
          • \n" + + "\n" + + "\n" + + "

            Field Detail

            ", + "\n" + + "
              \n" + + "
            • \n" + + "\n" + + "\n" + + "

              Constructor Detail

              ", + "\n" + + "
                \n" + + "
              • \n" + + "\n" + + "\n" + + "

                Method Detail

                "); + + // Negated test for enum page + checkOutput("pkg/AnotherClass.ModalExclusionType.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "
                ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
            \n" + + "
          • \n" + + "\n" + + "\n" + + "

            Enum Constant Detail

            ", + "\n" + + "
              \n" + + "
            • \n" + + "\n" + + "\n" + + "

              Method Detail

              "); + + // Negated test for interface page + checkOutput("pkg2/Interface.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "
              ", + "\n" + + "
          ", + "\n" + + "
            \n" + + "
          • \n" + + "\n" + + "\n" + + "

            Method Detail

            "); + + // Negated test for error page + checkOutput("pkg/TestError.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "
            ", + "\n" + + "
              \n" + + "
            • \n" + + "\n" + + "\n" + + "

              Constructor Summary

              ", + "\n" + + "
                \n" + + "
              • \n" + + "\n" + + "\n" + + "

                Constructor Detail

                "); + + // Negated test for exception page + checkOutput("pkg/TestException.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "
                ", + "\n" + + "
                  \n" + + "
                • \n" + + "\n" + + "\n" + + "

                  Constructor Summary

                  ", + "\n" + + "
                    \n" + + "
                  • \n" + + "\n" + + "\n" + + "

                    Constructor Detail

                    "); + + // Negated test for annotation page + checkOutput("pkg2/TestAnnotationType.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "
                    ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
            \n" + + "
          • \n" + + "\n" + + "\n" + + "

            Element Detail

            "); + + // Negated test for class use page + checkOutput("pkg1/class-use/RegClass.html", false, + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "
            ", + "
          ", + "
        • \n" + + "\n" + + "\n" + + "

          Uses of RegClass in pkg

          \n" + + "
        • "); + + // Negated test for main index page + checkOutput("index.html", false, + "", + "\n" + + "
          \n"); + } + + void html4Output() { + // Test for overview-frame page + checkOutput("overview-frame.html", true, + "", + "\n" + + "
            \n" + + "
          • All Classes
          • ", + "
            \n" + + "

            Packages

            "); + + // Test for allclasses-frame page + checkOutput("allclasses-frame.html", true, + "", + "\n" + + "
              \n" + + "
            • "); + + // Test for allclasses-noframe page + checkOutput("allclasses-noframe.html", true, + "", + "\n" + + "
                \n" + + "
              • "); + + // Test for overview-summary page + checkOutput("overview-summary.html", true, + "", + "\n" + + "\n" + + "", + "
          \n" + + "
          ", + "\n" + + "
          \n" + + ""); + + // Test for package-frame page + checkOutput("pkg/package-frame.html", true, + "", + "\n" + + "

          pkg

          "); + + // Test for package-summary page + checkOutput("pkg/package-summary.html", true, + "", + "\n" + + "\n" + + "", + "", + "
          ", + "
          ", + "
          ", + "
          ", + "
          "); + + // Test for package-tree page + checkOutput("pkg/package-tree.html", true, + "", + "\n" + + "\n" + + "", + "
        • "); + + // Test for package-use page + checkOutput("pkg1/package-use.html", true, + "", + "\n" + + "\n" + + "", + "
        • "); + + // Test for constant-values page + checkOutput("constant-values.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "
          ", + "
          "); + + // Test for deprecated-list page + checkOutput("deprecated-list.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "
          \n" + + "

          Deprecated API

          \n" + + "

          Contents

          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          ", + "
          "); + + // Test for serialized-form page + checkOutput("serialized-form.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "
          ", + "
        • \n" + + "

          Package pkg

          "); + + // Test for overview-tree page + checkOutput("overview-tree.html", true, + "", + "\n" + + "\n" + + "", + "
        • ", + "\n" + + "
        • \n" + + "
          ", + "

          Hierarchy For All Packages

          \n" + + "Package Hierarchies:", + "
          \n" + + "

          Class Hierarchy

          ", + "\n" + + "

          Interface Hierarchy

          ", + "\n" + + "

          Enum Hierarchy

          "); + + // Test for index-all page + checkOutput("index-all.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "
          \n" + + "
          "); + + // Test for src-html page + checkOutput("src-html/pkg/AnotherClass.html", true, + "", + "\n" + + "
          "); + + // Test for help-doc page + checkOutput("help-doc.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "
          \n" + + "
          ", + "
            \n" + + "
          • \n" + + "

            Overview

            ", + "
          • \n" + + "

            Package

            ", + "
          • \n" + + "

            Class/Interface

            "); + + // Test for a regular class page and members (nested class, field, constructore and method) + checkOutput("pkg/AnotherClass.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "
            ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
            \n" + + "
          • \n" + + "\n" + + "\n" + + "

            Field Detail

            ", + "\n" + + "
              \n" + + "
            • \n" + + "\n" + + "\n" + + "

              Constructor Detail

              ", + "\n" + + "
                \n" + + "
              • \n" + + "\n" + + "\n" + + "

                Method Detail

                "); + + // Test for enum page + checkOutput("pkg/AnotherClass.ModalExclusionType.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "
                ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
            \n" + + "
          • \n" + + "\n" + + "\n" + + "

            Enum Constant Detail

            ", + "\n" + + "
              \n" + + "
            • \n" + + "\n" + + "\n" + + "

              Method Detail

              "); + + // Test for interface page + checkOutput("pkg2/Interface.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "
              ", + "\n" + + "
          ", + "\n" + + "
            \n" + + "
          • \n" + + "\n" + + "\n" + + "

            Method Detail

            "); + + // Test for error page + checkOutput("pkg/TestError.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "
            ", + "\n" + + "
              \n" + + "
            • \n" + + "\n" + + "\n" + + "

              Constructor Summary

              ", + "\n" + + "
                \n" + + "
              • \n" + + "\n" + + "\n" + + "

                Constructor Detail

                "); + + // Test for exception page + checkOutput("pkg/TestException.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "
                ", + "\n" + + "
                  \n" + + "
                • \n" + + "\n" + + "\n" + + "

                  Constructor Summary

                  ", + "\n" + + "
                    \n" + + "
                  • \n" + + "\n" + + "\n" + + "

                    Constructor Detail

                    "); + + // Test for annotation page + checkOutput("pkg2/TestAnnotationType.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "
                    ", + "\n" + + "
          ", + "\n" + + "
          ", + "\n" + + "
            \n" + + "
          • \n" + + "\n" + + "\n" + + "

            Element Detail

            "); + + // Test for class use page + checkOutput("pkg1/class-use/RegClass.html", true, + "", + "\n" + + "\n" + + "", + "\n" + + "\n" + + "
            ", + "
          ", + "
        • \n" + + "\n" + + "\n" + + "

          Uses of RegClass in pkg

          \n" + + "
        • "); + + // Test for main index page + checkOutput("index.html", true, + "", + "", + "\n" + + "
          \n" + + "
          \n" + + "
          \n" + + "\n" + + "
          "); + } + + void html4NegatedOutput() { + // Negated test for overview-frame page + checkOutput("overview-frame.html", false, + "", + "\n" + + "
            \n" + + "
          • All Classes
          • ", + "
            \n" + + "

            Packages

            "); + + // Negated test for allclasses-frame page + checkOutput("allclasses-frame.html", false, + "", + "\n" + + "
              \n" + + "
            • "); + + // Negated test for allclasses-noframe page + checkOutput("allclasses-noframe.html", false, + "", + "\n" + + "
                \n" + + "
              • "); + + // Negated test for overview-summary page + checkOutput("overview-summary.html", false, + "", + "\n" + + "\n" + + "", + "
          \n" + + "
          ", + "
          \n" + + "