# HG changeset patch # User chegar # Date 1512469725 0 # Node ID 64298b1e890babfc848e074afaa98c0b553c1df5 # Parent 10b34c929b4f9c3913284e4ba5e6f8e1d6e548ef# Parent f14a1972f35de5a721c1bd6eb789c462d4f4b60a http-client-branch: merge with default diff -r 10b34c929b4f -r 64298b1e890b .hgtags --- a/.hgtags Tue Dec 05 10:21:41 2017 +0000 +++ b/.hgtags Tue Dec 05 10:28:45 2017 +0000 @@ -458,3 +458,4 @@ e6278add9ff28fab70fe1cc4c1d65f7363dc9445 jdk-10+31 a2008587c13fa05fa2dbfcb09fe987576fbedfd1 jdk-10+32 bbd692ad4fa300ecca7939ffbe3b1d5e52a28cc6 jdk-10+33 +89deac44e51517841491ba86ff44aa82a5ca96b3 jdk-10+34 diff -r 10b34c929b4f -r 64298b1e890b doc/testing.html --- a/doc/testing.html Tue Dec 05 10:21:41 2017 +0000 +++ b/doc/testing.html Tue Dec 05 10:28:45 2017 +0000 @@ -57,6 +57,7 @@

Gtest

Since the Hotspot Gtest suite is so quick, the default is to run all tests. This is specified by just gtest, or as a fully qualified test descriptor gtest:all.

If you want, you can single out an individual test or a group of tests, for instance gtest:LogDecorations or gtest:LogDecorations.level_test_vm. This can be particularly useful if you want to run a shaky test repeatedly.

+

For Gtest, there is a separate test suite for each JVM variant. The JVM variant is defined by adding /<variant> to the test descriptor, e.g. gtest:Log/client. If you specify no variant, gtest will run once for each JVM variant present (e.g. server, client). So if you only have the server JVM present, then gtest:all will be equivalent to gtest:all/server.

Test results and summary

At the end of the test run, a summary of all tests run will be presented. This will have a consistent look, regardless of what test suites were used. This is a sample summary:

==============================
diff -r 10b34c929b4f -r 64298b1e890b doc/testing.md
--- a/doc/testing.md	Tue Dec 05 10:21:41 2017 +0000
+++ b/doc/testing.md	Tue Dec 05 10:28:45 2017 +0000
@@ -81,6 +81,12 @@
 instance `gtest:LogDecorations` or `gtest:LogDecorations.level_test_vm`. This
 can be particularly useful if you want to run a shaky test repeatedly.
 
+For Gtest, there is a separate test suite for each JVM variant. The JVM variant
+is defined by adding `/` to the test descriptor, e.g.
+`gtest:Log/client`. If you specify no variant, gtest will run once for each JVM
+variant present (e.g. server, client). So if you only have the server JVM
+present, then `gtest:all` will be equivalent to `gtest:all/server`.
+
 ## Test results and summary
 
 At the end of the test run, a summary of all tests run will be presented. This
diff -r 10b34c929b4f -r 64298b1e890b make/CompileJavaModules.gmk
--- a/make/CompileJavaModules.gmk	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/CompileJavaModules.gmk	Tue Dec 05 10:28:45 2017 +0000
@@ -300,7 +300,9 @@
 
 ################################################################################
 
-java.xml_SETUP := GENERATE_JDKBYTECODE_NOWARNINGS
+java.xml_ADD_JAVAC_FLAGS += -Xdoclint:all/protected \
+    '-Xdoclint/package:$(call CommaList, javax.xml.catalog javax.xml.datatype \
+    javax.xml.transform javax.xml.validation javax.xml.xpath)'
 java.xml_CLEAN += .properties
 
 ################################################################################
diff -r 10b34c929b4f -r 64298b1e890b make/InitSupport.gmk
--- a/make/InitSupport.gmk	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/InitSupport.gmk	Tue Dec 05 10:28:45 2017 +0000
@@ -279,7 +279,9 @@
           # generated files.
           ifeq ($$(MAKE_RESTARTS),)
             ifeq ($$(words $$(matching_confs)), 1)
-              $$(info Building configuration '$$(matching_confs)' (matching CONF=$$(CONF)))
+              ifneq ($$(findstring $$(LOG_LEVEL), info debug trace),)
+                $$(info Building configuration '$$(matching_confs)' (matching CONF=$$(CONF)))
+              endif
             else
               $$(info Building these configurations (matching CONF=$$(CONF)):)
               $$(foreach var, $$(matching_confs), $$(info * $$(var)))
diff -r 10b34c929b4f -r 64298b1e890b make/RunTests.gmk
--- a/make/RunTests.gmk	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/RunTests.gmk	Tue Dec 05 10:28:45 2017 +0000
@@ -68,6 +68,7 @@
 TEST_RESULTS_DIR := $(OUTPUTDIR)/test-results
 TEST_SUPPORT_DIR := $(OUTPUTDIR)/test-support
 TEST_SUMMARY := $(TEST_RESULTS_DIR)/test-summary.txt
+TEST_LAST_IDS := $(TEST_SUPPORT_DIR)/test-last-ids.txt
 
 ifeq ($(CUSTOM_ROOT), )
   JTREG_TOPDIR := $(TOPDIR)
@@ -87,6 +88,9 @@
       -timeoutHandlerTimeout:0
 endif
 
+GTEST_LAUNCHER_DIRS := $(patsubst %/gtestLauncher, %, $(wildcard $(TEST_IMAGE_DIR)/hotspot/gtest/*/gtestLauncher))
+GTEST_VARIANTS := $(strip $(patsubst $(TEST_IMAGE_DIR)/hotspot/gtest/%, %, $(GTEST_LAUNCHER_DIRS)))
+
 ################################################################################
 # Parse control variables
 ################################################################################
@@ -165,16 +169,23 @@
 # Helper function to determine if a test specification is a Gtest test
 #
 # It is a Gtest test if it is either "gtest", or "gtest:" followed by an optional
-# test filter string.
+# test filter string, and an optional "/" to select a specific JVM
+# variant. If no variant is specified, all found variants are tested.
 define ParseGtestTestSelection
   $(if $(filter gtest%, $1), \
     $(if $(filter gtest, $1), \
-      gtest:all \
+      $(addprefix gtest:all/, $(GTEST_VARIANTS)) \
     , \
-      $(if $(filter gtest:, $1), \
-        gtest:all \
+      $(if $(strip $(or $(filter gtest/%, $1) $(filter gtest:/%, $1))), \
+        $(patsubst gtest:/%, gtest:all/%, $(patsubst gtest/%, gtest:/%, $1)) \
       , \
-        $1 \
+        $(if $(filter gtest:%, $1), \
+          $(if $(findstring /, $1), \
+            $1 \
+          , \
+            $(addprefix $1/, $(GTEST_VARIANTS)) \
+          ) \
+        ) \
       ) \
     ) \
   )
@@ -228,7 +239,8 @@
   $(if $(findstring :, $(TEST_NAME)), \
     $(if $(filter :%, $(TEST_NAME)), \
       $(eval TEST_GROUP := $(patsubst :%, %, $(TEST_NAME))) \
-      $(eval TEST_ROOTS := $(JTREG_TESTROOTS)) \
+      $(eval TEST_ROOTS := $(foreach test_root, $(JTREG_TESTROOTS), \
+          $(call CleanupJtregPath, $(test_root)))) \
     , \
       $(eval TEST_PATH := $(word 1, $(subst :, $(SPACE), $(TEST_NAME)))) \
       $(eval TEST_GROUP := $(word 2, $(subst :, $(SPACE), $(TEST_NAME)))) \
@@ -251,6 +263,15 @@
   )
 endef
 
+# Helper function to determine if a test specification is a special test
+#
+# It is a special test if it is "special:" followed by a test name.
+define ParseSpecialTestSelection
+  $(if $(filter special:%, $1), \
+    $1 \
+  )
+endef
+
 ifeq ($(TEST), )
   $(info No test selection given in TEST!)
   $(info Please use e.g. 'run-test TEST=tier1' or 'run-test-tier1')
@@ -270,6 +291,9 @@
     $(eval PARSED_TESTS += $(call ParseJtregTestSelection, $(test))) \
   ) \
   $(if $(strip $(PARSED_TESTS)), , \
+    $(eval PARSED_TESTS += $(call ParseSpecialTestSelection, $(test))) \
+  ) \
+  $(if $(strip $(PARSED_TESTS)), , \
     $(eval UNKNOWN_TEST := $(test)) \
   ) \
   $(eval TESTS_TO_RUN += $(PARSED_TESTS)) \
@@ -316,8 +340,14 @@
 define SetupRunGtestTestBody
   $1_TEST_RESULTS_DIR := $$(TEST_RESULTS_DIR)/$1
   $1_TEST_SUPPORT_DIR := $$(TEST_SUPPORT_DIR)/$1
+  $1_EXITCODE := $$($1_TEST_RESULTS_DIR)/exitcode.txt
 
-  $1_TEST_NAME := $$(strip $$(patsubst gtest:%, %, $$($1_TEST)))
+  $1_VARIANT :=  $$(lastword $$(subst /, , $$($1_TEST)))
+  ifeq ($$(filter $$($1_VARIANT), $$(GTEST_VARIANTS)), )
+    $$(error Invalid gtest variant '$$($1_VARIANT)'. Valid variants: $$(GTEST_VARIANTS))
+  endif
+  $1_TEST_NAME := $$(strip $$(patsubst %/$$($1_VARIANT), %, \
+      $$(patsubst gtest:%, %, $$($1_TEST))))
   ifneq ($$($1_TEST_NAME), all)
     $1_GTEST_FILTER := --gtest_filter=$$($1_TEST_NAME)*
   endif
@@ -331,11 +361,14 @@
 	$$(call LogWarn, Running test '$$($1_TEST)')
 	$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
 	$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/gtest, \
-	    $$(FIXPATH) $$(TEST_IMAGE_DIR)/hotspot/gtest/server/gtestLauncher \
-	    -jdk $(JDK_IMAGE_DIR) $$($1_GTEST_FILTER) \
-	    --gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \
-	    $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \
-	    > >($(TEE) $$($1_TEST_RESULTS_DIR)/gtest.txt) || true )
+	    $$(FIXPATH) $$(TEST_IMAGE_DIR)/hotspot/gtest/$$($1_VARIANT)/gtestLauncher \
+	         -jdk $(JDK_IMAGE_DIR) $$($1_GTEST_FILTER) \
+	         --gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \
+	         $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \
+	        > >($(TEE) $$($1_TEST_RESULTS_DIR)/gtest.txt) \
+	    && $$(ECHO) $$$$? > $$($1_EXITCODE) \
+	    || $$(ECHO) $$$$? > $$($1_EXITCODE) \
+	)
 
   $1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/gtest.txt
 
@@ -343,7 +376,7 @@
 	$$(call LogWarn, Finished running test '$$($1_TEST)')
 	$$(call LogWarn, Test report is stored in $$(strip \
 	    $$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR))))
-	$$(if  $$(wildcard $$($1_RESULT_FILE)), \
+	$$(if $$(wildcard $$($1_RESULT_FILE)), \
 	  $$(eval $1_TOTAL := $$(shell $$(AWK) '/==========.* tests? from .* \
 	      test cases? ran/ { print $$$$2 }' $$($1_RESULT_FILE))) \
 	  $$(if $$($1_TOTAL), , $$(eval $1_TOTAL := 0)) \
@@ -398,6 +431,7 @@
 define SetupRunJtregTestBody
   $1_TEST_RESULTS_DIR := $$(TEST_RESULTS_DIR)/$1
   $1_TEST_SUPPORT_DIR := $$(TEST_SUPPORT_DIR)/$1
+  $1_EXITCODE := $$($1_TEST_RESULTS_DIR)/exitcode.txt
 
   $1_TEST_NAME := $$(strip $$(patsubst jtreg:%, %, $$($1_TEST)))
 
@@ -505,7 +539,10 @@
 	        -workDir:$$($1_TEST_SUPPORT_DIR) \
 	        $$(JTREG_OPTIONS) \
 	        $$(JTREG_FAILURE_HANDLER_OPTIONS) \
-	        $$($1_TEST_NAME) || true )
+	        $$($1_TEST_NAME) \
+	    && $$(ECHO) $$$$? > $$($1_EXITCODE) \
+	    || $$(ECHO) $$$$? > $$($1_EXITCODE) \
+	)
 
   $1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/text/stats.txt
 
@@ -513,7 +550,7 @@
 	$$(call LogWarn, Finished running test '$$($1_TEST)')
 	$$(call LogWarn, Test report is stored in $$(strip \
 	    $$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR))))
-	$$(if  $$(wildcard $$($1_RESULT_FILE)), \
+	$$(if $$(wildcard $$($1_RESULT_FILE)), \
 	  $$(eval $1_PASSED := $$(shell $$(AWK) '{ gsub(/[,;]/, ""); \
 	      for (i=1; i<=NF; i++) { if ($$$$i == "passed:") \
 	      print $$$$(i+1) } }' $$($1_RESULT_FILE))) \
@@ -540,6 +577,69 @@
   TARGETS += $1
 endef
 
+################################################################################
+
+### Rules for special tests
+
+SetupRunSpecialTest = $(NamedParamsMacroTemplate)
+define SetupRunSpecialTestBody
+  $1_TEST_RESULTS_DIR := $$(TEST_RESULTS_DIR)/$1
+  $1_TEST_SUPPORT_DIR := $$(TEST_SUPPORT_DIR)/$1
+  $1_EXITCODE := $$($1_TEST_RESULTS_DIR)/exitcode.txt
+
+  $1_FULL_TEST_NAME := $$(strip $$(patsubst special:%, %, $$($1_TEST)))
+  ifneq ($$(findstring :, $$($1_FULL_TEST_NAME)), )
+    $1_TEST_NAME := $$(firstword $$(subst :, ,$$($1_FULL_TEST_NAME)))
+    $1_TEST_ARGS := $$(strip $$(patsubst special:$$($1_TEST_NAME):%, %, $$($1_TEST)))
+  else
+    $1_TEST_NAME := $$($1_FULL_TEST_NAME)
+    $1_TEST_ARGS :=
+  endif
+
+  ifeq ($$($1_TEST_NAME), hotspot-internal)
+    $1_TEST_COMMAND_LINE := \
+        $$(JDK_IMAGE_DIR)/bin/java -XX:+ExecuteInternalVMTests \
+        -XX:+ShowMessageBoxOnError -version
+  else ifeq ($$($1_TEST_NAME), failure-handler)
+    $1_TEST_COMMAND_LINE := \
+        ($(CD) $(TOPDIR)/make/test && $(MAKE) $(MAKE_ARGS) -f \
+        BuildFailureHandler.gmk test)
+  else ifeq ($$($1_TEST_NAME), make)
+    $1_TEST_COMMAND_LINE := \
+        ($(CD) $(TOPDIR)/test/make && $(MAKE) $(MAKE_ARGS) -f \
+        TestMake.gmk $$($1_TEST_ARGS))
+  else
+    $$(error Invalid special test specification: $$($1_TEST_NAME))
+  endif
+
+  run-test-$1:
+	$$(call LogWarn)
+	$$(call LogWarn, Running test '$$($1_TEST)')
+	$$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR))
+	$$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/test-execution, \
+	    $$($1_TEST_COMMAND_LINE) \
+	        > >($(TEE) $$($1_TEST_RESULTS_DIR)/test-output.txt) \
+	    && $$(ECHO) $$$$? > $$($1_EXITCODE) \
+	    || $$(ECHO) $$$$? > $$($1_EXITCODE) \
+	)
+
+  $1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/gtest.txt
+
+  # We can not parse the various "special" tests.
+  parse-test-$1: run-test-$1
+	$$(call LogWarn, Finished running test '$$($1_TEST)')
+	$$(call LogWarn, Test report is stored in $$(strip \
+	    $$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR))))
+	$$(call LogWarn, Warning: Special test results are not properly parsed!)
+	$$(eval $1_PASSED := 0)
+	$$(eval $1_FAILED := 0)
+	$$(eval $1_ERROR := 0)
+	$$(eval $1_TOTAL := 0)
+
+  $1: run-test-$1 parse-test-$1
+
+  TARGETS += $1
+endef
 
 ################################################################################
 # Setup and execute make rules for all selected tests
@@ -552,10 +652,13 @@
 UseJtregTestHandler = \
   $(if $(filter jtreg:%, $1), true)
 
+UseSpecialTestHandler = \
+  $(if $(filter special:%, $1), true)
+
 # Now process each test to run and setup a proper make rule
 $(foreach test, $(TESTS_TO_RUN), \
   $(eval TEST_ID := $(shell $(ECHO) $(strip $(test)) | \
-      $(TR) -cs '[a-z][A-Z][0-9]\n' '_')) \
+      $(TR) -cs '[a-z][A-Z][0-9]\n' '[_*1000]')) \
   $(eval ALL_TEST_IDS += $(TEST_ID)) \
   $(if $(call UseCustomTestHandler, $(test)), \
     $(eval $(call SetupRunCustomTest, $(TEST_ID), \
@@ -572,6 +675,11 @@
         TEST := $(test), \
     )) \
   ) \
+  $(if $(call UseSpecialTestHandler, $(test)), \
+    $(eval $(call SetupRunSpecialTest, $(TEST_ID), \
+        TEST := $(test), \
+    )) \
+  ) \
 )
 
 # Sort also removes duplicates, so if there is any we'll get fewer words.
@@ -592,6 +700,8 @@
         # Create and print a table of the result of all tests run
 	$(RM) $(TEST_SUMMARY).old 2> /dev/null
 	$(MV) $(TEST_SUMMARY) $(TEST_SUMMARY).old 2> /dev/null || true
+	$(RM) $(TEST_LAST_IDS).old 2> /dev/null
+	$(MV) $(TEST_LAST_IDS) $(TEST_LAST_IDS).old 2> /dev/null || true
 	$(ECHO) >> $(TEST_SUMMARY) ==============================
 	$(ECHO) >> $(TEST_SUMMARY) Test summary
 	$(ECHO) >> $(TEST_SUMMARY) ==============================
@@ -599,8 +709,9 @@
 	    TEST TOTAL PASS FAIL ERROR " "
 	$(foreach test, $(TESTS_TO_RUN), \
 	  $(eval TEST_ID := $(shell $(ECHO) $(strip $(test)) | \
-	      $(TR) -cs '[a-z][A-Z][0-9]\n' '_')) \
-	  $(eval NAME_PATTERN := $(shell $(ECHO) $(test) | $(TR) -c \\n _)) \
+	      $(TR) -cs '[a-z][A-Z][0-9]\n' '[_*1000]')) \
+	    $(ECHO) >> $(TEST_LAST_IDS) $(TEST_ID) $(NEWLINE) \
+	  $(eval NAME_PATTERN := $(shell $(ECHO) $(test) | $(TR) -c '\n' '[_*1000]')) \
 	  $(if $(filter __________________________________________________%, $(NAME_PATTERN)), \
 	    $(eval TEST_NAME := ) \
 	    $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s\n" "  " "$(test)"  $(NEWLINE) \
diff -r 10b34c929b4f -r 64298b1e890b make/autoconf/basics.m4
--- a/make/autoconf/basics.m4	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/autoconf/basics.m4	Tue Dec 05 10:28:45 2017 +0000
@@ -1092,10 +1092,6 @@
     # We can build without it.
     LDD="true"
   fi
-  BASIC_PATH_PROGS(OTOOL, otool)
-  if test "x$OTOOL" = "x"; then
-    OTOOL="true"
-  fi
   BASIC_PATH_PROGS(READELF, [greadelf readelf])
   BASIC_PATH_PROGS(DOT, dot)
   BASIC_PATH_PROGS(HG, hg)
diff -r 10b34c929b4f -r 64298b1e890b make/autoconf/generated-configure.sh
--- a/make/autoconf/generated-configure.sh	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/autoconf/generated-configure.sh	Tue Dec 05 10:28:45 2017 +0000
@@ -818,6 +818,8 @@
 DUMPBIN
 RC
 MT
+INSTALL_NAME_TOOL
+OTOOL
 LIPO
 ac_ct_AR
 AR
@@ -932,7 +934,6 @@
 HG
 DOT
 READELF
-OTOOL
 LDD
 ZIPEXE
 UNZIP
@@ -1277,7 +1278,6 @@
 UNZIP
 ZIPEXE
 LDD
-OTOOL
 READELF
 DOT
 HG
@@ -1310,6 +1310,8 @@
 AS
 AR
 LIPO
+OTOOL
+INSTALL_NAME_TOOL
 STRIP
 NM
 GNM
@@ -2226,7 +2228,6 @@
   UNZIP       Override default value for UNZIP
   ZIPEXE      Override default value for ZIPEXE
   LDD         Override default value for LDD
-  OTOOL       Override default value for OTOOL
   READELF     Override default value for READELF
   DOT         Override default value for DOT
   HG          Override default value for HG
@@ -2260,6 +2261,9 @@
   AS          Override default value for AS
   AR          Override default value for AR
   LIPO        Override default value for LIPO
+  OTOOL       Override default value for OTOOL
+  INSTALL_NAME_TOOL
+              Override default value for INSTALL_NAME_TOOL
   STRIP       Override default value for STRIP
   NM          Override default value for NM
   GNM         Override default value for GNM
@@ -5155,7 +5159,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1511359342
+DATE_WHEN_GENERATED=1512410983
 
 ###############################################################################
 #
@@ -22126,206 +22130,6 @@
   # Publish this variable in the help.
 
 
-  if [ -z "${OTOOL+x}" ]; then
-    # The variable is not set by user, try to locate tool using the code snippet
-    for ac_prog in otool
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_OTOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $OTOOL in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_OTOOL="$OTOOL" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_OTOOL="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-OTOOL=$ac_cv_path_OTOOL
-if test -n "$OTOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
-$as_echo "$OTOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$OTOOL" && break
-done
-
-  else
-    # The variable is set, but is it from the command line or the environment?
-
-    # Try to remove the string !OTOOL! from our list.
-    try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!OTOOL!/}
-    if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then
-      # If it failed, the variable was not from the command line. Ignore it,
-      # but warn the user (except for BASH, which is always set by the calling BASH).
-      if test "xOTOOL" != xBASH; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of OTOOL from the environment. Use command line variables instead." >&5
-$as_echo "$as_me: WARNING: Ignoring value of OTOOL from the environment. Use command line variables instead." >&2;}
-      fi
-      # Try to locate tool using the code snippet
-      for ac_prog in otool
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_OTOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $OTOOL in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_OTOOL="$OTOOL" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_OTOOL="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-OTOOL=$ac_cv_path_OTOOL
-if test -n "$OTOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
-$as_echo "$OTOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$OTOOL" && break
-done
-
-    else
-      # If it succeeded, then it was overridden by the user. We will use it
-      # for the tool.
-
-      # First remove it from the list of overridden variables, so we can test
-      # for unknown variables in the end.
-      CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
-
-      # Check if we try to supply an empty value
-      if test "x$OTOOL" = x; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool OTOOL= (no value)" >&5
-$as_echo "$as_me: Setting user supplied tool OTOOL= (no value)" >&6;}
-        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OTOOL" >&5
-$as_echo_n "checking for OTOOL... " >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
-$as_echo "disabled" >&6; }
-      else
-        # Check if the provided tool contains a complete path.
-        tool_specified="$OTOOL"
-        tool_basename="${tool_specified##*/}"
-        if test "x$tool_basename" = "x$tool_specified"; then
-          # A command without a complete path is provided, search $PATH.
-          { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool OTOOL=$tool_basename" >&5
-$as_echo "$as_me: Will search for user supplied tool OTOOL=$tool_basename" >&6;}
-          # Extract the first word of "$tool_basename", so it can be a program name with args.
-set dummy $tool_basename; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_OTOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $OTOOL in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_OTOOL="$OTOOL" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_OTOOL="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-OTOOL=$ac_cv_path_OTOOL
-if test -n "$OTOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
-$as_echo "$OTOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-          if test "x$OTOOL" = x; then
-            as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5
-          fi
-        else
-          # Otherwise we believe it is a complete path. Use it as it is.
-          { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool OTOOL=$tool_specified" >&5
-$as_echo "$as_me: Will use user supplied tool OTOOL=$tool_specified" >&6;}
-          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OTOOL" >&5
-$as_echo_n "checking for OTOOL... " >&6; }
-          if test ! -x "$tool_specified"; then
-            { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
-            as_fn_error $? "User supplied tool OTOOL=$tool_specified does not exist or is not executable" "$LINENO" 5
-          fi
-          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5
-$as_echo "$tool_specified" >&6; }
-        fi
-      fi
-    fi
-
-  fi
-
-
-  if test "x$OTOOL" = "x"; then
-    OTOOL="true"
-  fi
-
-
-  # Publish this variable in the help.
-
-
   if [ -z "${READELF+x}" ]; then
     # The variable is not set by user, try to locate tool using the code snippet
     for ac_prog in greadelf readelf
@@ -39588,6 +39392,986 @@
     fi
   fi
 
+
+
+
+  # Publish this variable in the help.
+
+
+  if [ -z "${OTOOL+x}" ]; then
+    # The variable is not set by user, try to locate tool using the code snippet
+    for ac_prog in otool
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $OTOOL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_OTOOL="$OTOOL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_OTOOL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+OTOOL=$ac_cv_path_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$OTOOL" && break
+done
+
+  else
+    # The variable is set, but is it from the command line or the environment?
+
+    # Try to remove the string !OTOOL! from our list.
+    try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!OTOOL!/}
+    if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then
+      # If it failed, the variable was not from the command line. Ignore it,
+      # but warn the user (except for BASH, which is always set by the calling BASH).
+      if test "xOTOOL" != xBASH; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of OTOOL from the environment. Use command line variables instead." >&5
+$as_echo "$as_me: WARNING: Ignoring value of OTOOL from the environment. Use command line variables instead." >&2;}
+      fi
+      # Try to locate tool using the code snippet
+      for ac_prog in otool
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $OTOOL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_OTOOL="$OTOOL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_OTOOL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+OTOOL=$ac_cv_path_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$OTOOL" && break
+done
+
+    else
+      # If it succeeded, then it was overridden by the user. We will use it
+      # for the tool.
+
+      # First remove it from the list of overridden variables, so we can test
+      # for unknown variables in the end.
+      CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
+
+      # Check if we try to supply an empty value
+      if test "x$OTOOL" = x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool OTOOL= (no value)" >&5
+$as_echo "$as_me: Setting user supplied tool OTOOL= (no value)" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OTOOL" >&5
+$as_echo_n "checking for OTOOL... " >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+      else
+        # Check if the provided tool contains a complete path.
+        tool_specified="$OTOOL"
+        tool_basename="${tool_specified##*/}"
+        if test "x$tool_basename" = "x$tool_specified"; then
+          # A command without a complete path is provided, search $PATH.
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool OTOOL=$tool_basename" >&5
+$as_echo "$as_me: Will search for user supplied tool OTOOL=$tool_basename" >&6;}
+          # Extract the first word of "$tool_basename", so it can be a program name with args.
+set dummy $tool_basename; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $OTOOL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_OTOOL="$OTOOL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_OTOOL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+OTOOL=$ac_cv_path_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+          if test "x$OTOOL" = x; then
+            as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5
+          fi
+        else
+          # Otherwise we believe it is a complete path. Use it as it is.
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool OTOOL=$tool_specified" >&5
+$as_echo "$as_me: Will use user supplied tool OTOOL=$tool_specified" >&6;}
+          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OTOOL" >&5
+$as_echo_n "checking for OTOOL... " >&6; }
+          if test ! -x "$tool_specified"; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+            as_fn_error $? "User supplied tool OTOOL=$tool_specified does not exist or is not executable" "$LINENO" 5
+          fi
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5
+$as_echo "$tool_specified" >&6; }
+        fi
+      fi
+    fi
+
+  fi
+
+
+
+  if test "x$OTOOL" = x; then
+    as_fn_error $? "Could not find required tool for OTOOL" "$LINENO" 5
+  fi
+
+
+
+  # Only process if variable expands to non-empty
+
+  if test "x$OTOOL" != 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="$OTOOL"
+  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"`
+    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 OTOOL, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of OTOOL, 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 OTOOL" "$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 OTOOL, which resolves as \"$new_path\", is invalid." >&5
+$as_echo "$as_me: The path of OTOOL, 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 OTOOL" "$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="$OTOOL"
+  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 OTOOL, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of OTOOL, 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 OTOOL" "$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="$OTOOL"
+      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 OTOOL, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of OTOOL, 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 OTOOL" "$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
+      OTOOL="$new_complete"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OTOOL to \"$new_complete\"" >&5
+$as_echo "$as_me: Rewriting OTOOL to \"$new_complete\"" >&6;}
+    fi
+  fi
+
+
+
+
+  # Publish this variable in the help.
+
+
+  if [ -z "${INSTALL_NAME_TOOL+x}" ]; then
+    # The variable is not set by user, try to locate tool using the code snippet
+    for ac_prog in install_name_tool
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_INSTALL_NAME_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $INSTALL_NAME_TOOL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_INSTALL_NAME_TOOL="$INSTALL_NAME_TOOL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_INSTALL_NAME_TOOL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+INSTALL_NAME_TOOL=$ac_cv_path_INSTALL_NAME_TOOL
+if test -n "$INSTALL_NAME_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL_NAME_TOOL" >&5
+$as_echo "$INSTALL_NAME_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$INSTALL_NAME_TOOL" && break
+done
+
+  else
+    # The variable is set, but is it from the command line or the environment?
+
+    # Try to remove the string !INSTALL_NAME_TOOL! from our list.
+    try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!INSTALL_NAME_TOOL!/}
+    if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then
+      # If it failed, the variable was not from the command line. Ignore it,
+      # but warn the user (except for BASH, which is always set by the calling BASH).
+      if test "xINSTALL_NAME_TOOL" != xBASH; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of INSTALL_NAME_TOOL from the environment. Use command line variables instead." >&5
+$as_echo "$as_me: WARNING: Ignoring value of INSTALL_NAME_TOOL from the environment. Use command line variables instead." >&2;}
+      fi
+      # Try to locate tool using the code snippet
+      for ac_prog in install_name_tool
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_INSTALL_NAME_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $INSTALL_NAME_TOOL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_INSTALL_NAME_TOOL="$INSTALL_NAME_TOOL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_INSTALL_NAME_TOOL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+INSTALL_NAME_TOOL=$ac_cv_path_INSTALL_NAME_TOOL
+if test -n "$INSTALL_NAME_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL_NAME_TOOL" >&5
+$as_echo "$INSTALL_NAME_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$INSTALL_NAME_TOOL" && break
+done
+
+    else
+      # If it succeeded, then it was overridden by the user. We will use it
+      # for the tool.
+
+      # First remove it from the list of overridden variables, so we can test
+      # for unknown variables in the end.
+      CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
+
+      # Check if we try to supply an empty value
+      if test "x$INSTALL_NAME_TOOL" = x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool INSTALL_NAME_TOOL= (no value)" >&5
+$as_echo "$as_me: Setting user supplied tool INSTALL_NAME_TOOL= (no value)" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for INSTALL_NAME_TOOL" >&5
+$as_echo_n "checking for INSTALL_NAME_TOOL... " >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+      else
+        # Check if the provided tool contains a complete path.
+        tool_specified="$INSTALL_NAME_TOOL"
+        tool_basename="${tool_specified##*/}"
+        if test "x$tool_basename" = "x$tool_specified"; then
+          # A command without a complete path is provided, search $PATH.
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool INSTALL_NAME_TOOL=$tool_basename" >&5
+$as_echo "$as_me: Will search for user supplied tool INSTALL_NAME_TOOL=$tool_basename" >&6;}
+          # Extract the first word of "$tool_basename", so it can be a program name with args.
+set dummy $tool_basename; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_INSTALL_NAME_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $INSTALL_NAME_TOOL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_INSTALL_NAME_TOOL="$INSTALL_NAME_TOOL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_INSTALL_NAME_TOOL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+INSTALL_NAME_TOOL=$ac_cv_path_INSTALL_NAME_TOOL
+if test -n "$INSTALL_NAME_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL_NAME_TOOL" >&5
+$as_echo "$INSTALL_NAME_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+          if test "x$INSTALL_NAME_TOOL" = x; then
+            as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5
+          fi
+        else
+          # Otherwise we believe it is a complete path. Use it as it is.
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool INSTALL_NAME_TOOL=$tool_specified" >&5
+$as_echo "$as_me: Will use user supplied tool INSTALL_NAME_TOOL=$tool_specified" >&6;}
+          { $as_echo "$as_me:${as_lineno-$LINENO}: checking for INSTALL_NAME_TOOL" >&5
+$as_echo_n "checking for INSTALL_NAME_TOOL... " >&6; }
+          if test ! -x "$tool_specified"; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+            as_fn_error $? "User supplied tool INSTALL_NAME_TOOL=$tool_specified does not exist or is not executable" "$LINENO" 5
+          fi
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5
+$as_echo "$tool_specified" >&6; }
+        fi
+      fi
+    fi
+
+  fi
+
+
+
+  if test "x$INSTALL_NAME_TOOL" = x; then
+    as_fn_error $? "Could not find required tool for INSTALL_NAME_TOOL" "$LINENO" 5
+  fi
+
+
+
+  # Only process if variable expands to non-empty
+
+  if test "x$INSTALL_NAME_TOOL" != 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="$INSTALL_NAME_TOOL"
+  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"`
+    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 INSTALL_NAME_TOOL, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of INSTALL_NAME_TOOL, 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 INSTALL_NAME_TOOL" "$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 INSTALL_NAME_TOOL, which resolves as \"$new_path\", is invalid." >&5
+$as_echo "$as_me: The path of INSTALL_NAME_TOOL, 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 INSTALL_NAME_TOOL" "$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="$INSTALL_NAME_TOOL"
+  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 INSTALL_NAME_TOOL, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of INSTALL_NAME_TOOL, 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 INSTALL_NAME_TOOL" "$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="$INSTALL_NAME_TOOL"
+      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 INSTALL_NAME_TOOL, which resolves as \"$complete\", is not found." >&5
+$as_echo "$as_me: The path of INSTALL_NAME_TOOL, 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 INSTALL_NAME_TOOL" "$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
+      INSTALL_NAME_TOOL="$new_complete"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting INSTALL_NAME_TOOL to \"$new_complete\"" >&5
+$as_echo "$as_me: Rewriting INSTALL_NAME_TOOL to \"$new_complete\"" >&6;}
+    fi
+  fi
+
   fi
 
   if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
@@ -64486,17 +65270,18 @@
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUNDLE_FREETYPE" >&5
 $as_echo "$BUNDLE_FREETYPE" >&6; }
 
-  fi # end freetype needed
-
-  FREETYPE_LICENSE=""
-  if test "x$with_freetype_license" = "xyes"; then
-    as_fn_error $? "--with-freetype-license must have a value" "$LINENO" 5
-  elif test "x$with_freetype_license" != "x"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype license" >&5
+    if test "x$BUNDLE_FREETYPE" = xyes; then
+      FREETYPE_LICENSE=""
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype license" >&5
 $as_echo_n "checking for freetype license... " >&6; }
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_freetype_license" >&5
+      if test "x$with_freetype_license" = "xyes"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+        as_fn_error $? "--with-freetype-license must have a value" "$LINENO" 5
+      elif test "x$with_freetype_license" != "x"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_freetype_license" >&5
 $as_echo "$with_freetype_license" >&6; }
-    FREETYPE_LICENSE="$with_freetype_license"
+        FREETYPE_LICENSE="$with_freetype_license"
 
   # Only process if variable expands to non-empty
 
@@ -64629,10 +65414,154 @@
     fi
   fi
 
-    if test ! -f "$FREETYPE_LICENSE"; then
-      as_fn_error $? "$FREETYPE_LICENSE cannot be found" "$LINENO" 5
-    fi
-  fi
+        if test ! -f "$FREETYPE_LICENSE"; then
+          as_fn_error $? "$FREETYPE_LICENSE cannot be found" "$LINENO" 5
+        fi
+      else
+        if test "x$with_freetype" != "x" && test -f $with_freetype/freetype.md; then
+          FREETYPE_LICENSE="$with_freetype/freetype.md"
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_LICENSE" >&5
+$as_echo "$FREETYPE_LICENSE" >&6; }
+
+  # Only process if variable expands to non-empty
+
+  if test "x$FREETYPE_LICENSE" != x; then
+    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$FREETYPE_LICENSE"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of FREETYPE_LICENSE, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of FREETYPE_LICENSE, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of FREETYPE_LICENSE" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-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 $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    FREETYPE_LICENSE="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FREETYPE_LICENSE to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting FREETYPE_LICENSE to \"$new_path\"" >&6;}
+  fi
+
+    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$FREETYPE_LICENSE"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    FREETYPE_LICENSE="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FREETYPE_LICENSE to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting FREETYPE_LICENSE to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+    else
+      # We're on a unix platform. Hooray! :)
+      path="$FREETYPE_LICENSE"
+      has_space=`$ECHO "$path" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of FREETYPE_LICENSE, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of FREETYPE_LICENSE, which resolves as \"$path\", is invalid." >&6;}
+        as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+      fi
+
+      # Use eval to expand a potential ~
+      eval path="$path"
+      if test ! -f "$path" && test ! -d "$path"; then
+        as_fn_error $? "The path of FREETYPE_LICENSE, which resolves as \"$path\", is not found." "$LINENO" 5
+      fi
+
+      if test -d "$path"; then
+        FREETYPE_LICENSE="`cd "$path"; $THEPWDCMD -L`"
+      else
+        dir="`$DIRNAME "$path"`"
+        base="`$BASENAME "$path"`"
+        FREETYPE_LICENSE="`cd "$dir"; $THEPWDCMD -L`/$base"
+      fi
+    fi
+  fi
+
+        else
+          { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+        fi
+      fi
+    fi
+
+  fi # end freetype needed
 
 
 
@@ -65334,23 +66263,6 @@
 fi
 
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for which libpng to use" >&5
-$as_echo_n "checking for which libpng to use... " >&6; }
-
-  # default is bundled
-  DEFAULT_LIBPNG=bundled
-  # if user didn't specify, use DEFAULT_LIBPNG
-  if test "x${with_libpng}" = "x"; then
-    with_libpng=${DEFAULT_LIBPNG}
-  fi
-
-  if test "x${with_libpng}" = "xbundled"; then
-    USE_EXTERNAL_LIBPNG=false
-    PNG_CFLAGS=""
-    PNG_LIBS=""
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5
-$as_echo "bundled" >&6; }
-  elif test "x${with_libpng}" = "xsystem"; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PNG" >&5
@@ -65418,6 +66330,23 @@
 $as_echo "yes" >&6; }
 	LIBPNG_FOUND=yes
 fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for which libpng to use" >&5
+$as_echo_n "checking for which libpng to use... " >&6; }
+
+  # default is bundled
+  DEFAULT_LIBPNG=bundled
+  # if user didn't specify, use DEFAULT_LIBPNG
+  if test "x${with_libpng}" = "x"; then
+    with_libpng=${DEFAULT_LIBPNG}
+  fi
+
+  if test "x${with_libpng}" = "xbundled"; then
+    USE_EXTERNAL_LIBPNG=false
+    PNG_CFLAGS=""
+    PNG_LIBS=""
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5
+$as_echo "bundled" >&6; }
+  elif test "x${with_libpng}" = "xsystem"; then
     if test "x${LIBPNG_FOUND}" = "xyes"; then
       # PKG_CHECK_MODULES will set PNG_CFLAGS and PNG_LIBS
       USE_EXTERNAL_LIBPNG=true
@@ -65515,6 +66444,40 @@
       USE_EXTERNAL_LIBZ=true
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: system" >&5
 $as_echo "system" >&6; }
+
+      if test "x$USE_EXTERNAL_LIBPNG" != "xtrue"; then
+        # If we use bundled libpng, we must verify that we have a proper zlib.
+        # For instance zlib-ng has had issues with inflateValidate().
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for system zlib functionality" >&5
+$as_echo_n "checking for system zlib functionality... " >&6; }
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "zlib.h"
+int
+main ()
+{
+
+                #if ZLIB_VERNUM >= 0x1281
+                  inflateValidate(NULL, 0);
+                #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+else
+
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: not ok" >&5
+$as_echo "not ok" >&6; }
+                as_fn_error $? "System zlib not working correctly" "$LINENO" 5
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+      fi
     else
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: system not found" >&5
 $as_echo "system not found" >&6; }
diff -r 10b34c929b4f -r 64298b1e890b make/autoconf/lib-bundled.m4
--- a/make/autoconf/lib-bundled.m4	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/autoconf/lib-bundled.m4	Tue Dec 05 10:28:45 2017 +0000
@@ -113,6 +113,7 @@
   AC_ARG_WITH(libpng, [AS_HELP_STRING([--with-libpng],
      [use libpng from build system or OpenJDK source (system, bundled) @<:@bundled@:>@])])
 
+  PKG_CHECK_MODULES(PNG, libpng, [LIBPNG_FOUND=yes], [LIBPNG_FOUND=no])
   AC_MSG_CHECKING([for which libpng to use])
 
   # default is bundled
@@ -128,7 +129,6 @@
     PNG_LIBS=""
     AC_MSG_RESULT([bundled])
   elif test "x${with_libpng}" = "xsystem"; then
-    PKG_CHECK_MODULES(PNG, libpng, [LIBPNG_FOUND=yes], [LIBPNG_FOUND=no])
     if test "x${LIBPNG_FOUND}" = "xyes"; then
       # PKG_CHECK_MODULES will set PNG_CFLAGS and PNG_LIBS
       USE_EXTERNAL_LIBPNG=true
@@ -183,6 +183,24 @@
     if test "x${ZLIB_FOUND}" = "xyes"; then
       USE_EXTERNAL_LIBZ=true
       AC_MSG_RESULT([system])
+
+      if test "x$USE_EXTERNAL_LIBPNG" != "xtrue"; then
+        # If we use bundled libpng, we must verify that we have a proper zlib.
+        # For instance zlib-ng has had issues with inflateValidate().
+        AC_MSG_CHECKING([for system zlib functionality])
+        AC_COMPILE_IFELSE(
+            [AC_LANG_PROGRAM([#include "zlib.h"], [
+                #if ZLIB_VERNUM >= 0x1281
+                  inflateValidate(NULL, 0);
+                #endif
+            ])],
+            [AC_MSG_RESULT([ok])],
+            [
+                AC_MSG_RESULT([not ok])
+                AC_MSG_ERROR([System zlib not working correctly])
+            ]
+        )
+      fi
     else
       AC_MSG_RESULT([system not found])
       AC_MSG_ERROR([--with-zlib=system specified, but no zlib found!])
diff -r 10b34c929b4f -r 64298b1e890b make/autoconf/lib-freetype.m4
--- a/make/autoconf/lib-freetype.m4	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/autoconf/lib-freetype.m4	Tue Dec 05 10:28:45 2017 +0000
@@ -443,20 +443,31 @@
     fi
     AC_MSG_RESULT([$BUNDLE_FREETYPE])
 
-  fi # end freetype needed
+    if test "x$BUNDLE_FREETYPE" = xyes; then
+      FREETYPE_LICENSE=""
+      AC_MSG_CHECKING([for freetype license])
+      if test "x$with_freetype_license" = "xyes"; then
+        AC_MSG_RESULT([no])
+        AC_MSG_ERROR([--with-freetype-license must have a value])
+      elif test "x$with_freetype_license" != "x"; then
+        AC_MSG_RESULT([$with_freetype_license])
+        FREETYPE_LICENSE="$with_freetype_license"
+        BASIC_FIXUP_PATH(FREETYPE_LICENSE)
+        if test ! -f "$FREETYPE_LICENSE"; then
+          AC_MSG_ERROR([$FREETYPE_LICENSE cannot be found])
+        fi
+      else
+        if test "x$with_freetype" != "x" && test -f $with_freetype/freetype.md; then
+          FREETYPE_LICENSE="$with_freetype/freetype.md"
+          AC_MSG_RESULT([$FREETYPE_LICENSE])
+          BASIC_FIXUP_PATH(FREETYPE_LICENSE)
+        else
+          AC_MSG_RESULT([no])
+        fi
+      fi
+    fi
 
-  FREETYPE_LICENSE=""
-  if test "x$with_freetype_license" = "xyes"; then
-    AC_MSG_ERROR([--with-freetype-license must have a value])
-  elif test "x$with_freetype_license" != "x"; then
-    AC_MSG_CHECKING([for freetype license])
-    AC_MSG_RESULT([$with_freetype_license])
-    FREETYPE_LICENSE="$with_freetype_license"
-    BASIC_FIXUP_PATH(FREETYPE_LICENSE)
-    if test ! -f "$FREETYPE_LICENSE"; then
-      AC_MSG_ERROR([$FREETYPE_LICENSE cannot be found])
-    fi
-  fi
+  fi # end freetype needed
 
   AC_SUBST(FREETYPE_BUNDLE_LIB_PATH)
   AC_SUBST(FREETYPE_CFLAGS)
diff -r 10b34c929b4f -r 64298b1e890b make/autoconf/spec.gmk.in
--- a/make/autoconf/spec.gmk.in	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/autoconf/spec.gmk.in	Tue Dec 05 10:28:45 2017 +0000
@@ -293,6 +293,7 @@
 FREETYPE_CFLAGS:=@FREETYPE_CFLAGS@
 FREETYPE_BUNDLE_LIB_PATH=@FREETYPE_BUNDLE_LIB_PATH@
 FREETYPE_LICENSE=@FREETYPE_LICENSE@
+FONTCONFIG_CFLAGS:=@FONTCONFIG_CFLAGS@
 CUPS_CFLAGS:=@CUPS_CFLAGS@
 ALSA_LIBS:=@ALSA_LIBS@
 ALSA_CFLAGS:=@ALSA_CFLAGS@
@@ -471,6 +472,7 @@
 STRIP:=@STRIP@
 
 LIPO:=@LIPO@
+INSTALL_NAME_TOOL:=@INSTALL_NAME_TOOL@
 
 # Options to linker to specify a mapfile.
 # (Note absence of := assignment, because we do not want to evaluate the macro body here)
diff -r 10b34c929b4f -r 64298b1e890b make/autoconf/toolchain.m4
--- a/make/autoconf/toolchain.m4	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/autoconf/toolchain.m4	Tue Dec 05 10:28:45 2017 +0000
@@ -628,6 +628,10 @@
   if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
     BASIC_PATH_PROGS(LIPO, lipo)
     BASIC_FIXUP_EXECUTABLE(LIPO)
+    BASIC_REQUIRE_PROGS(OTOOL, otool)
+    BASIC_FIXUP_EXECUTABLE(OTOOL)
+    BASIC_REQUIRE_PROGS(INSTALL_NAME_TOOL, install_name_tool)
+    BASIC_FIXUP_EXECUTABLE(INSTALL_NAME_TOOL)
   fi
 
   if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
diff -r 10b34c929b4f -r 64298b1e890b make/conf/jib-profiles.js
--- a/make/conf/jib-profiles.js	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/conf/jib-profiles.js	Tue Dec 05 10:28:45 2017 +0000
@@ -429,7 +429,7 @@
         "macosx-x64": {
             target_os: "macosx",
             target_cpu: "x64",
-            dependencies: ["devkit"],
+            dependencies: ["devkit", "freetype"],
             configure_args: concat(common.configure_args_64bit, "--with-zlib=system",
                 "--with-macosx-version-max=10.7.0"),
         },
@@ -662,21 +662,6 @@
         }
     });
 
-    // The windows ri profile needs to add the freetype license file
-    profilesRiFreetype = {
-        "windows-x86-ri": {
-            configure_args: "--with-freetype-license="
-                + input.get("freetype", "install_path")
-                + "/freetype-2.7.1-v120-x86/freetype.md"
-        },
-        "windows-x64-ri": {
-            configure_args: "--with-freetype-license="
-                + input.get("freetype", "install_path")
-                + "/freetype-2.7.1-v120-x64/freetype.md"
-        }
-    };
-    profiles = concatObjects(profiles, profilesRiFreetype);
-
     // Profiles used to run tests. Used in JPRT and Mach 5.
     var testOnlyProfiles = {
         "run-test-jprt": {
@@ -788,6 +773,12 @@
     var boot_jdk_platform = (input.build_os == "macosx" ? "osx" : input.build_os)
         + "-" + input.build_cpu;
 
+    var freetype_version = {
+        windows_x64: "2.7.1-v120+1.1",
+        windows_x86: "2.7.1-v120+1.1",
+        macosx_x64: "2.7.1-Xcode6.3-MacOSX10.9+1.0"
+    }[input.target_platform];
+
     var dependencies = {
 
         boot_jdk: {
@@ -852,7 +843,7 @@
         freetype: {
             organization: common.organization,
             ext: "tar.gz",
-            revision: "2.7.1-v120+1.0",
+            revision: freetype_version,
             module: "freetype-" + input.target_platform
         },
 
diff -r 10b34c929b4f -r 64298b1e890b make/copy/Copy-java.desktop.gmk
--- a/make/copy/Copy-java.desktop.gmk	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/copy/Copy-java.desktop.gmk	Tue Dec 05 10:28:45 2017 +0000
@@ -44,7 +44,8 @@
 ################################################################################
 
 ifneq ($(FREETYPE_BUNDLE_LIB_PATH), )
-  # We need to bundle the freetype library, so it will be available at runtime as well as link time.
+  # We need to bundle the freetype library, so it will be available at runtime
+  # as well as link time.
   #
   # NB: Default freetype build system uses -h linker option and
   # result .so contains hardcoded library name that is later
@@ -61,10 +62,10 @@
   #
   #TODO: rework this to avoid hardcoding library name in the makefile
   #
-  ifeq ($(OPENJDK_TARGET_OS), windows)
+  ifneq ($(filter $(OPENJDK_TARGET_OS), linux solaris), )
+    FREETYPE_TARGET_LIB := $(LIB_DST_DIR)/$(call SHARED_LIBRARY,freetype).6
+  else
     FREETYPE_TARGET_LIB := $(LIB_DST_DIR)/$(call SHARED_LIBRARY,freetype)
-  else
-    FREETYPE_TARGET_LIB := $(LIB_DST_DIR)/$(call SHARED_LIBRARY,freetype).6
   endif
 
   # We can't use $(install-file) in this rule because it preserves symbolic links and
diff -r 10b34c929b4f -r 64298b1e890b make/data/charsetmapping/charsets
--- a/make/data/charsetmapping/charsets	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/data/charsetmapping/charsets	Tue Dec 05 10:28:45 2017 +0000
@@ -492,7 +492,7 @@
 
 charset x-MS950-HKSCS MS950_HKSCS
     package sun.nio.cs.ext
-    type    source
+    type    template
     hisname MS950_HKSCS
     ascii   true
     alias   MS950_HKSCS          # JDK historical;
diff -r 10b34c929b4f -r 64298b1e890b make/data/charsetmapping/stdcs-windows
--- a/make/data/charsetmapping/stdcs-windows	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/data/charsetmapping/stdcs-windows	Tue Dec 05 10:28:45 2017 +0000
@@ -13,4 +13,5 @@
 MS936
 MS949
 MS950
+MS950_HKSCS
 MS950_HKSCS_XP
diff -r 10b34c929b4f -r 64298b1e890b make/hotspot/symbols/symbols-unix
--- a/make/hotspot/symbols/symbols-unix	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/hotspot/symbols/symbols-unix	Tue Dec 05 10:28:45 2017 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
 JVM_ArrayCopy
 JVM_AssertionStatusDirectives
 JVM_CallStackWalk
-JVM_ClassDepth
-JVM_ClassLoaderDepth
 JVM_Clone
 JVM_ConstantPoolGetClassAt
 JVM_ConstantPoolGetClassAtIfLoaded
@@ -47,8 +45,6 @@
 JVM_ConstantPoolGetTagAt
 JVM_ConstantPoolGetUTF8At
 JVM_CountStackFrames
-JVM_CurrentClassLoader
-JVM_CurrentLoadedClass
 JVM_CurrentThread
 JVM_CurrentTimeMillis
 JVM_DefineClass
diff -r 10b34c929b4f -r 64298b1e890b make/jdk/src/classes/build/tools/charsetmapping/Main.java
--- a/make/jdk/src/classes/build/tools/charsetmapping/Main.java	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/jdk/src/classes/build/tools/charsetmapping/Main.java	Tue Dec 05 10:28:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,6 +54,7 @@
                 new File(args[SRC_DIR], args[CHARSETS]));
             String[] osStdcs = getOSStdCSList(new File(args[SRC_DIR], args[OS]));
             boolean hasBig5_HKSCS = false;
+            boolean hasMS950_HKSCS = false;
             boolean hasMS950_HKSCS_XP = false;
             boolean hasEUC_TW = false;
             for (String name : osStdcs) {
@@ -63,6 +64,8 @@
                 }
                 if (name.equals("Big5_HKSCS")) {
                     hasBig5_HKSCS = true;
+                } else if (name.equals("MS950_HKSCS")) {
+                    hasMS950_HKSCS = true;
                 } else if (name.equals("MS950_HKSCS_XP")) {
                     hasMS950_HKSCS_XP = true;
                 } else if (name.equals("EUC_TW")) {
@@ -98,12 +101,15 @@
                          args[TEMPLATE],
                          args[OS].endsWith("windows") ? "windows" : "unix");
 
-            // HKSCSMapping2008/XP.java goes together with Big5/MS950XP_HKSCS
-            if (isStandard && hasBig5_HKSCS || isExtended && !hasBig5_HKSCS) {
+            // HKSCSMapping(2008).java goes std if one of Big5_HKSCS MS950_HKSCS
+            // is in std
+            if (isStandard && (hasBig5_HKSCS || hasMS950_HKSCS) ||
+                isExtended && !(hasBig5_HKSCS  || hasMS950_HKSCS)) {
                 HKSCS.genClass2008(args[SRC_DIR], args[DST_DIR],
                                    isStandard ? "sun.nio.cs" : "sun.nio.cs.ext",
                                    new File(args[COPYRIGHT_SRC], "HKSCS.java"));
             }
+            // HKSCS_XPMapping.java goes together with MS950XP_HKSCS
             if (isStandard && hasMS950_HKSCS_XP || isExtended && !hasMS950_HKSCS_XP) {
                 HKSCS.genClassXP(args[SRC_DIR], args[DST_DIR],
                                  isStandard ? "sun.nio.cs" : "sun.nio.cs.ext",
diff -r 10b34c929b4f -r 64298b1e890b make/lib/Awt2dLibraries.gmk
--- a/make/lib/Awt2dLibraries.gmk	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/lib/Awt2dLibraries.gmk	Tue Dec 05 10:28:45 2017 +0000
@@ -658,7 +658,7 @@
 
 $(eval $(call SetupNativeCompilation,BUILD_LIBFONTMANAGER, \
     LIBRARY := fontmanager, \
-    OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+    OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libfontmanager, \
     SRC := $(LIBFONTMANAGER_SRC), \
     EXCLUDE_FILES := $(LIBFONTMANAGER_EXCLUDE_FILES) \
         AccelGlyphCache.c, \
@@ -702,6 +702,21 @@
     OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libfontmanager, \
 ))
 
+$(INSTALL_LIBRARIES_HERE)/$(call SHARED_LIBRARY,fontmanager): $(BUILD_LIBFONTMANAGER_TARGET)
+	$(install-file)
+        ifneq ($(FREETYPE_BUNDLE_LIB_PATH), )
+          ifeq ($(OPENJDK_TARGET_OS), macosx)
+            # If bundling freetype on macosx, we need to rewrite the rpath location
+            # in the libfontmanager library to point to the bundled location
+	    $(INSTALL_NAME_TOOL) -change \
+	        `$(OTOOL) -D $(FREETYPE_BUNDLE_LIB_PATH)/$(call SHARED_LIBRARY,freetype) | $(TAIL) -n1` \
+	        '@rpath/$(call SHARED_LIBRARY,freetype)' \
+	        $@
+          endif
+        endif
+
+BUILD_LIBFONTMANAGER += $(INSTALL_LIBRARIES_HERE)/$(call SHARED_LIBRARY,fontmanager)
+
 $(BUILD_LIBFONTMANAGER): $(BUILD_LIBAWT)
 
 ifneq (, $(findstring $(OPENJDK_TARGET_OS), solaris aix))
diff -r 10b34c929b4f -r 64298b1e890b make/mapfiles/libjava/mapfile-vers
--- a/make/mapfiles/libjava/mapfile-vers	Tue Dec 05 10:21:41 2017 +0000
+++ b/make/mapfiles/libjava/mapfile-vers	Tue Dec 05 10:28:45 2017 +0000
@@ -205,10 +205,6 @@
 		Java_java_lang_Runtime_runFinalization0;
 		Java_java_lang_Runtime_totalMemory;
 		Java_java_lang_Runtime_availableProcessors;
-		Java_java_lang_SecurityManager_classDepth;
-		Java_java_lang_SecurityManager_classLoaderDepth0;
-		Java_java_lang_SecurityManager_currentClassLoader0;
-		Java_java_lang_SecurityManager_currentLoadedClass0;
 		Java_java_lang_SecurityManager_getClassContext;
 		Java_java_lang_Shutdown_halt0;
                 Java_java_lang_StackTraceElement_initStackTraceElement;
diff -r 10b34c929b4f -r 64298b1e890b src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	Tue Dec 05 10:21:41 2017 +0000
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	Tue Dec 05 10:28:45 2017 +0000
@@ -148,6 +148,16 @@
       PrefetchCopyIntervalInBytes = 32760;
   }
 
+  if (AllocatePrefetchDistance !=-1 && (AllocatePrefetchDistance & 7)) {
+    warning("AllocatePrefetchDistance must be multiple of 8");
+    AllocatePrefetchDistance &= ~7;
+  }
+
+  if (AllocatePrefetchStepSize & 7) {
+    warning("AllocatePrefetchStepSize must be multiple of 8");
+    AllocatePrefetchStepSize &= ~7;
+  }
+
   if (SoftwarePrefetchHintDistance != -1 &&
        (SoftwarePrefetchHintDistance & 7)) {
     warning("SoftwarePrefetchHintDistance must be -1, or a multiple of 8");
diff -r 10b34c929b4f -r 64298b1e890b src/hotspot/share/prims/jvm.cpp
--- a/src/hotspot/share/prims/jvm.cpp	Tue Dec 05 10:21:41 2017 +0000
+++ b/src/hotspot/share/prims/jvm.cpp	Tue Dec 05 10:28:45 2017 +0000
@@ -3137,64 +3137,6 @@
 
 // java.lang.SecurityManager ///////////////////////////////////////////////////////////////////////
 
-static bool is_trusted_frame(JavaThread* jthread, vframeStream* vfst) {
-  assert(jthread->is_Java_thread(), "must be a Java thread");
-  if (jthread->privileged_stack_top() == NULL) return false;
-  if (jthread->privileged_stack_top()->frame_id() == vfst->frame_id()) {
-    oop loader = jthread->privileged_stack_top()->class_loader();
-    if (loader == NULL) return true;
-    bool trusted = java_lang_ClassLoader::is_trusted_loader(loader);
-    if (trusted) return true;
-  }
-  return false;
-}
-
-JVM_ENTRY(jclass, JVM_CurrentLoadedClass(JNIEnv *env))
-  JVMWrapper("JVM_CurrentLoadedClass");
-  ResourceMark rm(THREAD);
-
-  for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
-    // if a method in a class in a trusted loader is in a doPrivileged, return NULL
-    bool trusted = is_trusted_frame(thread, &vfst);
-    if (trusted) return NULL;
-
-    Method* m = vfst.method();
-    if (!m->is_native()) {
-      InstanceKlass* holder = m->method_holder();
-      oop loader = holder->class_loader();
-      if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
-        return (jclass) JNIHandles::make_local(env, holder->java_mirror());
-      }
-    }
-  }
-  return NULL;
-JVM_END
-
-
-JVM_ENTRY(jobject, JVM_CurrentClassLoader(JNIEnv *env))
-  JVMWrapper("JVM_CurrentClassLoader");
-  ResourceMark rm(THREAD);
-
-  for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
-
-    // if a method in a class in a trusted loader is in a doPrivileged, return NULL
-    bool trusted = is_trusted_frame(thread, &vfst);
-    if (trusted) return NULL;
-
-    Method* m = vfst.method();
-    if (!m->is_native()) {
-      InstanceKlass* holder = m->method_holder();
-      assert(holder->is_klass(), "just checking");
-      oop loader = holder->class_loader();
-      if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
-        return JNIHandles::make_local(env, loader);
-      }
-    }
-  }
-  return NULL;
-JVM_END
-
-
 JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env))
   JVMWrapper("JVM_GetClassContext");
   ResourceMark rm(THREAD);
@@ -3234,58 +3176,6 @@
 JVM_END
 
 
-JVM_ENTRY(jint, JVM_ClassDepth(JNIEnv *env, jstring name))
-  JVMWrapper("JVM_ClassDepth");
-  ResourceMark rm(THREAD);
-  Handle h_name (THREAD, JNIHandles::resolve_non_null(name));
-  Handle class_name_str = java_lang_String::internalize_classname(h_name, CHECK_0);
-
-  const char* str = java_lang_String::as_utf8_string(class_name_str());
-  TempNewSymbol class_name_sym = SymbolTable::probe(str, (int)strlen(str));
-  if (class_name_sym == NULL) {
-    return -1;
-  }
-
-  int depth = 0;
-
-  for(vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
-    if (!vfst.method()->is_native()) {
-      InstanceKlass* holder = vfst.method()->method_holder();
-      assert(holder->is_klass(), "just checking");
-      if (holder->name() == class_name_sym) {
-        return depth;
-      }
-      depth++;
-    }
-  }
-  return -1;
-JVM_END
-
-
-JVM_ENTRY(jint, JVM_ClassLoaderDepth(JNIEnv *env))
-  JVMWrapper("JVM_ClassLoaderDepth");
-  ResourceMark rm(THREAD);
-  int depth = 0;
-  for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
-    // if a method in a class in a trusted loader is in a doPrivileged, return -1
-    bool trusted = is_trusted_frame(thread, &vfst);
-    if (trusted) return -1;
-
-    Method* m = vfst.method();
-    if (!m->is_native()) {
-      InstanceKlass* holder = m->method_holder();
-      assert(holder->is_klass(), "just checking");
-      oop loader = holder->class_loader();
-      if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
-        return depth;
-      }
-      depth++;
-    }
-  }
-  return -1;
-JVM_END
-
-
 // java.lang.Package ////////////////////////////////////////////////////////////////
 
 
diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/lang/Class.java
--- a/src/java.base/share/classes/java/lang/Class.java	Tue Dec 05 10:21:41 2017 +0000
+++ b/src/java.base/share/classes/java/lang/Class.java	Tue Dec 05 10:28:45 2017 +0000
@@ -53,12 +53,11 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 import java.util.StringJoiner;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
@@ -1771,7 +1770,7 @@
         if (sm != null) {
             checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
         }
-        return copyFields(privateGetPublicFields(null));
+        return copyFields(privateGetPublicFields());
     }
 
 
@@ -3026,7 +3025,7 @@
     // Returns an array of "root" fields. These Field objects must NOT
     // be propagated to the outside world, but must instead be copied
     // via ReflectionFactory.copyField.
-    private Field[] privateGetPublicFields(Set> traversedInterfaces) {
+    private Field[] privateGetPublicFields() {
         Field[] res;
         ReflectionData rd = reflectionData();
         if (rd != null) {
@@ -3034,35 +3033,25 @@
             if (res != null) return res;
         }
 
-        // No cached value available; compute value recursively.
-        // Traverse in correct order for getField().
-        List fields = new ArrayList<>();
-        if (traversedInterfaces == null) {
-            traversedInterfaces = new HashSet<>();
-        }
+        // Use a linked hash set to ensure order is preserved and
+        // fields from common super interfaces are not duplicated
+        LinkedHashSet fields = new LinkedHashSet<>();
 
         // Local fields
-        Field[] tmp = privateGetDeclaredFields(true);
-        addAll(fields, tmp);
+        addAll(fields, privateGetDeclaredFields(true));
 
         // Direct superinterfaces, recursively
-        for (Class c : getInterfaces()) {
-            if (!traversedInterfaces.contains(c)) {
-                traversedInterfaces.add(c);
-                addAll(fields, c.privateGetPublicFields(traversedInterfaces));
-            }
+        for (Class si : getInterfaces()) {
+            addAll(fields, si.privateGetPublicFields());
         }
 
         // Direct superclass, recursively
-        if (!isInterface()) {
-            Class c = getSuperclass();
-            if (c != null) {
-                addAll(fields, c.privateGetPublicFields(traversedInterfaces));
-            }
+        Class sc = getSuperclass();
+        if (sc != null) {
+            addAll(fields, sc.privateGetPublicFields());
         }
 
-        res = new Field[fields.size()];
-        fields.toArray(res);
+        res = fields.toArray(new Field[0]);
         if (rd != null) {
             rd.publicFields = res;
         }
diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/lang/SecurityManager.java
--- a/src/java.base/share/classes/java/lang/SecurityManager.java	Tue Dec 05 10:21:41 2017 +0000
+++ b/src/java.base/share/classes/java/lang/SecurityManager.java	Tue Dec 05 10:28:45 2017 +0000
@@ -101,7 +101,7 @@
  * checkPermission returns quietly. If denied, a
  * SecurityException is thrown.
  * 

- * As of Java 2 SDK v1.2, the default implementation of each of the other + * The default implementation of each of the other * check methods in SecurityManager is to * call the SecurityManager checkPermission method * to determine if the calling thread has permission to perform the requested @@ -197,10 +197,10 @@ * See {@extLink security_guide_permissions * Permissions in the Java Development Kit (JDK)} * for permission-related information. - * This document includes, for example, a table listing the various SecurityManager + * This document includes a table listing the various SecurityManager * check methods and the permission(s) the default * implementation of each such method requires. - * It also contains a table of all the version 1.2 methods + * It also contains a table of the methods * that require permissions, and for each such method tells * which permission it requires. * @@ -228,20 +228,7 @@ * * @since 1.0 */ -public -class SecurityManager { - - /** - * This field is true if there is a security check in - * progress; false otherwise. - * - * @deprecated This type of security checking is not recommended. - * It is recommended that the checkPermission - * call be used instead. This field is subject to removal in a - * future version of Java SE. - */ - @Deprecated(since="1.2", forRemoval=true) - protected boolean inCheck; +public class SecurityManager { /* * Have we been initialized. Effective against finalizer attacks. @@ -262,24 +249,6 @@ } /** - * Tests if there is a security check in progress. - * - * @return the value of the inCheck field. This field - * should contain true if a security check is - * in progress, - * false otherwise. - * @see java.lang.SecurityManager#inCheck - * @deprecated This type of security checking is not recommended. - * It is recommended that the checkPermission - * call be used instead. This method is subject to removal in a - * future version of Java SE. - */ - @Deprecated(since="1.2", forRemoval=true) - public boolean getInCheck() { - return inCheck; - } - - /** * Constructs a new SecurityManager. * *

If there is a security manager already installed, this method first @@ -322,198 +291,6 @@ protected native Class[] getClassContext(); /** - * Returns the class loader of the most recently executing method from - * a class defined using a non-system class loader. A non-system - * class loader is defined as being a class loader that is not equal to - * the system class loader (as returned - * by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors. - *

- * This method will return - * null in the following three cases: - *

    - *
  1. All methods on the execution stack are from classes - * defined using the system class loader or one of its ancestors. - * - *
  2. All methods on the execution stack up to the first - * "privileged" caller - * (see {@link java.security.AccessController#doPrivileged}) - * are from classes - * defined using the system class loader or one of its ancestors. - * - *
  3. A call to checkPermission with - * java.security.AllPermission does not - * result in a SecurityException. - * - *
- * - * @return the class loader of the most recent occurrence on the stack - * of a method from a class defined using a non-system class - * loader. - * - * @deprecated This type of security checking is not recommended. - * It is recommended that the checkPermission - * call be used instead. This method is subject to removal in a - * future version of Java SE. - * - * @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader - * @see #checkPermission(java.security.Permission) checkPermission - */ - @Deprecated(since="1.2", forRemoval=true) - protected ClassLoader currentClassLoader() { - ClassLoader cl = currentClassLoader0(); - if ((cl != null) && hasAllPermission()) - cl = null; - return cl; - } - - private native ClassLoader currentClassLoader0(); - - /** - * Returns the class of the most recently executing method from - * a class defined using a non-system class loader. A non-system - * class loader is defined as being a class loader that is not equal to - * the system class loader (as returned - * by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors. - *

- * This method will return - * null in the following three cases: - *

    - *
  1. All methods on the execution stack are from classes - * defined using the system class loader or one of its ancestors. - * - *
  2. All methods on the execution stack up to the first - * "privileged" caller - * (see {@link java.security.AccessController#doPrivileged}) - * are from classes - * defined using the system class loader or one of its ancestors. - * - *
  3. A call to checkPermission with - * java.security.AllPermission does not - * result in a SecurityException. - * - *
- * - * @return the class of the most recent occurrence on the stack - * of a method from a class defined using a non-system class - * loader. - * - * @deprecated This type of security checking is not recommended. - * It is recommended that the checkPermission - * call be used instead. This method is subject to removal in a - * future version of Java SE. - * - * @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader - * @see #checkPermission(java.security.Permission) checkPermission - */ - @Deprecated(since="1.2", forRemoval=true) - protected Class currentLoadedClass() { - Class c = currentLoadedClass0(); - if ((c != null) && hasAllPermission()) - c = null; - return c; - } - - /** - * Returns the stack depth of the specified class. - * - * @param name the fully qualified name of the class to search for. - * @return the depth on the stack frame of the first occurrence of a - * method from a class with the specified name; - * -1 if such a frame cannot be found. - * @deprecated This type of security checking is not recommended. - * It is recommended that the checkPermission - * call be used instead. This method is subject to removal in a - * future version of Java SE. - */ - @Deprecated(since="1.2", forRemoval=true) - protected native int classDepth(String name); - - /** - * Returns the stack depth of the most recently executing method - * from a class defined using a non-system class loader. A non-system - * class loader is defined as being a class loader that is not equal to - * the system class loader (as returned - * by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors. - *

- * This method will return - * -1 in the following three cases: - *

    - *
  1. All methods on the execution stack are from classes - * defined using the system class loader or one of its ancestors. - * - *
  2. All methods on the execution stack up to the first - * "privileged" caller - * (see {@link java.security.AccessController#doPrivileged}) - * are from classes - * defined using the system class loader or one of its ancestors. - * - *
  3. A call to checkPermission with - * java.security.AllPermission does not - * result in a SecurityException. - * - *
- * - * @return the depth on the stack frame of the most recent occurrence of - * a method from a class defined using a non-system class loader. - * - * @deprecated This type of security checking is not recommended. - * It is recommended that the checkPermission - * call be used instead. This method is subject to removal in a - * future version of Java SE. - * - * @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader - * @see #checkPermission(java.security.Permission) checkPermission - */ - @Deprecated(since="1.2", forRemoval=true) - protected int classLoaderDepth() { - int depth = classLoaderDepth0(); - if (depth != -1) { - if (hasAllPermission()) - depth = -1; - else - depth--; // make sure we don't include ourself - } - return depth; - } - - private native int classLoaderDepth0(); - - /** - * Tests if a method from a class with the specified - * name is on the execution stack. - * - * @param name the fully qualified name of the class. - * @return true if a method from a class with the specified - * name is on the execution stack; false otherwise. - * @deprecated This type of security checking is not recommended. - * It is recommended that the checkPermission - * call be used instead. This method is subject to removal in a - * future version of Java SE. - */ - @Deprecated(since="1.2", forRemoval=true) - protected boolean inClass(String name) { - return classDepth(name) >= 0; - } - - /** - * Basically, tests if a method from a class defined using a - * class loader is on the execution stack. - * - * @return true if a call to currentClassLoader - * has a non-null return value. - * - * @deprecated This type of security checking is not recommended. - * It is recommended that the checkPermission - * call be used instead. This method is subject to removal in a - * future version of Java SE. - * @see #currentClassLoader() currentClassLoader - */ - @Deprecated(since="1.2", forRemoval=true) - protected boolean inClassLoader() { - return currentClassLoader() != null; - } - - /** * Creates an object that encapsulates the current execution * environment. The result of this method is used, for example, by the * three-argument checkConnect method and by the @@ -1698,64 +1475,32 @@ } /** - * Throws a SecurityException if the - * calling thread is not allowed to access members. - *

- * The default policy is to allow access to PUBLIC members, as well - * as access to classes that have the same class loader as the caller. - * In all other cases, this method calls checkPermission - * with the RuntimePermission("accessDeclaredMembers") - * permission. - *

- * If this method is overridden, then a call to - * super.checkMemberAccess cannot be made, - * as the default implementation of checkMemberAccess - * relies on the code being checked being at a stack depth of - * 4. + * Throws a {@code SecurityException} if the calling thread does + * not have {@code AllPermission}. * * @param clazz the class that reflection is to be performed on. - * * @param which type of access, PUBLIC or DECLARED. - * - * @exception SecurityException if the caller does not have - * permission to access members. - * @exception NullPointerException if the clazz argument is - * null. - * - * @deprecated This method relies on the caller being at a stack depth - * of 4 which is error-prone and cannot be enforced by the runtime. - * Users of this method should instead invoke {@link #checkPermission} - * directly. - * This method is subject to removal in a future version of Java SE. - * - * @see java.lang.reflect.Member + * @throws SecurityException if the caller does not have + * {@code AllPermission} + * @throws NullPointerException if the {@code clazz} argument is + * {@code null} + * @deprecated This method was originally used to check if the calling + * thread was allowed to access members. It relied on the + * caller being at a stack depth of 4 which is error-prone and + * cannot be enforced by the runtime. The method has been + * obsoleted and code should instead use + * {@link #checkPermission} to check + * {@code RuntimePermission("accessDeclaredMembers")}. This + * method is subject to removal in a future version of Java SE. * @since 1.1 * @see #checkPermission(java.security.Permission) checkPermission */ @Deprecated(since="1.8", forRemoval=true) - @CallerSensitive public void checkMemberAccess(Class clazz, int which) { if (clazz == null) { throw new NullPointerException("class can't be null"); } - if (which != Member.PUBLIC) { - Class stack[] = getClassContext(); - /* - * stack depth of 4 should be the caller of one of the - * methods in java.lang.Class that invoke checkMember - * access. The stack should look like: - * - * someCaller [3] - * java.lang.Class.someReflectionAPI [2] - * java.lang.Class.checkMemberAccess [1] - * SecurityManager.checkMemberAccess [0] - * - */ - if ((stack.length<4) || - (stack[3].getClassLoader() != clazz.getClassLoader())) { - checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); - } - } + checkPermission(SecurityConstants.ALL_PERMISSION); } /** @@ -1792,8 +1537,6 @@ checkPermission(new SecurityPermission(target)); } - private native Class currentLoadedClass0(); - /** * Returns the thread group into which to instantiate any new * thread being created at the time this is being called. diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/lang/System.java --- a/src/java.base/share/classes/java/lang/System.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/lang/System.java Tue Dec 05 10:28:45 2017 +0000 @@ -63,8 +63,8 @@ import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.HotSpotIntrinsicCandidate; -import jdk.internal.misc.JavaLangAccess;; -import jdk.internal.misc.SharedSecrets;; +import jdk.internal.misc.JavaLangAccess; +import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.VM; import jdk.internal.logger.LoggerFinderLoader; import jdk.internal.logger.LazyLoggers; diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/util/Collection.java --- a/src/java.base/share/classes/java/util/Collection.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/util/Collection.java Tue Dec 05 10:28:45 2017 +0000 @@ -54,19 +54,15 @@ * constructors) but all of the general-purpose {@code Collection} * implementations in the Java platform libraries comply. * - *

The "destructive" methods contained in this interface, that is, the - * methods that modify the collection on which they operate, are specified to - * throw {@code UnsupportedOperationException} if this collection does not - * support the operation. If this is the case, these methods may, but are not - * required to, throw an {@code UnsupportedOperationException} if the - * invocation would have no effect on the collection. For example, invoking - * the {@link #addAll(Collection)} method on an unmodifiable collection may, - * but is not required to, throw the exception if the collection to be added - * is empty. + *

Certain methods are specified to be + * optional. If a collection implementation doesn't implement a + * particular operation, it should define the corresponding method to throw + * {@code UnsupportedOperationException}. Such methods are marked "optional + * operation" in method specifications of the collections interfaces. * - *

- * Some collection implementations have restrictions on the elements that - * they may contain. For example, some implementations prohibit null elements, + *

Some collection implementations + * have restrictions on the elements that they may contain. + * For example, some implementations prohibit null elements, * and some have restrictions on the types of their elements. Attempting to * add an ineligible element throws an unchecked exception, typically * {@code NullPointerException} or {@code ClassCastException}. Attempting @@ -111,6 +107,86 @@ * methods. Implementations may optionally handle the self-referential scenario, * however most current implementations do not do so. * + *

View Collections

+ * + *

Most collections manage storage for elements they contain. By contrast, view + * collections themselves do not store elements, but instead they rely on a + * backing collection to store the actual elements. Operations that are not handled + * by the view collection itself are delegated to the backing collection. Examples of + * view collections include the wrapper collections returned by methods such as + * {@link Collections#checkedCollection Collections.checkedCollection}, + * {@link Collections#synchronizedCollection Collections.synchronizedCollection}, and + * {@link Collections#unmodifiableCollection Collections.unmodifiableCollection}. + * Other examples of view collections include collections that provide a + * different representation of the same elements, for example, as + * provided by {@link List#subList List.subList}, + * {@link NavigableSet#subSet NavigableSet.subSet}, or + * {@link Map#entrySet Map.entrySet}. + * Any changes made to the backing collection are visible in the view collection. + * Correspondingly, any changes made to the view collection — if changes + * are permitted — are written through to the backing collection. + * Although they technically aren't collections, instances of + * {@link Iterator} and {@link ListIterator} can also allow modifications + * to be written through to the backing collection, and in some cases, + * modifications to the backing collection will be visible to the Iterator + * during iteration. + * + *

Unmodifiable Collections

+ * + *

Certain methods of this interface are considered "destructive" and are called + * "mutator" methods in that they modify the group of objects contained within + * the collection on which they operate. They can be specified to throw + * {@code UnsupportedOperationException} if this collection implementation + * does not support the operation. Such methods should (but are not required + * to) throw an {@code UnsupportedOperationException} if the invocation would + * have no effect on the collection. For example, consider a collection that + * does not support the {@link #add add} operation. What will happen if the + * {@link #addAll addAll} method is invoked on this collection, with an empty + * collection as the argument? The addition of zero elements has no effect, + * so it is permissible for this collection simply to do nothing and not to throw + * an exception. However, it is recommended that such cases throw an exception + * unconditionally, as throwing only in certain cases can lead to + * programming errors. + * + *

An unmodifiable collection is a collection, all of whose + * mutator methods (as defined above) are specified to throw + * {@code UnsupportedOperationException}. Such a collection thus cannot be + * modified by calling any methods on it. For a collection to be properly + * unmodifiable, any view collections derived from it must also be unmodifiable. + * For example, if a List is unmodifiable, the List returned by + * {@link List#subList List.subList} is also unmodifiable. + * + *

An unmodifiable collection is not necessarily immutable. If the + * contained elements are mutable, the entire collection is clearly + * mutable, even though it might be unmodifiable. For example, consider + * two unmodifiable lists containing mutable elements. The result of calling + * {@code list1.equals(list2)} might differ from one call to the next if + * the elements had been mutated, even though both lists are unmodifiable. + * However, if an unmodifiable collection contains all immutable elements, + * it can be considered effectively immutable. + * + *

Unmodifiable View Collections

+ * + *

An unmodifiable view collection is a collection that is unmodifiable + * and that is also a view onto a backing collection. Its mutator methods throw + * {@code UnsupportedOperationException}, as described above, while + * reading and querying methods are delegated to the backing collection. + * The effect is to provide read-only access to the backing collection. + * This is useful for a component to provide users with read access to + * an internal collection, while preventing them from modifying such + * collections unexpectedly. Examples of unmodifiable view collections + * are those returned by the + * {@link Collections#unmodifiableCollection Collections.unmodifiableCollection}, + * {@link Collections#unmodifiableList Collections.unmodifiableList}, and + * related methods. + * + *

Note that changes to the backing collection might still be possible, + * and if they occur, they are visible through the unmodifiable view. Thus, + * an unmodifiable view collection is not necessarily immutable. However, + * if the backing collection of an unmodifiable view is effectively immutable, + * or if the only reference to the backing collection is through an + * unmodifiable view, the view can be considered effectively immutable. + * *

This interface is a member of the * * Java Collections Framework. @@ -192,7 +268,8 @@ * Returns an array containing all of the elements in this collection. * If this collection makes any guarantees as to what order its elements * are returned by its iterator, this method must return the elements in - * the same order. + * the same order. The returned array's {@linkplain Class#getComponentType + * runtime component type} is {@code Object}. * *

The returned array will be "safe" in that no references to it are * maintained by this collection. (In other words, this method must @@ -202,7 +279,8 @@ *

This method acts as bridge between array-based and collection-based * APIs. * - * @return an array containing all of the elements in this collection + * @return an array, whose {@linkplain Class#getComponentType runtime component + * type} is {@code Object}, containing all of the elements in this collection */ Object[] toArray(); @@ -239,14 +317,14 @@ * Note that {@code toArray(new Object[0])} is identical in function to * {@code toArray()}. * - * @param the runtime type of the array to contain the collection + * @param the component type of the array to contain the collection * @param a the array into which the elements of this collection are to be * stored, if it is big enough; otherwise, a new array of the same * runtime type is allocated for this purpose. * @return an array containing all of the elements in this collection - * @throws ArrayStoreException if the runtime type of the specified array - * is not a supertype of the runtime type of every element in - * this collection + * @throws ArrayStoreException if the runtime type of any element in this + * collection is not assignable to the {@linkplain Class#getComponentType + * runtime component type} of the specified array * @throws NullPointerException if the specified array is null */ T[] toArray(T[] a); diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/util/Collections.java --- a/src/java.base/share/classes/java/util/Collections.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/util/Collections.java Tue Dec 05 10:28:45 2017 +0000 @@ -989,9 +989,8 @@ // Unmodifiable Wrappers /** - * Returns an unmodifiable view of the specified collection. This method - * allows modules to provide users with "read-only" access to internal - * collections. Query operations on the returned collection "read through" + * Returns an unmodifiable view of the + * specified collection. Query operations on the returned collection "read through" * to the specified collection, and attempts to modify the returned * collection, whether direct or via its iterator, result in an * {@code UnsupportedOperationException}.

@@ -1102,9 +1101,8 @@ } /** - * Returns an unmodifiable view of the specified set. This method allows - * modules to provide users with "read-only" access to internal sets. - * Query operations on the returned set "read through" to the specified + * Returns an unmodifiable view of the + * specified set. Query operations on the returned set "read through" to the specified * set, and attempts to modify the returned set, whether direct or via its * iterator, result in an {@code UnsupportedOperationException}.

* @@ -1132,9 +1130,8 @@ } /** - * Returns an unmodifiable view of the specified sorted set. This method - * allows modules to provide users with "read-only" access to internal - * sorted sets. Query operations on the returned sorted set "read + * Returns an unmodifiable view of the + * specified sorted set. Query operations on the returned sorted set "read * through" to the specified sorted set. Attempts to modify the returned * sorted set, whether direct, via its iterator, or via its * {@code subSet}, {@code headSet}, or {@code tailSet} views, result in @@ -1180,9 +1177,8 @@ } /** - * Returns an unmodifiable view of the specified navigable set. This method - * allows modules to provide users with "read-only" access to internal - * navigable sets. Query operations on the returned navigable set "read + * Returns an unmodifiable view of the + * specified navigable set. Query operations on the returned navigable set "read * through" to the specified navigable set. Attempts to modify the returned * navigable set, whether direct, via its iterator, or via its * {@code subSet}, {@code headSet}, or {@code tailSet} views, result in @@ -1269,9 +1265,8 @@ } /** - * Returns an unmodifiable view of the specified list. This method allows - * modules to provide users with "read-only" access to internal - * lists. Query operations on the returned list "read through" to the + * Returns an unmodifiable view of the + * specified list. Query operations on the returned list "read through" to the * specified list, and attempts to modify the returned list, whether * direct or via its iterator, result in an * {@code UnsupportedOperationException}.

@@ -1415,9 +1410,8 @@ } /** - * Returns an unmodifiable view of the specified map. This method - * allows modules to provide users with "read-only" access to internal - * maps. Query operations on the returned map "read through" + * Returns an unmodifiable view of the + * specified map. Query operations on the returned map "read through" * to the specified map, and attempts to modify the returned * map, whether direct or via its collection views, result in an * {@code UnsupportedOperationException}.

@@ -1765,9 +1759,8 @@ } /** - * Returns an unmodifiable view of the specified sorted map. This method - * allows modules to provide users with "read-only" access to internal - * sorted maps. Query operations on the returned sorted map "read through" + * Returns an unmodifiable view of the + * specified sorted map. Query operations on the returned sorted map "read through" * to the specified sorted map. Attempts to modify the returned * sorted map, whether direct, via its collection views, or via its * {@code subMap}, {@code headMap}, or {@code tailMap} views, result in @@ -1809,9 +1802,8 @@ } /** - * Returns an unmodifiable view of the specified navigable map. This method - * allows modules to provide users with "read-only" access to internal - * navigable maps. Query operations on the returned navigable map "read + * Returns an unmodifiable view of the + * specified navigable map. Query operations on the returned navigable map "read * through" to the specified navigable map. Attempts to modify the returned * navigable map, whether direct, via its collection views, or via its * {@code subMap}, {@code headMap}, or {@code tailMap} views, result in diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/util/List.java --- a/src/java.base/share/classes/java/util/List.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/util/List.java Tue Dec 05 10:28:45 2017 +0000 @@ -87,15 +87,16 @@ * Such exceptions are marked as "optional" in the specification for this * interface. * - *

Immutable List Static Factory Methods

- *

The {@link List#of(Object...) List.of()} static factory methods - * provide a convenient way to create immutable lists. The {@code List} + *

Unmodifiable Lists

+ *

The {@link List#of(Object...) List.of} and + * {@link List#copyOf List.copyOf} static factory methods + * provide a convenient way to create unmodifiable lists. The {@code List} * instances created by these methods have the following characteristics: * *

    - *
  • They are structurally immutable. Elements cannot be added, removed, - * or replaced. Calling any mutator method will always cause - * {@code UnsupportedOperationException} to be thrown. + *
  • They are unmodifiable. Elements cannot + * be added, removed, or replaced. Calling any mutator method on the List + * will always cause {@code UnsupportedOperationException} to be thrown. * However, if the contained elements are themselves mutable, * this may cause the List's contents to appear to change. *
  • They disallow {@code null} elements. Attempts to create them with @@ -777,9 +778,9 @@ } /** - * Returns an immutable list containing zero elements. + * Returns an unmodifiable list containing zero elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @return an empty {@code List} @@ -791,9 +792,9 @@ } /** - * Returns an immutable list containing one element. + * Returns an unmodifiable list containing one element. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the single element @@ -807,9 +808,9 @@ } /** - * Returns an immutable list containing two elements. + * Returns an unmodifiable list containing two elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the first element @@ -824,9 +825,9 @@ } /** - * Returns an immutable list containing three elements. + * Returns an unmodifiable list containing three elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the first element @@ -842,9 +843,9 @@ } /** - * Returns an immutable list containing four elements. + * Returns an unmodifiable list containing four elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the first element @@ -861,9 +862,9 @@ } /** - * Returns an immutable list containing five elements. + * Returns an unmodifiable list containing five elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the first element @@ -881,9 +882,9 @@ } /** - * Returns an immutable list containing six elements. + * Returns an unmodifiable list containing six elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the first element @@ -903,9 +904,9 @@ } /** - * Returns an immutable list containing seven elements. + * Returns an unmodifiable list containing seven elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the first element @@ -926,9 +927,9 @@ } /** - * Returns an immutable list containing eight elements. + * Returns an unmodifiable list containing eight elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the first element @@ -950,9 +951,9 @@ } /** - * Returns an immutable list containing nine elements. + * Returns an unmodifiable list containing nine elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the first element @@ -975,9 +976,9 @@ } /** - * Returns an immutable list containing ten elements. + * Returns an unmodifiable list containing ten elements. * - * See Immutable List Static Factory Methods for details. + * See Unmodifiable Lists for details. * * @param the {@code List}'s element type * @param e1 the first element @@ -1001,8 +1002,8 @@ } /** - * Returns an immutable list containing an arbitrary number of elements. - * See Immutable List Static Factory Methods for details. + * Returns an unmodifiable list containing an arbitrary number of elements. + * See Unmodifiable Lists for details. * * @apiNote * This method also accepts a single array as an argument. The element type of @@ -1039,4 +1040,29 @@ return new ImmutableCollections.ListN<>(elements); } } + + /** + * Returns an unmodifiable List containing the elements of + * the given Collection, in its iteration order. The given Collection must not be null, + * and it must not contain any null elements. If the given Collection is subsequently + * modified, the returned List will not reflect such modifications. + * + * @implNote + * If the given Collection is an unmodifiable List, + * calling copyOf will generally not create a copy. + * + * @param the {@code List}'s element type + * @param coll a {@code Collection} from which elements are drawn, must be non-null + * @return a {@code List} containing the elements of the given {@code Collection} + * @throws NullPointerException if coll is null, or if it contains any nulls + * @since 10 + */ + @SuppressWarnings("unchecked") + static List copyOf(Collection coll) { + if (coll instanceof ImmutableCollections.AbstractImmutableList) { + return (List)coll; + } else { + return (List)List.of(coll.toArray()); + } + } } diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/util/Map.java --- a/src/java.base/share/classes/java/util/Map.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/util/Map.java Tue Dec 05 10:28:45 2017 +0000 @@ -110,17 +110,18 @@ * Implementations may optionally handle the self-referential scenario, however * most current implementations do not do so. * - *

    Immutable Map Static Factory Methods

    - *

    The {@link Map#of() Map.of()} and - * {@link Map#ofEntries(Map.Entry...) Map.ofEntries()} - * static factory methods provide a convenient way to create immutable maps. + *

    Unmodifiable Maps

    + *

    The {@link Map#of() Map.of}, + * {@link Map#ofEntries(Map.Entry...) Map.ofEntries}, and + * {@link Map#copyOf Map.copyOf} + * static factory methods provide a convenient way to create unmodifiable maps. * The {@code Map} * instances created by these methods have the following characteristics: * *

      - *
    • They are structurally immutable. Keys and values cannot be added, - * removed, or updated. Calling any mutator method will always cause - * {@code UnsupportedOperationException} to be thrown. + *
    • They are unmodifiable. Keys and values + * cannot be added, removed, or updated. Calling any mutator method on the Map + * will always cause {@code UnsupportedOperationException} to be thrown. * However, if the contained keys or values are themselves mutable, this may cause the * Map to behave inconsistently or its contents to appear to change. *
    • They disallow {@code null} keys and values. Attempts to create them with @@ -1276,8 +1277,8 @@ } /** - * Returns an immutable map containing zero mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing zero mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1290,8 +1291,8 @@ } /** - * Returns an immutable map containing a single mapping. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing a single mapping. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1307,8 +1308,8 @@ } /** - * Returns an immutable map containing two mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing two mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1327,8 +1328,8 @@ } /** - * Returns an immutable map containing three mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing three mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1349,8 +1350,8 @@ } /** - * Returns an immutable map containing four mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing four mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1373,8 +1374,8 @@ } /** - * Returns an immutable map containing five mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing five mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1399,8 +1400,8 @@ } /** - * Returns an immutable map containing six mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing six mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1429,8 +1430,8 @@ } /** - * Returns an immutable map containing seven mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing seven mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1461,8 +1462,8 @@ } /** - * Returns an immutable map containing eight mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing eight mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1495,8 +1496,8 @@ } /** - * Returns an immutable map containing nine mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing nine mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1531,8 +1532,8 @@ } /** - * Returns an immutable map containing ten mappings. - * See Immutable Map Static Factory Methods for details. + * Returns an unmodifiable map containing ten mappings. + * See Unmodifiable Maps for details. * * @param the {@code Map}'s key type * @param the {@code Map}'s value type @@ -1569,9 +1570,9 @@ } /** - * Returns an immutable map containing keys and values extracted from the given entries. + * Returns an unmodifiable map containing keys and values extracted from the given entries. * The entries themselves are not stored in the map. - * See Immutable Map Static Factory Methods for details. + * See Unmodifiable Maps for details. * * @apiNote * It is convenient to create the map entries using the {@link Map#entry Map.entry()} method. @@ -1602,15 +1603,17 @@ @SafeVarargs @SuppressWarnings("varargs") static Map ofEntries(Entry... entries) { - if (entries.length == 0) { // implicit null check of entries + if (entries.length == 0) { // implicit null check of entries array return ImmutableCollections.Map0.instance(); } else if (entries.length == 1) { + // implicit null check of the array slot return new ImmutableCollections.Map1<>(entries[0].getKey(), entries[0].getValue()); } else { Object[] kva = new Object[entries.length << 1]; int a = 0; for (Entry entry : entries) { + // implicit null checks of each array slot kva[a++] = entry.getKey(); kva[a++] = entry.getValue(); } @@ -1619,7 +1622,7 @@ } /** - * Returns an immutable {@link Entry} containing the given key and value. + * Returns an unmodifiable {@link Entry} containing the given key and value. * These entries are suitable for populating {@code Map} instances using the * {@link Map#ofEntries Map.ofEntries()} method. * The {@code Entry} instances created by this method have the following characteristics: @@ -1627,7 +1630,7 @@ *
        *
      • They disallow {@code null} keys and values. Attempts to create them using a {@code null} * key or value result in {@code NullPointerException}. - *
      • They are immutable. Calls to {@link Entry#setValue Entry.setValue()} + *
      • They are unmodifiable. Calls to {@link Entry#setValue Entry.setValue()} * on a returned {@code Entry} result in {@code UnsupportedOperationException}. *
      • They are not serializable. *
      • They are value-based. @@ -1655,4 +1658,30 @@ // KeyValueHolder checks for nulls return new KeyValueHolder<>(k, v); } + + /** + * Returns an unmodifiable Map containing the entries + * of the given Map. The given Map must not be null, and it must not contain any + * null keys or values. If the given Map is subsequently modified, the returned + * Map will not reflect such modifications. + * + * @implNote + * If the given Map is an unmodifiable Map, + * calling copyOf will generally not create a copy. + * + * @param the {@code Map}'s key type + * @param the {@code Map}'s value type + * @param map a {@code Map} from which entries are drawn, must be non-null + * @return a {@code Map} containing the entries of the given {@code Map} + * @throws NullPointerException if map is null, or if it contains any null keys or values + * @since 10 + */ + @SuppressWarnings({"rawtypes","unchecked"}) + static Map copyOf(Map map) { + if (map instanceof ImmutableCollections.AbstractImmutableMap) { + return (Map)map; + } else { + return (Map)Map.ofEntries(map.entrySet().toArray(new Entry[0])); + } + } } diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/util/Set.java --- a/src/java.base/share/classes/java/util/Set.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/util/Set.java Tue Dec 05 10:28:45 2017 +0000 @@ -63,15 +63,16 @@ * Such exceptions are marked as "optional" in the specification for this * interface. * - *

        Immutable Set Static Factory Methods

        - *

        The {@link Set#of(Object...) Set.of()} static factory methods - * provide a convenient way to create immutable sets. The {@code Set} + *

        Unmodifiable Sets

        + *

        The {@link Set#of(Object...) Set.of} and + * {@link Set#copyOf Set.copyOf} static factory methods + * provide a convenient way to create unmodifiable sets. The {@code Set} * instances created by these methods have the following characteristics: * *

          - *
        • They are structurally immutable. Elements cannot be added or - * removed. Calling any mutator method will always cause - * {@code UnsupportedOperationException} to be thrown. + *
        • They are unmodifiable. Elements cannot + * be added or removed. Calling any mutator method on the Set + * will always cause {@code UnsupportedOperationException} to be thrown. * However, if the contained elements are themselves mutable, this may cause the * Set to behave inconsistently or its contents to appear to change. *
        • They disallow {@code null} elements. Attempts to create them with @@ -439,8 +440,8 @@ } /** - * Returns an immutable set containing zero elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing zero elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @return an empty {@code Set} @@ -452,8 +453,8 @@ } /** - * Returns an immutable set containing one element. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing one element. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the single element @@ -467,8 +468,8 @@ } /** - * Returns an immutable set containing two elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing two elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the first element @@ -484,8 +485,8 @@ } /** - * Returns an immutable set containing three elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing three elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the first element @@ -502,8 +503,8 @@ } /** - * Returns an immutable set containing four elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing four elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the first element @@ -521,8 +522,8 @@ } /** - * Returns an immutable set containing five elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing five elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the first element @@ -541,8 +542,8 @@ } /** - * Returns an immutable set containing six elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing six elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the first element @@ -563,8 +564,8 @@ } /** - * Returns an immutable set containing seven elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing seven elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the first element @@ -586,8 +587,8 @@ } /** - * Returns an immutable set containing eight elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing eight elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the first element @@ -610,8 +611,8 @@ } /** - * Returns an immutable set containing nine elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing nine elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the first element @@ -635,8 +636,8 @@ } /** - * Returns an immutable set containing ten elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing ten elements. + * See Unmodifiable Sets for details. * * @param the {@code Set}'s element type * @param e1 the first element @@ -661,8 +662,8 @@ } /** - * Returns an immutable set containing an arbitrary number of elements. - * See Immutable Set Static Factory Methods for details. + * Returns an unmodifiable set containing an arbitrary number of elements. + * See Unmodifiable Sets for details. * * @apiNote * This method also accepts a single array as an argument. The element type of @@ -700,4 +701,30 @@ return new ImmutableCollections.SetN<>(elements); } } + + /** + * Returns an unmodifiable Set containing the elements + * of the given Collection. The given Collection must not be null, and it must not + * contain any null elements. If the given Collection contains duplicate elements, + * an arbitrary element of the duplicates is preserved. If the given Collection is + * subsequently modified, the returned Set will not reflect such modifications. + * + * @implNote + * If the given Collection is an unmodifiable Set, + * calling copyOf will generally not create a copy. + * + * @param the {@code Set}'s element type + * @param coll a {@code Collection} from which elements are drawn, must be non-null + * @return a {@code Set} containing the elements of the given {@code Collection} + * @throws NullPointerException if coll is null, or if it contains any nulls + * @since 10 + */ + @SuppressWarnings("unchecked") + static Set copyOf(Collection coll) { + if (coll instanceof ImmutableCollections.AbstractImmutableSet) { + return (Set)coll; + } else { + return (Set)Set.of(new HashSet<>(coll).toArray()); + } + } } diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java --- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java Tue Dec 05 10:28:45 2017 +0000 @@ -38,11 +38,15 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.concurrent.locks.LockSupport; import java.util.function.BiConsumer; import java.util.function.BiPredicate; import java.util.function.Consumer; +import static java.util.concurrent.Flow.Publisher; +import static java.util.concurrent.Flow.Subscriber; +import static java.util.concurrent.Flow.Subscription; /** * A {@link Flow.Publisher} that asynchronously issues submitted @@ -74,6 +78,14 @@ * Flow#defaultBufferSize()} may provide a useful starting point for * choosing a capacity based on expected rates, resources, and usages. * + *

          A single SubmissionPublisher may be shared among multiple + * sources. Actions in a source thread prior to publishing an item or + * issuing a signal + * happen-before actions subsequent to the corresponding + * access by each subscriber. But reported estimates of lag and demand + * are designed for use in monitoring, not for synchronization + * control, and may reflect stale or inaccurate views of progress. + * *

          Publication methods support different policies about what to do * when buffers are saturated. Method {@link #submit(Object) submit} * blocks until resources are available. This is simplest, but least @@ -158,19 +170,27 @@ * @author Doug Lea * @since 9 */ -public class SubmissionPublisher implements Flow.Publisher, +public class SubmissionPublisher implements Publisher, AutoCloseable { /* * Most mechanics are handled by BufferedSubscription. This class * mainly tracks subscribers and ensures sequentiality, by using - * built-in synchronization locks across public methods. (Using + * built-in synchronization locks across public methods. Using * built-in locks works well in the most typical case in which - * only one thread submits items). + * only one thread submits items. We extend this idea in + * submission methods by detecting single-ownership to reduce + * producer-consumer synchronization strength. */ /** The largest possible power of two array size. */ static final int BUFFER_CAPACITY_LIMIT = 1 << 30; + /** + * Initial buffer capacity used when maxBufferCapacity is + * greater. Must be a power of two. + */ + static final int INITIAL_CAPACITY = 32; + /** Round capacity to power of 2, at most limit. */ static final int roundCapacity(int cap) { int n = cap - 1; @@ -206,7 +226,7 @@ * but we expect that subscribing is much less common than * publishing. Unsubscribing occurs only during traversal loops, * when BufferedSubscription methods return negative values - * signifying that they have been disabled. To reduce + * signifying that they have been closed. To reduce * head-of-line blocking, submit and offer methods first call * BufferedSubscription.offer on each subscriber, and place * saturated ones in retries list (using nextRetry field), and @@ -216,12 +236,16 @@ /** Run status, updated only within locks */ volatile boolean closed; + /** Set true on first call to subscribe, to initialize possible owner */ + boolean subscribed; + /** The first caller thread to subscribe, or null if thread ever changed */ + Thread owner; /** If non-null, the exception in closeExceptionally */ volatile Throwable closedException; // Parameters for constructing BufferedSubscriptions final Executor executor; - final BiConsumer, ? super Throwable> onNextHandler; + final BiConsumer, ? super Throwable> onNextHandler; final int maxBufferCapacity; /** @@ -245,7 +269,7 @@ * positive */ public SubmissionPublisher(Executor executor, int maxBufferCapacity, - BiConsumer, ? super Throwable> handler) { + BiConsumer, ? super Throwable> handler) { if (executor == null) throw new NullPointerException(); if (maxBufferCapacity <= 0) @@ -311,12 +335,19 @@ * @param subscriber the subscriber * @throws NullPointerException if subscriber is null */ - public void subscribe(Flow.Subscriber subscriber) { + public void subscribe(Subscriber subscriber) { if (subscriber == null) throw new NullPointerException(); + int max = maxBufferCapacity; // allocate initial array + Object[] array = new Object[max < INITIAL_CAPACITY ? + max : INITIAL_CAPACITY]; BufferedSubscription subscription = - new BufferedSubscription(subscriber, executor, - onNextHandler, maxBufferCapacity); + new BufferedSubscription(subscriber, executor, onNextHandler, + array, max); synchronized (this) { + if (!subscribed) { + subscribed = true; + owner = Thread.currentThread(); + } for (BufferedSubscription b = clients, pred = null;;) { if (b == null) { Throwable ex; @@ -332,7 +363,7 @@ break; } BufferedSubscription next = b.next; - if (b.isDisabled()) { // remove + if (b.isClosed()) { // remove b.next = null; // detach if (pred == null) clients = next; @@ -351,6 +382,107 @@ } /** + * Common implementation for all three forms of submit and offer. + * Acts as submit if nanos == Long.MAX_VALUE, else offer. + */ + private int doOffer(T item, long nanos, + BiPredicate, ? super T> onDrop) { + if (item == null) throw new NullPointerException(); + int lag = 0; + boolean complete, unowned; + synchronized (this) { + Thread t = Thread.currentThread(), o; + BufferedSubscription b = clients; + if ((unowned = ((o = owner) != t)) && o != null) + owner = null; // disable bias + if (b == null) + complete = closed; + else { + complete = false; + boolean cleanMe = false; + BufferedSubscription retries = null, rtail = null, next; + do { + next = b.next; + int stat = b.offer(item, unowned); + if (stat == 0) { // saturated; add to retry list + b.nextRetry = null; // avoid garbage on exceptions + if (rtail == null) + retries = b; + else + rtail.nextRetry = b; + rtail = b; + } + else if (stat < 0) // closed + cleanMe = true; // remove later + else if (stat > lag) + lag = stat; + } while ((b = next) != null); + + if (retries != null || cleanMe) + lag = retryOffer(item, nanos, onDrop, retries, lag, cleanMe); + } + } + if (complete) + throw new IllegalStateException("Closed"); + else + return lag; + } + + /** + * Helps, (timed) waits for, and/or drops buffers on list; returns + * lag or negative drops (for use in offer). + */ + private int retryOffer(T item, long nanos, + BiPredicate, ? super T> onDrop, + BufferedSubscription retries, int lag, + boolean cleanMe) { + for (BufferedSubscription r = retries; r != null;) { + BufferedSubscription nextRetry = r.nextRetry; + r.nextRetry = null; + if (nanos > 0L) + r.awaitSpace(nanos); + int stat = r.retryOffer(item); + if (stat == 0 && onDrop != null && onDrop.test(r.subscriber, item)) + stat = r.retryOffer(item); + if (stat == 0) + lag = (lag >= 0) ? -1 : lag - 1; + else if (stat < 0) + cleanMe = true; + else if (lag >= 0 && stat > lag) + lag = stat; + r = nextRetry; + } + if (cleanMe) + cleanAndCount(); + return lag; + } + + /** + * Returns current list count after removing closed subscribers. + * Call only while holding lock. Used mainly by retryOffer for + * cleanup. + */ + private int cleanAndCount() { + int count = 0; + BufferedSubscription pred = null, next; + for (BufferedSubscription b = clients; b != null; b = next) { + next = b.next; + if (b.isClosed()) { + b.next = null; + if (pred == null) + clients = next; + else + pred.next = next; + } + else { + pred = b; + ++count; + } + } + return count; + } + + /** * Publishes the given item to each current subscriber by * asynchronously invoking its {@link Flow.Subscriber#onNext(Object) * onNext} method, blocking uninterruptibly while resources for any @@ -373,55 +505,7 @@ * @throws RejectedExecutionException if thrown by Executor */ public int submit(T item) { - if (item == null) throw new NullPointerException(); - int lag = 0; - boolean complete; - synchronized (this) { - complete = closed; - BufferedSubscription b = clients; - if (!complete) { - BufferedSubscription pred = null, r = null, rtail = null; - while (b != null) { - BufferedSubscription next = b.next; - int stat = b.offer(item); - if (stat < 0) { // disabled - b.next = null; - if (pred == null) - clients = next; - else - pred.next = next; - } - else { - if (stat > lag) - lag = stat; - else if (stat == 0) { // place on retry list - b.nextRetry = null; - if (rtail == null) - r = b; - else - rtail.nextRetry = b; - rtail = b; - } - pred = b; - } - b = next; - } - while (r != null) { - BufferedSubscription nextRetry = r.nextRetry; - r.nextRetry = null; - int stat = r.submit(item); - if (stat > lag) - lag = stat; - else if (stat < 0 && clients == r) - clients = r.next; // postpone internal unsubscribes - r = nextRetry; - } - } - } - if (complete) - throw new IllegalStateException("Closed"); - else - return lag; + return doOffer(item, Long.MAX_VALUE, null); } /** @@ -462,8 +546,8 @@ * @throws RejectedExecutionException if thrown by Executor */ public int offer(T item, - BiPredicate, ? super T> onDrop) { - return doOffer(0L, item, onDrop); + BiPredicate, ? super T> onDrop) { + return doOffer(item, 0L, onDrop); } /** @@ -510,71 +594,11 @@ * @throws RejectedExecutionException if thrown by Executor */ public int offer(T item, long timeout, TimeUnit unit, - BiPredicate, ? super T> onDrop) { - return doOffer(unit.toNanos(timeout), item, onDrop); - } - - /** Common implementation for both forms of offer */ - final int doOffer(long nanos, T item, - BiPredicate, ? super T> onDrop) { - if (item == null) throw new NullPointerException(); - int lag = 0, drops = 0; - boolean complete; - synchronized (this) { - complete = closed; - BufferedSubscription b = clients; - if (!complete) { - BufferedSubscription pred = null, r = null, rtail = null; - while (b != null) { - BufferedSubscription next = b.next; - int stat = b.offer(item); - if (stat < 0) { - b.next = null; - if (pred == null) - clients = next; - else - pred.next = next; - } - else { - if (stat > lag) - lag = stat; - else if (stat == 0) { - b.nextRetry = null; - if (rtail == null) - r = b; - else - rtail.nextRetry = b; - rtail = b; - } - else if (stat > lag) - lag = stat; - pred = b; - } - b = next; - } - while (r != null) { - BufferedSubscription nextRetry = r.nextRetry; - r.nextRetry = null; - int stat = (nanos > 0L) - ? r.timedOffer(item, nanos) - : r.offer(item); - if (stat == 0 && onDrop != null && - onDrop.test(r.subscriber, item)) - stat = r.offer(item); - if (stat == 0) - ++drops; - else if (stat > lag) - lag = stat; - else if (stat < 0 && clients == r) - clients = r.next; - r = nextRetry; - } - } - } - if (complete) - throw new IllegalStateException("Closed"); - else - return (drops > 0) ? -drops : lag; + BiPredicate, ? super T> onDrop) { + long nanos = unit.toNanos(timeout); + // distinguishes from untimed (only wrt interrupt policy) + if (nanos == Long.MAX_VALUE) --nanos; + return doOffer(item, nanos, onDrop); } /** @@ -591,6 +615,7 @@ // no need to re-check closed here b = clients; clients = null; + owner = null; closed = true; } while (b != null) { @@ -621,8 +646,9 @@ synchronized (this) { b = clients; if (!closed) { // don't clobber racing close + closedException = error; clients = null; - closedException = error; + owner = null; closed = true; } } @@ -662,18 +688,16 @@ */ public boolean hasSubscribers() { boolean nonEmpty = false; - if (!closed) { - synchronized (this) { - for (BufferedSubscription b = clients; b != null;) { - BufferedSubscription next = b.next; - if (b.isDisabled()) { - b.next = null; - b = clients = next; - } - else { - nonEmpty = true; - break; - } + synchronized (this) { + for (BufferedSubscription b = clients; b != null;) { + BufferedSubscription next = b.next; + if (b.isClosed()) { + b.next = null; + b = clients = next; + } + else { + nonEmpty = true; + break; } } } @@ -686,27 +710,9 @@ * @return the number of current subscribers */ public int getNumberOfSubscribers() { - int count = 0; - if (!closed) { - synchronized (this) { - BufferedSubscription pred = null, next; - for (BufferedSubscription b = clients; b != null; b = next) { - next = b.next; - if (b.isDisabled()) { - b.next = null; - if (pred == null) - clients = next; - else - pred.next = next; - } - else { - pred = b; - ++count; - } - } - } + synchronized (this) { + return cleanAndCount(); } - return count; } /** @@ -734,13 +740,13 @@ * * @return list of current subscribers */ - public List> getSubscribers() { - ArrayList> subs = new ArrayList<>(); + public List> getSubscribers() { + ArrayList> subs = new ArrayList<>(); synchronized (this) { BufferedSubscription pred = null, next; for (BufferedSubscription b = clients; b != null; b = next) { next = b.next; - if (b.isDisabled()) { + if (b.isClosed()) { b.next = null; if (pred == null) clients = next; @@ -761,14 +767,14 @@ * @return true if currently subscribed * @throws NullPointerException if subscriber is null */ - public boolean isSubscribed(Flow.Subscriber subscriber) { + public boolean isSubscribed(Subscriber subscriber) { if (subscriber == null) throw new NullPointerException(); if (!closed) { synchronized (this) { BufferedSubscription pred = null, next; for (BufferedSubscription b = clients; b != null; b = next) { next = b.next; - if (b.isDisabled()) { + if (b.isClosed()) { b.next = null; if (pred == null) clients = next; @@ -872,16 +878,15 @@ } /** Subscriber for method consume */ - private static final class ConsumerSubscriber - implements Flow.Subscriber { + static final class ConsumerSubscriber implements Subscriber { final CompletableFuture status; final Consumer consumer; - Flow.Subscription subscription; + Subscription subscription; ConsumerSubscriber(CompletableFuture status, Consumer consumer) { this.status = status; this.consumer = consumer; } - public final void onSubscribe(Flow.Subscription subscription) { + public final void onSubscribe(Subscription subscription) { this.subscription = subscription; status.whenComplete((v, e) -> subscription.cancel()); if (!status.isDone()) @@ -925,634 +930,534 @@ } /** - * A bounded (ring) buffer with integrated control to start a - * consumer task whenever items are available. The buffer - * algorithm is similar to one used inside ForkJoinPool (see its - * internal documentation for details) specialized for the case of - * at most one concurrent producer and consumer, and power of two - * buffer sizes. This allows methods to operate without locks even - * while supporting resizing, blocking, task-triggering, and - * garbage-free buffers (nulling out elements when consumed), - * although supporting these does impose a bit of overhead - * compared to plain fixed-size ring buffers. - * - * The publisher guarantees a single producer via its lock. We - * ensure in this class that there is at most one consumer. The - * request and cancel methods must be fully thread-safe but are - * coded to exploit the most common case in which they are only - * called by consumers (usually within onNext). + * A resizable array-based ring buffer with integrated control to + * start a consumer task whenever items are available. The buffer + * algorithm is specialized for the case of at most one concurrent + * producer and consumer, and power of two buffer sizes. It relies + * primarily on atomic operations (CAS or getAndSet) at the next + * array slot to put or take an element, at the "tail" and "head" + * indices written only by the producer and consumer respectively. * - * Execution control is managed using the ACTIVE ctl bit. We - * ensure that a task is active when consumable items (and - * usually, SUBSCRIBE, ERROR or COMPLETE signals) are present and - * there is demand (unfilled requests). This is complicated on - * the creation side by the possibility of exceptions when trying - * to execute tasks. These eventually force DISABLED state, but - * sometimes not directly. On the task side, termination (clearing - * ACTIVE) that would otherwise race with producers or request() - * calls uses the CONSUME keep-alive bit to force a recheck. + * We ensure internally that there is at most one active consumer + * task at any given time. The publisher guarantees a single + * producer via its lock. Sync among producers and consumers + * relies on volatile fields "ctl", "demand", and "waiting" (along + * with element access). Other variables are accessed in plain + * mode, relying on outer ordering and exclusion, and/or enclosing + * them within other volatile accesses. Some atomic operations are + * avoided by tracking single threaded ownership by producers (in + * the style of biased locking). * - * The ctl field also manages run state. When DISABLED, no further - * updates are possible. Disabling may be preceded by setting - * ERROR or COMPLETE (or both -- ERROR has precedence), in which - * case the associated Subscriber methods are invoked, possibly - * synchronously if there is no active consumer task (including - * cases where execute() failed). The cancel() method is supported - * by treating as ERROR but suppressing onError signal. + * Execution control and protocol state are managed using field + * "ctl". Methods to subscribe, close, request, and cancel set + * ctl bits (mostly using atomic boolean method getAndBitwiseOr), + * and ensure that a task is running. (The corresponding consumer + * side actions are in method consume.) To avoid starting a new + * task on each action, ctl also includes a keep-alive bit + * (ACTIVE) that is refreshed if needed on producer actions. + * (Maintaining agreement about keep-alives requires most atomic + * updates to be full SC/Volatile strength, which is still much + * cheaper than using one task per item.) Error signals + * additionally null out items and/or fields to reduce termination + * latency. The cancel() method is supported by treating as ERROR + * but suppressing onError signal. * * Support for blocking also exploits the fact that there is only * one possible waiter. ManagedBlocker-compatible control fields * are placed in this class itself rather than in wait-nodes. - * Blocking control relies on the "waiter" field. Producers set - * the field before trying to block, but must then recheck (via - * offer) before parking. Signalling then just unparks and clears - * waiter field. If the producer and/or consumer are using a - * ForkJoinPool, the producer attempts to help run consumer tasks - * via ForkJoinPool.helpAsyncBlocker before blocking. + * Blocking control relies on the "waiting" and "waiter" + * fields. Producers set them before trying to block. Signalling + * unparks and clears fields. If the producer and/or consumer are + * using a ForkJoinPool, the producer attempts to help run + * consumer tasks via ForkJoinPool.helpAsyncBlocker before + * blocking. * - * This class uses @Contended and heuristic field declaration - * ordering to reduce false-sharing-based memory contention among - * instances of BufferedSubscription, but it does not currently - * attempt to avoid memory contention among buffers. This field - * and element packing can hurt performance especially when each - * publisher has only one client operating at a high rate. - * Addressing this may require allocating substantially more space - * than users expect. + * Usages of this class may encounter any of several forms of + * memory contention. We try to ameliorate across them without + * unduly impacting footprints in low-contention usages where it + * isn't needed. Buffer arrays start out small and grow only as + * needed. The class uses @Contended and heuristic field + * declaration ordering to reduce false-sharing memory contention + * across instances of BufferedSubscription (as in, multiple + * subscribers per publisher). We additionally segregate some + * fields that would otherwise nearly always encounter cache line + * contention among producers and consumers. To reduce contention + * across time (vs space), consumers only periodically update + * other fields (see method takeItems), at the expense of possibly + * staler reporting of lags and demand (bounded at 12.5% == 1/8 + * capacity) and possibly more atomic operations. + * + * Other forms of imbalance and slowdowns can occur during startup + * when producer and consumer methods are compiled and/or memory + * is allocated at different rates. This is ameliorated by + * artificially subdividing some consumer methods, including + * isolation of all subscriber callbacks. This code also includes + * typical power-of-two array screening idioms to avoid compilers + * generating traps, along with the usual SSA-based inline + * assignment coding style. Also, all methods and fields have + * default visibility to simplify usage by callers. */ @SuppressWarnings("serial") @jdk.internal.vm.annotation.Contended - private static final class BufferedSubscription - implements Flow.Subscription, ForkJoinPool.ManagedBlocker { - // Order-sensitive field declarations - long timeout; // > 0 if timed wait - volatile long demand; // # unfilled requests - int maxCapacity; // reduced on OOME - int putStat; // offer result for ManagedBlocker + static final class BufferedSubscription + implements Subscription, ForkJoinPool.ManagedBlocker { + long timeout; // Long.MAX_VALUE if untimed wait + int head; // next position to take + int tail; // next position to put + final int maxCapacity; // max buffer size volatile int ctl; // atomic run state flags - volatile int head; // next position to take - int tail; // next position to put - Object[] array; // buffer: null if disabled - Flow.Subscriber subscriber; // null if disabled - Executor executor; // null if disabled - BiConsumer, ? super Throwable> onNextHandler; - volatile Throwable pendingError; // holds until onError issued - volatile Thread waiter; // blocked producer thread - T putItem; // for offer within ManagedBlocker + Object[] array; // buffer + final Subscriber subscriber; + final BiConsumer, ? super Throwable> onNextHandler; + Executor executor; // null on error + Thread waiter; // blocked producer thread + Throwable pendingError; // holds until onError issued BufferedSubscription next; // used only by publisher BufferedSubscription nextRetry; // used only by publisher - // ctl values - static final int ACTIVE = 0x01; // consumer task active - static final int CONSUME = 0x02; // keep-alive for consumer task - static final int DISABLED = 0x04; // final state - static final int ERROR = 0x08; // signal onError then disable - static final int SUBSCRIBE = 0x10; // signal onSubscribe - static final int COMPLETE = 0x20; // signal onComplete when done + @jdk.internal.vm.annotation.Contended("c") // segregate + volatile long demand; // # unfilled requests + @jdk.internal.vm.annotation.Contended("c") + volatile int waiting; // nonzero if producer blocked + + // ctl bit values + static final int CLOSED = 0x01; // if set, other bits ignored + static final int ACTIVE = 0x02; // keep-alive for consumer task + static final int REQS = 0x04; // (possibly) nonzero demand + static final int ERROR = 0x08; // issues onError when noticed + static final int COMPLETE = 0x10; // issues onComplete when done + static final int RUN = 0x20; // task is or will be running + static final int OPEN = 0x40; // true after subscribe static final long INTERRUPTED = -1L; // timeout vs interrupt sentinel - /** - * Initial buffer capacity used when maxBufferCapacity is - * greater. Must be a power of two. - */ - static final int DEFAULT_INITIAL_CAP = 32; - - BufferedSubscription(Flow.Subscriber subscriber, + BufferedSubscription(Subscriber subscriber, Executor executor, - BiConsumer, + BiConsumer, ? super Throwable> onNextHandler, + Object[] array, int maxBufferCapacity) { this.subscriber = subscriber; this.executor = executor; this.onNextHandler = onNextHandler; + this.array = array; this.maxCapacity = maxBufferCapacity; - this.array = new Object[maxBufferCapacity < DEFAULT_INITIAL_CAP ? - (maxBufferCapacity < 2 ? // at least 2 slots - 2 : maxBufferCapacity) : - DEFAULT_INITIAL_CAP]; + } + + // Wrappers for some VarHandle methods + + final boolean weakCasCtl(int cmp, int val) { + return CTL.weakCompareAndSet(this, cmp, val); } - final boolean isDisabled() { - return ctl == DISABLED; + final int getAndBitwiseOrCtl(int bits) { + return (int)CTL.getAndBitwiseOr(this, bits); } + final long subtractDemand(int k) { + long n = (long)(-k); + return n + (long)DEMAND.getAndAdd(this, n); + } + + final boolean casDemand(long cmp, long val) { + return DEMAND.compareAndSet(this, cmp, val); + } + + // Utilities used by SubmissionPublisher + /** - * Returns estimated number of buffered items, or -1 if - * disabled. - */ - final int estimateLag() { - int n; - return (ctl == DISABLED) ? -1 : ((n = tail - head) > 0) ? n : 0; - } - - /** - * Tries to add item and start consumer task if necessary. - * @return -1 if disabled, 0 if dropped, else estimated lag + * Returns true if closed (consumer task may still be running). */ - final int offer(T item) { - int h = head, t = tail, cap, size, stat; - Object[] a = array; - if (a != null && (cap = a.length) > 0 && cap >= (size = t + 1 - h)) { - a[(cap - 1) & t] = item; // relaxed writes OK - tail = t + 1; - stat = size; - } - else - stat = growAndAdd(a, item); - return (stat > 0 && - (ctl & (ACTIVE | CONSUME)) != (ACTIVE | CONSUME)) ? - startOnOffer(stat) : stat; + final boolean isClosed() { + return (ctl & CLOSED) != 0; } /** - * Tries to create or expand buffer, then adds item if possible. + * Returns estimated number of buffered items, or negative if + * closed. + */ + final int estimateLag() { + int c = ctl, n = tail - head; + return ((c & CLOSED) != 0) ? -1 : (n < 0) ? 0 : n; + } + + // Methods for submitting items + + /** + * Tries to add item and start consumer task if necessary. + * @return negative if closed, 0 if saturated, else estimated lag */ - private int growAndAdd(Object[] a, T item) { - boolean alloc; - int cap, stat; - if ((ctl & (ERROR | DISABLED)) != 0) { - cap = 0; - stat = -1; - alloc = false; - } - else if (a == null || (cap = a.length) <= 0) { - cap = 0; - stat = 1; - alloc = true; - } - else { - VarHandle.fullFence(); // recheck - int h = head, t = tail, size = t + 1 - h; - if (cap >= size) { - a[(cap - 1) & t] = item; + final int offer(T item, boolean unowned) { + Object[] a; + int stat = 0, cap = ((a = array) == null) ? 0 : a.length; + int t = tail, i = t & (cap - 1), n = t + 1 - head; + if (cap > 0) { + boolean added; + if (n >= cap && cap < maxCapacity) // resize + added = growAndoffer(item, a, t); + else if (n >= cap || unowned) // need volatile CAS + added = QA.compareAndSet(a, i, null, item); + else { // can use release mode + QA.setRelease(a, i, item); + added = true; + } + if (added) { tail = t + 1; - stat = size; - alloc = false; - } - else if (cap >= maxCapacity) { - stat = 0; // cannot grow - alloc = false; - } - else { - stat = cap + 1; - alloc = true; + stat = n; } } - if (alloc) { - int newCap = (cap > 0) ? cap << 1 : 1; - if (newCap <= cap) - stat = 0; - else { - Object[] newArray = null; - try { - newArray = new Object[newCap]; - } catch (Throwable ex) { // try to cope with OOME - } - if (newArray == null) { - if (cap > 0) - maxCapacity = cap; // avoid continuous failure - stat = 0; - } - else { - array = newArray; - int t = tail; - int newMask = newCap - 1; - if (a != null && cap > 0) { - int mask = cap - 1; - for (int j = head; j != t; ++j) { - int k = j & mask; - Object x = QA.getAcquire(a, k); - if (x != null && // races with consumer - QA.compareAndSet(a, k, x, null)) - newArray[j & newMask] = x; - } - } - newArray[t & newMask] = item; - tail = t + 1; - } + return startOnOffer(stat); + } + + /** + * Tries to expand buffer and add item, returning true on + * success. Currently fails only if out of memory. + */ + final boolean growAndoffer(T item, Object[] a, int t) { + int cap = 0, newCap = 0; + Object[] newArray = null; + if (a != null && (cap = a.length) > 0 && (newCap = cap << 1) > 0) { + try { + newArray = new Object[newCap]; + } catch (OutOfMemoryError ex) { } } + if (newArray == null) + return false; + else { // take and move items + int newMask = newCap - 1; + newArray[t-- & newMask] = item; + for (int mask = cap - 1, k = mask; k >= 0; --k) { + Object x = QA.getAndSet(a, t & mask, null); + if (x == null) + break; // already consumed + else + newArray[t-- & newMask] = x; + } + array = newArray; + VarHandle.releaseFence(); // release array and slots + return true; + } + } + + /** + * Version of offer for retries (no resize or bias) + */ + final int retryOffer(T item) { + Object[] a; + int stat = 0, t = tail, h = head, cap; + if ((a = array) != null && (cap = a.length) > 0 && + QA.compareAndSet(a, (cap - 1) & t, null, item)) + stat = (tail = t + 1) - h; + return startOnOffer(stat); + } + + /** + * Tries to start consumer task after offer. + * @return negative if now closed, else argument + */ + final int startOnOffer(int stat) { + int c; // start or keep alive if requests exist and not active + if (((c = ctl) & (REQS | ACTIVE)) == REQS && + ((c = getAndBitwiseOrCtl(RUN | ACTIVE)) & (RUN | CLOSED)) == 0) + tryStart(); + else if ((c & CLOSED) != 0) + stat = -1; return stat; } /** - * Spins/helps/blocks while offer returns 0. Called only if - * initial offer return 0. - */ - final int submit(T item) { - int stat; - if ((stat = offer(item)) == 0) { - putItem = item; - timeout = 0L; - putStat = 0; - ForkJoinPool.helpAsyncBlocker(executor, this); - if ((stat = putStat) == 0) { - try { - ForkJoinPool.managedBlock(this); - } catch (InterruptedException ie) { - timeout = INTERRUPTED; - } - stat = putStat; - } - if (timeout < 0L) - Thread.currentThread().interrupt(); - } - return stat; - } - - /** - * Timeout version; similar to submit. - */ - final int timedOffer(T item, long nanos) { - int stat; - if ((stat = offer(item)) == 0 && (timeout = nanos) > 0L) { - putItem = item; - putStat = 0; - ForkJoinPool.helpAsyncBlocker(executor, this); - if ((stat = putStat) == 0) { - try { - ForkJoinPool.managedBlock(this); - } catch (InterruptedException ie) { - timeout = INTERRUPTED; - } - stat = putStat; - } - if (timeout < 0L) - Thread.currentThread().interrupt(); - } - return stat; - } - - /** - * Tries to start consumer task after offer. - * @return -1 if now disabled, else argument + * Tries to start consumer task. Sets error state on failure. */ - private int startOnOffer(int stat) { - for (;;) { - Executor e; int c; - if ((c = ctl) == DISABLED || (e = executor) == null) { - stat = -1; - break; - } - else if ((c & ACTIVE) != 0) { // ensure keep-alive - if ((c & CONSUME) != 0 || - CTL.compareAndSet(this, c, c | CONSUME)) - break; - } - else if (demand == 0L || tail == head) - break; - else if (CTL.compareAndSet(this, c, c | (ACTIVE | CONSUME))) { - try { - e.execute(new ConsumerTask(this)); - break; - } catch (RuntimeException | Error ex) { // back out - do {} while (((c = ctl) & DISABLED) == 0 && - (c & ACTIVE) != 0 && - !CTL.weakCompareAndSet - (this, c, c & ~ACTIVE)); - throw ex; - } - } - } - return stat; - } - - private void signalWaiter(Thread w) { - waiter = null; - LockSupport.unpark(w); // release producer - } - - /** - * Nulls out most fields, mainly to avoid garbage retention - * until publisher unsubscribes, but also to help cleanly stop - * upon error by nulling required components. - */ - private void detach() { - Thread w = waiter; - executor = null; - subscriber = null; - pendingError = null; - signalWaiter(w); - } - - /** - * Issues error signal, asynchronously if a task is running, - * else synchronously. - */ - final void onError(Throwable ex) { - for (int c;;) { - if (((c = ctl) & (ERROR | DISABLED)) != 0) - break; - else if ((c & ACTIVE) != 0) { - pendingError = ex; - if (CTL.compareAndSet(this, c, c | ERROR)) - break; // cause consumer task to exit - } - else if (CTL.compareAndSet(this, c, DISABLED)) { - Flow.Subscriber s = subscriber; - if (s != null && ex != null) { - try { - s.onError(ex); - } catch (Throwable ignore) { - } - } - detach(); - break; - } + final void tryStart() { + try { + Executor e; + ConsumerTask task = new ConsumerTask(this); + if ((e = executor) != null) // skip if disabled on error + e.execute(task); + } catch (RuntimeException | Error ex) { + getAndBitwiseOrCtl(ERROR | CLOSED); + throw ex; } } + // Signals to consumer tasks + /** - * Tries to start consumer task upon a signal or request; - * disables on failure. + * Sets the given control bits, starting task if not running or closed. + * @param bits state bits, assumed to include RUN but not CLOSED */ - private void startOrDisable() { - Executor e; - if ((e = executor) != null) { // skip if already disabled - try { - e.execute(new ConsumerTask(this)); - } catch (Throwable ex) { // back out and force signal - for (int c;;) { - if ((c = ctl) == DISABLED || (c & ACTIVE) == 0) - break; - if (CTL.compareAndSet(this, c, c & ~ACTIVE)) { - onError(ex); - break; - } - } - } - } + final void startOnSignal(int bits) { + if ((ctl & bits) != bits && + (getAndBitwiseOrCtl(bits) & (RUN | CLOSED)) == 0) + tryStart(); + } + + final void onSubscribe() { + startOnSignal(RUN | ACTIVE); } final void onComplete() { - for (int c;;) { - if ((c = ctl) == DISABLED) - break; - if (CTL.compareAndSet(this, c, - c | (ACTIVE | CONSUME | COMPLETE))) { - if ((c & ACTIVE) == 0) - startOrDisable(); - break; - } - } + startOnSignal(RUN | ACTIVE | COMPLETE); } - final void onSubscribe() { - for (int c;;) { - if ((c = ctl) == DISABLED) - break; - if (CTL.compareAndSet(this, c, - c | (ACTIVE | CONSUME | SUBSCRIBE))) { - if ((c & ACTIVE) == 0) - startOrDisable(); - break; - } + final void onError(Throwable ex) { + int c; Object[] a; // to null out buffer on async error + if (ex != null) + pendingError = ex; // races are OK + if (((c = getAndBitwiseOrCtl(ERROR | RUN | ACTIVE)) & CLOSED) == 0) { + if ((c & RUN) == 0) + tryStart(); + else if ((a = array) != null) + Arrays.fill(a, null); } } - /** - * Causes consumer task to exit if active (without reporting - * onError unless there is already a pending error), and - * disables. - */ - public void cancel() { - for (int c;;) { - if ((c = ctl) == DISABLED) - break; - else if ((c & ACTIVE) != 0) { - if (CTL.compareAndSet(this, c, - c | (CONSUME | ERROR))) - break; - } - else if (CTL.compareAndSet(this, c, DISABLED)) { - detach(); - break; - } - } + public final void cancel() { + onError(null); } - /** - * Adds to demand and possibly starts task. - */ - public void request(long n) { + public final void request(long n) { if (n > 0L) { for (;;) { - long prev = demand, d; - if ((d = prev + n) < prev) // saturate - d = Long.MAX_VALUE; - if (DEMAND.compareAndSet(this, prev, d)) { - for (int c, h;;) { - if ((c = ctl) == DISABLED) - break; - else if ((c & ACTIVE) != 0) { - if ((c & CONSUME) != 0 || - CTL.compareAndSet(this, c, c | CONSUME)) - break; - } - else if ((h = head) != tail) { - if (CTL.compareAndSet(this, c, - c | (ACTIVE|CONSUME))) { - startOrDisable(); - break; - } - } - else if (head == h && tail == h) - break; // else stale - if (demand == 0L) - break; - } + long p = demand, d = p + n; // saturate + if (casDemand(p, d < p ? Long.MAX_VALUE : d)) break; - } } + startOnSignal(RUN | ACTIVE | REQS); } else onError(new IllegalArgumentException( "non-positive subscription request")); } - public final boolean isReleasable() { // for ManagedBlocker - T item = putItem; - if (item != null) { - if ((putStat = offer(item)) == 0) - return false; - putItem = null; - } - return true; - } - - public final boolean block() { // for ManagedBlocker - T item = putItem; - if (item != null) { - putItem = null; - long nanos = timeout; - long deadline = (nanos > 0L) ? System.nanoTime() + nanos : 0L; - while ((putStat = offer(item)) == 0) { - if (Thread.interrupted()) { - timeout = INTERRUPTED; - if (nanos > 0L) - break; - } - else if (nanos > 0L && - (nanos = deadline - System.nanoTime()) <= 0L) - break; - else if (waiter == null) - waiter = Thread.currentThread(); - else { - if (nanos > 0L) - LockSupport.parkNanos(this, nanos); - else - LockSupport.park(this); - waiter = null; - } - } - } - waiter = null; - return true; - } + // Consumer task actions /** - * Consumer loop, called from ConsumerTask, or indirectly - * when helping during submit. + * Consumer loop, called from ConsumerTask, or indirectly when + * helping during submit. */ final void consume() { - Flow.Subscriber s; - int h = head; - if ((s = subscriber) != null) { // else disabled - for (;;) { - long d = demand; - int c; Object[] a; int n, i; Object x; Thread w; - if (((c = ctl) & (ERROR | SUBSCRIBE | DISABLED)) != 0) { - if (!checkControl(s, c)) - break; - } - else if ((a = array) == null || h == tail || - (n = a.length) == 0 || - (x = QA.getAcquire(a, i = (n - 1) & h)) == null) { - if (!checkEmpty(s, c)) - break; + Subscriber s; + if ((s = subscriber) != null) { // hoist checks + subscribeOnOpen(s); + long d = demand; + for (int h = head, t = tail;;) { + int c, taken; boolean empty; + if (((c = ctl) & ERROR) != 0) { + closeOnError(s, null); + break; } - else if (d == 0L) { - if (!checkDemand(c)) - break; + else if ((taken = takeItems(s, d, h)) > 0) { + head = h += taken; + d = subtractDemand(taken); + } + else if ((empty = (t == h)) && (c & COMPLETE) != 0) { + closeOnComplete(s); // end of stream + break; } - else if (((c & CONSUME) != 0 || - CTL.compareAndSet(this, c, c | CONSUME)) && - QA.compareAndSet(a, i, x, null)) { - HEAD.setRelease(this, ++h); - DEMAND.getAndAdd(this, -1L); - if ((w = waiter) != null) - signalWaiter(w); - try { - @SuppressWarnings("unchecked") T y = (T) x; - s.onNext(y); - } catch (Throwable ex) { - handleOnNext(s, ex); - } + else if ((d = demand) == 0L && (c & REQS) != 0) + weakCasCtl(c, c & ~REQS); // exhausted demand + else if (d != 0L && (c & REQS) == 0) + weakCasCtl(c, c | REQS); // new demand + else if (t == (t = tail) && (empty || d == 0L)) { + int bit = ((c & ACTIVE) != 0) ? ACTIVE : RUN; + if (weakCasCtl(c, c & ~bit) && bit == RUN) + break; // un-keep-alive or exit } } } } /** - * Responds to control events in consume(). + * Consumes some items until unavailable or bound or error. + * + * @param s subscriber + * @param d current demand + * @param h current head + * @return number taken */ - private boolean checkControl(Flow.Subscriber s, int c) { - boolean stat = true; - if ((c & SUBSCRIBE) != 0) { - if (CTL.compareAndSet(this, c, c & ~SUBSCRIBE)) { - try { - if (s != null) - s.onSubscribe(this); - } catch (Throwable ex) { - onError(ex); - } + final int takeItems(Subscriber s, long d, int h) { + Object[] a; + int k = 0, cap; + if ((a = array) != null && (cap = a.length) > 0) { + int m = cap - 1, b = (m >>> 3) + 1; // min(1, cap/8) + int n = (d < (long)b) ? (int)d : b; + for (; k < n; ++h, ++k) { + Object x = QA.getAndSet(a, h & m, null); + if (waiting != 0) + signalWaiter(); + if (x == null) + break; + else if (!consumeNext(s, x)) + break; } } - else if ((c & ERROR) != 0) { - Throwable ex = pendingError; - ctl = DISABLED; // no need for CAS - if (ex != null) { // null if errorless cancel - try { - if (s != null) - s.onError(ex); - } catch (Throwable ignore) { - } - } - } - else { - detach(); - stat = false; - } - return stat; + return k; } - /** - * Responds to apparent emptiness in consume(). - */ - private boolean checkEmpty(Flow.Subscriber s, int c) { - boolean stat = true; - if (head == tail) { - if ((c & CONSUME) != 0) - CTL.compareAndSet(this, c, c & ~CONSUME); - else if ((c & COMPLETE) != 0) { - if (CTL.compareAndSet(this, c, DISABLED)) { - try { - if (s != null) - s.onComplete(); - } catch (Throwable ignore) { - } - } - } - else if (CTL.compareAndSet(this, c, c & ~ACTIVE)) - stat = false; + final boolean consumeNext(Subscriber s, Object x) { + try { + @SuppressWarnings("unchecked") T y = (T) x; + if (s != null) + s.onNext(y); + return true; + } catch (Throwable ex) { + handleOnNext(s, ex); + return false; } - return stat; - } - - /** - * Responds to apparent zero demand in consume(). - */ - private boolean checkDemand(int c) { - boolean stat = true; - if (demand == 0L) { - if ((c & CONSUME) != 0) - CTL.compareAndSet(this, c, c & ~CONSUME); - else if (CTL.compareAndSet(this, c, c & ~ACTIVE)) - stat = false; - } - return stat; } /** * Processes exception in Subscriber.onNext. */ - private void handleOnNext(Flow.Subscriber s, Throwable ex) { - BiConsumer, ? super Throwable> h; - if ((h = onNextHandler) != null) { - try { + final void handleOnNext(Subscriber s, Throwable ex) { + BiConsumer, ? super Throwable> h; + try { + if ((h = onNextHandler) != null) h.accept(s, ex); - } catch (Throwable ignore) { + } catch (Throwable ignore) { + } + closeOnError(s, ex); + } + + /** + * Issues subscriber.onSubscribe if this is first signal. + */ + final void subscribeOnOpen(Subscriber s) { + if ((ctl & OPEN) == 0 && (getAndBitwiseOrCtl(OPEN) & OPEN) == 0) + consumeSubscribe(s); + } + + final void consumeSubscribe(Subscriber s) { + try { + if (s != null) // ignore if disabled + s.onSubscribe(this); + } catch (Throwable ex) { + closeOnError(s, ex); + } + } + + /** + * Issues subscriber.onComplete unless already closed. + */ + final void closeOnComplete(Subscriber s) { + if ((getAndBitwiseOrCtl(CLOSED) & CLOSED) == 0) + consumeComplete(s); + } + + final void consumeComplete(Subscriber s) { + try { + if (s != null) + s.onComplete(); + } catch (Throwable ignore) { + } + } + + /** + * Issues subscriber.onError, and unblocks producer if needed. + */ + final void closeOnError(Subscriber s, Throwable ex) { + if ((getAndBitwiseOrCtl(ERROR | CLOSED) & CLOSED) == 0) { + if (ex == null) + ex = pendingError; + pendingError = null; // detach + executor = null; // suppress racing start calls + signalWaiter(); + consumeError(s, ex); + } + } + + final void consumeError(Subscriber s, Throwable ex) { + try { + if (ex != null && s != null) + s.onError(ex); + } catch (Throwable ignore) { + } + } + + // Blocking support + + /** + * Unblocks waiting producer. + */ + final void signalWaiter() { + Thread w; + waiting = 0; + if ((w = waiter) != null) + LockSupport.unpark(w); + } + + /** + * Returns true if closed or space available. + * For ManagedBlocker. + */ + public final boolean isReleasable() { + Object[] a; int cap; + return ((ctl & CLOSED) != 0 || + ((a = array) != null && (cap = a.length) > 0 && + QA.getAcquire(a, (cap - 1) & tail) == null)); + } + + /** + * Helps or blocks until timeout, closed, or space available. + */ + final void awaitSpace(long nanos) { + if (!isReleasable()) { + ForkJoinPool.helpAsyncBlocker(executor, this); + if (!isReleasable()) { + timeout = nanos; + try { + ForkJoinPool.managedBlock(this); + } catch (InterruptedException ie) { + timeout = INTERRUPTED; + } + if (timeout == INTERRUPTED) + Thread.currentThread().interrupt(); } } - onError(ex); + } + + /** + * Blocks until closed, space available or timeout. + * For ManagedBlocker. + */ + public final boolean block() { + long nanos = timeout; + boolean timed = (nanos < Long.MAX_VALUE); + long deadline = timed ? System.nanoTime() + nanos : 0L; + while (!isReleasable()) { + if (Thread.interrupted()) { + timeout = INTERRUPTED; + if (timed) + break; + } + else if (timed && (nanos = deadline - System.nanoTime()) <= 0L) + break; + else if (waiter == null) + waiter = Thread.currentThread(); + else if (waiting == 0) + waiting = 1; + else if (timed) + LockSupport.parkNanos(this, nanos); + else + LockSupport.park(this); + } + waiter = null; + waiting = 0; + return true; } // VarHandle mechanics - private static final VarHandle CTL; - private static final VarHandle TAIL; - private static final VarHandle HEAD; - private static final VarHandle DEMAND; - private static final VarHandle QA; + static final VarHandle CTL; + static final VarHandle DEMAND; + static final VarHandle QA; static { try { MethodHandles.Lookup l = MethodHandles.lookup(); CTL = l.findVarHandle(BufferedSubscription.class, "ctl", int.class); - TAIL = l.findVarHandle(BufferedSubscription.class, "tail", - int.class); - HEAD = l.findVarHandle(BufferedSubscription.class, "head", - int.class); DEMAND = l.findVarHandle(BufferedSubscription.class, "demand", long.class); QA = MethodHandles.arrayElementVarHandle(Object[].class); diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java Tue Dec 05 10:28:45 2017 +0000 @@ -422,8 +422,8 @@ * @return {@code true} if interrupted while waiting */ final boolean acquireQueued(final Node node, long arg) { + boolean interrupted = false; try { - boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { @@ -431,12 +431,13 @@ p.next = null; // help GC return interrupted; } - if (shouldParkAfterFailedAcquire(p, node) && - parkAndCheckInterrupt()) - interrupted = true; + if (shouldParkAfterFailedAcquire(p, node)) + interrupted |= parkAndCheckInterrupt(); } } catch (Throwable t) { cancelAcquire(node); + if (interrupted) + selfInterrupt(); throw t; } } @@ -510,8 +511,8 @@ */ private void doAcquireShared(long arg) { final Node node = addWaiter(Node.SHARED); + boolean interrupted = false; try { - boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head) { @@ -519,18 +520,18 @@ if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC - if (interrupted) - selfInterrupt(); return; } } - if (shouldParkAfterFailedAcquire(p, node) && - parkAndCheckInterrupt()) - interrupted = true; + if (shouldParkAfterFailedAcquire(p, node)) + interrupted |= parkAndCheckInterrupt(); } } catch (Throwable t) { cancelAcquire(node); throw t; + } finally { + if (interrupted) + selfInterrupt(); } } diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Tue Dec 05 10:28:45 2017 +0000 @@ -505,7 +505,7 @@ * * @return the predecessor of this node */ - final Node predecessor() throws NullPointerException { + final Node predecessor() { Node p = prev; if (p == null) throw new NullPointerException(); @@ -902,8 +902,8 @@ * @return {@code true} if interrupted while waiting */ final boolean acquireQueued(final Node node, int arg) { + boolean interrupted = false; try { - boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { @@ -911,12 +911,13 @@ p.next = null; // help GC return interrupted; } - if (shouldParkAfterFailedAcquire(p, node) && - parkAndCheckInterrupt()) - interrupted = true; + if (shouldParkAfterFailedAcquire(p, node)) + interrupted |= parkAndCheckInterrupt(); } } catch (Throwable t) { cancelAcquire(node); + if (interrupted) + selfInterrupt(); throw t; } } @@ -990,8 +991,8 @@ */ private void doAcquireShared(int arg) { final Node node = addWaiter(Node.SHARED); + boolean interrupted = false; try { - boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head) { @@ -999,18 +1000,18 @@ if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC - if (interrupted) - selfInterrupt(); return; } } - if (shouldParkAfterFailedAcquire(p, node) && - parkAndCheckInterrupt()) - interrupted = true; + if (shouldParkAfterFailedAcquire(p, node)) + interrupted |= parkAndCheckInterrupt(); } } catch (Throwable t) { cancelAcquire(node); throw t; + } finally { + if (interrupted) + selfInterrupt(); } } diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/java/util/stream/Collectors.java --- a/src/java.base/share/classes/java/util/stream/Collectors.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/java/util/stream/Collectors.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -116,6 +116,8 @@ = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH)); static final Set CH_NOID = Collections.emptySet(); + static final Set CH_UNORDERED_NOID + = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED)); private Collectors() { } @@ -279,6 +281,26 @@ } /** + * Returns a {@code Collector} that accumulates the input elements into an + * unmodifiable List in encounter + * order. The returned Collector disallows null values and will throw + * {@code NullPointerException} if it is presented with a null value. + * + * @param the type of the input elements + * @return a {@code Collector} that accumulates the input elements into an + * unmodifiable List in encounter order + * @since 10 + */ + @SuppressWarnings("unchecked") + public static + Collector> toUnmodifiableList() { + return new CollectorImpl<>((Supplier>) ArrayList::new, List::add, + (left, right) -> { left.addAll(right); return left; }, + list -> (List)List.of(list.toArray()), + CH_NOID); + } + + /** * Returns a {@code Collector} that accumulates the input elements into a * new {@code Set}. There are no guarantees on the type, mutability, * serializability, or thread-safety of the {@code Set} returned; if more @@ -306,6 +328,36 @@ } /** + * Returns a {@code Collector} that accumulates the input elements into an + * unmodifiable Set. The returned + * Collector disallows null values and will throw {@code NullPointerException} + * if it is presented with a null value. If the input contains duplicate elements, + * an arbitrary element of the duplicates is preserved. + * + *

          This is an {@link Collector.Characteristics#UNORDERED unordered} + * Collector. + * + * @param the type of the input elements + * @return a {@code Collector} that accumulates the input elements into an + * unmodifiable Set + * @since 10 + */ + @SuppressWarnings("unchecked") + public static + Collector> toUnmodifiableSet() { + return new CollectorImpl<>((Supplier>) HashSet::new, Set::add, + (left, right) -> { + if (left.size() < right.size()) { + right.addAll(left); return right; + } else { + left.addAll(right); return left; + } + }, + set -> (Set)Set.of(set.toArray()), + CH_UNORDERED_NOID); + } + + /** * Returns a {@code Collector} that concatenates the input elements into a * {@code String}, in encounter order. * @@ -1353,7 +1405,7 @@ *

          If the mapped keys contain duplicates (according to * {@link Object#equals(Object)}), an {@code IllegalStateException} is * thrown when the collection operation is performed. If the mapped keys - * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)} + * might have duplicates, use {@link #toMap(Function, Function, BinaryOperator)} * instead. * *

          There are no guarantees on the type, mutability, serializability, @@ -1411,6 +1463,45 @@ } /** + * Returns a {@code Collector} that accumulates the input elements into an + * unmodifiable Map, + * whose keys and values are the result of applying the provided + * mapping functions to the input elements. + * + *

          If the mapped keys contain duplicates (according to + * {@link Object#equals(Object)}), an {@code IllegalStateException} is + * thrown when the collection operation is performed. If the mapped keys + * might have duplicates, use {@link #toUnmodifiableMap(Function, Function, BinaryOperator)} + * to handle merging of the values. + * + *

          The returned Collector disallows null keys and values. If either mapping function + * returns null, {@code NullPointerException} will be thrown. + * + * @param the type of the input elements + * @param the output type of the key mapping function + * @param the output type of the value mapping function + * @param keyMapper a mapping function to produce keys, must be non-null + * @param valueMapper a mapping function to produce values, must be non-null + * @return a {@code Collector} that accumulates the input elements into an + * unmodifiable Map, whose keys and values + * are the result of applying the provided mapping functions to the input elements + * @throws NullPointerException if either keyMapper or valueMapper is null + * + * @see #toUnmodifiableMap(Function, Function, BinaryOperator) + * @since 10 + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static + Collector> toUnmodifiableMap(Function keyMapper, + Function valueMapper) { + Objects.requireNonNull(keyMapper, "keyMapper"); + Objects.requireNonNull(valueMapper, "valueMapper"); + return collectingAndThen( + toMap(keyMapper, valueMapper), + map -> (Map)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0]))); + } + + /** * Returns a {@code Collector} that accumulates elements into a * {@code Map} whose keys and values are the result of applying the provided * mapping functions to the input elements. @@ -1473,6 +1564,51 @@ return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); } + + /** + * Returns a {@code Collector} that accumulates the input elements into an + * unmodifiable Map, + * whose keys and values are the result of applying the provided + * mapping functions to the input elements. + * + *

          If the mapped + * keys contain duplicates (according to {@link Object#equals(Object)}), + * the value mapping function is applied to each equal element, and the + * results are merged using the provided merging function. + * + *

          The returned Collector disallows null keys and values. If either mapping function + * returns null, {@code NullPointerException} will be thrown. + * + * @param the type of the input elements + * @param the output type of the key mapping function + * @param the output type of the value mapping function + * @param keyMapper a mapping function to produce keys, must be non-null + * @param valueMapper a mapping function to produce values, must be non-null + * @param mergeFunction a merge function, used to resolve collisions between + * values associated with the same key, as supplied + * to {@link Map#merge(Object, Object, BiFunction)}, + * must be non-null + * @return a {@code Collector} that accumulates the input elements into an + * unmodifiable Map, whose keys and values + * are the result of applying the provided mapping functions to the input elements + * @throws NullPointerException if the keyMapper, valueMapper, or mergeFunction is null + * + * @see #toUnmodifiableMap(Function, Function) + * @since 10 + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static + Collector> toUnmodifiableMap(Function keyMapper, + Function valueMapper, + BinaryOperator mergeFunction) { + Objects.requireNonNull(keyMapper, "keyMapper"); + Objects.requireNonNull(valueMapper, "valueMapper"); + Objects.requireNonNull(mergeFunction, "mergeFunction"); + return collectingAndThen( + toMap(keyMapper, valueMapper, mergeFunction, HashMap::new), + map -> (Map)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0]))); + } + /** * Returns a {@code Collector} that accumulates elements into a * {@code Map} whose keys and values are the result of applying the provided diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java --- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ import java.nio.channels.FileChannel; import java.nio.channels.SeekableByteChannel; import java.nio.file.*; -import java.nio.file.DirectoryStream.Filter;; +import java.nio.file.DirectoryStream.Filter; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.FileAttribute; @@ -274,7 +274,7 @@ if (o.path.length() == 0) { return this; } - StringBuilder sb = new StringBuilder(path.length() + o.path.length()); + StringBuilder sb = new StringBuilder(path.length() + o.path.length() + 1); sb.append(path); if (path.charAt(path.length() - 1) != '/') sb.append('/'); @@ -478,12 +478,15 @@ // Remove DotSlash(./) and resolve DotDot (..) components private String getResolved() { - if (path.length() == 0) { + int length = path.length(); + if (length == 0 || (path.indexOf("./") == -1 && path.charAt(length - 1) != '.')) { return path; + } else { + return resolvePath(); } - if (path.indexOf('.') == -1) { - return path; - } + } + + private String resolvePath() { int length = path.length(); char[] to = new char[length]; int nc = getNameCount(); diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/jdk/internal/util/jar/VersionedStream.java --- a/src/java.base/share/classes/jdk/internal/util/jar/VersionedStream.java Tue Dec 05 10:21:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.internal.util.jar; - -import java.util.Objects; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.stream.Stream; - -public class VersionedStream { - private static final String META_INF_VERSIONS = "META-INF/versions/"; - - /** - * Returns a stream of versioned entries, derived from the base names of - * all entries in a multi-release {@code JarFile} that are present either in - * the base directory or in any versioned directory with a version number - * less than or equal to the {@code Runtime.Version::major} that the - * {@code JarFile} was opened with. These versioned entries are aliases - * for the real entries -- i.e. the names are base names and the content - * may come from a versioned directory entry. If the {@code jarFile} is not - * a multi-release jar, a stream of all entries is returned. - * - * @param jf the input JarFile - * @return stream of entries - * @since 9 - */ - public static Stream stream(JarFile jf) { - if (jf.isMultiRelease()) { - int version = jf.getVersion().major(); - return jf.stream() - .map(je -> getBaseSuffix(je, version)) - .filter(Objects::nonNull) - .distinct() - .map(jf::getJarEntry); - } - return jf.stream(); - } - - private static String getBaseSuffix(JarEntry je, int version) { - String name = je.getName(); - if (name.startsWith(META_INF_VERSIONS)) { - int len = META_INF_VERSIONS.length(); - int index = name.indexOf('/', len); - if (index == -1 || index == (name.length() - 1)) { - // filter out META-INF/versions/* and META-INF/versions/*/ - return null; - } - try { - if (Integer.parseInt(name, len, index, 10) > version) { - // not an integer - return null; - } - } catch (NumberFormatException x) { - // silently remove malformed entries - return null; - } - // We know name looks like META-INF/versions/*/* - return name.substring(index + 1); - } - return name; - } -} diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/classes/sun/security/tools/keytool/Main.java --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java Tue Dec 05 10:28:45 2017 +0000 @@ -2746,12 +2746,12 @@ if (rfc) { dumpCert(cert, out); } else { - out.println("Certificate #" + i++); + out.println("Certificate #" + i); out.println("===================================="); printX509Cert((X509Certificate)cert, out); out.println(); } - checkWeak(oneInMany(rb.getString("the.certificate"), i, chain.size()), cert); + checkWeak(oneInMany(rb.getString("the.certificate"), i++, chain.size()), cert); } catch (Exception e) { if (debug) { e.printStackTrace(); diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/native/include/jvm.h --- a/src/java.base/share/native/include/jvm.h Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/native/include/jvm.h Tue Dec 05 10:28:45 2017 +0000 @@ -262,21 +262,9 @@ /* * java.lang.SecurityManager */ -JNIEXPORT jclass JNICALL -JVM_CurrentLoadedClass(JNIEnv *env); - -JNIEXPORT jobject JNICALL -JVM_CurrentClassLoader(JNIEnv *env); - JNIEXPORT jobjectArray JNICALL JVM_GetClassContext(JNIEnv *env); -JNIEXPORT jint JNICALL -JVM_ClassDepth(JNIEnv *env, jstring name); - -JNIEXPORT jint JNICALL -JVM_ClassLoaderDepth(JNIEnv *env); - /* * java.lang.Package */ diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/native/libjava/SecurityManager.c --- a/src/java.base/share/native/libjava/SecurityManager.c Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/native/libjava/SecurityManager.c Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,53 +76,3 @@ return JVM_GetClassContext(env); } - -JNIEXPORT jclass JNICALL -Java_java_lang_SecurityManager_currentLoadedClass0(JNIEnv *env, jobject this) -{ - /* Make sure the security manager instance is initialized */ - if (!check(env, this)) { - return NULL; /* exception */ - } - - return JVM_CurrentLoadedClass(env); -} - -JNIEXPORT jobject JNICALL -Java_java_lang_SecurityManager_currentClassLoader0(JNIEnv *env, jobject this) -{ - /* Make sure the security manager instance is initialized */ - if (!check(env, this)) { - return NULL; /* exception */ - } - - return JVM_CurrentClassLoader(env); -} - -JNIEXPORT jint JNICALL -Java_java_lang_SecurityManager_classDepth(JNIEnv *env, jobject this, - jstring name) -{ - /* Make sure the security manager instance is initialized */ - if (!check(env, this)) { - return -1; /* exception */ - } - - if (name == NULL) { - JNU_ThrowNullPointerException(env, 0); - return -1; - } - - return JVM_ClassDepth(env, name); -} - -JNIEXPORT jint JNICALL -Java_java_lang_SecurityManager_classLoaderDepth0(JNIEnv *env, jobject this) -{ - /* Make sure the security manager instance is initialized */ - if (!check(env, this)) { - return -1; /* exception */ - } - - return JVM_ClassLoaderDepth(env); -} diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/native/libzip/Deflater.c --- a/src/java.base/share/native/libzip/Deflater.c Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/native/libzip/Deflater.c Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -164,17 +164,14 @@ res = deflateParams(strm, level, strategy); (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0); (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0); - switch (res) { case Z_OK: (*env)->SetBooleanField(env, this, setParamsID, JNI_FALSE); + case Z_BUF_ERROR: this_off += this_len - strm->avail_in; (*env)->SetIntField(env, this, offID, this_off); (*env)->SetIntField(env, this, lenID, strm->avail_in); return (jint) (len - strm->avail_out); - case Z_BUF_ERROR: - (*env)->SetBooleanField(env, this, setParamsID, JNI_FALSE); - return 0; default: JNU_ThrowInternalError(env, strm->msg); return 0; @@ -203,19 +200,17 @@ res = deflate(strm, finish ? Z_FINISH : flush); (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0); (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0); - switch (res) { case Z_STREAM_END: (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE); /* fall through */ case Z_OK: + case Z_BUF_ERROR: this_off += this_len - strm->avail_in; (*env)->SetIntField(env, this, offID, this_off); (*env)->SetIntField(env, this, lenID, strm->avail_in); return len - strm->avail_out; - case Z_BUF_ERROR: - return 0; - default: + default: JNU_ThrowInternalError(env, strm->msg); return 0; } diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/native/libzip/zlib/deflate.c --- a/src/java.base/share/native/libzip/zlib/deflate.c Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/native/libzip/zlib/deflate.c Tue Dec 05 10:28:45 2017 +0000 @@ -505,8 +505,6 @@ s->pending = 0; s->pending_out = s->pending_buf; - s->high_water = 0; /* reset to its inital value 0 */ - if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } @@ -520,7 +518,7 @@ s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; + s->last_flush = -2; _tr_init(s); @@ -613,7 +611,7 @@ func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && - s->high_water) { + s->last_flush != -2) { /* Flush the last buffer: */ int err = deflate(strm, Z_BLOCK); if (err == Z_STREAM_ERROR) diff -r 10b34c929b4f -r 64298b1e890b src/java.base/share/native/libzip/zlib/patches/ChangeLog_java --- a/src/java.base/share/native/libzip/zlib/patches/ChangeLog_java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/share/native/libzip/zlib/patches/ChangeLog_java Tue Dec 05 10:28:45 2017 +0000 @@ -93,4 +93,6 @@ s->status = #ifdef GZIP +(7) deflate.c undo (6), replaced withe the official zlib repo fix see#305/#f969409 + diff -r 10b34c929b4f -r 64298b1e890b src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java --- a/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java Tue Dec 05 10:28:45 2017 +0000 @@ -45,41 +45,33 @@ ExtendedSocketOptions.getInstance(); protected void setOption(SocketOption name, T value) throws IOException { - if (!extendedOptions.isOptionSupported(name)) { - if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { - super.setOption(name, value); + if (isClosed()) { + throw new SocketException("Socket closed"); + } + if (supportedOptions().contains(name)) { + if (extendedOptions.isOptionSupported(name)) { + extendedOptions.setOption(fd, name, value); } else { - if (supportedOptions().contains(name)) { - super.setOption(name, value); - } else { - throw new UnsupportedOperationException("unsupported option"); - } + super.setOption(name, value); } } else { - if (isClosed()) { - throw new SocketException("Socket closed"); - } - extendedOptions.setOption(fd, name, value); + throw new UnsupportedOperationException("unsupported option"); } } @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { - if (!extendedOptions.isOptionSupported(name)) { - if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { - return super.getOption(name); + if (isClosed()) { + throw new SocketException("Socket closed"); + } + if (supportedOptions().contains(name)) { + if (extendedOptions.isOptionSupported(name)) { + return (T) extendedOptions.getOption(fd, name); } else { - if (supportedOptions().contains(name)) { - return super.getOption(name); - } else { - throw new UnsupportedOperationException("unsupported option"); - } + return super.getOption(name); } } else { - if (isClosed()) { - throw new SocketException("Socket closed"); - } - return (T) extendedOptions.getOption(fd, name); + throw new UnsupportedOperationException("unsupported option"); } } diff -r 10b34c929b4f -r 64298b1e890b src/java.base/unix/classes/java/net/PlainSocketImpl.java --- a/src/java.base/unix/classes/java/net/PlainSocketImpl.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.base/unix/classes/java/net/PlainSocketImpl.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,58 +58,57 @@ ExtendedSocketOptions.getInstance(); protected void setOption(SocketOption name, T value) throws IOException { - if (!extendedOptions.isOptionSupported(name)) { - if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { - super.setOption(name, value); + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + if (supportedOptions().contains(name)) { + if (extendedOptions.isOptionSupported(name)) { + extendedOptions.setOption(fd, name, value); } else { - if (supportedOptions().contains(name)) { - super.setOption(name, value); - } else { - throw new UnsupportedOperationException("unsupported option"); - } + super.setOption(name, value); } } else { - if (getSocket() == null) { - throw new UnsupportedOperationException("unsupported option"); - } - if (isClosedOrPending()) { - throw new SocketException("Socket closed"); - } - extendedOptions.setOption(fd, name, value); + throw new UnsupportedOperationException("unsupported option"); } } @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { - if (!extendedOptions.isOptionSupported(name)) { - if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { - return super.getOption(name); + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + if (supportedOptions().contains(name)) { + if (extendedOptions.isOptionSupported(name)) { + return (T) extendedOptions.getOption(fd, name); } else { - if (supportedOptions().contains(name)) { - return super.getOption(name); - } else { - throw new UnsupportedOperationException("unsupported option"); - } + return super.getOption(name); } } else { - if (getSocket() == null) { - throw new UnsupportedOperationException("unsupported option"); - } - if (isClosedOrPending()) { - throw new SocketException("Socket closed"); - } - return (T) extendedOptions.getOption(fd, name); + throw new UnsupportedOperationException("unsupported option"); } } protected Set> supportedOptions() { HashSet> options = new HashSet<>(super.supportedOptions()); - if (getSocket() != null) { - options.addAll(extendedOptions.options()); - } + addExtSocketOptions(extendedOptions.options(), options); return options; } + private void addExtSocketOptions(Set> extOptions, + Set> options) { + extOptions.forEach((option) -> { + if (option.name().equals("SO_FLOW_SLA")) { + // SO_FLOW_SLA is Solaris specific option which is not applicable + // for ServerSockets. + // getSocket() will always return null for server socket + if (getSocket() != null) { + options.add(option); + } + } else { + options.add(option); + } + }); + } protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { diff -r 10b34c929b4f -r 64298b1e890b src/java.desktop/share/classes/sun/applet/AppletSecurity.java --- a/src/java.desktop/share/classes/sun/applet/AppletSecurity.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.desktop/share/classes/sun/applet/AppletSecurity.java Tue Dec 05 10:28:45 2017 +0000 @@ -48,6 +48,8 @@ import sun.awt.AWTPermissions; import sun.security.util.SecurityConstants; +import static java.lang.StackWalker.*; +import static java.lang.StackWalker.Option.*; /** @@ -106,11 +108,90 @@ }); } + private static final StackWalker walker = + AccessController.doPrivileged( + (PrivilegedAction) () -> + StackWalker.getInstance(RETAIN_CLASS_REFERENCE)); + /** + * Returns the class loader of the most recently executing method from + * a class defined using a non-system class loader. A non-system + * class loader is defined as being a class loader that is not equal to + * the system class loader (as returned + * by {@link ClassLoader#getSystemClassLoader}) or one of its ancestors. + *

          + * This method will return + * null in the following three cases: + *

            + *
          1. All methods on the execution stack are from classes + * defined using the system class loader or one of its ancestors. + * + *
          2. All methods on the execution stack up to the first + * "privileged" caller + * (see {@link java.security.AccessController#doPrivileged}) + * are from classes + * defined using the system class loader or one of its ancestors. + * + *
          3. A call to checkPermission with + * java.security.AllPermission does not + * result in a SecurityException. + *
          + * + * NOTE: This is an implementation of the SecurityManager.currentClassLoader + * method that uses StackWalker. SecurityManager.currentClassLoader + * has been removed from SE. This is a temporary workaround which is + * only needed while applets are still supported. + * + * @return the class loader of the most recent occurrence on the stack + * of a method from a class defined using a non-system class + * loader. + */ + private static ClassLoader currentClassLoader() { + StackFrame f = + walker.walk(s -> s.takeWhile(AppletSecurity::isNonPrivileged) + .filter(AppletSecurity::isNonSystemFrame) + .findFirst()) + .orElse(null); + + SecurityManager sm = System.getSecurityManager(); + if (f != null && sm != null) { + try { + sm.checkPermission(new AllPermission()); + } catch (SecurityException se) { + return f.getDeclaringClass().getClassLoader(); + } + } + return null; + } + + /** + * Returns true if the StackFrame is not AccessController.doPrivileged. + */ + private static boolean isNonPrivileged(StackFrame f) { + // possibly other doPrivileged variants + Class c = f.getDeclaringClass(); + return c == AccessController.class && + f.getMethodName().equals("doPrivileged"); + } + + /** + * Returns true if the StackFrame is not from a class defined by the + * system class loader or one of its ancestors. + */ + private static boolean isNonSystemFrame(StackFrame f) { + ClassLoader loader = ClassLoader.getSystemClassLoader(); + ClassLoader ld = f.getDeclaringClass().getClassLoader(); + if (ld == null || ld == loader) return false; + + while ((loader = loader.getParent()) != null) { + if (ld == loader) + return false; + } + return true; + } + /** * get the current (first) instance of an AppletClassLoader on the stack. */ - @SuppressWarnings({"deprecation", - "removal"}) // SecurityManager.currentClassLoader() private AppletClassLoader currentAppletClassLoader() { // try currentClassLoader first diff -r 10b34c929b4f -r 64298b1e890b src/java.desktop/share/classes/sun/awt/FontDescriptor.java --- a/src/java.desktop/share/classes/sun/awt/FontDescriptor.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.desktop/share/classes/sun/awt/FontDescriptor.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; -import java.io.IOException;; +import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.StandardCharsets; diff -r 10b34c929b4f -r 64298b1e890b src/java.security.jgss/share/native/libj2gss/GSSLibStub.c --- a/src/java.security.jgss/share/native/libj2gss/GSSLibStub.c Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.security.jgss/share/native/libj2gss/GSSLibStub.c Tue Dec 05 10:28:45 2017 +0000 @@ -1410,7 +1410,6 @@ checkStatus(env, jobj, GSS_S_CONTEXT_EXPIRED, 0, "[GSSLibStub_getMic]"); return NULL; } - contextHdl = (gss_ctx_id_t) jlong_to_ptr(pContext); qop = (gss_qop_t) jqop; initGSSBuffer(env, jmsg, &msg); if ((*env)->ExceptionCheck(env)) { diff -r 10b34c929b4f -r 64298b1e890b src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java --- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java Tue Dec 05 10:28:45 2017 +0000 @@ -505,7 +505,7 @@ } // add namespace declarations for (NamespaceDeclaration namespace : this.namespaceDeclarations) { - target.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri); + newElement.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri); } // add attribute declarations for (AttributeDeclaration attribute : this.attributeDeclarations) { diff -r 10b34c929b4f -r 64298b1e890b src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java --- a/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java Tue Dec 05 10:28:45 2017 +0000 @@ -499,7 +499,7 @@ } // add namespace declarations for (NamespaceDeclaration namespace : this.namespaceDeclarations) { - target.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri); + newElement.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri); } // add attribute declarations for (AttributeDeclaration attribute : this.attributeDeclarations) { diff -r 10b34c929b4f -r 64298b1e890b src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java Tue Dec 05 10:28:45 2017 +0000 @@ -32,6 +32,7 @@ * * @version $Id: ConstantDouble.java 1747278 2016-06-07 17:28:43Z britter $ * @see Constant + * @LastModified: Nov 2017 */ public final class ConstantDouble extends Constant implements ConstantObject { @@ -121,6 +122,6 @@ */ @Override public Object getConstantValue( final ConstantPool cp ) { - return new Double(bytes); + return bytes; } } diff -r 10b34c929b4f -r 64298b1e890b src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java Tue Dec 05 10:28:45 2017 +0000 @@ -32,6 +32,7 @@ * * @version $Id: ConstantFloat.java 1747278 2016-06-07 17:28:43Z britter $ * @see Constant + * @LastModified: Nov 2017 */ public final class ConstantFloat extends Constant implements ConstantObject { @@ -122,6 +123,6 @@ */ @Override public Object getConstantValue( final ConstantPool cp ) { - return new Float(bytes); + return bytes; } } diff -r 10b34c929b4f -r 64298b1e890b src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCONST.java --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCONST.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/DCONST.java Tue Dec 05 10:28:45 2017 +0000 @@ -26,6 +26,7 @@ *
          Stack: ... -> ..., 
          * * @version $Id: DCONST.java 1747278 2016-06-07 17:28:43Z britter $ + * @LastModified: Nov 2017 */ public class DCONST extends Instruction implements ConstantPushInstruction { @@ -55,7 +56,7 @@ @Override public Number getValue() { - return new Double(value); + return value; } diff -r 10b34c929b4f -r 64298b1e890b src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCONST.java --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCONST.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FCONST.java Tue Dec 05 10:28:45 2017 +0000 @@ -26,6 +26,7 @@ *
          Stack: ... -> ..., 
          * * @version $Id: FCONST.java 1747278 2016-06-07 17:28:43Z britter $ + * @LastModified: Nov 2017 */ public class FCONST extends Instruction implements ConstantPushInstruction { @@ -57,7 +58,7 @@ @Override public Number getValue() { - return new Float(value); + return value; } diff -r 10b34c929b4f -r 64298b1e890b src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -41,6 +40,7 @@ * * The invokedynamic instruction in The Java Virtual Machine Specification * @since 6.0 + * @LastModified: Nov 2017 */ public class INVOKEDYNAMIC extends InvokeInstruction { @@ -124,8 +124,14 @@ /** * Override the parent method because our classname is held elsewhere. + * + * @param cpg the ConstantPool generator + * @deprecated in FieldOrMethod + * + * @return name of the referenced class/interface */ @Override + @Deprecated public String getClassName( final ConstantPoolGen cpg ) { final ConstantPool cp = cpg.getConstantPool(); final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) cp.getConstant(super.getIndex(), Const.CONSTANT_InvokeDynamic); diff -r 10b34c929b4f -r 64298b1e890b src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java Tue Dec 05 10:28:45 2017 +0000 @@ -32,6 +32,7 @@ * @version $Id: InstructionFactory.java 1749603 2016-06-21 20:50:19Z ggregory $ * @see Const * @see InstructionConst + * @LastModified: Nov 2017 */ public class InstructionFactory { @@ -573,7 +574,7 @@ + short_names[dest - Const.T_CHAR]; Instruction i = null; try { - i = (Instruction) java.lang.Class.forName(name).newInstance(); + i = (Instruction) java.lang.Class.forName(name).getDeclaredConstructor().newInstance(); } catch (final Exception e) { throw new RuntimeException("Could not find instruction: " + name, e); } diff -r 10b34c929b4f -r 64298b1e890b src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java Tue Dec 05 10:28:45 2017 +0000 @@ -32,6 +32,7 @@ *
          Stack: ... -> ..., item
          * * @version $Id: LDC.java 1749603 2016-06-21 20:50:19Z ggregory $ + * @LastModified: Nov 2017 */ public class LDC extends CPInstruction implements PushInstruction, ExceptionThrower { @@ -104,9 +105,9 @@ c = cpg.getConstantPool().getConstant(i); return ((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes(); case com.sun.org.apache.bcel.internal.Const.CONSTANT_Float: - return new Float(((com.sun.org.apache.bcel.internal.classfile.ConstantFloat) c).getBytes()); + return ((com.sun.org.apache.bcel.internal.classfile.ConstantFloat) c).getBytes(); case com.sun.org.apache.bcel.internal.Const.CONSTANT_Integer: - return Integer.valueOf(((com.sun.org.apache.bcel.internal.classfile.ConstantInteger) c).getBytes()); + return ((com.sun.org.apache.bcel.internal.classfile.ConstantInteger) c).getBytes(); case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: final int nameIndex = ((com.sun.org.apache.bcel.internal.classfile.ConstantClass) c).getNameIndex(); c = cpg.getConstantPool().getConstant(nameIndex); diff -r 10b34c929b4f -r 64298b1e890b src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC2_W.java --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC2_W.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC2_W.java Tue Dec 05 10:28:45 2017 +0000 @@ -26,6 +26,7 @@ *
          Stack: ... -> ..., item.word1, item.word2
          * * @version $Id: LDC2_W.java 1749603 2016-06-21 20:50:19Z ggregory $ + * @LastModified: Nov 2017 */ public class LDC2_W extends CPInstruction implements PushInstruction { @@ -59,9 +60,9 @@ final com.sun.org.apache.bcel.internal.classfile.Constant c = cpg.getConstantPool().getConstant(super.getIndex()); switch (c.getTag()) { case com.sun.org.apache.bcel.internal.Const.CONSTANT_Long: - return Long.valueOf(((com.sun.org.apache.bcel.internal.classfile.ConstantLong) c).getBytes()); + return ((com.sun.org.apache.bcel.internal.classfile.ConstantLong) c).getBytes(); case com.sun.org.apache.bcel.internal.Const.CONSTANT_Double: - return new Double(((com.sun.org.apache.bcel.internal.classfile.ConstantDouble) c).getBytes()); + return ((com.sun.org.apache.bcel.internal.classfile.ConstantDouble) c).getBytes(); default: // Never reached throw new RuntimeException("Unknown or invalid constant type at " + super.getIndex()); } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS.java.template --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS.java.template Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS.java.template Tue Dec 05 10:28:45 2017 +0000 @@ -31,6 +31,7 @@ import sun.nio.cs.DoubleByte; import sun.nio.cs.HKSCS; import sun.nio.cs.HistoricallyNamedCharset; +import sun.nio.cs.*; import static sun.nio.cs.CharsetMapping.*; public class Big5_HKSCS extends Charset implements HistoricallyNamedCharset diff -r 10b34c929b4f -r 64298b1e890b src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS.java --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS.java Tue Dec 05 10:21:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.nio.cs.ext; - -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import sun.nio.cs.HistoricallyNamedCharset; -import sun.nio.cs.*; -import static sun.nio.cs.CharsetMapping.*; - -public class MS950_HKSCS extends Charset implements HistoricallyNamedCharset -{ - public MS950_HKSCS() { - super("x-MS950-HKSCS", ExtendedCharsets.aliasesFor("x-MS950-HKSCS")); - } - - public String historicalName() { - return "MS950_HKSCS"; - } - - public boolean contains(Charset cs) { - return ((cs.name().equals("US-ASCII")) - || (cs instanceof MS950) - || (cs instanceof MS950_HKSCS)); - } - - public CharsetDecoder newDecoder() { - return new Decoder(this); - } - - public CharsetEncoder newEncoder() { - return new Encoder(this); - } - - static class Decoder extends HKSCS.Decoder { - private static DoubleByte.Decoder ms950 = - (DoubleByte.Decoder)new MS950().newDecoder(); - - private static char[][] b2cBmp = new char[0x100][]; - private static char[][] b2cSupp = new char[0x100][]; - static { - initb2c(b2cBmp, HKSCSMapping.b2cBmpStr); - initb2c(b2cSupp, HKSCSMapping.b2cSuppStr); - } - - private Decoder(Charset cs) { - super(cs, ms950, b2cBmp, b2cSupp); - } - } - - private static class Encoder extends HKSCS.Encoder { - private static DoubleByte.Encoder ms950 = - (DoubleByte.Encoder)new MS950().newEncoder(); - - static char[][] c2bBmp = new char[0x100][]; - static char[][] c2bSupp = new char[0x100][]; - static { - initc2b(c2bBmp, HKSCSMapping.b2cBmpStr, HKSCSMapping.pua); - initc2b(c2bSupp, HKSCSMapping.b2cSuppStr, null); - } - - private Encoder(Charset cs) { - super(cs, ms950, c2bBmp, c2bSupp); - } - } -} diff -r 10b34c929b4f -r 64298b1e890b src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS.java.template --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS.java.template Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 $PACKAGE$; + +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import sun.nio.cs.HistoricallyNamedCharset; +import sun.nio.cs.*; +import static sun.nio.cs.CharsetMapping.*; + +public class MS950_HKSCS extends Charset implements HistoricallyNamedCharset +{ + public MS950_HKSCS() { + super("x-MS950-HKSCS", $ALIASES$); + } + + public String historicalName() { + return "MS950_HKSCS"; + } + + public boolean contains(Charset cs) { + return ((cs.name().equals("US-ASCII")) + || (cs instanceof MS950) + || (cs instanceof MS950_HKSCS)); + } + + public CharsetDecoder newDecoder() { + return new Decoder(this); + } + + public CharsetEncoder newEncoder() { + return new Encoder(this); + } + + static class Decoder extends HKSCS.Decoder { + private static DoubleByte.Decoder ms950 = + (DoubleByte.Decoder)new MS950().newDecoder(); + + private static char[][] b2cBmp = new char[0x100][]; + private static char[][] b2cSupp = new char[0x100][]; + static { + initb2c(b2cBmp, HKSCSMapping.b2cBmpStr); + initb2c(b2cSupp, HKSCSMapping.b2cSuppStr); + } + + private Decoder(Charset cs) { + super(cs, ms950, b2cBmp, b2cSupp); + } + } + + private static class Encoder extends HKSCS.Encoder { + private static DoubleByte.Encoder ms950 = + (DoubleByte.Encoder)new MS950().newEncoder(); + + static char[][] c2bBmp = new char[0x100][]; + static char[][] c2bSupp = new char[0x100][]; + static { + initc2b(c2bBmp, HKSCSMapping.b2cBmpStr, HKSCSMapping.pua); + initc2b(c2bSupp, HKSCSMapping.b2cSuppStr, null); + } + + private Encoder(Charset cs) { + super(cs, ms950, c2bBmp, c2bSupp); + } + } +} diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/source/doctree/DocCommentTree.java --- a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocCommentTree.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocCommentTree.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.source.doctree; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -69,4 +70,39 @@ * @return the block tags of a documentation comment */ List getBlockTags(); + + /** + * Returns a list of trees containing the content (if any) preceding + * the content of the documentation comment. + * When the {@code DocCommentTree} has been read from a documentation + * comment in a Java source file, the list will be empty. + * When the {@code DocCommentTree} has been read from an HTML file, this + * represents the content from the beginning of the file up to and + * including the {@code } tag. + * + * @implSpec This implementation returns an empty list. + * + * @return the list of trees + * @since 10 + */ + default List getPreamble() { + return Collections.emptyList(); + } + + /** + * Returns a list of trees containing the content (if any) following the + * content of the documentation comment. + * When the {@code DocCommentTree} has been read from a documentation + * comment in a Java source file, the list will be empty. + * When {@code DocCommentTree} has been read from an HTML file, this + * represents the content from the {@code } tag to the end of file. + * + * @implSpec This implementation returns an empty list. + * + * @return the list of trees + * @since 10 + */ + default List getPostamble() { + return Collections.emptyList(); + } } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java --- a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java Tue Dec 05 10:28:45 2017 +0000 @@ -78,6 +78,12 @@ DOC_ROOT("docRoot"), /** + * Used for instances of {@link DocTypeTree} + * representing an HTML DocType declaration. + */ + DOC_TYPE, + + /** * Used for instances of {@link EndElementTree} * representing the end of an HTML element. */ diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java --- a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java Tue Dec 05 10:28:45 2017 +0000 @@ -105,6 +105,21 @@ R visitDocRoot(DocRootTree node, P p); /** + * Visits a DocTypeTree node. + * + * @implSpec Visits a {@code DocTypeTree} node + * by calling {@code visitOther(node, p)}. + * + * @param node the node being visited + * @param p a parameter value + * @return a result value + * @since 10 + */ + default R visitDocType(DocTypeTree node, P p) { + return visitOther(node, p); + } + + /** * Visits an EndElementTree node. * @param node the node being visited * @param p a parameter value @@ -130,11 +145,19 @@ /** * Visits a HiddenTree node. + * + * @implSpec Visits a {@code HiddenTree} node + * by calling {@code visitOther(node, p)}. + * * @param node the node being visited * @param p a parameter value * @return a result value + * + * @since 9 */ - R visitHidden(HiddenTree node, P p); + default R visitHidden(HiddenTree node, P p) { + return visitOther(node, p); + } /** * Visits an IdentifierTree node. @@ -146,11 +169,19 @@ /** * Visits an IndexTree node. + * + * @implSpec Visits an {@code IndexTree} node + * by calling {@code visitOther(node, p)}. + * * @param node the node being visited * @param p a parameter value * @return a result value + * + * @since 9 */ - R visitIndex(IndexTree node, P p); + default R visitIndex(IndexTree node, P p) { + return visitOther(node, p); + } /** * Visits an InheritDocTree node. @@ -186,11 +217,19 @@ /** * Visits a ProvidesTree node. + * + * @implSpec Visits a {@code ProvidesTree} node + * by calling {@code visitOther(node, p)}. + * * @param node the node being visited * @param p a parameter value * @return a result value + * + * @since 9 */ - R visitProvides(ProvidesTree node, P p); + default R visitProvides(ProvidesTree node, P p) { + return visitOther(node, p); + } /** * Visits a ReferenceTree node. @@ -267,7 +306,9 @@ * @return a result value * @since 10 */ - default R visitSummary(SummaryTree node, P p) { return visitOther(node, p);} + default R visitSummary(SummaryTree node, P p) { + return visitOther(node, p); + } /** * Visits a TextTree node. @@ -303,11 +344,19 @@ /** * Visits a UsesTree node. + * + * @implSpec Visits a {@code UsesTree} node + * by calling {@code visitOther(node, p)}. + * * @param node the node being visited * @param p a parameter value * @return a result value + * + * @since 9 */ - R visitUses(UsesTree node, P p); + default R visitUses(UsesTree node, P p) { + return visitOther(node, p); + } /** * Visits a ValueTree node. diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/source/doctree/DocTypeTree.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTypeTree.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.source.doctree; + +/** + * A tree node for a {@code doctype} declaration. + * + *

          + * <!doctype text> + * + * @since 10 + */ +public interface DocTypeTree extends DocTree { + /** + * Returns the text of the doctype declaration. + * @return text + */ + String getText(); +} diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java --- a/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java Tue Dec 05 10:28:45 2017 +0000 @@ -39,6 +39,7 @@ import com.sun.source.doctree.DocCommentTree; import com.sun.source.doctree.DocRootTree; import com.sun.source.doctree.DocTree; +import com.sun.source.doctree.DocTypeTree; import com.sun.source.doctree.EndElementTree; import com.sun.source.doctree.EntityTree; import com.sun.source.doctree.ErroneousTree; @@ -121,6 +122,20 @@ */ DocCommentTree newDocCommentTree(List fullBody, List tags); + + /** + * Create a new {@code DocCommentTree} object, to represent the enitire doc comment. + * @param fullBody the entire body of the doc comment + * @param tags the block tags in the doc comment + * @param preamble the meta content of an html file including the body tag + * @param postamble the meta content of an html including the closing body tag + * @return a {@code DocCommentTree} object + * @since 10 + */ + DocCommentTree newDocCommentTree(List fullBody, + List tags, + List preamble, + List postamble); /** * Create a new {@code DocRootTree} object, to represent an {@code {@docroot} } tag. * @return a {@code DocRootTree} object @@ -128,6 +143,14 @@ DocRootTree newDocRootTree(); /** + * Create a new {@code DocTypeTree}, to represent a {@code DOCTYPE} HTML declaration. + * @param text the content of the declaration + * @return a {@code CommentTree} object + * @since 10 + */ + DocTypeTree newDocTypeTree(String text); + + /** * Create a new {@code EndElement} object, to represent the end of an HTML element. * @param name the name of the HTML element * @return an {@code EndElementTree} object diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java --- a/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java Tue Dec 05 10:28:45 2017 +0000 @@ -206,6 +206,18 @@ * @return the result of scanning */ @Override + public R visitDocType(DocTypeTree node, P p) { + return null; + } + + /** + * {@inheritDoc} This implementation returns {@code null}. + * + * @param node {@inheritDoc} + * @param p {@inheritDoc} + * @return the result of scanning + */ + @Override public R visitEndElement(EndElementTree node, P p) { return null; } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java --- a/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java Tue Dec 05 10:28:45 2017 +0000 @@ -98,13 +98,12 @@ /** * Returns the doc comment tree of the given file. The file must be * an HTML file, in which case the doc comment tree represents the - * contents of the <body> tag, and any enclosing tags are ignored. + * entire contents of the file. * Returns {@code null} if no doc comment was found. * Future releases may support additional file types. * * @param fileObject the content container * @return the doc comment tree - * * @since 9 */ public abstract DocCommentTree getDocCommentTree(FileObject fileObject); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java --- a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java Tue Dec 05 10:28:45 2017 +0000 @@ -168,6 +168,19 @@ } /** + * {@inheritDoc} + * + * @implSpec This implementation calls {@code defaultAction}. + * + * @param node {@inheritDoc} + * @param p {@inheritDoc} + * @return the result of {@code defaultAction} + * @since 10 + */ + @Override + public R visitDocType(DocTypeTree node, P p) { return defaultAction(node, p); } + + /** * {@inheritDoc} This implementation calls {@code defaultAction}. * * @param node {@inheritDoc} @@ -175,9 +188,7 @@ * @return the result of {@code defaultAction} */ @Override - public R visitEndElement(EndElementTree node, P p) { - return defaultAction(node, p); - } + public R visitEndElement(EndElementTree node, P p) { return defaultAction(node, p);} /** * {@inheritDoc} This implementation calls {@code defaultAction}. @@ -209,6 +220,8 @@ * @param node {@inheritDoc} * @param p {@inheritDoc} * @return the result of {@code defaultAction} + * + * @since 9 */ @Override public R visitHidden(HiddenTree node, P p) { @@ -233,6 +246,8 @@ * @param node {@inheritDoc} * @param p {@inheritDoc} * @return the result of {@code defaultAction} + * + * @since 9 */ @Override public R visitIndex(IndexTree node, P p) { @@ -293,6 +308,8 @@ * @param node {@inheritDoc} * @param p {@inheritDoc} * @return the result of {@code defaultAction} + * + * @since 9 */ @Override public R visitProvides(ProvidesTree node, P p) { @@ -462,6 +479,8 @@ * @param node {@inheritDoc} * @param p {@inheritDoc} * @return the result of {@code defaultAction} + * + * @since 9 */ @Override public R visitUses(UsesTree node, P p) { diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java Tue Dec 05 10:28:45 2017 +0000 @@ -28,9 +28,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.text.BreakIterator; -import java.util.HashMap; +import java.util.Collections; import java.util.HashSet; -import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -59,6 +58,8 @@ import com.sun.source.doctree.DocCommentTree; import com.sun.source.doctree.DocTree; +import com.sun.source.doctree.EndElementTree; +import com.sun.source.doctree.StartElementTree; import com.sun.source.tree.CatchTree; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.Scope; @@ -68,6 +69,7 @@ import com.sun.source.util.DocTreeScanner; import com.sun.source.util.DocTrees; import com.sun.source.util.JavacTask; +import com.sun.source.util.SimpleDocTreeVisitor; import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Scope.NamedImportScope; @@ -1006,16 +1008,7 @@ public String getText() { try { CharSequence rawDoc = fileObject.getCharContent(true); - Pattern bodyPat = - Pattern.compile("(?is).*?]*>(.*)= 0) { + if (source.compareTo(Source.JDK9) >= 0) { values.add(LintCategory.DEP_ANN); } values.add(LintCategory.REQUIRES_TRANSITIVE_AUTOMATIC); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java Tue Dec 05 10:28:45 2017 +0000 @@ -31,7 +31,12 @@ import static javax.lang.model.SourceVersion.*; import com.sun.tools.javac.jvm.Target; +import com.sun.tools.javac.resources.CompilerProperties.Errors; +import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.util.*; +import com.sun.tools.javac.util.JCDiagnostic.Error; +import com.sun.tools.javac.util.JCDiagnostic.Fragment; + import static com.sun.tools.javac.main.Option.*; /** The source language version accepted. @@ -59,22 +64,22 @@ /** 1.5 introduced generics, attributes, foreach, boxing, static import, * covariant return, enums, varargs, et al. */ - JDK1_5("1.5"), + JDK5("5"), /** 1.6 reports encoding problems as errors instead of warnings. */ - JDK1_6("1.6"), + JDK6("6"), /** 1.7 introduced try-with-resources, multi-catch, string switch, etc. */ - JDK1_7("1.7"), + JDK7("7"), /** 1.8 lambda expressions and default methods. */ - JDK1_8("1.8"), + JDK8("8"), /** 1.9 modularity. */ - JDK1_9("1.9"), + JDK9("9"), /** 1.10 covers the to be determined language features that will be added in JDK 10. */ - JDK1_10("1.10"); + JDK10("10"); private static final Context.Key sourceKey = new Context.Key<>(); @@ -97,19 +102,19 @@ for (Source s : values()) { tab.put(s.name, s); } - tab.put("5", JDK1_5); // Make 5 an alias for 1.5 - tab.put("6", JDK1_6); // Make 6 an alias for 1.6 - tab.put("7", JDK1_7); // Make 7 an alias for 1.7 - tab.put("8", JDK1_8); // Make 8 an alias for 1.8 - tab.put("9", JDK1_9); // Make 9 an alias for 1.9 - tab.put("10", JDK1_10); // Make 10 an alias for 1.10 + tab.put("1.5", JDK5); // Make 5 an alias for 1.5 + tab.put("1.6", JDK6); // Make 6 an alias for 1.6 + tab.put("1.7", JDK7); // Make 7 an alias for 1.7 + tab.put("1.8", JDK8); // Make 8 an alias for 1.8 + tab.put("1.9", JDK9); // Make 9 an alias for 1.9 + tab.put("1.10", JDK10); // Make 10 an alias for 1.10 } private Source(String name) { this.name = name; } - public static final Source MIN = Source.JDK1_6; + public static final Source MIN = Source.JDK6; private static final Source MAX = values()[values().length - 1]; @@ -120,114 +125,108 @@ } public Target requiredTarget() { - if (this.compareTo(JDK1_10) >= 0) return Target.JDK1_10; - if (this.compareTo(JDK1_9) >= 0) return Target.JDK1_9; - if (this.compareTo(JDK1_8) >= 0) return Target.JDK1_8; - if (this.compareTo(JDK1_7) >= 0) return Target.JDK1_7; - if (this.compareTo(JDK1_6) >= 0) return Target.JDK1_6; - if (this.compareTo(JDK1_5) >= 0) return Target.JDK1_5; + if (this.compareTo(JDK10) >= 0) return Target.JDK1_10; + if (this.compareTo(JDK9) >= 0) return Target.JDK1_9; + if (this.compareTo(JDK8) >= 0) return Target.JDK1_8; + if (this.compareTo(JDK7) >= 0) return Target.JDK1_7; + if (this.compareTo(JDK6) >= 0) return Target.JDK1_6; + if (this.compareTo(JDK5) >= 0) return Target.JDK1_5; if (this.compareTo(JDK1_4) >= 0) return Target.JDK1_4; return Target.JDK1_1; } - public boolean allowDiamond() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowMulticatch() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowImprovedRethrowAnalysis() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowImprovedCatchAnalysis() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowModules() { - return compareTo(JDK1_9) >= 0; - } - public boolean allowTryWithResources() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowEffectivelyFinalVariablesInTryWithResources() { - return compareTo(JDK1_9) >= 0; - } - public boolean allowBinaryLiterals() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowUnderscoresInLiterals() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowStringsInSwitch() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowDeprecationOnImport() { - return compareTo(JDK1_9) < 0; - } - public boolean allowSimplifiedVarargs() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowObjectToPrimitiveCast() { - return compareTo(JDK1_7) >= 0; - } - public boolean enforceThisDotInit() { - return compareTo(JDK1_7) >= 0; - } - public boolean allowPoly() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowLambda() { - return compareTo(JDK1_8) >= 0; + /** + * Models a feature of the Java programming language. Each feature can be associated with a + * minimum source level, a maximum source level and a diagnostic fragment describing the feature, + * which is used to generate error messages of the kind {@code feature XYZ not supported in source N}. + */ + public enum Feature { + + DIAMOND(JDK7, Fragments.FeatureDiamond, DiagKind.NORMAL), + MULTICATCH(JDK7, Fragments.FeatureMulticatch, DiagKind.PLURAL), + IMPROVED_RETHROW_ANALYSIS(JDK7), + IMPROVED_CATCH_ANALYSIS(JDK7), + MODULES(JDK9, Fragments.FeatureModules, DiagKind.PLURAL), + TRY_WITH_RESOURCES(JDK7, Fragments.FeatureTryWithResources, DiagKind.NORMAL), + EFFECTIVELY_FINAL_VARIABLES_IN_TRY_WITH_RESOURCES(JDK9, Fragments.FeatureVarInTryWithResources, DiagKind.PLURAL), + BINARY_LITERALS(JDK7, Fragments.FeatureBinaryLit, DiagKind.PLURAL), + UNDERSCORES_IN_LITERALS(JDK7, Fragments.FeatureUnderscoreLit, DiagKind.PLURAL), + STRINGS_IN_SWITCH(JDK7, Fragments.FeatureStringSwitch, DiagKind.PLURAL), + DEPRECATION_ON_IMPORT(MIN, JDK9), + SIMPLIFIED_VARARGS(JDK7), + OBJECT_TO_PRIMITIVE_CAST(JDK7), + ENFORCE_THIS_DOT_INIT(JDK7), + POLY(JDK8), + LAMBDA(JDK8, Fragments.FeatureLambda, DiagKind.PLURAL), + METHOD_REFERENCES(JDK8, Fragments.FeatureMethodReferences, DiagKind.PLURAL), + DEFAULT_METHODS(JDK8, Fragments.FeatureDefaultMethods, DiagKind.PLURAL), + STATIC_INTERFACE_METHODS(JDK8, Fragments.FeatureStaticIntfMethods, DiagKind.PLURAL), + STATIC_INTERFACE_METHODS_INVOKE(JDK8, Fragments.FeatureStaticIntfMethodInvoke, DiagKind.PLURAL), + STRICT_METHOD_CLASH_CHECK(JDK8), + EFFECTIVELY_FINAL_IN_INNER_CLASSES(JDK8), + TYPE_ANNOTATIONS(JDK8, Fragments.FeatureTypeAnnotations, DiagKind.PLURAL), + ANNOTATIONS_AFTER_TYPE_PARAMS(JDK8, Fragments.FeatureAnnotationsAfterTypeParams, DiagKind.PLURAL), + REPEATED_ANNOTATIONS(JDK8, Fragments.FeatureRepeatableAnnotations, DiagKind.PLURAL), + INTERSECTION_TYPES_IN_CAST(JDK8, Fragments.FeatureIntersectionTypesInCast, DiagKind.PLURAL), + GRAPH_INFERENCE(JDK8), + FUNCTIONAL_INTERFACE_MOST_SPECIFIC(JDK8), + POST_APPLICABILITY_VARARGS_ACCESS_CHECK(JDK8), + MAP_CAPTURES_TO_BOUNDS(MIN, JDK7), + PRIVATE_SAFE_VARARGS(JDK9), + DIAMOND_WITH_ANONYMOUS_CLASS_CREATION(JDK9, Fragments.FeatureDiamondAndAnonClass, DiagKind.NORMAL), + UNDERSCORE_IDENTIFIER(MIN, JDK8), + PRIVATE_INTERFACE_METHODS(JDK9, Fragments.FeaturePrivateIntfMethods, DiagKind.PLURAL), + LOCAL_VARIABLE_TYPE_INFERENCE(JDK10); + + enum DiagKind { + NORMAL, + PLURAL; + } + + private final Source minLevel; + private final Source maxLevel; + private final Fragment optFragment; + private final DiagKind optKind; + + Feature(Source minLevel) { + this(minLevel, null, null); + } + + Feature(Source minLevel, Fragment optFragment, DiagKind optKind) { + this(minLevel, MAX, optFragment, optKind); + } + + Feature(Source minLevel, Source maxLevel) { + this(minLevel, maxLevel, null, null); + } + + Feature(Source minLevel, Source maxLevel, Fragment optFragment, DiagKind optKind) { + this.minLevel = minLevel; + this.maxLevel = maxLevel; + this.optFragment = optFragment; + this.optKind = optKind; + } + + public boolean allowedInSource(Source source) { + return source.compareTo(minLevel) >= 0 && + source.compareTo(maxLevel) <= 0; + } + + public Fragment fragment(String sourceName) { + Assert.checkNonNull(optFragment); + return optKind == DiagKind.NORMAL ? + Fragments.FeatureNotSupportedInSource(optFragment, sourceName, minLevel.name) : + Fragments.FeatureNotSupportedInSourcePlural(optFragment, sourceName, minLevel.name); + } + + public Error error(String sourceName) { + Assert.checkNonNull(optFragment); + return optKind == DiagKind.NORMAL ? + Errors.FeatureNotSupportedInSource(optFragment, sourceName, minLevel.name) : + Errors.FeatureNotSupportedInSourcePlural(optFragment, sourceName, minLevel.name); + } } - public boolean allowMethodReferences() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowDefaultMethods() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowStaticInterfaceMethods() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowStrictMethodClashCheck() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowEffectivelyFinalInInnerClasses() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowTypeAnnotations() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowAnnotationsAfterTypeParams() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowRepeatedAnnotations() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowIntersectionTypesInCast() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowGraphInference() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowFunctionalInterfaceMostSpecific() { - return compareTo(JDK1_8) >= 0; - } - public boolean allowPostApplicabilityVarargsAccessCheck() { - return compareTo(JDK1_8) >= 0; - } - public boolean mapCapturesToBounds() { - return compareTo(JDK1_8) < 0; - } - public boolean allowPrivateSafeVarargs() { - return compareTo(JDK1_9) >= 0; - } - public boolean allowDiamondWithAnonymousClassCreation() { - return compareTo(JDK1_9) >= 0; - } - public boolean allowUnderscoreIdentifier() { - return compareTo(JDK1_8) <= 0; - } - public boolean allowPrivateInterfaceMethods() { return compareTo(JDK1_9) >= 0; } - public boolean allowLocalVariableTypeInference() { return compareTo(JDK1_10) >= 0; } + public static SourceVersion toSourceVersion(Source source) { switch(source) { case JDK1_2: @@ -236,17 +235,17 @@ return RELEASE_3; case JDK1_4: return RELEASE_4; - case JDK1_5: + case JDK5: return RELEASE_5; - case JDK1_6: + case JDK6: return RELEASE_6; - case JDK1_7: + case JDK7: return RELEASE_7; - case JDK1_8: + case JDK8: return RELEASE_8; - case JDK1_9: + case JDK9: return RELEASE_9; - case JDK1_10: + case JDK10: return RELEASE_10; default: return null; diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java Tue Dec 05 10:28:45 2017 +0000 @@ -35,6 +35,7 @@ import javax.lang.model.element.ElementVisitor; import com.sun.tools.javac.code.Scope.WriteableScope; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.Completer; import com.sun.tools.javac.code.Symbol.CompletionFailure; @@ -468,7 +469,7 @@ scope.enter(errSymbol); Source source = Source.instance(context); - if (source.allowModules()) { + if (Feature.MODULES.allowedInSource(source)) { java_base = enterModule(names.java_base); //avoid completing java.base during the Symtab initialization java_base.completer = Completer.NULL_COMPLETER; diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Tue Dec 05 10:28:45 2017 +0000 @@ -41,6 +41,7 @@ import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Lint.LintCategory; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; import com.sun.tools.javac.code.TypeMetadata.Entry.Kind; import com.sun.tools.javac.comp.AttrContext; @@ -113,9 +114,9 @@ syms = Symtab.instance(context); names = Names.instance(context); Source source = Source.instance(context); - allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast(); - allowDefaultMethods = source.allowDefaultMethods(); - mapCapturesToBounds = source.mapCapturesToBounds(); + allowObjectToPrimitiveCast = Feature.OBJECT_TO_PRIMITIVE_CAST.allowedInSource(source); + allowDefaultMethods = Feature.DEFAULT_METHODS.allowedInSource(source); + mapCapturesToBounds = Feature.MAP_CAPTURES_TO_BOUNDS.allowedInSource(source); chk = Check.instance(context); enter = Enter.instance(context); capturedName = names.fromString(""); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java Tue Dec 05 10:28:45 2017 +0000 @@ -29,6 +29,7 @@ import com.sun.source.tree.LambdaExpressionTree; import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Types; import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext; @@ -128,7 +129,7 @@ String findOpt = options.get("find"); //parse modes Source source = Source.instance(context); - allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation(); + allowDiamondWithAnonymousClassCreation = Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.allowedInSource(source); analyzerModes = AnalyzerMode.getAnalyzerModes(findOpt, source); } @@ -137,17 +138,17 @@ * the {@code -XDfind} option. */ enum AnalyzerMode { - DIAMOND("diamond", Source::allowDiamond), - LAMBDA("lambda", Source::allowLambda), - METHOD("method", Source::allowGraphInference), - LOCAL("local", Source::allowLocalVariableTypeInference); + DIAMOND("diamond", Feature.DIAMOND), + LAMBDA("lambda", Feature.LAMBDA), + METHOD("method", Feature.GRAPH_INFERENCE), + LOCAL("local", Feature.LOCAL_VARIABLE_TYPE_INFERENCE); final String opt; - final Predicate sourceFilter; + final Feature feature; - AnalyzerMode(String opt, Predicate sourceFilter) { + AnalyzerMode(String opt, Feature feature) { this.opt = opt; - this.sourceFilter = sourceFilter; + this.feature = feature; } /** @@ -168,7 +169,7 @@ for (AnalyzerMode mode : values()) { if (modes.contains(mode.opt)) { res.add(mode); - } else if (modes.contains("-" + mode.opt) || !mode.sourceFilter.test(source)) { + } else if (modes.contains("-" + mode.opt) || !mode.feature.allowedInSource(source)) { res.remove(mode); } } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Tue Dec 05 10:28:45 2017 +0000 @@ -30,10 +30,12 @@ import com.sun.tools.javac.code.Attribute.TypeCompound; import com.sun.tools.javac.code.Kinds.KindSelector; import com.sun.tools.javac.code.Scope.WriteableScope; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.TypeMetadata.Entry.Kind; import com.sun.tools.javac.comp.Check.CheckContext; import com.sun.tools.javac.resources.CompilerProperties.Errors; +import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.TreeInfo; @@ -121,7 +123,7 @@ theUnfinishedDefaultValue = new Attribute.Error(syms.errType); Source source = Source.instance(context); - allowRepeatedAnnos = source.allowRepeatedAnnotations(); + allowRepeatedAnnos = Feature.REPEATED_ANNOTATIONS.allowedInSource(source); sourceName = source.name; blockCount = 1; @@ -344,7 +346,7 @@ if (annotated.containsKey(a.type.tsym)) { if (!allowRepeatedAnnos) { - log.error(DiagnosticFlag.SOURCE_LEVEL, a.pos(), Errors.RepeatableAnnotationsNotSupportedInSource(sourceName)); + log.error(DiagnosticFlag.SOURCE_LEVEL, a.pos(), Feature.REPEATED_ANNOTATIONS.error(sourceName)); } ListBuffer l = annotated.get(a.type.tsym); l = l.append(c); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Tue Dec 05 10:28:45 2017 +0000 @@ -38,6 +38,7 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Scope.WriteableScope; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.TypeMetadata.Annotations; @@ -150,12 +151,12 @@ Options options = Options.instance(context); Source source = Source.instance(context); - allowStringsInSwitch = source.allowStringsInSwitch(); - allowPoly = source.allowPoly(); - allowTypeAnnos = source.allowTypeAnnotations(); - allowLambda = source.allowLambda(); - allowDefaultMethods = source.allowDefaultMethods(); - allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); + allowStringsInSwitch = Feature.STRINGS_IN_SWITCH.allowedInSource(source); + allowPoly = Feature.POLY.allowedInSource(source); + allowTypeAnnos = Feature.TYPE_ANNOTATIONS.allowedInSource(source); + allowLambda = Feature.LAMBDA.allowedInSource(source); + allowDefaultMethods = Feature.DEFAULT_METHODS.allowedInSource(source); + allowStaticInterfaceMethods = Feature.STATIC_INTERFACE_METHODS.allowedInSource(source); sourceName = source.name; useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning"); @@ -1392,7 +1393,7 @@ boolean enumSwitch = (seltype.tsym.flags() & Flags.ENUM) != 0; boolean stringSwitch = types.isSameType(seltype, syms.stringType); if (stringSwitch && !allowStringsInSwitch) { - log.error(DiagnosticFlag.SOURCE_LEVEL, tree.selector.pos(), Errors.StringSwitchNotSupportedInSource(sourceName)); + log.error(DiagnosticFlag.SOURCE_LEVEL, tree.selector.pos(), Feature.STRINGS_IN_SWITCH.error(sourceName)); } if (!enumSwitch && !stringSwitch) seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType); @@ -3667,7 +3668,7 @@ } if (!allowStaticInterfaceMethods && sitesym.isInterface() && sym.isStatic() && sym.kind == MTH) { - log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(), Errors.StaticIntfMethodInvokeNotSupportedInSource(sourceName)); + log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(), Feature.STATIC_INTERFACE_METHODS_INVOKE.error(sourceName)); } } else if (sym.kind != ERR && (sym.flags() & STATIC) != 0 && diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Tue Dec 05 10:28:45 2017 +0000 @@ -33,6 +33,7 @@ import com.sun.tools.javac.code.Attribute.Compound; import com.sun.tools.javac.code.Directive.ExportsDirective; import com.sun.tools.javac.code.Directive.RequiresDirective; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.resources.CompilerProperties.Errors; @@ -127,11 +128,6 @@ fileManager = context.get(JavaFileManager.class); source = Source.instance(context); - allowSimplifiedVarargs = source.allowSimplifiedVarargs(); - allowDefaultMethods = source.allowDefaultMethods(); - allowStrictMethodClashCheck = source.allowStrictMethodClashCheck(); - allowPrivateSafeVarargs = source.allowPrivateSafeVarargs(); - allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation(); warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers"); Target target = Target.instance(context); @@ -156,26 +152,6 @@ deferredLintHandler = DeferredLintHandler.instance(context); } - /** Switch: simplified varargs enabled? - */ - boolean allowSimplifiedVarargs; - - /** Switch: default methods enabled? - */ - boolean allowDefaultMethods; - - /** Switch: should unrelated return types trigger a method clash? - */ - boolean allowStrictMethodClashCheck; - - /** Switch: can the @SafeVarargs annotation be applied to private methods? - */ - boolean allowPrivateSafeVarargs; - - /** Switch: can diamond inference be used in anonymous instance creation ? - */ - boolean allowDiamondWithAnonymousClassCreation; - /** Character for synthetic names */ char syntheticNameChar; @@ -256,7 +232,7 @@ * @param pos Position to be used for error reporting. */ void warnUnsafeVararg(DiagnosticPosition pos, String key, Object... args) { - if (lint.isEnabled(LintCategory.VARARGS) && allowSimplifiedVarargs) + if (lint.isEnabled(LintCategory.VARARGS) && Feature.SIMPLIFIED_VARARGS.allowedInSource(source)) log.warning(LintCategory.VARARGS, pos, key, args); } @@ -814,9 +790,9 @@ t.isErroneous()) { return checkClassType(tree.clazz.pos(), t, true); } else { - if (tree.def != null && !allowDiamondWithAnonymousClassCreation) { + if (tree.def != null && !Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.allowedInSource(source)) { log.error(DiagnosticFlag.SOURCE_LEVEL, tree.clazz.pos(), - Errors.CantApplyDiamond1(t, Fragments.DiamondAndAnonClassNotSupportedInSource(source.name))); + Errors.CantApplyDiamond1(t, Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.fragment(source.name))); } if (t.tsym.type.getTypeArguments().isEmpty()) { log.error(tree.clazz.pos(), @@ -906,7 +882,7 @@ void checkVarargsMethodDecl(Env env, JCMethodDecl tree) { MethodSymbol m = tree.sym; - if (!allowSimplifiedVarargs) return; + if (!Feature.SIMPLIFIED_VARARGS.allowedInSource(source)) return; boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null; Type varargElemType = null; if (m.isVarArgs()) { @@ -914,7 +890,7 @@ } if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) { if (varargElemType != null) { - JCDiagnostic msg = allowPrivateSafeVarargs ? + JCDiagnostic msg = Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ? diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargs(m)) : diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargsFinalOnly(m)); log.error(tree, @@ -942,7 +918,7 @@ return (s.flags() & VARARGS) != 0 && (s.isConstructor() || (s.flags() & (STATIC | FINAL | - (allowPrivateSafeVarargs ? PRIVATE : 0) )) != 0); + (Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ? PRIVATE : 0) )) != 0); } Type checkLocalVarType(DiagnosticPosition pos, Type t, Name name) { @@ -1019,7 +995,7 @@ if (useVarargs) { Type argtype = owntype.getParameterTypes().last(); if (!types.isReifiable(argtype) && - (!allowSimplifiedVarargs || + (!Feature.SIMPLIFIED_VARARGS.allowedInSource(source) || sym.baseSymbol().attribute(syms.trustMeType.tsym) == null || !isTrustMeAllowedOnMethod(sym))) { warnUnchecked(env.tree.pos(), @@ -2489,7 +2465,7 @@ if (m2 == m1) continue; //if (i) the signature of 'sym' is not a subsignature of m1 (seen as //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error - if (!types.isSubSignature(sym.type, types.memberType(site, m2), allowStrictMethodClashCheck) && + if (!types.isSubSignature(sym.type, types.memberType(site, m2), Feature.STRICT_METHOD_CLASH_CHECK.allowedInSource(source)) && types.hasSameArgs(m2.erasure(types), m1.erasure(types))) { sym.flags_field |= CLASH; if (m1 == sym) { @@ -2534,7 +2510,7 @@ for (Symbol s : types.membersClosure(site, true).getSymbolsByName(sym.name, cf)) { //if (i) the signature of 'sym' is not a subsignature of m1 (seen as //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error - if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) { + if (!types.isSubSignature(sym.type, types.memberType(site, s), Feature.STRICT_METHOD_CLASH_CHECK.allowedInSource(source))) { if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) { log.error(pos, Errors.NameClashSameErasureNoHide(sym, sym.location(), s, s.location())); @@ -2634,7 +2610,7 @@ void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site, MethodSymbol msym1, MethodSymbol msym2) { if (msym1 != msym2 && - allowDefaultMethods && + Feature.DEFAULT_METHODS.allowedInSource(source) && lint.isEnabled(LintCategory.OVERLOADS) && (msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 && (msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) { diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Tue Dec 05 10:28:45 2017 +0000 @@ -32,6 +32,7 @@ import com.sun.source.tree.LambdaExpressionTree.BodyKind; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Scope.WriteableScope; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.resources.CompilerProperties.Warnings; import com.sun.tools.javac.tree.*; @@ -291,10 +292,10 @@ rs = Resolve.instance(context); diags = JCDiagnostic.Factory.instance(context); Source source = Source.instance(context); - allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis(); - allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis(); - allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses(); - enforceThisDotInit = source.enforceThisDotInit(); + allowImprovedRethrowAnalysis = Feature.IMPROVED_RETHROW_ANALYSIS.allowedInSource(source); + allowImprovedCatchAnalysis = Feature.IMPROVED_CATCH_ANALYSIS.allowedInSource(source); + allowEffectivelyFinalInInnerClasses = Feature.EFFECTIVELY_FINAL_IN_INNER_CLASSES.allowedInSource(source); + enforceThisDotInit = Feature.ENFORCE_THIS_DOT_INIT.allowedInSource(source); } /** diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Tue Dec 05 10:28:45 2017 +0000 @@ -25,6 +25,7 @@ package com.sun.tools.javac.comp; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Type.UndetVar.UndetVarListener; import com.sun.tools.javac.code.Types.TypeMapping; import com.sun.tools.javac.comp.Attr.CheckMode; @@ -116,7 +117,8 @@ log = Log.instance(context); inferenceException = new InferenceException(diags); Options options = Options.instance(context); - allowGraphInference = Source.instance(context).allowGraphInference() + Source source = Source.instance(context); + allowGraphInference = Feature.GRAPH_INFERENCE.allowedInSource(source) && options.isUnset("useLegacyInference"); dependenciesFolder = options.get("debug.dumpInferenceGraphsTo"); pendingGraphs = List.nil(); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Tue Dec 05 10:28:45 2017 +0000 @@ -66,6 +66,7 @@ import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.ModuleFinder; import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.Completer; @@ -185,7 +186,7 @@ types = Types.instance(context); fileManager = context.get(JavaFileManager.class); source = Source.instance(context); - allowModules = source.allowModules(); + allowModules = Feature.MODULES.allowedInSource(source); Options options = Options.instance(context); allowAccessIntoSystem = options.isUnset(Option.RELEASE); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Tue Dec 05 10:28:45 2017 +0000 @@ -28,6 +28,7 @@ import com.sun.tools.javac.api.Formattable.LocalizedString; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Scope.WriteableScope; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.comp.Attr.ResultInfo; @@ -137,15 +138,15 @@ verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); Target target = Target.instance(context); allowMethodHandles = target.hasMethodHandles(); - allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific(); - allowLocalVariableTypeInference = source.allowLocalVariableTypeInference(); + allowFunctionalInterfaceMostSpecific = Feature.FUNCTIONAL_INTERFACE_MOST_SPECIFIC.allowedInSource(source); + allowLocalVariableTypeInference = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source); checkVarargsAccessAfterResolution = - source.allowPostApplicabilityVarargsAccessCheck(); + Feature.POST_APPLICABILITY_VARARGS_ACCESS_CHECK.allowedInSource(source); polymorphicSignatureScope = WriteableScope.create(syms.noSymbol); inapplicableMethodException = new InapplicableMethodException(diags); - allowModules = source.allowModules(); + allowModules = Feature.MODULES.allowedInSource(source); } /** error symbols, which are returned when resolution fails diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java Tue Dec 05 10:28:45 2017 +0000 @@ -29,6 +29,7 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.TypeCompound; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.tree.*; @@ -94,8 +95,8 @@ make = TreeMaker.instance(context); resolve = Resolve.instance(context); Source source = Source.instance(context); - allowInterfaceBridges = source.allowDefaultMethods(); - allowGraphInference = source.allowGraphInference(); + allowInterfaceBridges = Feature.DEFAULT_METHODS.allowedInSource(source); + allowGraphInference = Feature.GRAPH_INFERENCE.allowedInSource(source); annotate = Annotate.instance(context); attr = Attr.instance(context); } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Tue Dec 05 10:28:45 2017 +0000 @@ -37,6 +37,7 @@ import com.sun.tools.javac.code.Scope.NamedImportScope; import com.sun.tools.javac.code.Scope.StarImportScope; import com.sun.tools.javac.code.Scope.WriteableScope; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; @@ -137,8 +138,8 @@ typeEnvs = TypeEnvs.instance(context); dependencies = Dependencies.instance(context); Source source = Source.instance(context); - allowTypeAnnos = source.allowTypeAnnotations(); - allowDeprecationOnImport = source.allowDeprecationOnImport(); + allowTypeAnnos = Feature.TYPE_ANNOTATIONS.allowedInSource(source); + allowDeprecationOnImport = Feature.DEPRECATION_ON_IMPORT.allowedInSource(source); } /** Switch: support type annotations. diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Dec 05 10:28:45 2017 +0000 @@ -42,6 +42,7 @@ import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.comp.Annotate; import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter; import com.sun.tools.javac.code.*; @@ -246,8 +247,8 @@ verbose = options.isSet(Option.VERBOSE); Source source = Source.instance(context); - allowSimplifiedVarargs = source.allowSimplifiedVarargs(); - allowModules = source.allowModules(); + allowSimplifiedVarargs = Feature.SIMPLIFIED_VARARGS.allowedInSource(source); + allowModules = Feature.MODULES.allowedInSource(source); saveParameterNames = options.isSet(PARAMETERS); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Tue Dec 05 10:28:45 2017 +0000 @@ -54,6 +54,7 @@ import com.sun.tools.doclint.DocLint; import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.file.BaseFileManager; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.jvm.Profile; diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Dec 05 10:28:45 2017 +0000 @@ -52,6 +52,7 @@ import com.sun.tools.javac.api.MultiTaskListener; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Lint.LintCategory; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.CompletionFailure; import com.sun.tools.javac.code.Symbol.PackageSymbol; @@ -684,7 +685,7 @@ if (sep == -1) { msym = modules.getDefaultModule(); typeName = name; - } else if (source.allowModules()) { + } else if (Feature.MODULES.allowedInSource(source)) { Name modName = names.fromString(name.substring(0, sep)); msym = moduleFinder.findModule(modName); @@ -1544,7 +1545,7 @@ env.tree = transTypes.translateTopLevelClass(env.tree, localMake); compileStates.put(env, CompileState.TRANSTYPES); - if (source.allowLambda() && scanner.hasLambdas) { + if (Feature.LAMBDA.allowedInSource(source) && scanner.hasLambdas) { if (shouldStop(CompileState.UNLAMBDA)) return; diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java Tue Dec 05 10:28:45 2017 +0000 @@ -51,6 +51,7 @@ import com.sun.tools.javac.code.Directive.RequiresDirective; import com.sun.tools.javac.code.Directive.RequiresFlag; import com.sun.tools.javac.code.Scope.WriteableScope; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Enter; @@ -114,7 +115,7 @@ javacTaskImpl = t instanceof JavacTaskImpl ? (JavacTaskImpl) t : null; log = Log.instance(context); Source source = Source.instance(context); - allowModules = source.allowModules(); + allowModules = Feature.MODULES.allowedInSource(source); } @Override @DefinedBy(Api.LANGUAGE_MODEL) diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java Tue Dec 05 10:28:45 2017 +0000 @@ -36,10 +36,12 @@ import com.sun.tools.javac.tree.DCTree; import com.sun.tools.javac.tree.DCTree.DCAttribute; import com.sun.tools.javac.tree.DCTree.DCDocComment; +import com.sun.tools.javac.tree.DCTree.DCEndElement; import com.sun.tools.javac.tree.DCTree.DCEndPosTree; import com.sun.tools.javac.tree.DCTree.DCErroneous; import com.sun.tools.javac.tree.DCTree.DCIdentifier; import com.sun.tools.javac.tree.DCTree.DCReference; +import com.sun.tools.javac.tree.DCTree.DCStartElement; import com.sun.tools.javac.tree.DCTree.DCText; import com.sun.tools.javac.tree.DocTreeMaker; import com.sun.tools.javac.tree.JCTree; @@ -50,6 +52,7 @@ import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Position; +import com.sun.tools.javac.util.StringUtils; import static com.sun.tools.javac.util.LayoutCharacters.*; @@ -68,11 +71,14 @@ } } + private enum Phase {PREAMBLE, BODY, POSTAMBLE}; + final ParserFactory fac; final DiagnosticSource diagSource; final Comment comment; final DocTreeMaker m; final Names names; + final boolean isFileContent; BreakIterator sentenceBreaker; @@ -93,17 +99,23 @@ Map tagParsers; - public DocCommentParser(ParserFactory fac, DiagnosticSource diagSource, Comment comment) { + public DocCommentParser(ParserFactory fac, DiagnosticSource diagSource, + Comment comment, boolean isFileContent) { this.fac = fac; this.diagSource = diagSource; this.comment = comment; names = fac.names; + this.isFileContent = isFileContent; m = fac.docTreeMaker; initTagParsers(); } + public DocCommentParser(ParserFactory fac, DiagnosticSource diagSource, Comment comment) { + this(fac, diagSource, comment, false); + } + public DocCommentParser(ParserFactory fac) { - this(fac, null, null); + this(fac, null, null, false); } public DCDocComment parse() { @@ -115,13 +127,22 @@ bp = -1; nextChar(); - List body = blockContent(); + List preamble = isFileContent ? blockContent(Phase.PREAMBLE) : List.nil(); + List body = blockContent(Phase.BODY); List tags = blockTags(); - int pos = !body.isEmpty() - ? body.head.pos - : !tags.isEmpty() ? tags.head.pos : Position.NOPOS; + List postamble = isFileContent ? blockContent(Phase.POSTAMBLE) : List.nil(); - DCDocComment dc = m.at(pos).newDocCommentTree(comment, body, tags); + int pos = Position.NOPOS; + if (!preamble.isEmpty()) + pos = preamble.head.pos; + else if (!body.isEmpty()) + pos = body.head.pos; + else if (!tags.isEmpty()) + pos = tags.head.pos; + else if (!postamble.isEmpty()) + pos = postamble.head.pos; + + DCDocComment dc = m.at(pos).newDocCommentTree(comment, body, tags, preamble, postamble); return dc; } @@ -133,13 +154,17 @@ } } + protected List blockContent() { + return blockContent(Phase.BODY); + } + /** * Read block content, consisting of text, html and inline tags. * Terminated by the end of input, or the beginning of the next block tag: * i.e. @ as the first non-whitespace character on a line. */ @SuppressWarnings("fallthrough") - protected List blockContent() { + protected List blockContent(Phase phase) { ListBuffer trees = new ListBuffer<>(); textStart = -1; @@ -160,8 +185,36 @@ case '<': newline = false; + if (isFileContent) { + switch (phase) { + case PREAMBLE: + if (peek("body")) { + trees.add(html()); + if (textStart == -1) { + textStart = bp; + lastNonWhite = -1; + } + // mark this as the start, for processing purposes + newline = true; + break loop; + } + break; + case BODY: + if (peek("/body")) { + addPendingText(trees, lastNonWhite); + break loop; + } + break; + default: + // fallthrough + } + } addPendingText(trees, bp - 1); trees.add(html()); + + if (phase == Phase.PREAMBLE || phase == Phase.POSTAMBLE) { + break; // Ignore newlines after html tags, in the meta content + } if (textStart == -1) { textStart = bp; lastNonWhite = -1; @@ -734,11 +787,37 @@ } } + boolean peek(String s) { + final int savedpos = bp; + try { + if (ch == '<') + nextChar(); + + if (ch == '/') { + if (s.charAt(0) != ch) { + return false; + } else { + s = s.substring(1, s.length()); + nextChar(); + } + } + + if (isIdentifierStart(ch)) { + Name name = readIdentifier(); + return StringUtils.toLowerCase(name.toString()).equals(s); + } + return false; + } finally { + bp = savedpos; + ch = buf[bp]; + } + } + /** * Read the start or end of an HTML tag, or an HTML comment * {@literal } or {@literal } */ - protected DCTree html() { + private DCTree html() { int p = bp; nextChar(); if (isIdentifierStart(ch)) { @@ -790,6 +869,19 @@ nextChar(); } } + } else if (isIdentifierStart(ch) && peek("doctype")) { + readIdentifier(); + nextChar(); + skipWhitespace(); + int d = bp; + while (bp < buflen) { + if (ch == '>') { + int mark = bp; + nextChar(); + return m.at(d).newDocTypeTree(newString(d, mark)); + } + nextChar(); + } } } @@ -1316,4 +1408,5 @@ tagParsers.put(names.fromString(p.getTreeKind().tagName), p); } + } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Tue Dec 05 10:28:45 2017 +0000 @@ -26,8 +26,11 @@ package com.sun.tools.javac.parser; import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; +import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.util.*; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import java.nio.CharBuffer; @@ -46,14 +49,6 @@ private static final boolean scannerDebug = false; - /** Allow binary literals. - */ - private boolean allowBinaryLiterals; - - /** Allow underscores in literals. - */ - private boolean allowUnderscoresInLiterals; - /** The source language setting. */ private Source source; @@ -121,14 +116,24 @@ this.tokens = fac.tokens; this.source = fac.source; this.reader = reader; - this.allowBinaryLiterals = source.allowBinaryLiterals(); - this.allowUnderscoresInLiterals = source.allowUnderscoresInLiterals(); + } + + private void checkSourceLevel(int pos, Feature feature) { + if (!feature.allowedInSource(source)) { + lexError(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name)); + } } /** Report an error at the given position using the provided arguments. */ - protected void lexError(int pos, String key, Object... args) { - log.error(pos, key, args); + protected void lexError(int pos, JCDiagnostic.Error key) { + log.error(pos, key); + tk = TokenKind.ERROR; + errPos = pos; + } + + protected void lexError(DiagnosticFlag flags, int pos, JCDiagnostic.Error key) { + log.error(flags, pos, key); tk = TokenKind.ERROR; errPos = pos; } @@ -175,7 +180,7 @@ case '\\': reader.putChar('\\', true); break; default: - lexError(reader.bp, "illegal.esc.char"); + lexError(reader.bp, Errors.IllegalEscChar); } } } else if (reader.bp != reader.buflen) { @@ -190,17 +195,14 @@ if (reader.ch != '_') { reader.putChar(false); } else { - if (!allowUnderscoresInLiterals) { - lexError(pos, "unsupported.underscore.lit", source.name); - allowUnderscoresInLiterals = true; - } + checkSourceLevel(pos, Feature.UNDERSCORES_IN_LITERALS); } saveCh = reader.ch; savePos = reader.bp; reader.scanChar(); } while (reader.digit(pos, digitRadix) >= 0 || reader.ch == '_'); if (saveCh == '_') - lexError(savePos, "illegal.underscore"); + lexError(savePos, Errors.IllegalUnderscore); } /** Read fractional part of hexadecimal floating point number. @@ -216,11 +218,11 @@ if (reader.digit(pos, 10) >= 0) { scanDigits(pos, 10); if (!hexFloatsWork) - lexError(pos, "unsupported.cross.fp.lit"); + lexError(pos, Errors.UnsupportedCrossFpLit); } else - lexError(pos, "malformed.fp.lit"); + lexError(pos, Errors.MalformedFpLit); } else { - lexError(pos, "malformed.fp.lit"); + lexError(pos, Errors.MalformedFpLit); } if (reader.ch == 'f' || reader.ch == 'F') { reader.putChar(true); @@ -254,7 +256,7 @@ scanDigits(pos, 10); return; } - lexError(pos, "malformed.fp.lit"); + lexError(pos, Errors.MalformedFpLit); reader.sp = sp1; } } @@ -287,14 +289,14 @@ scanDigits(pos, 16); } if (!seendigit) - lexError(pos, "invalid.hex.number"); + lexError(pos, Errors.InvalidHexNumber); else scanHexExponentAndSuffix(pos); } private void skipIllegalUnderscores() { if (reader.ch == '_') { - lexError(reader.bp, "illegal.underscore"); + lexError(reader.bp, Errors.IllegalUnderscore); while (reader.ch == '_') reader.scanChar(); } @@ -329,10 +331,10 @@ if (!seenValidDigit) { switch (radix) { case 2: - lexError(pos, "invalid.binary.number"); + lexError(pos, Errors.InvalidBinaryNumber); break; case 16: - lexError(pos, "invalid.hex.number"); + lexError(pos, Errors.InvalidHexNumber); break; } } @@ -504,10 +506,7 @@ skipIllegalUnderscores(); scanNumber(pos, 16); } else if (reader.ch == 'b' || reader.ch == 'B') { - if (!allowBinaryLiterals) { - lexError(pos, "unsupported.binary.lit", source.name); - allowBinaryLiterals = true; - } + checkSourceLevel(pos, Feature.BINARY_LITERALS); reader.scanChar(); skipIllegalUnderscores(); scanNumber(pos, 2); @@ -519,7 +518,7 @@ reader.scanChar(); } while (reader.ch == '_'); if (reader.digit(pos, 10) < 0) { - lexError(savePos, "illegal.underscore"); + lexError(savePos, Errors.IllegalUnderscore); } } scanNumber(pos, 8); @@ -542,7 +541,7 @@ reader.putChar('.'); tk = TokenKind.ELLIPSIS; } else { - lexError(savePos, "illegal.dot"); + lexError(savePos, Errors.IllegalDot); } } else { tk = TokenKind.DOT; @@ -600,7 +599,7 @@ comments = addComment(comments, processComment(pos, reader.bp, style)); break; } else { - lexError(pos, "unclosed.comment"); + lexError(pos, Errors.UnclosedComment); break loop; } } else if (reader.ch == '=') { @@ -613,17 +612,17 @@ case '\'': reader.scanChar(); if (reader.ch == '\'') { - lexError(pos, "empty.char.lit"); + lexError(pos, Errors.EmptyCharLit); reader.scanChar(); } else { if (reader.ch == CR || reader.ch == LF) - lexError(pos, "illegal.line.end.in.char.lit"); + lexError(pos, Errors.IllegalLineEndInCharLit); scanLitChar(pos); if (reader.ch == '\'') { reader.scanChar(); tk = TokenKind.CHARLITERAL; } else { - lexError(pos, "unclosed.char.lit"); + lexError(pos, Errors.UnclosedCharLit); } } break loop; @@ -635,7 +634,7 @@ tk = TokenKind.STRINGLITERAL; reader.scanChar(); } else { - lexError(pos, "unclosed.str.lit"); + lexError(pos, Errors.UnclosedStrLit); } break loop; default: @@ -676,7 +675,7 @@ String.format("%s", reader.ch) : String.format("\\u%04x", (int)reader.ch); } - lexError(pos, "illegal.char", arg); + lexError(pos, Errors.IllegalChar(arg)); reader.scanChar(); } } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Tue Dec 05 10:28:45 2017 +0000 @@ -26,12 +26,15 @@ package com.sun.tools.javac.parser; import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import com.sun.source.tree.ModuleTree.ModuleKind; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.parser.Tokens.*; import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; import com.sun.tools.javac.resources.CompilerProperties; @@ -41,6 +44,7 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +import com.sun.tools.javac.util.JCDiagnostic.Error; import com.sun.tools.javac.util.List; import static com.sun.tools.javac.parser.Tokens.TokenKind.*; @@ -163,23 +167,7 @@ this.log = fac.log; this.names = fac.names; this.source = fac.source; - this.allowTWR = source.allowTryWithResources(); - this.allowEffectivelyFinalVariablesInTWR = - source.allowEffectivelyFinalVariablesInTryWithResources(); - this.allowDiamond = source.allowDiamond(); - this.allowMulticatch = source.allowMulticatch(); this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true); - this.allowLambda = source.allowLambda(); - this.allowMethodReferences = source.allowMethodReferences(); - this.allowDefaultMethods = source.allowDefaultMethods(); - this.allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); - this.allowIntersectionTypesInCast = source.allowIntersectionTypesInCast(); - this.allowTypeAnnotations = source.allowTypeAnnotations(); - this.allowModules = source.allowModules(); - this.allowAnnotationsAfterTypeParams = source.allowAnnotationsAfterTypeParams(); - this.allowUnderscoreIdentifier = source.allowUnderscoreIdentifier(); - this.allowPrivateInterfaceMethods = source.allowPrivateInterfaceMethods(); - this.allowLocalVariableTypeInference = source.allowLocalVariableTypeInference(); this.keepDocComments = keepDocComments; this.parseModuleInfo = parseModuleInfo; docComments = newDocCommentTable(keepDocComments, fac); @@ -198,54 +186,10 @@ return keepDocComments ? new LazyDocCommentTable(fac) : null; } - /** Switch: Should diamond operator be recognized? - */ - boolean allowDiamond; - - /** Switch: Should multicatch clause be accepted? - */ - boolean allowMulticatch; - - /** Switch: should we recognize try-with-resources? - */ - boolean allowTWR; - - /** Switch: should we allow (effectively) final variables as resources in try-with-resources? - */ - boolean allowEffectivelyFinalVariablesInTWR; - /** Switch: should we fold strings? */ boolean allowStringFolding; - /** Switch: should we recognize lambda expressions? - */ - boolean allowLambda; - - /** Switch: should we allow method/constructor references? - */ - boolean allowMethodReferences; - - /** Switch: should we recognize modules? - */ - boolean allowModules; - - /** Switch: should we allow default methods in interfaces? - */ - boolean allowDefaultMethods; - - /** Switch: should we allow static methods in interfaces? - */ - boolean allowStaticInterfaceMethods; - - /** Switch: should we allow private (instance) methods in interfaces? - */ - boolean allowPrivateInterfaceMethods; - - /** Switch: should we allow intersection types in cast? - */ - boolean allowIntersectionTypesInCast; - /** Switch: should we keep docComments? */ boolean keepDocComments; @@ -254,27 +198,11 @@ */ boolean keepLineMap; - /** Switch: should we recognize type annotations? - */ - boolean allowTypeAnnotations; - - /** Switch: should we allow annotations after the method type parameters? - */ - boolean allowAnnotationsAfterTypeParams; - - /** Switch: should we allow '_' as an identifier? - */ - boolean allowUnderscoreIdentifier; - /** Switch: is "this" allowed as an identifier? * This is needed to parse receiver types. */ boolean allowThisIdent; - /** Switch: is local variable inference allowed? - */ - boolean allowLocalVariableTypeInference; - /** The type of the method receiver, as specified by a first "this" parameter. */ JCVariableDecl receiverParam; @@ -628,7 +556,7 @@ } else if (token.kind == THIS) { if (allowThisIdent) { // Make sure we're using a supported source version. - checkTypeAnnotations(); + checkSourceLevel(Feature.TYPE_ANNOTATIONS); Name name = token.name(); nextToken(); return name; @@ -638,7 +566,7 @@ return names.error; } } else if (token.kind == UNDERSCORE) { - if (allowUnderscoreIdentifier) { + if (Feature.UNDERSCORE_IDENTIFIER.allowedInSource(source)) { warning(token.pos, "underscore.as.identifier"); } else { error(token.pos, "underscore.as.identifier"); @@ -1170,7 +1098,7 @@ int pos1 = pos; List targets = List.of(t = parseType()); while (token.kind == AMP) { - checkIntersectionTypesInCast(); + checkSourceLevel(Feature.INTERSECTION_TYPES_IN_CAST); accept(AMP); targets = targets.prepend(parseType()); } @@ -1771,7 +1699,7 @@ } JCExpression lambdaExpressionOrStatementRest(List args, int pos) { - checkLambda(); + checkSourceLevel(Feature.LAMBDA); accept(ARROW); return token.kind == LBRACE ? @@ -1890,7 +1818,7 @@ if (token.kind == LT) { nextToken(); if (token.kind == GT && diamondAllowed) { - checkDiamond(); + checkSourceLevel(Feature.DIAMOND); mode |= DIAMOND; nextToken(); return List.nil(); @@ -2065,7 +1993,7 @@ } JCExpression memberReferenceSuffix(int pos1, JCExpression t) { - checkMethodReferences(); + checkSourceLevel(Feature.METHOD_REFERENCES); mode = EXPR; List typeArgs = null; if (token.kind == LT) { @@ -2568,7 +2496,7 @@ nextToken(); List resources = List.nil(); if (token.kind == LPAREN) { - checkTryWithResources(); + checkSourceLevel(Feature.TRY_WITH_RESOURCES); nextToken(); resources = resources(); accept(RPAREN); @@ -2584,7 +2512,7 @@ } } else { if (resources.isEmpty()) { - if (allowTWR) { + if (Feature.TRY_WITH_RESOURCES.allowedInSource(source)) { error(pos, "try.without.catch.finally.or.resource.decls"); } else { error(pos, "try.without.catch.or.finally"); @@ -2701,7 +2629,7 @@ ListBuffer catchTypes = new ListBuffer<>(); catchTypes.add(parseType()); while (token.kind == BAR) { - checkMulticatch(); + checkSourceLevel(Feature.MULTICATCH); nextToken(); // Instead of qualident this is now parseType. // But would that allow too much, e.g. arrays or generics? @@ -2870,7 +2798,7 @@ case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; case STRICTFP : flag = Flags.STRICTFP; break; case MONKEYS_AT : flag = Flags.ANNOTATION; break; - case DEFAULT : checkDefaultMethods(); flag = Flags.DEFAULT; break; + case DEFAULT : checkSourceLevel(Feature.DEFAULT_METHODS); flag = Flags.DEFAULT; break; case ERROR : flag = 0; nextToken(); break; default: break loop; } @@ -2914,7 +2842,7 @@ JCAnnotation annotation(int pos, Tag kind) { // accept(AT); // AT consumed by caller if (kind == Tag.TYPE_ANNOTATION) { - checkTypeAnnotations(); + checkSourceLevel(Feature.TYPE_ANNOTATIONS); } JCTree ident = qualident(false); List fieldValues = annotationFieldValuesOpt(); @@ -3028,7 +2956,7 @@ boolean localDecl) { JCVariableDecl head = variableDeclaratorRest(pos, mods, type, name, reqInit, dc, localDecl); - boolean implicit = allowLocalVariableTypeInference && head.vartype == null; + boolean implicit = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && head.vartype == null; vdefs.append(head); while (token.kind == COMMA) { if (implicit) { @@ -3066,7 +2994,7 @@ else if (reqInit) syntaxError(token.pos, "expected", EQ); JCTree elemType = TreeInfo.innermostType(type, true); int startPos = Position.NOPOS; - if (allowLocalVariableTypeInference && elemType.hasTag(IDENT)) { + if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && elemType.hasTag(IDENT)) { Name typeName = ((JCIdent)elemType).name; if (isRestrictedLocalVarTypeName(typeName)) { if (type.hasTag(TYPEARRAY)) { @@ -3100,7 +3028,7 @@ } boolean isRestrictedLocalVarTypeName(Name name) { - return allowLocalVariableTypeInference && name == names.var; + return Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) && name == names.var; } /** VariableDeclaratorId = Ident BracketsOpt @@ -3176,7 +3104,7 @@ JCModifiers mods = toP(F.at(startPos).Modifiers(Flags.FINAL)); return variableDeclaratorRest(token.pos, mods, t, ident(), true, null, true); } else { - checkVariableInTryWithResources(startPos); + checkSourceLevel(Feature.EFFECTIVELY_FINAL_VARIABLES_IN_TRY_WITH_RESOURCES); if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) { log.error(t.pos(), Errors.TryWithResourcesExprNeedsVar); } @@ -3278,10 +3206,7 @@ JCModuleDecl moduleDecl(JCModifiers mods, ModuleKind kind, Comment dc) { int pos = token.pos; - if (!allowModules) { - log.error(pos, Errors.ModulesNotSupportedInSource(source.name)); - allowModules = true; - } + checkSourceLevel(Feature.MODULES); nextToken(); JCExpression name = qualident(false); @@ -3700,7 +3625,7 @@ List annosAfterParams = annotationsOpt(Tag.ANNOTATION); if (annosAfterParams.nonEmpty()) { - checkAnnotationsAfterTypeParams(annosAfterParams.head.pos); + checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS); mods.annotations = mods.annotations.appendList(annosAfterParams); if (mods.pos == Position.NOPOS) mods.pos = mods.annotations.head.pos; @@ -3768,10 +3693,10 @@ Comment dc) { if (isInterface) { if ((mods.flags & Flags.STATIC) != 0) { - checkStaticInterfaceMethods(); + checkSourceLevel(Feature.STATIC_INTERFACE_METHODS); } if ((mods.flags & Flags.PRIVATE) != 0) { - checkPrivateInterfaceMethods(); + checkSourceLevel(Feature.PRIVATE_INTERFACE_METHODS); } } JCVariableDecl prevReceiverParam = this.receiverParam; @@ -4226,64 +4151,13 @@ } } - void checkDiamond() { - if (!allowDiamond) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.DiamondNotSupportedInSource(source.name)); - } - } - void checkMulticatch() { - if (!allowMulticatch) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.MulticatchNotSupportedInSource(source.name)); - } - } - void checkTryWithResources() { - if (!allowTWR) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.TryWithResourcesNotSupportedInSource(source.name)); - } - } - void checkVariableInTryWithResources(int startPos) { - if (!allowEffectivelyFinalVariablesInTWR) { - log.error(DiagnosticFlag.SOURCE_LEVEL, startPos, Errors.VarInTryWithResourcesNotSupportedInSource(source.name)); - } - } - void checkLambda() { - if (!allowLambda) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.LambdaNotSupportedInSource(source.name)); - } + void checkSourceLevel(Feature feature) { + checkSourceLevel(token.pos, feature); } - void checkMethodReferences() { - if (!allowMethodReferences) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.MethodReferencesNotSupportedInSource(source.name)); - } - } - void checkDefaultMethods() { - if (!allowDefaultMethods) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.DefaultMethodsNotSupportedInSource(source.name)); - } - } - void checkIntersectionTypesInCast() { - if (!allowIntersectionTypesInCast) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.IntersectionTypesInCastNotSupportedInSource(source.name)); - } - } - void checkStaticInterfaceMethods() { - if (!allowStaticInterfaceMethods) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.StaticIntfMethodsNotSupportedInSource(source.name)); - } - } - void checkTypeAnnotations() { - if (!allowTypeAnnotations) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, Errors.TypeAnnotationsNotSupportedInSource(source.name)); - } - } - void checkPrivateInterfaceMethods() { - if (!allowPrivateInterfaceMethods) { - log.error(DiagnosticFlag.SOURCE_LEVEL, token.pos, CompilerProperties.Errors.PrivateIntfMethodsNotSupportedInSource(source.name)); - } - } - protected void checkAnnotationsAfterTypeParams(int pos) { - if (!allowAnnotationsAfterTypeParams) { - log.error(DiagnosticFlag.SOURCE_LEVEL, pos, Errors.AnnotationsAfterTypeParamsNotSupportedInSource(source.name)); + + protected void checkSourceLevel(int pos, Feature feature) { + if (!feature.allowedInSource(source)) { + log.error(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name)); } } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue Dec 05 10:28:45 2017 +0000 @@ -53,6 +53,7 @@ import com.sun.tools.javac.api.MultiTaskListener; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Scope.WriteableScope; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.ClassType; import com.sun.tools.javac.code.Types; @@ -116,7 +117,6 @@ private final boolean fatalErrors; private final boolean werror; private final boolean showResolveErrors; - private final boolean allowModules; private final JavacFiler filer; private final JavacMessager messager; @@ -233,8 +233,6 @@ initialCompleter = ClassFinder.instance(context).getCompleter(); chk = Check.instance(context); initProcessorLoader(); - - allowModules = source.allowModules(); } public void setProcessors(Iterable processors) { @@ -770,7 +768,7 @@ if (psi.processorIterator.hasNext()) { ProcessorState ps = new ProcessorState(psi.processorIterator.next(), - log, source, allowModules, + log, source, Feature.MODULES.allowedInSource(source), JavacProcessingEnvironment.this); psi.procStateList.add(ps); return ps; @@ -837,7 +835,7 @@ for(TypeElement a : annotationsPresent) { ModuleElement mod = elementUtils.getModuleOf(a); - String moduleSpec = allowModules && mod != null ? mod.getQualifiedName() + "/" : ""; + String moduleSpec = Feature.MODULES.allowedInSource(source) && mod != null ? mod.getQualifiedName() + "/" : ""; unmatchedAnnotations.put(moduleSpec + a.getQualifiedName().toString(), a); } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Dec 05 10:28:45 2017 +0000 @@ -2601,38 +2601,87 @@ ({3}) ######################################## -# Diagnostics for language feature changes +# Diagnostics for language feature changes. +# Such diagnostics have a common template which can be customized by using a feature +# diagnostic fragment (one of those given below). ######################################## -# 0: string -compiler.err.modules.not.supported.in.source=\ - modules are not supported in -source {0}\n\ - (use -source 9 or higher to enable modules) - -# 0: string -compiler.misc.diamond.and.anon.class.not.supported.in.source=\ - cannot use ''<>'' with anonymous inner classes in -source {0}\n\ - (use -source 9 or higher to enable ''<>'' with anonymous inner classes) - -# 0: string -compiler.err.unsupported.binary.lit=\ - binary literals are not supported in -source {0}\n\ - (use -source 7 or higher to enable binary literals) - -# 0: string -compiler.err.unsupported.underscore.lit=\ - underscores in literals are not supported in -source {0}\n\ - (use -source 7 or higher to enable underscores in literals) - -# 0: string -compiler.err.try.with.resources.not.supported.in.source=\ - try-with-resources is not supported in -source {0}\n\ - (use -source 7 or higher to enable try-with-resources) - -# 0: string -compiler.err.var.in.try.with.resources.not.supported.in.source=\ - variables in try-with-resources not supported in -source {0}\n\ - (use -source 9 or higher to enable variables in try-with-resources) +# 0: message segment (feature), 1: string (found version), 2: string (expected version) +compiler.err.feature.not.supported.in.source=\ + {0} is not supported in -source {1}\n\ + (use -source {2} or higher to enable {0}) + +# 0: message segment (feature), 1: string (found version), 2: string (expected version) +compiler.err.feature.not.supported.in.source.plural=\ + {0} are not supported in -source {1}\n\ + (use -source {2} or higher to enable {0}) + +# 0: message segment (feature), 1: string (found version), 2: string (expected version) +compiler.misc.feature.not.supported.in.source=\ + {0} is not supported in -source {1}\n\ + (use -source {2} or higher to enable {0}) + +# 0: message segment (feature), 1: string (found version), 2: string (expected version) +compiler.misc.feature.not.supported.in.source.plural=\ + {0} are not supported in -source {1}\n\ + (use -source {2} or higher to enable {0}) + +compiler.misc.feature.modules=\ + modules + +compiler.misc.feature.diamond.and.anon.class=\ + ''<>'' with anonymous inner classes + +compiler.misc.feature.binary.lit=\ + binary literals + +compiler.misc.feature.underscore.lit=\ + underscores in literals + +compiler.misc.feature.try.with.resources=\ + try-with-resources + +compiler.misc.feature.var.in.try.with.resources=\ + variables in try-with-resources + +compiler.misc.feature.type.annotations=\ + type annotations + +compiler.misc.feature.annotations.after.type.params=\ + annotations after method type parameters + +compiler.misc.feature.repeatable.annotations=\ + repeated annotations + +compiler.misc.feature.diamond=\ + diamond operator + +compiler.misc.feature.multicatch=\ + multi-catch statements + +compiler.misc.feature.string.switch=\ + strings in switch + +compiler.misc.feature.lambda=\ + lambda expressions + +compiler.misc.feature.method.references=\ + method references + +compiler.misc.feature.default.methods=\ + default methods + +compiler.misc.feature.intersection.types.in.cast=\ + intersection types + +compiler.misc.feature.static.intf.methods=\ + static interface methods + +compiler.misc.feature.static.intf.method.invoke=\ + static interface method invocations + +compiler.misc.feature.private.intf.methods=\ + private interface methods compiler.warn.underscore.as.identifier=\ as of release 9, ''_'' is a keyword, and may not be used as an identifier @@ -2694,71 +2743,6 @@ compiler.err.no.annotations.on.dot.class=\ no annotations are allowed in the type of a class literal -# 0: string -compiler.err.type.annotations.not.supported.in.source=\ - type annotations are not supported in -source {0}\n\ -(use -source 8 or higher to enable type annotations) - -# 0: string -compiler.err.annotations.after.type.params.not.supported.in.source=\ - annotations after method type parameters are not supported in -source {0}\n\ -(use -source 8 or higher to enable annotations after method type parameters) - -# 0: string -compiler.err.repeatable.annotations.not.supported.in.source=\ - repeated annotations are not supported in -source {0}\n\ -(use -source 8 or higher to enable repeated annotations) - -# 0: string -compiler.err.diamond.not.supported.in.source=\ - diamond operator is not supported in -source {0}\n\ - (use -source 7 or higher to enable diamond operator) - -# 0: string -compiler.err.multicatch.not.supported.in.source=\ - multi-catch statement is not supported in -source {0}\n\ - (use -source 7 or higher to enable multi-catch statement) - -# 0: string -compiler.err.string.switch.not.supported.in.source=\ - strings in switch are not supported in -source {0}\n\ - (use -source 7 or higher to enable strings in switch) - -# 0: string -compiler.err.lambda.not.supported.in.source=\ - lambda expressions are not supported in -source {0}\n\ - (use -source 8 or higher to enable lambda expressions) - -# 0: string -compiler.err.method.references.not.supported.in.source=\ - method references are not supported in -source {0}\n\ - (use -source 8 or higher to enable method references) - -# 0: string -compiler.err.default.methods.not.supported.in.source=\ - default methods are not supported in -source {0}\n\ - (use -source 8 or higher to enable default methods) - -# 0: string -compiler.err.intersection.types.in.cast.not.supported.in.source=\ - intersection types in cast are not supported in -source {0}\n\ - (use -source 8 or higher to enable intersection types in cast) - -# 0: string -compiler.err.static.intf.methods.not.supported.in.source=\ - static interface methods are not supported in -source {0}\n\ - (use -source 8 or higher to enable static interface methods) - -# 0: string -compiler.err.static.intf.method.invoke.not.supported.in.source=\ - static interface method invocations are not supported in -source {0}\n\ - (use -source 8 or higher to enable static interface method invocations) - -# 0: string -compiler.err.private.intf.methods.not.supported.in.source=\ - private interface methods are not supported in -source {0}\n\ - (use -source 9 or higher to enable private interface methods) - ######################################## # Diagnostics for verbose resolution # used by Resolve (debug only) diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java Tue Dec 05 10:28:45 2017 +0000 @@ -109,17 +109,23 @@ public final List firstSentence; public final List body; public final List tags; + public final List preamble; + public final List postamble; public DCDocComment(Comment comment, List fullBody, List firstSentence, List body, - List tags) { + List tags, + List preamble, + List postamble) { this.comment = comment; this.firstSentence = firstSentence; this.fullBody = fullBody; this.body = body; this.tags = tags; + this.preamble = preamble; + this.postamble = postamble; } @Override @DefinedBy(Api.COMPILER_TREE) @@ -152,6 +158,15 @@ return tags; } + @Override @DefinedBy(Api.COMPILER_TREE) + public List getPreamble() { + return preamble; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public List getPostamble() { + return postamble; + } } public static abstract class DCBlockTag extends DCTree implements BlockTagTree { @@ -288,6 +303,29 @@ } } + public static class DCDocType extends DCTree implements DocTypeTree { + public final String text; + + DCDocType(String text) { + this.text = text; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Kind getKind() { + return Kind.DOC_TYPE; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public R accept(DocTreeVisitor v, D d) { + return v.visitDocType(this, d); + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public String getText() { + return text; + } + } + public static class DCEndElement extends DCTree implements EndElementTree { public final Name name; diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java Tue Dec 05 10:28:45 2017 +0000 @@ -225,6 +225,16 @@ } @Override @DefinedBy(Api.COMPILER_TREE) + public Void visitDocType(DocTypeTree node, Void p) { + try { + print(node.getText()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return null; + } + + @Override @DefinedBy(Api.COMPILER_TREE) public Void visitEndElement(EndElementTree node, Void p) { try { print(" fullBody, List tags) { + @Override @DefinedBy(Api.COMPILER_TREE) + public DCDocComment newDocCommentTree(List fullBody, List tags) { Pair, List> pair = splitBody(fullBody); - DCDocComment tree = new DCDocComment(comment, cast(fullBody), pair.fst, pair.snd, cast(tags)); + List preamble = Collections.emptyList(); + List postamble = Collections.emptyList(); + + return newDocCommentTree(fullBody, tags, preamble, postamble); + } + + public DCDocComment newDocCommentTree(Comment comment, + List fullBody, + List tags, + List preamble, + List postamble) { + Pair, List> pair = splitBody(fullBody); + DCDocComment tree = new DCDocComment(comment, cast(fullBody), pair.fst, pair.snd, + cast(tags), cast(preamble), cast(postamble)); tree.pos = pos; return tree; } @@ -208,7 +225,10 @@ * where the trees are being synthesized by a tool. */ @Override @DefinedBy(Api.COMPILER_TREE) - public DCDocComment newDocCommentTree(List fullBody, List tags) { + public DCDocComment newDocCommentTree(List fullBody, + List tags, + List preamble, + List postamble) { ListBuffer lb = new ListBuffer<>(); lb.addAll(cast(fullBody)); List fBody = lb.toList(); @@ -236,7 +256,8 @@ } }; Pair, List> pair = splitBody(fullBody); - DCDocComment tree = new DCDocComment(c, fBody, pair.fst, pair.snd, cast(tags)); + DCDocComment tree = new DCDocComment(c, fBody, pair.fst, pair.snd, cast(tags), + cast(preamble), cast(postamble)); return tree; } @@ -248,6 +269,13 @@ } @Override @DefinedBy(Api.COMPILER_TREE) + public DCDocType newDocTypeTree(String text) { + DCDocType tree = new DCDocType(text); + tree.pos = pos; + return tree; + } + + @Override @DefinedBy(Api.COMPILER_TREE) public DCEndElement newEndElementTree(Name name) { DCEndElement tree = new DCEndElement(name); tree.pos = pos; diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java Tue Dec 05 10:28:45 2017 +0000 @@ -426,7 +426,7 @@ /** A set of "not-supported-in-source-X" errors produced so far. This is used to only generate * one such error per file. */ - protected Set> recordedSourceLevelErrors = new HashSet<>(); + protected Set>> recordedSourceLevelErrors = new HashSet<>(); public boolean hasDiagnosticListener() { return diagListener != null; @@ -521,13 +521,29 @@ if (!d.isFlagSet(DiagnosticFlag.SOURCE_LEVEL)) return true; - Pair coords = new Pair<>(file, d.getCode()); + Pair> coords = new Pair<>(file, getCode(d)); boolean shouldReport = !recordedSourceLevelErrors.contains(coords); if (shouldReport) recordedSourceLevelErrors.add(coords); return shouldReport; } + //where + private List getCode(JCDiagnostic d) { + ListBuffer buf = new ListBuffer<>(); + getCodeRecursive(buf, d); + return buf.toList(); + } + + private void getCodeRecursive(ListBuffer buf, JCDiagnostic d) { + buf.add(d.getCode()); + for (Object o : d.getArgs()) { + if (o instanceof JCDiagnostic) { + getCodeRecursive(buf, (JCDiagnostic)o); + } + } + } + /** Prompt user after an error. */ public void prompt() { diff -r 10b34c929b4f -r 64298b1e890b src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocHelper.java --- a/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocHelper.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocHelper.java Tue Dec 05 10:28:45 2017 +0000 @@ -61,6 +61,7 @@ import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; @@ -214,7 +215,9 @@ } } - DocCommentTree docCommentTree = parseDocComment(task, docComment); + Pair parsed = parseDocComment(task, docComment); + DocCommentTree docCommentTree = parsed.fst; + int offset = parsed.snd; IOException[] exception = new IOException[1]; Map replace = new TreeMap<>((span1, span2) -> span2[0] - span1[0]); @@ -349,7 +352,10 @@ if (inherited == null) { return null; } - DocCommentTree inheritedDocTree = parseDocComment(inheritedJavacTask, inherited); + Pair parsed = + parseDocComment(inheritedJavacTask, inherited); + DocCommentTree inheritedDocTree = parsed.fst; + int offset = parsed.snd; List> inheritedText = new ArrayList<>(); DocTree parent = interestingParent.peek(); switch (parent.getKind()) { @@ -391,7 +397,6 @@ break; } if (!inheritedText.isEmpty()) { - long offset = trees.getSourcePositions().getStartPosition(null, inheritedDocTree, inheritedDocTree); long start = Long.MAX_VALUE; long end = Long.MIN_VALUE; @@ -475,7 +480,6 @@ return docComment; StringBuilder replacedInheritDoc = new StringBuilder(docComment); - int offset = (int) trees.getSourcePositions().getStartPosition(null, docCommentTree, docCommentTree); for (Entry e : replace.entrySet()) { replacedInheritDoc.delete(e.getKey()[0] - offset, e.getKey()[1] - offset + 1); @@ -507,22 +511,28 @@ } private DocTree parseBlockTag(JavacTask task, String blockTag) { - DocCommentTree dc = parseDocComment(task, blockTag); + DocCommentTree dc = parseDocComment(task, blockTag).fst; return dc.getBlockTags().get(0); } - private DocCommentTree parseDocComment(JavacTask task, String javadoc) { + private Pair parseDocComment(JavacTask task, String javadoc) { DocTrees trees = DocTrees.instance(task); try { - return trees.getDocCommentTree(new SimpleJavaFileObject(new URI("mem://doc.html"), javax.tools.JavaFileObject.Kind.HTML) { + SimpleJavaFileObject fo = + new SimpleJavaFileObject(new URI("mem://doc.html"), Kind.HTML) { @Override @DefinedBy(Api.COMPILER) - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + public CharSequence getCharContent(boolean ignoreEncodingErrors) + throws IOException { return "" + javadoc + ""; } - }); + }; + DocCommentTree tree = trees.getDocCommentTree(fo); + int offset = (int) trees.getSourcePositions().getStartPosition(null, tree, tree); + offset += "".length() + 1; + return Pair.of(tree, offset); } catch (URISyntaxException ex) { - return null; + throw new IllegalStateException(ex); } } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/RootDocImpl.java Tue Dec 05 10:28:45 2017 +0000 @@ -34,6 +34,7 @@ import javax.tools.StandardJavaFileManager; import com.sun.javadoc.*; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; @@ -388,7 +389,7 @@ } public boolean isFunctionalInterface(AnnotationDesc annotationDesc) { - return env.source.allowLambda() + return Feature.LAMBDA.allowedInSource(env.source) && annotationDesc.annotationType().qualifiedName().equals( env.syms.functionalInterfaceType.toString()); } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 com.sun.source.doctree.DocTree; +import com.sun.source.doctree.EndElementTree; +import com.sun.source.doctree.StartElementTree; +import com.sun.source.doctree.TextTree; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; +import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.DocFileElement; +import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler; +import jdk.javadoc.internal.doclets.toolkit.util.DocFile; +import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; +import jdk.javadoc.internal.doclets.toolkit.util.DocPath; +import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; +import jdk.javadoc.internal.doclets.toolkit.util.Utils; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ModuleElement; +import javax.lang.model.element.PackageElement; +import javax.tools.FileObject; +import javax.tools.JavaFileManager.Location; +import java.util.Collections; +import java.util.List; + +public class DocFilesHandlerImpl implements DocFilesHandler { + + public final Element element; + public final Location location; + public final DocPath source; + public final HtmlConfiguration configuration; + + /** + * Constructor to construct the DocFilesWriter object. + * + * @param configuration the configuration of this doclet. + * @param element the containing element of the doc-files. + * + */ + public DocFilesHandlerImpl(HtmlConfiguration configuration, Element element) { + this.configuration = configuration; + this.element = element; + + switch (element.getKind()) { + case MODULE: + location = configuration.utils.getLocationForModule((ModuleElement)element); + source = DocPaths.DOC_FILES; + break; + case PACKAGE: + location = configuration.utils.getLocationForPackage((PackageElement)element); + source = DocPath.forPackage((PackageElement)element).resolve(DocPaths.DOC_FILES); + break; + default: + throw new AssertionError("unsupported element " + element); + } + } + + /** + * Copy doc-files directory and its contents from the source + * elements directory to the generated documentation directory. + * + * @throws DocFileIOException if there is a problem while copying + * the documentation files + */ + + public void copyDocFiles() throws DocFileIOException { + boolean first = true; + for (DocFile srcdir : DocFile.list(configuration, location, source)) { + if (!srcdir.isDirectory()) { + continue; + } + DocPath path = null; + switch (this.element.getKind()) { + case MODULE: + path = DocPath.forModule((ModuleElement)this.element); + break; + case PACKAGE: + path = DocPath.forPackage((PackageElement)this.element); + break; + default: + throw new AssertionError("unknown kind:" + this.element.getKind()); + } + copyDirectory(srcdir, path.resolve(DocPaths.DOC_FILES), first); + first = false; + } + } + + + private void copyDirectory(DocFile srcdir, final DocPath dstDocPath, + boolean first) throws DocFileIOException { + DocFile dstdir = DocFile.createFileForOutput(configuration, dstDocPath); + if (srcdir.isSameFile(dstdir)) { + return; + } + for (DocFile srcfile: srcdir.list()) { + DocFile destfile = dstdir.resolve(srcfile.getName()); + if (srcfile.isFile()) { + if (destfile.exists() && !first) { + configuration.messages.warning("doclet.Copy_Overwrite_warning", + srcfile.getPath(), dstdir.getPath()); + } else { + configuration.messages.notice("doclet.Copying_File_0_To_Dir_1", + srcfile.getPath(), dstdir.getPath()); + if (Utils.toLowerCase(srcfile.getPath()).endsWith(".html")) { + handleHtmlFile(srcfile, dstDocPath); + } else { + destfile.copyFile(srcfile); + } + } + } else if (srcfile.isDirectory()) { + if (configuration.copydocfilesubdirs + && !configuration.shouldExcludeDocFileDir(srcfile.getName())) { + DocPath dirDocPath = dstDocPath.resolve(srcfile.getName()); + copyDirectory(srcfile, dirDocPath, first); + } + } + } + } + + private void handleHtmlFile(DocFile srcfile, DocPath dstPath) throws DocFileIOException { + DocPath dfilePath = dstPath.resolve(srcfile.getName()); + HtmlDocletWriter docletWriter = new DocFileWriter(configuration, dfilePath, element); + + Utils utils = configuration.utils; + + FileObject fileObject = srcfile.getFileObject(); + DocFileElement dfElement = new DocFileElement(element, fileObject); + String title = getWindowTitle(docletWriter, dfElement).trim(); + HtmlTree htmlContent = docletWriter.getBody(true, title); + docletWriter.addTop(htmlContent); + docletWriter.addNavLinks(true, htmlContent); + + List fullBody = utils.getFullBody(dfElement); + Content bodyContent = docletWriter.commentTagsToContent(null, dfElement, fullBody, false); + + docletWriter.addTagsInfo(dfElement, bodyContent); + htmlContent.addContent(bodyContent); + + docletWriter.addNavLinks(false, htmlContent); + docletWriter.addBottom(htmlContent); + docletWriter.printHtmlDocument(Collections.emptyList(), false, htmlContent); + } + + private String getWindowTitle(HtmlDocletWriter docletWriter, Element element) { + List preamble = configuration.utils.getPreamble(element); + StringBuilder sb = new StringBuilder(); + boolean titleFound = false; + loop: + for (DocTree dt : preamble) { + switch (dt.getKind()) { + case START_ELEMENT: + StartElementTree nodeStart = (StartElementTree)dt; + if (Utils.toLowerCase(nodeStart.getName().toString()).equals("title")) { + titleFound = true; + } + break; + + case END_ELEMENT: + EndElementTree nodeEnd = (EndElementTree)dt; + if (Utils.toLowerCase(nodeEnd.getName().toString()).equals("title")) { + break loop; + } + break; + + case TEXT: + TextTree nodeText = (TextTree)dt; + if (titleFound) + sb.append(nodeText.getBody()); + break; + + default: + // do nothing + } + } + return docletWriter.getWindowTitle(sb.toString().trim()); + } + + private static class DocFileWriter extends HtmlDocletWriter { + + final PackageElement pkg; + + /** + * Constructor to construct the HtmlDocletWriter object. + * + * @param configuration the configuruation of this doclet. + * @param path the file to be generated. + * @param e the anchoring element. + */ + public DocFileWriter(HtmlConfiguration configuration, DocPath path, Element e) { + super(configuration, path); + switch (e.getKind()) { + case PACKAGE: + pkg = (PackageElement)e; + break; + default: + throw new AssertionError("unsupported element: " + e.getKind()); + } + } + + /** + * Get the module link. + * + * @return a content tree for the module link + */ + @Override + protected Content getNavLinkModule() { + Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(pkg), + contents.moduleLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + + /** + * Get this package link. + * + * @return a content tree for the package link + */ + @Override + protected Content getNavLinkPackage() { + Content linkContent = getPackageLink(pkg, + contents.packageLabel); + Content li = HtmlTree.LI(linkContent); + return li; + } + } +} diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Tue Dec 05 10:28:45 2017 +0000 @@ -2268,13 +2268,14 @@ * @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 map annotation type element to annotation 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) { + ContentBuilder annotation, + Map map, + int indent, boolean linkBreak) { linkInfo.label = new StringContent("@"); linkInfo.label.addContent(annotationDoc.getSimpleName()); annotation.addContent(getLink(linkInfo)); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java Tue Dec 05 10:28:45 2017 +0000 @@ -26,6 +26,7 @@ package jdk.javadoc.internal.doclets.formats.html; +import javax.lang.model.element.Element; import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -37,6 +38,7 @@ 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.DocFilesHandler; import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter; @@ -235,4 +237,12 @@ public SerializedFormWriter getSerializedFormWriter() { return new SerializedFormWriterImpl(configuration); } + + /** + * {@inheritDoc} + */ + @Override + public DocFilesHandler getDocFilesHandler(Element element) { + return new DocFilesHandlerImpl(configuration, element); + } } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java Tue Dec 05 10:28:45 2017 +0000 @@ -375,7 +375,6 @@ } initialized = true; this.docEnv = docEnv; - overviewElement = new OverviewElement(docEnv); Splitter specifiedSplitter = new Splitter(docEnv, false); specifiedModuleElements = Collections.unmodifiableSet(specifiedSplitter.mset); specifiedPackageElements = Collections.unmodifiableSet(specifiedSplitter.pset); @@ -715,6 +714,7 @@ * initializes certain components before anything else is started. */ protected boolean finishOptionSettings0() throws DocletException { + initDestDirectory(); for (String link : linkList) { extern.link(link, reporter); @@ -731,6 +731,7 @@ group.checkPackageGroups(grp.first, grp.second); } }); + overviewElement = new OverviewElement(workArounds.getUnnamedPackage(), getOverviewPath()); return true; } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java Tue Dec 05 10:28:45 2017 +0000 @@ -177,8 +177,11 @@ PackageElement pe = null; switch (e.getKind()) { case OTHER: - fo = configuration.getOverviewPath(); - pe = configuration.workArounds.getUnnamedPackage(); + if (e instanceof DocletElement) { + DocletElement de = (DocletElement)e; + fo = de.getFileObject(); + pe = de.getPackageElement(); + } break; case PACKAGE: fo = configuration.workArounds.getJavaFileObject((PackageElement)e); @@ -209,13 +212,12 @@ }); } - public void setDocCommentTree(Element element, List fullBody, - List blockTags, Utils utils) { + public void setDocCommentTree(Element element, List fullBody, + List blockTags, Utils utils) { DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, blockTags); dcTreesMap.put(element, new DocCommentDuo(null, docTree)); - // There maybe an entry with the original comments usually null, - // therefore remove that entry if it exists, and allow a new one - // to be reestablished. + // A method having null comment (no comment) that might need to be replaced + // with a synthetic comment, remove such a comment from the cache. utils.removeCommentHelper(element); } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/DocFileElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/DocFileElement.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.toolkit; + +import java.lang.annotation.Annotation; +import java.util.Set; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ElementVisitor; +import javax.lang.model.element.Name; +import javax.lang.model.element.PackageElement; +import javax.lang.model.type.TypeMirror; +import javax.tools.FileObject; + +import jdk.javadoc.doclet.DocletEnvironment; + +/** + * This is a pseudo element wrapper for doc-files html contents, essentially to + * associate the doc-file's html documentation's DocCommentTree to an element. + * + *

          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 DocFileElement implements DocletElement { + + private final Element element; + private final FileObject fo; + + public DocFileElement(Element element, FileObject fo) { + this.element = element; + this.fo = fo; + } + + @Override + public PackageElement getPackageElement() { + switch(element.getKind()) { + case MODULE: + // uncomment to support doc-files in modules + // return configuration.workArounds.getUnnamedPackage(); + throw new UnsupportedOperationException("not implemented"); + case PACKAGE: + return (PackageElement)element; + default: + throw new AssertionError("unknown kind: " + element.getKind()); + } + } + + @Override + public FileObject getFileObject() { + return fo; + } + + @Override + public Kind getSubKind() { + return Kind.DOCFILE; + } +} + diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/DocFilesHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/DocFilesHandler.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.toolkit; + +/** + * The interface for copying doc-files to the 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. + */ + +public interface DocFilesHandler { + void copyDocFiles() throws DocletException; +} diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/DocletElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/DocletElement.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.toolkit; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ElementVisitor; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.Name; +import javax.lang.model.element.PackageElement; +import javax.lang.model.type.TypeMirror; +import javax.tools.FileObject; +import java.lang.annotation.Annotation; +import java.util.Set; + +public interface DocletElement extends Element { + + public default TypeMirror asType() { + throw new UnsupportedOperationException("Unsupported method"); + } + + default ElementKind getKind() { + return ElementKind.OTHER; + } + + default Set getModifiers() { + throw new UnsupportedOperationException("Unsupported method"); + } + + default Name getSimpleName() { + throw new UnsupportedOperationException("Unsupported method"); + } + + default Element getEnclosingElement() { + throw new UnsupportedOperationException("Unsupported method"); + } + + default java.util.List getEnclosedElements() { + throw new UnsupportedOperationException("Unsupported method"); + } + + default java.util.List getAnnotationMirrors() { + throw new UnsupportedOperationException("Unsupported method"); + } + + default A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException("Unsupported method"); + } + + default R accept(ElementVisitor v, P p) { + return v.visitUnknown(this, p); + } + + default A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException("Unsupported method"); + } + + /** + * Returns the anchoring package element, in the case of a + * module element, this is the module's unnamed package. + * @return the anchor element. + */ + PackageElement getPackageElement(); + + /** + * Returns the file object associated with this special + * element such as overview.html, doc-file/foo.html. + * @return the file object + */ + FileObject getFileObject(); + + /** + * Returns the subkind of this element. + * @return a subkind + */ + Kind getSubKind(); + + /** + * Sub kind enums that this element supports. + */ + public static enum Kind { + OVERVIEW, DOCFILE; + } +} diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/OverviewElement.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/OverviewElement.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/OverviewElement.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,9 @@ package jdk.javadoc.internal.doclets.toolkit; -import java.lang.annotation.Annotation; -import java.util.Set; - -import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ElementVisitor; -import javax.lang.model.element.Name; -import javax.lang.model.type.TypeMirror; - -import jdk.javadoc.doclet.DocletEnvironment; +import javax.lang.model.element.PackageElement; +import javax.tools.FileObject; /** * This is a pseudo element wrapper for the overview element, essentially to @@ -46,62 +38,28 @@ * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class OverviewElement implements Element { - - public final DocletEnvironment docEnv; - - OverviewElement(DocletEnvironment docEnv) { - this.docEnv = docEnv; - } - - @Override - public TypeMirror asType() { - throw new UnsupportedOperationException("Unsupported method"); - } +public class OverviewElement implements DocletElement { - @Override - public ElementKind getKind() { - return ElementKind.OTHER; - } + private final PackageElement pkg; + private final FileObject fo; - @Override - public Set getModifiers() { - throw new UnsupportedOperationException("Unsupported method"); - } - - @Override - public Name getSimpleName() { - throw new UnsupportedOperationException("Unsupported method"); + public OverviewElement(PackageElement pkg, FileObject fo) { + this.pkg = pkg; + this.fo = fo; } @Override - public Element getEnclosingElement() { - throw new UnsupportedOperationException("Unsupported method"); + public PackageElement getPackageElement() { + return pkg; } - @Override - public java.util.List getEnclosedElements() { - throw new UnsupportedOperationException("Unsupported method"); - } - - @Override - public java.util.List getAnnotationMirrors() { - throw new UnsupportedOperationException("Unsupported method"); + public FileObject getFileObject() { + return fo; } @Override - public A getAnnotation(Class annotationType) { - throw new UnsupportedOperationException("Unsupported method"); - } - - @Override - public R accept(ElementVisitor v, P p) { - return v.visitUnknown(this, p); - } - - @Override - public A[] getAnnotationsByType(Class annotationType) { - throw new UnsupportedOperationException("Unsupported method"); + public Kind getSubKind() { + return Kind.OVERVIEW; } } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java Tue Dec 05 10:28:45 2017 +0000 @@ -55,6 +55,7 @@ import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Scope; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; @@ -187,7 +188,7 @@ // TODO: we need ElementUtils.getPackage to cope with input strings // to return the proper unnamedPackage for all supported releases. PackageElement getUnnamedPackage() { - return (toolEnv.source.allowModules()) + return (Feature.MODULES.allowedInSource(toolEnv.source)) ? toolEnv.syms.unnamedModule.unnamedPackage : toolEnv.syms.noModule.unnamedPackage; } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package jdk.javadoc.internal.doclets.toolkit; +import javax.lang.model.element.Element; import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -222,4 +223,11 @@ * @return the writer for the serialized form. */ public SerializedFormWriter getSerializedFormWriter(); + + /** + * Return the handler for doc files. + * + * @return the handler for the doc files. + */ + DocFilesHandler getDocFilesHandler(Element pkg); } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeBuilder.java Tue Dec 05 10:28:45 2017 +0000 @@ -30,6 +30,7 @@ import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter; import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler; import jdk.javadoc.internal.doclets.toolkit.DocletException; @@ -132,7 +133,10 @@ //Only copy doc files dir if the containing package is not //documented AND if we have not documented a class from the same //package already. Otherwise, we are making duplicate copies. - utils.copyDocFiles(containingPackage); + DocFilesHandler docFilesHandler = configuration + .getWriterFactory() + .getDocFilesHandler(containingPackage); + docFilesHandler.copyDocFiles(); containingPackagesSeen.add(containingPackage); } } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/BuilderFactory.java Tue Dec 05 10:28:45 2017 +0000 @@ -34,12 +34,15 @@ import javax.lang.model.type.TypeMirror; import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter; +import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration; import jdk.javadoc.internal.doclets.toolkit.ClassWriter; -import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration; import jdk.javadoc.internal.doclets.toolkit.PropertyWriter; import jdk.javadoc.internal.doclets.toolkit.WriterFactory; import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; + + + /** * The factory for constructing builders. * @@ -87,7 +90,7 @@ * @param pkg the package being documented. * @param prevPkg the previous package being documented. * @param nextPkg the next package being documented. - * @return the builder that builds the constant summary. + * @return the builder that builds the package summary. */ public AbstractBuilder getPackageSummaryBuilder(PackageElement pkg, PackageElement prevPkg, PackageElement nextPkg) { diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java Tue Dec 05 10:28:45 2017 +0000 @@ -30,6 +30,7 @@ import jdk.javadoc.internal.doclets.toolkit.ClassWriter; import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler; import jdk.javadoc.internal.doclets.toolkit.DocletException; import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; import jdk.javadoc.internal.doclets.toolkit.util.Utils; @@ -269,7 +270,7 @@ * * @throws DocFileIOException if there is a problem while copying the files */ - private void copyDocFiles() throws DocFileIOException { + private void copyDocFiles() throws DocletException { PackageElement containingPackage = utils.containingPackage(typeElement); if ((configuration.packages == null || !configuration.packages.contains(containingPackage)) && @@ -277,7 +278,10 @@ //Only copy doc files dir if the containing package is not //documented AND if we have not documented a class from the same //package already. Otherwise, we are making duplicate copies. - utils.copyDocFiles(containingPackage); + DocFilesHandler docFilesHandler = configuration + .getWriterFactory() + .getDocFilesHandler(containingPackage); + docFilesHandler.copyDocFiles(); containingPackagesSeen.add(containingPackage); } } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java Tue Dec 05 10:28:45 2017 +0000 @@ -30,7 +30,6 @@ import jdk.javadoc.internal.doclets.toolkit.Content; import jdk.javadoc.internal.doclets.toolkit.DocletException; import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter; -import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; /** @@ -117,7 +116,9 @@ moduleWriter.addModuleFooter(contentTree); moduleWriter.printDocument(contentTree); - utils.copyDirectory(mdle, DocPaths.moduleSummary(mdle)); + // uncomment to support doc-files in modules + // DocFilesHandler docFilesHandler = configuration.getWriterFactory().getDocFilesWriter(mdle); + // docFilesHandler.copyDocFiles(); } /** diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PackageSummaryBuilder.java Tue Dec 05 10:28:45 2017 +0000 @@ -32,6 +32,7 @@ import javax.lang.model.element.TypeElement; import jdk.javadoc.internal.doclets.toolkit.Content; +import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler; import jdk.javadoc.internal.doclets.toolkit.DocletException; import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter; @@ -122,7 +123,10 @@ packageWriter.addPackageFooter(contentTree); packageWriter.printDocument(contentTree); - utils.copyDocFiles(packageElement); + DocFilesHandler docFilesHandler = configuration + .getWriterFactory() + .getDocFilesHandler(packageElement); + docFilesHandler.copyDocFiles(); } /** diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java Tue Dec 05 10:28:45 2017 +0000 @@ -43,6 +43,7 @@ import jdk.javadoc.doclet.Doclet; import jdk.javadoc.doclet.DocletEnvironment; import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration; +import jdk.javadoc.internal.doclets.toolkit.DocletElement; import jdk.javadoc.internal.doclets.toolkit.Messages; import jdk.javadoc.internal.doclets.toolkit.Resources; @@ -571,6 +572,7 @@ return serializedFormTags; } + @SuppressWarnings("fallthrough") /** * Returns the custom tags for a given element. * @@ -597,7 +599,17 @@ case PACKAGE: return getPackageCustomTaglets(); case OTHER: - return getOverviewCustomTaglets(); + if (e instanceof DocletElement) { + DocletElement de = (DocletElement)e; + switch (de.getSubKind()) { + case DOCFILE: + return getPackageCustomTaglets(); + case OVERVIEW: + return getOverviewCustomTaglets(); + default: + // fall through + } + } default: throw new AssertionError("unknown element: " + e + " ,kind: " + e.getKind()); } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFile.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFile.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFile.java Tue Dec 05 10:28:45 2017 +0000 @@ -33,6 +33,7 @@ import java.io.UnsupportedEncodingException; import java.io.Writer; +import javax.tools.FileObject; import javax.tools.JavaFileManager.Location; import javax.tools.StandardLocation; @@ -102,6 +103,12 @@ } /** + * Returns a file object for the file. + * @return a file object + */ + public abstract FileObject getFileObject(); + + /** * Open an input stream for the file. * * @return an open input stream for the file diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPath.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPath.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPath.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package jdk.javadoc.internal.doclets.toolkit.util; +import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -73,6 +74,12 @@ return (typeElement == null) ? empty : new DocPath(utils.getSimpleName(typeElement) + ".html"); } + public static DocPath forModule(ModuleElement mdle) { + return mdle == null || mdle.isUnnamed() + ? empty + : DocPath.create(mdle.getQualifiedName().toString()); + } + /** * Return the path for the package of a class. * For example, if the class is java.lang.Object, diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java Tue Dec 05 10:28:45 2017 +0000 @@ -170,6 +170,11 @@ /** The name of the file for the package usage info. */ public static final DocPath PACKAGE_USE = DocPath.create("package-use.html"); + /** The name of the output directory for module documentation files. */ + public static DocPath moduleDocFiles(ModuleElement mdle) { + return DocPath.create(mdle.getQualifiedName() + "-doc-files"); + } + /** The name of the file for the module frame. */ public static DocPath moduleFrame(ModuleElement mdle) { return DocPath.create(mdle.getQualifiedName() + "-frame.html"); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java Tue Dec 05 10:28:45 2017 +0000 @@ -151,6 +151,11 @@ this.file = newFile(getDestDir(), path.getPath()); } + @Override + public FileObject getFileObject() { + return getJavaFileObjectForInput(file); + } + /** * Open an input stream for the file. * diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Tue Dec 05 10:28:45 2017 +0000 @@ -74,10 +74,12 @@ import com.sun.source.doctree.DocTree.Kind; import com.sun.source.doctree.ParamTree; import com.sun.source.doctree.SerialFieldTree; +import com.sun.source.doctree.StartElementTree; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.LineMap; import com.sun.source.util.DocSourcePositions; import com.sun.source.util.DocTrees; +import com.sun.source.util.SimpleDocTreeVisitor; import com.sun.source.util.TreePath; import com.sun.tools.javac.model.JavacTypes; import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration; @@ -265,97 +267,7 @@ return getEnclosingTypeElement(e) == null || isStatic(e); } - /** - * Copy doc-files directory and its contents from the source - * package directory to the generated documentation directory. - * For example, given a package java.lang, this method will copy - * the doc-files directory, found in the package directory to the - * generated documentation hierarchy. - * - * @param pe the package containing the doc files to be copied - * @throws DocFileIOException if there is a problem while copying - * the documentation files - */ - public void copyDocFiles(PackageElement pe) throws DocFileIOException { - Location sourceLoc = getLocationForPackage(pe); - copyDirectory(sourceLoc, DocPath.forPackage(pe).resolve(DocPaths.DOC_FILES)); - } - - /** - * Copy the given directory contents from the source package directory - * to the generated documentation directory. For example, given a package - * java.lang, this method will copy the entire directory, to the generated - * documentation hierarchy. - * - * @param pe the package containing the directory to be copied - * @param dir the directory to be copied - * @throws DocFileIOException if there is a problem while copying - * the documentation files - */ - public void copyDirectory(PackageElement pe, DocPath dir) throws DocFileIOException { - copyDirectory(getLocationForPackage(pe), dir); - } - - /** - * Copy the given directory and its contents from the source - * module directory to the generated documentation directory. - * For example, given a package java.lang, this method will - * copy the entire directory, to the generated documentation - * hierarchy. - * - * @param mdle the module containing the directory to be copied - * @param dir the directory to be copied - * @throws DocFileIOException if there is a problem while copying - * the documentation files - */ - public void copyDirectory(ModuleElement mdle, DocPath dir) throws DocFileIOException { - copyDirectory(getLocationForModule(mdle), dir); - } - - /** - * Copy files from a doc path location to the output. - * - * @param locn the location from which to read files - * @param dir the directory to be copied - * @throws DocFileIOException if there is a problem - * copying the files - */ - public void copyDirectory(Location locn, DocPath dir) throws DocFileIOException { - boolean first = true; - for (DocFile f : DocFile.list(configuration, locn, dir)) { - if (!f.isDirectory()) { - continue; - } - DocFile srcdir = f; - DocFile destdir = DocFile.createFileForOutput(configuration, dir); - if (srcdir.isSameFile(destdir)) { - continue; - } - - for (DocFile srcfile: srcdir.list()) { - DocFile destfile = destdir.resolve(srcfile.getName()); - if (srcfile.isFile()) { - if (destfile.exists() && !first) { - messages.warning("doclet.Copy_Overwrite_warning", - srcfile.getPath(), destdir.getPath()); - } else { - messages.notice("doclet.Copying_File_0_To_Dir_1", - srcfile.getPath(), destdir.getPath()); - destfile.copyFile(srcfile); - } - } else if (srcfile.isDirectory()) { - if (configuration.copydocfilesubdirs - && !configuration.shouldExcludeDocFileDir(srcfile.getName())) { - copyDirectory(locn, dir.resolve(srcfile.getName())); - } - } - } - - first = false; - } - } - - protected Location getLocationForPackage(PackageElement pd) { + public Location getLocationForPackage(PackageElement pd) { ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(pd); if (mdle == null) @@ -364,7 +276,7 @@ return getLocationForModule(mdle); } - protected Location getLocationForModule(ModuleElement mdle) { + public Location getLocationForModule(ModuleElement mdle) { Location loc = configuration.workArounds.getLocationForModule(mdle); if (loc != null) return loc; @@ -3096,6 +3008,10 @@ if (!configuration.isAllowScriptInComments()) { DocCommentTree dct = configuration.cmtUtils.parse( URI.create("option://" + name.replace("-", "")), "" + value + ""); + + if (dct == null) + return; + try { javaScriptScanner.scan(dct, null, p -> { throw new JavaScriptScanner.Fault(); @@ -3123,6 +3039,13 @@ return dcTree; } + public List getPreamble(Element element) { + DocCommentTree docCommentTree = getDocCommentTree(element); + return docCommentTree == null + ? Collections.emptyList() + : docCommentTree.getPreamble(); + } + public List getFullBody(Element element) { DocCommentTree docCommentTree = getDocCommentTree(element); return (docCommentTree == null) diff -r 10b34c929b4f -r 64298b1e890b src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java Tue Dec 05 10:28:45 2017 +0000 @@ -55,6 +55,7 @@ import com.sun.tools.javac.code.Kinds.Kind; import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.CompletionFailure; @@ -222,7 +223,7 @@ else locs.add(StandardLocation.CLASS_PATH); } - if (source.allowModules() && toolEnv.fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) + if (Feature.MODULES.allowedInSource(source) && toolEnv.fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) locs.add(StandardLocation.PATCH_MODULE_PATH); this.locations = Collections.unmodifiableList(locs); diff -r 10b34c929b4f -r 64298b1e890b src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java --- a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Tue Dec 05 10:28:45 2017 +0000 @@ -34,6 +34,7 @@ import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +import com.sun.tools.javac.util.JCDiagnostic.Error; import com.sun.tools.javac.util.Log; import java.io.PrintWriter; import java.io.StringWriter; @@ -78,7 +79,7 @@ Context context = new Context(); Log log = CaLog.createLog(context); context.put(Log.class, log); - context.put(Source.class, Source.JDK1_9); + context.put(Source.class, Source.JDK9); scannerFactory = ScannerFactory.instance(context); } @@ -138,6 +139,11 @@ } @Override + public void error(int pos, Error errorKey) { + die(); + } + + @Override public void error(int pos, String key, Object... args) { die(); } diff -r 10b34c929b4f -r 64298b1e890b src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java --- a/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java Tue Dec 05 10:21:41 2017 +0000 +++ b/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java Tue Dec 05 10:28:45 2017 +0000 @@ -25,6 +25,7 @@ package jdk.jshell; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.TypeTag; import com.sun.tools.javac.parser.JavacParser; import com.sun.tools.javac.parser.ParserFactory; @@ -191,7 +192,7 @@ List annosAfterParams = annotationsOpt(Tag.ANNOTATION); if (annosAfterParams.nonEmpty()) { - checkAnnotationsAfterTypeParams(annosAfterParams.head.pos); + checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS); mods.annotations = mods.annotations.appendList(annosAfterParams); if (mods.pos == Position.NOPOS) { mods.pos = mods.annotations.head.pos; diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/io/Serializable/maskSyntheticModifier/MaskSyntheticModifierTest.java --- a/test/jdk/java/io/Serializable/maskSyntheticModifier/MaskSyntheticModifierTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/io/Serializable/maskSyntheticModifier/MaskSyntheticModifierTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -30,6 +30,7 @@ * serialVersionUID calculation. */ +import java.io.File; import java.io.ObjectStreamClass; import java.nio.file.Files; import java.nio.file.Paths; @@ -46,7 +47,10 @@ } private static void setup() throws Exception { + // Copy the class file to the first component of the class path + String cp = System.getProperty("java.class.path"); + String cp1 = cp.substring(0, cp.indexOf(File.pathSeparatorChar)); Files.copy(Paths.get(System.getProperty("test.src"), "Foo.class"), - Paths.get("Foo.class"), StandardCopyOption.REPLACE_EXISTING); + Paths.get(cp1, "Foo.class"), StandardCopyOption.REPLACE_EXISTING); } } diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/lang/SecurityManager/DepMethodsRequireAllPerm.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/lang/SecurityManager/DepMethodsRequireAllPerm.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8004502 8008793 8029886 8186535 + * @summary Sanity check that the SecurityManager checkMemberAccess method and + * methods that used to check AWTPermission now check for AllPermission + */ + +import java.security.AllPermission; +import java.security.Permission; + +public class DepMethodsRequireAllPerm { + + static class MySecurityManager extends SecurityManager { + final Class expectedClass; + + MySecurityManager(Class c) { + expectedClass = c; + } + + @Override + public void checkPermission(Permission perm) { + if (perm.getClass() != expectedClass) + throw new RuntimeException("Got: " + perm.getClass() + ", expected: " + expectedClass); + super.checkPermission(perm); + } + } + + public static void main(String[] args) { + MySecurityManager sm = new MySecurityManager(AllPermission.class); + + try { + sm.checkAwtEventQueueAccess(); + throw new RuntimeException("SecurityException expected"); + } catch (SecurityException expected) { } + + try { + sm.checkSystemClipboardAccess(); + throw new RuntimeException("SecurityException expected"); + } catch (SecurityException expected) { } + + try { + sm.checkTopLevelWindow(null); + throw new RuntimeException("NullPointException expected"); + } catch (NullPointerException expected) { } + + if (sm.checkTopLevelWindow(new Object())) { + throw new RuntimeException("checkTopLevelWindow expected to return false"); + } + + try { + sm.checkMemberAccess(Object.class, java.lang.reflect.Member.DECLARED); + throw new RuntimeException("SecurityException expected"); + } catch (SecurityException expected) { } + + try { + sm.checkMemberAccess(null, java.lang.reflect.Member.DECLARED); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException expected) { } + } +} diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/lang/SecurityManager/NoAWT.java --- a/test/jdk/java/lang/SecurityManager/NoAWT.java Tue Dec 05 10:21:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please 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 8004502 8008793 8029886 - * @summary Sanity check that SecurityManager methods that used to check - * AWTPermission now check for AllPermission - */ - -import java.security.AllPermission; -import java.security.Permission; - -public class NoAWT { - - static class MySecurityManager extends SecurityManager { - final Class expectedClass; - - MySecurityManager(Class c) { - expectedClass = c; - } - - @Override - public void checkPermission(Permission perm) { - if (perm.getClass() != expectedClass) - throw new RuntimeException("Got: " + perm.getClass() + ", expected: " + expectedClass); - super.checkPermission(perm); - } - } - - public static void main(String[] args) { - MySecurityManager sm = new MySecurityManager(AllPermission.class); - - try { - sm.checkAwtEventQueueAccess(); - throw new RuntimeException("SecurityException expected"); - } catch (SecurityException expected) { } - - try { - sm.checkSystemClipboardAccess(); - throw new RuntimeException("SecurityException expected"); - } catch (SecurityException expected) { } - - try { - sm.checkTopLevelWindow(null); - throw new RuntimeException("NullPointException expected"); - } catch (NullPointerException expected) { } - - if (sm.checkTopLevelWindow(new Object())) { - throw new RuntimeException("checkTopLevelWindow expected to return false"); - } - } -} diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/lang/reflect/StaticFieldsOnInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/lang/reflect/StaticFieldsOnInterface.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8186961 + * @run main/othervm StaticFieldsOnInterface C + * @run main/othervm StaticFieldsOnInterface D + * @run main/othervm StaticFieldsOnInterface Y + */ + +public class StaticFieldsOnInterface { + /* + A + / \ + B C + \ / + D + + Interface A has a public field + Ensure B, C, D only report exactly one public field + + A + / + X A + |/ + Y + + Ensure class Y, extending class X, reports exactly one public field + */ + + public interface A { + public static final int CONSTANT = 42; + } + + public interface B extends A { + } + + public interface C extends A { + } + + public interface D extends B, C { + } + + static class X implements A {} + static class Y extends X implements A {} + + public static void main(String[] args) throws Exception { + char first = 'C'; + if (args.length > 0) { + first = args[0].charAt(0); + } + + assertOneField(A.class); + // D first + if (first == 'D') { + assertOneField(D.class); + assertOneField(C.class); + } + // C first + else if (first == 'C') { + assertOneField(C.class); + assertOneField(D.class); + } + else { + assertOneField(Y.class); + } + } + + static void assertOneField(Class c) { + int nfs = c.getFields().length; + if (nfs != 1) { + throw new AssertionError(String.format( + "Class %s does not have exactly one field: %d", c.getName(), nfs)); + } + } +} diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/net/SocketOption/UnsupportedOptionsTest.java --- a/test/jdk/java/net/SocketOption/UnsupportedOptionsTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/net/SocketOption/UnsupportedOptionsTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,8 @@ Class c = Class.forName("jdk.net.ExtendedSocketOptions"); Field field = c.getField("SO_FLOW_SLA"); socketOptions.add((SocketOption)field.get(null)); + field = c.getField("TCP_QUICKACK"); + socketOptions.add((SocketOption)field.get(null)); } catch (ClassNotFoundException e) { // ignore, jdk.net module not present } catch (ReflectiveOperationException e) { diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/util/Collection/MOAT.java --- a/test/jdk/java/util/Collection/MOAT.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/util/Collection/MOAT.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,8 @@ import java.util.concurrent.*; import static java.util.Collections.*; import java.lang.reflect.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class MOAT { // Collections under test must not be initialized to contain this value, @@ -230,6 +232,17 @@ testListMutatorsAlwaysThrow(list); } + List listCopy = List.copyOf(Arrays.asList(1, 2, 3)); + testCollection(listCopy); + testImmutableList(listCopy); + testListMutatorsAlwaysThrow(listCopy); + + List listCollected = Stream.of(1, 2, 3).collect(Collectors.toUnmodifiableList()); + equal(listCollected, List.of(1, 2, 3)); + testCollection(listCollected); + testImmutableList(listCollected); + testListMutatorsAlwaysThrow(listCollected); + // Immutable Set testEmptySet(Set.of()); testCollMutatorsAlwaysThrow(Set.of()); @@ -252,6 +265,18 @@ testCollMutatorsAlwaysThrow(set); } + Set setCopy = Set.copyOf(Arrays.asList(1, 2, 3)); + testCollection(setCopy); + testImmutableSet(setCopy); + testCollMutatorsAlwaysThrow(setCopy); + + Set setCollected = Stream.of(1, 1, 2, 3, 2, 3) + .collect(Collectors.toUnmodifiableSet()); + equal(setCollected, Set.of(1, 2, 3)); + testCollection(setCollected); + testImmutableSet(setCollected); + testCollMutatorsAlwaysThrow(setCollected); + // Immutable Map @SuppressWarnings("unchecked") @@ -280,6 +305,35 @@ testImmutableMap(map); testMapMutatorsAlwaysThrow(map); } + + Map mapCopy = Map.copyOf(new HashMap<>(Map.of(1, 101, 2, 202, 3, 303))); + testMap(mapCopy); + testImmutableMap(mapCopy); + testMapMutatorsAlwaysThrow(mapCopy); + + Map mapCollected1 = + Stream.of(1, 2, 3) + .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i)); + equal(mapCollected1, Map.of(1, 101, 2, 202, 3, 303)); + testMap(mapCollected1); + testImmutableMap(mapCollected1); + testMapMutatorsAlwaysThrow(mapCollected1); + + try { + Stream.of(1, 1, 2, 3, 2, 3) + .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i)); + fail("duplicates should have thrown an exception"); + } catch (IllegalStateException ise) { + pass(); + } + + Map mapCollected2 = + Stream.of(1, 1, 2, 3, 2, 3) + .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i, Integer::sum)); + equal(mapCollected2, Map.of(1, 202, 2, 404, 3, 606)); + testMap(mapCollected2); + testImmutableMap(mapCollected2); + testMapMutatorsAlwaysThrow(mapCollected2); } private static void checkContainsSelf(Collection c) { diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/util/Collection/SetFactories.java --- a/test/jdk/java/util/Collection/SetFactories.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/util/Collection/SetFactories.java Tue Dec 05 10:28:45 2017 +0000 @@ -40,6 +40,9 @@ import org.testng.annotations.Test; import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNotSame; +import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; @@ -275,9 +278,9 @@ static T serialClone(T obj) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(obj); - oos.close(); + try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(obj); + } ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return (T) ois.readObject(); @@ -285,4 +288,53 @@ throw new AssertionError(e); } } + + Set genSet() { + return new HashSet<>(Arrays.asList(1, 2, 3)); + } + + @Test + public void copyOfResultsEqual() { + Set orig = genSet(); + Set copy = Set.copyOf(orig); + + assertEquals(orig, copy); + assertEquals(copy, orig); + } + + @Test + public void copyOfModifiedUnequal() { + Set orig = genSet(); + Set copy = Set.copyOf(orig); + orig.add(4); + + assertNotEquals(orig, copy); + assertNotEquals(copy, orig); + } + + @Test + public void copyOfIdentity() { + Set orig = genSet(); + Set copy1 = Set.copyOf(orig); + Set copy2 = Set.copyOf(copy1); + + assertNotSame(orig, copy1); + assertSame(copy1, copy2); + } + + @Test(expectedExceptions=NullPointerException.class) + public void copyOfRejectsNullCollection() { + Set set = Set.copyOf(null); + } + + @Test(expectedExceptions=NullPointerException.class) + public void copyOfRejectsNullElements() { + Set set = Set.copyOf(Arrays.asList(1, null, 3)); + } + + @Test + public void copyOfAcceptsDuplicates() { + Set set = Set.copyOf(Arrays.asList(1, 1, 2, 3, 3, 3)); + assertEquals(set, Set.of(1, 2, 3)); + } } diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/util/List/ListFactories.java --- a/test/jdk/java/util/List/ListFactories.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/util/List/ListFactories.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,9 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNotSame; +import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; @@ -221,9 +224,9 @@ static T serialClone(T obj) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(obj); - oos.close(); + try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(obj); + } ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return (T) ois.readObject(); @@ -231,4 +234,47 @@ throw new AssertionError(e); } } + + List genList() { + return new ArrayList<>(Arrays.asList(1, 2, 3)); + } + + @Test + public void copyOfResultsEqual() { + List orig = genList(); + List copy = List.copyOf(orig); + + assertEquals(orig, copy); + assertEquals(copy, orig); + } + + @Test + public void copyOfModifiedUnequal() { + List orig = genList(); + List copy = List.copyOf(orig); + orig.add(4); + + assertNotEquals(orig, copy); + assertNotEquals(copy, orig); + } + + @Test + public void copyOfIdentity() { + List orig = genList(); + List copy1 = List.copyOf(orig); + List copy2 = List.copyOf(copy1); + + assertNotSame(orig, copy1); + assertSame(copy1, copy2); + } + + @Test(expectedExceptions=NullPointerException.class) + public void copyOfRejectsNullCollection() { + List list = List.copyOf(null); + } + + @Test(expectedExceptions=NullPointerException.class) + public void copyOfRejectsNullElements() { + List list = List.copyOf(Arrays.asList(1, null, 3)); + } } diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/util/Map/MapFactories.java --- a/test/jdk/java/util/Map/MapFactories.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/util/Map/MapFactories.java Tue Dec 05 10:28:45 2017 +0000 @@ -42,6 +42,9 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNotSame; +import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; @@ -70,6 +73,12 @@ } // for varargs Map.Entry methods + + @SuppressWarnings("unchecked") + Map.Entry[] genEmptyEntryArray1() { + return (Map.Entry[])new Map.Entry[1]; + } + @SuppressWarnings("unchecked") Map.Entry[] genEntries(int n) { return IntStream.range(0, n) @@ -322,21 +331,41 @@ } @Test(expectedExceptions=NullPointerException.class) - public void nullKeyDisallowedN() { - Map.Entry[] entries = genEntries(MAX_ENTRIES); - entries[0] = new AbstractMap.SimpleImmutableEntry(null, "a"); + public void nullKeyDisallowedVar1() { + Map.Entry[] entries = genEmptyEntryArray1(); + entries[0] = new AbstractMap.SimpleImmutableEntry<>(null, "a"); + Map map = Map.ofEntries(entries); + } + + @Test(expectedExceptions=NullPointerException.class) + public void nullValueDisallowedVar1() { + Map.Entry[] entries = genEmptyEntryArray1(); + entries[0] = new AbstractMap.SimpleImmutableEntry<>(0, null); Map map = Map.ofEntries(entries); } @Test(expectedExceptions=NullPointerException.class) - public void nullValueDisallowedN() { - Map.Entry[] entries = genEntries(MAX_ENTRIES); - entries[0] = new AbstractMap.SimpleImmutableEntry(0, null); + public void nullEntryDisallowedVar1() { + Map.Entry[] entries = genEmptyEntryArray1(); Map map = Map.ofEntries(entries); } @Test(expectedExceptions=NullPointerException.class) - public void nullEntryDisallowedN() { + public void nullKeyDisallowedVarN() { + Map.Entry[] entries = genEntries(MAX_ENTRIES); + entries[0] = new AbstractMap.SimpleImmutableEntry<>(null, "a"); + Map map = Map.ofEntries(entries); + } + + @Test(expectedExceptions=NullPointerException.class) + public void nullValueDisallowedVarN() { + Map.Entry[] entries = genEntries(MAX_ENTRIES); + entries[0] = new AbstractMap.SimpleImmutableEntry<>(0, null); + Map map = Map.ofEntries(entries); + } + + @Test(expectedExceptions=NullPointerException.class) + public void nullEntryDisallowedVarN() { Map.Entry[] entries = genEntries(MAX_ENTRIES); entries[5] = null; Map map = Map.ofEntries(entries); @@ -344,7 +373,7 @@ @Test(expectedExceptions=NullPointerException.class) public void nullArrayDisallowed() { - Map.ofEntries(null); + Map.ofEntries((Map.Entry[])null); } @Test(dataProvider="all") @@ -359,9 +388,9 @@ static T serialClone(T obj) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(obj); - oos.close(); + try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(obj); + } ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); return (T) ois.readObject(); @@ -370,6 +399,62 @@ } } + Map genMap() { + Map map = new HashMap<>(); + map.put(1, "a"); + map.put(2, "b"); + map.put(3, "c"); + return map; + } + + @Test + public void copyOfResultsEqual() { + Map orig = genMap(); + Map copy = Map.copyOf(orig); + + assertEquals(orig, copy); + assertEquals(copy, orig); + } + + @Test + public void copyOfModifiedUnequal() { + Map orig = genMap(); + Map copy = Map.copyOf(orig); + orig.put(4, "d"); + + assertNotEquals(orig, copy); + assertNotEquals(copy, orig); + } + + @Test + public void copyOfIdentity() { + Map orig = genMap(); + Map copy1 = Map.copyOf(orig); + Map copy2 = Map.copyOf(copy1); + + assertNotSame(orig, copy1); + assertSame(copy1, copy2); + } + + @Test(expectedExceptions=NullPointerException.class) + public void copyOfRejectsNullMap() { + Map map = Map.copyOf(null); + } + + @Test(expectedExceptions=NullPointerException.class) + public void copyOfRejectsNullKey() { + Map map = genMap(); + map.put(null, "x"); + Map copy = Map.copyOf(map); + } + + @Test(expectedExceptions=NullPointerException.class) + public void copyOfRejectsNullValue() { + Map map = genMap(); + map.put(-1, null); + Map copy = Map.copyOf(map); + } + // Map.entry() tests @Test(expectedExceptions=NullPointerException.class) @@ -386,7 +471,7 @@ public void entryBasicTests() { Map.Entry kvh1 = Map.entry("xyzzy", "plugh"); Map.Entry kvh2 = Map.entry("foobar", "blurfl"); - Map.Entry sie = new AbstractMap.SimpleImmutableEntry("xyzzy", "plugh"); + Map.Entry sie = new AbstractMap.SimpleImmutableEntry<>("xyzzy", "plugh"); assertTrue(kvh1.equals(sie)); assertTrue(sie.equals(kvh1)); @@ -404,5 +489,4 @@ Map map = Map.ofEntries(e1, e2); assertEquals(map.size(), 2); } - } diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java --- a/test/jdk/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -39,6 +39,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; import java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject; @@ -1283,4 +1284,57 @@ sync.release(); } + /** + * Tests scenario for + * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw + */ + public void testInterruptedFailingAcquire() throws InterruptedException { + final RuntimeException ex = new RuntimeException(); + + // A synchronizer only offering a choice of failure modes + class Sync extends AbstractQueuedLongSynchronizer { + boolean pleaseThrow; + @Override protected boolean tryAcquire(long ignored) { + if (pleaseThrow) throw ex; + return false; + } + @Override protected long tryAcquireShared(long ignored) { + if (pleaseThrow) throw ex; + return -1; + } + @Override protected boolean tryRelease(long ignored) { + return true; + } + @Override protected boolean tryReleaseShared(long ignored) { + return true; + } + } + + final Sync s = new Sync(); + + final Thread thread = newStartedThread(new CheckedRunnable() { + public void realRun() { + try { + if (ThreadLocalRandom.current().nextBoolean()) + s.acquire(1); + else + s.acquireShared(1); + shouldThrow(); + } catch (Throwable t) { + assertSame(ex, t); + assertTrue(Thread.interrupted()); + } + }}); + waitForThreadToEnterWaitState(thread); + assertSame(thread, s.getFirstQueuedThread()); + assertTrue(s.hasQueuedPredecessors()); + assertTrue(s.hasQueuedThreads()); + assertEquals(1, s.getQueueLength()); + + s.pleaseThrow = true; + thread.interrupt(); + s.release(1); + awaitTermination(thread); + } + } diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java --- a/test/jdk/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -36,9 +36,11 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject; @@ -1286,4 +1288,105 @@ sync.release(); } + /** + * Disabled demo test for (unfixed as of 2017-11) + * JDK-8191483: AbstractQueuedSynchronizer cancel/cancel race + * ant -Djsr166.tckTestClass=AbstractQueuedSynchronizerTest -Djsr166.methodFilter=testCancelCancelRace -Djsr166.runsPerTest=100 tck + */ + public void DISABLED_testCancelCancelRace() throws InterruptedException { + class Sync extends AbstractQueuedSynchronizer { + protected boolean tryAcquire(int acquires) { + return !hasQueuedPredecessors() && compareAndSetState(0, 1); + } + protected boolean tryRelease(int releases) { + return compareAndSetState(1, 0); + } + } + + Sync s = new Sync(); + s.acquire(1); // acquire to force other threads to enqueue + + // try to trigger double cancel race with two background threads + ArrayList threads = new ArrayList<>(); + Runnable failedAcquire = () -> { + try { + s.acquireInterruptibly(1); + shouldThrow(); + } catch (InterruptedException expected) {} + }; + for (int i = 0; i < 2; i++) { + Thread thread = new Thread(failedAcquire); + thread.start(); + threads.add(thread); + } + Thread.sleep(100); + for (Thread thread : threads) thread.interrupt(); + for (Thread thread : threads) awaitTermination(thread); + + s.release(1); + + // no one holds lock now, we should be able to acquire + if (!s.tryAcquire(1)) + throw new RuntimeException( + String.format( + "Broken: hasQueuedPredecessors=%s hasQueuedThreads=%s queueLength=%d firstQueuedThread=%s", + s.hasQueuedPredecessors(), + s.hasQueuedThreads(), + s.getQueueLength(), + s.getFirstQueuedThread())); + } + + /** + * Tests scenario for + * JDK-8191937: Lost interrupt in AbstractQueuedSynchronizer when tryAcquire methods throw + */ + public void testInterruptedFailingAcquire() throws InterruptedException { + final RuntimeException ex = new RuntimeException(); + + // A synchronizer only offering a choice of failure modes + class Sync extends AbstractQueuedSynchronizer { + boolean pleaseThrow; + @Override protected boolean tryAcquire(int ignored) { + if (pleaseThrow) throw ex; + return false; + } + @Override protected int tryAcquireShared(int ignored) { + if (pleaseThrow) throw ex; + return -1; + } + @Override protected boolean tryRelease(int ignored) { + return true; + } + @Override protected boolean tryReleaseShared(int ignored) { + return true; + } + } + + final Sync s = new Sync(); + + final Thread thread = newStartedThread(new CheckedRunnable() { + public void realRun() { + try { + if (ThreadLocalRandom.current().nextBoolean()) + s.acquire(1); + else + s.acquireShared(1); + shouldThrow(); + } catch (Throwable t) { + assertSame(ex, t); + assertTrue(Thread.interrupted()); + } + }}); + waitForThreadToEnterWaitState(thread); + assertSame(thread, s.getFirstQueuedThread()); + assertTrue(s.hasQueuedPredecessors()); + assertTrue(s.hasQueuedThreads()); + assertEquals(1, s.getQueueLength()); + + s.pleaseThrow = true; + thread.interrupt(); + s.release(1); + awaitTermination(thread); + } + } diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/util/concurrent/tck/StampedLockTest.java --- a/test/jdk/java/util/concurrent/tck/StampedLockTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/util/concurrent/tck/StampedLockTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -614,7 +614,7 @@ long s = lock.readLock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { - threadAssertEquals(0L, lock.tryWriteLock()); + assertEquals(0L, lock.tryWriteLock()); }}); awaitTermination(t); diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/util/concurrent/tck/SubmissionPublisherTest.java --- a/test/jdk/java/util/concurrent/tck/SubmissionPublisherTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/util/concurrent/tck/SubmissionPublisherTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -33,6 +33,7 @@ */ import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.Flow; @@ -429,7 +430,8 @@ * Cancelling a subscription eventually causes no more onNexts to be issued */ public void testCancel() { - SubmissionPublisher p = basicPublisher(); + SubmissionPublisher p = + new SubmissionPublisher(basicExecutor, 4); // must be < 20 TestSubscriber s1 = new TestSubscriber(); TestSubscriber s2 = new TestSubscriber(); p.subscribe(s1); @@ -666,7 +668,6 @@ p.subscribe(s1); p.subscribe(s2); for (int i = 1; i <= 20; ++i) { - assertTrue(p.estimateMinimumDemand() <= 1); assertTrue(p.submit(i) >= 0); } p.close(); @@ -1005,4 +1006,31 @@ assertTrue(count.get() < n); } + /** + * Tests scenario for + * JDK-8187947: A race condition in SubmissionPublisher + * cvs update -D '2017-11-25' src/main/java/util/concurrent/SubmissionPublisher.java && ant -Djsr166.expensiveTests=true -Djsr166.tckTestClass=SubmissionPublisherTest -Djsr166.methodFilter=testMissedSignal tck; cvs update -A src/main/java/util/concurrent/SubmissionPublisher.java + */ + public void testMissedSignal_8187947() throws Exception { + final int N = expensiveTests ? (1 << 20) : (1 << 10); + final CountDownLatch finished = new CountDownLatch(1); + final SubmissionPublisher pub = new SubmissionPublisher<>(); + class Sub implements Subscriber { + int received; + public void onSubscribe(Subscription s) { + s.request(N); + } + public void onNext(Boolean item) { + if (++received == N) + finished.countDown(); + else + CompletableFuture.runAsync(() -> pub.submit(Boolean.TRUE)); + } + public void onError(Throwable t) { throw new AssertionError(t); } + public void onComplete() {} + } + pub.subscribe(new Sub()); + CompletableFuture.runAsync(() -> pub.submit(Boolean.TRUE)); + await(finished); + } } diff -r 10b34c929b4f -r 64298b1e890b test/jdk/java/util/zip/InflateIn_DeflateOut.java --- a/test/jdk/java/util/zip/InflateIn_DeflateOut.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/java/util/zip/InflateIn_DeflateOut.java Tue Dec 05 10:28:45 2017 +0000 @@ -23,8 +23,9 @@ /** * @test - * @bug 4206909 4813885 - * @summary Test basic functionality of DeflaterOutputStream/InflaterInputStream and GZIPOutputStream/GZIPInputStream, including flush + * @bug 4206909 4813885 8191918 + * @summary Test basic functionality of DeflaterOutputStream/InflaterInputStream + * and GZIPOutputStream/GZIPInputStream, including flush * @key randomness */ @@ -147,6 +148,36 @@ check(Arrays.equals(data, buf)); } + private static void TestFlushableGZIPOutputStream() throws Throwable { + var random = new Random(new Date().getTime()); + + var byteOutStream = new ByteArrayOutputStream(); + var output = new FlushableGZIPOutputStream(byteOutStream); + + var data = new byte[random.nextInt(1024 * 1024)]; + var buf = new byte[data.length]; + random.nextBytes(data); + + output.write(data); + for (int i=0; i 0) { + out.write(buf, 0, len); + } + } while (len != 0); + } + +} diff -r 10b34c929b4f -r 64298b1e890b test/jdk/javax/xml/ws/8159058/SaajEmptyNamespaceTest.java --- a/test/jdk/javax/xml/ws/8159058/SaajEmptyNamespaceTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/javax/xml/ws/8159058/SaajEmptyNamespaceTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -23,7 +23,7 @@ /* * @test - * @bug 8159058 + * @bug 8159058 8186441 * @summary Test that empty default namespace declaration clears the * default namespace value * @modules java.xml.ws/com.sun.xml.internal.ws.api @@ -61,6 +61,26 @@ public class SaajEmptyNamespaceTest { /* + * Test that SOAP reader doesn't move namespaces declarations to SOAP body element + * as reported in JDK-8186441 + */ + @Test + public void testPreserveNamespacesPosition() throws Exception { + // Create SOAP message from XML string and process it with SAAJ reader + XMLStreamReader envelope = XMLInputFactory.newFactory().createXMLStreamReader( + new StringReader(INPUT_SOAP_MESSAGE_2)); + StreamMessage streamMessage = new StreamMessage(SOAPVersion.SOAP_11, + envelope, null); + SAAJFactory saajFact = new SAAJFactory(); + SOAPMessage soapMessage = saajFact.readAsSOAPMessage(SOAPVersion.SOAP_11, streamMessage); + + //Get SOAP body and convert it to string representation + SOAPBody body = soapMessage.getSOAPBody(); + String bodyAsString = nodeToText(body); + Assert.assertEquals(bodyAsString, PRESERVE_NAMESPACES_EXPECTED_RESULT); + } + + /* * Test that SOAP message with default namespace declaration that contains empty * string is properly processed by SAAJ reader. */ @@ -275,10 +295,28 @@ // Expected body content after SAAJ processing private static String EXPECTED_RESULT = "" + + " xmlns=\"http://example.org/test\"" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "" + "hogehoge" + "fugafuga" + "" + ""; + + private static String PRESERVE_NAMESPACES_EXPECTED_RESULT = + "" + +"" + +"Test_Contact" + +""; + + private static String INPUT_SOAP_MESSAGE_2 = "" + + "" + + "" + + "" + + "" + + "Test_Contact" + + "" + + "" + + "" + + ""; } diff -r 10b34c929b4f -r 64298b1e890b test/jdk/jdk/net/Sockets/ExtOptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/jdk/net/Sockets/ExtOptionTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8190843 + * @summary can not set/get extendedOptions to ServerSocket + * @modules jdk.net + * @run main ExtOptionTest + */ +import java.io.IOException; +import java.net.ServerSocket; + +import static jdk.net.ExtendedSocketOptions.TCP_QUICKACK; +import static jdk.net.ExtendedSocketOptions.SO_FLOW_SLA; + +public class ExtOptionTest { + + private static final String OS = "Linux"; + + public static void main(String args[]) throws IOException { + var operSys = System.getProperty("os.name"); + try (ServerSocket ss = new ServerSocket(0)) { + // currently TCP_QUICKACK is available only on Linux. + if (operSys.equals(OS)) { + ss.setOption(TCP_QUICKACK, true); + if (!ss.getOption(TCP_QUICKACK)) { + throw new RuntimeException("Test failed, TCP_QUICKACK should" + + " have been set"); + } + } else if (operSys.equals("SunOS")) { + if (ss.supportedOptions().contains(SO_FLOW_SLA)) { + throw new RuntimeException("Test failed, SO_FLOW_SLA is not " + + "applicable for ServerSocket"); + } + } else { + if (ss.supportedOptions().contains(TCP_QUICKACK)) { + ss.setOption(TCP_QUICKACK, true); + if (!ss.getOption(TCP_QUICKACK)) { + throw new RuntimeException("Test failed, TCP_QUICKACK should" + + " have been set"); + } + } + } + } + } +} diff -r 10b34c929b4f -r 64298b1e890b test/jdk/sun/security/tools/jarsigner/TimestampCheck.java --- a/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java Tue Dec 05 10:28:45 2017 +0000 @@ -694,11 +694,15 @@ gencert("ts", "-ext eku:critical=ts"); - // Issue another cert for "ts" with a different EKU. - // Length should be the same. Try several times. - keytool("-gencert -alias ca -infile ts.req -outfile ts2.cert " + - "-ext eku:critical=1.3.6.1.5.5.7.3.9"); for (int i = 0; i < 5; i++) { + // Issue another cert for "ts" with a different EKU. + // Length might be different because serial number is + // random. Try several times until a cert with the same + // length is generated so we can substitute ts.cert + // embedded in the PKCS7 block with ts2.cert. + // If cannot create one, related test will be ignored. + keytool("-gencert -alias ca -infile ts.req -outfile ts2.cert " + + "-ext eku:critical=1.3.6.1.5.5.7.3.9"); if (Files.size(Paths.get("ts.cert")) != Files.size(Paths.get("ts2.cert"))) { Files.delete(Paths.get("ts2.cert")); System.out.println("Warning: cannot create same length"); diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java --- a/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * 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 8131019 + * @bug 8131019 8190552 * @summary Test JavadocHelper * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java --- a/test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/TestCopyFiles.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * 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,8 +23,8 @@ /* * @test - * @bug 8157349 - * @summary test copy of doc-files + * @bug 8157349 8185985 + * @summary test copy of doc-files, and its contents for HTML meta content. * @library ../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build JavadocTester @@ -39,13 +39,123 @@ } @Test - void testDocFilesInModules() { + void testDocFilesInModulePackages() { javadoc("-d", "modules-out", + "-top", "phi-TOP-phi", + "-bottom", "phi-BOTTOM-phi", + "-header", "phi-HEADER-phi", + "-footer", "phi-FOOTER-phi", + "-windowtitle", "phi-WINDOW-TITLE-phi", + "--module-source-path", testSrc("modules"), + "--module", "acme.mdle"); + checkExit(Exit.OK); + checkOrder("p/doc-files/inpackage.html", + "\"Hello World\" (phi-WINDOW-TITLE-phi)", + "phi-TOP-phi", + // check top navbar + "Module", + "Package", + "Tree", + "Deprecated", + "Index", + "phi-HEADER-phi", + "In a named module acme.module and named package " + + "p.", + "\"simpleTagLabel\">Since:Module", + "Package", + "Tree", + "Deprecated", + "Index", + "phi-FOOTER-phi", + "phi-BOTTOM-phi" + ); + } + + @Test + void testDocFilesInMultiModulePackagesWithRecursiveCopy() { + javadoc("-d", "multi-modules-out-recursive", + "-docfilessubdirs", + "-top", "phi-TOP-phi", + "-bottom", "phi-BOTTOM-phi", + "-header", "phi-HEADER-phi", + "-footer", "phi-FOOTER-phi", + "-windowtitle", "phi-WINDOW-TITLE-phi", + "--module-source-path", testSrc("modules"), + "--module", "acme.mdle,acme2.mdle"); + checkExit(Exit.OK); + checkOrder("p/doc-files/inpackage.html", + "\"Hello World\" (phi-WINDOW-TITLE-phi)", + "phi-TOP-phi", + // check top navbar + "Module", + "Package", + "Tree", + "Deprecated", + "Index", + "phi-HEADER-phi", + "In a named module acme.module and named package " + + "p.", + "\"simpleTagLabel\">Since:Module", + "Package", + "Tree", + "Deprecated", + "Index", + "phi-FOOTER-phi", + "phi-BOTTOM-phi" + ); + + // check the bottom most doc file + checkOrder("p2/doc-files/sub-dir/sub-dir-1/SubSubReadme.html", + "SubSubReadme (phi-WINDOW-TITLE-phi)", + "phi-TOP-phi", + // check top navbar + "Module", + "Package", + "Tree", + "Deprecated", + "Index", + "phi-HEADER-phi", + "SubSubReadme.html at third level of doc-file directory.", + // check bottom navbar + "Module", + "Package", + "Tree", + "Deprecated", + "Index", + "phi-FOOTER-phi", + "phi-BOTTOM-phi" + ); + } + @Test + void testDocFilesInModulePackagesWithRecursiveCopy() { + javadoc("-d", "modules-out-recursive", + "-docfilessubdirs", "--module-source-path", testSrc("modules"), "--module", "acme.mdle"); checkExit(Exit.OK); checkOutput("p/doc-files/inpackage.html", true, - "In a named module and named package" + "In a named module acme.module and named package " + + "p." + ); + } + + @Test + void testDocFilesInModulePackagesWithRecursiveCopyWithExclusion() { + javadoc("-d", "modules-out-recursive-with-exclusion", + "-docfilessubdirs", + "-excludedocfilessubdir", "sub-dir", + "--module-source-path", testSrc("modules"), + "--module", "acme.mdle"); + checkExit(Exit.OK); + checkOutput("p/doc-files/inpackage.html", true, + "In a named module acme.module and named package " + + "p." ); } @@ -61,18 +171,71 @@ } @Test + void testDocFilesInPackagesWithRecursiveCopy() { + javadoc("-d", "packages-out-recursive", + "-docfilessubdirs", + "-sourcepath", testSrc("packages"), + "p1"); + checkExit(Exit.OK); + + checkOutput("p1/doc-files/inpackage.html", true, + "A named package in an unnamed module" + ); + + checkOutput("p1/doc-files/sub-dir/SubReadme.html", true, + "SubReadme", + "SubReadme.html at second level of doc-file directory." + ); + } + + @Test + void testDocFilesInPackagesWithRecursiveCopyWithExclusion() { + javadoc("-d", "packages-out-recursive-with-exclusion", + "-docfilessubdirs", + "-excludedocfilessubdir", "sub-dir", + "-sourcepath", testSrc("packages"), + "p1"); + checkExit(Exit.OK); + + checkOutput("p1/doc-files/inpackage.html", true, + "A named package in an unnamed module" + ); + } + + @Test void testDocFilesInUnnamedPackages() { javadoc("-d", "unnamed-out", + "-windowtitle", "phi-WINDOW-TITLE-phi", "-sourcepath", testSrc("unnamed"), testSrc("unnamed/Foo.java") ); checkExit(Exit.OK); checkOutput("doc-files/inpackage.html", true, + "(phi-WINDOW-TITLE-phi)\n", "In an unnamed package" ); } @Test + void testDocFilesInUnnamedPackagesWithRecursiveCopy() { + javadoc("-d", "unnamed-out-recursive", + "-docfilessubdirs", + "-windowtitle", "phi-WINDOW-TITLE-phi", + "-sourcepath", testSrc("unnamed"), + testSrc("unnamed/Foo.java") + ); + checkExit(Exit.OK); + checkOutput("doc-files/inpackage.html", true, + "(phi-WINDOW-TITLE-phi)\n", + "In an unnamed package" + ); + checkOutput("doc-files/doc-file/SubReadme.html", true, + "Beep Beep (phi-WINDOW-TITLE-phi)\n", + "SubReadme.html at second level of doc-file directory for unnamed package." + ); + } + + @Test void testDocFilesInPackagesSource7() { javadoc("-d", "packages-out-src7", "-source", "7", diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme.mdle/p/doc-files/inpackage.html --- a/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme.mdle/p/doc-files/inpackage.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme.mdle/p/doc-files/inpackage.html Tue Dec 05 10:28:45 2017 +0000 @@ -28,6 +28,8 @@ "Hello World" - In a named module and named package + In a named module acme.module and named package {@link p}. + @author Wile E. Coyote + @since 1940 diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme.mdle/p/doc-files/sub-dir/SubReadme.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme.mdle/p/doc-files/sub-dir/SubReadme.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,35 @@ + + + + + + + SubReadme + + + SubReadme.html at second level of doc-file directory for acme.module. + + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme.mdle/p/doc-files/sub-dir/sub-dir-1/SubSubReadme.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme.mdle/p/doc-files/sub-dir/sub-dir-1/SubSubReadme.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,35 @@ + + + + + + + SubSubReadme + + + SubSubReadme.html at third level of doc-file directory. + + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme.mdle/p/package.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme.mdle/p/package.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,37 @@ + + + + + + + package.html file for p + + + A named package {@link p} in a name module acme.mdle. + @author WECoyote + @since 1940 + + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/module-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/module-info.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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. + */ + + /** + * A test module. + */ +module acme2.mdle { + exports p2; +} diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/Foo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/Foo.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 p2; + +/** + * A test class. + */ +public class Foo {} diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/doc-files/inpackage.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/doc-files/inpackage.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,35 @@ + + + + + "Hello World" + + + In a named module acme2.mdle and named package {@link p2}. + @author Wile E. Coyote + @since 1940 + + diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/doc-files/sub-dir/SubReadme.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/doc-files/sub-dir/SubReadme.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,35 @@ + + + + + + + SubReadme + + + SubReadme.html at second level of doc-file directory for acme2.mdle. + + diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/doc-files/sub-dir/sub-dir-1/SubSubReadme.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/doc-files/sub-dir/sub-dir-1/SubSubReadme.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,35 @@ + + + + + + + SubSubReadme + + + SubSubReadme.html at third level of doc-file directory. + + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/package.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/acme2.mdle/p2/package.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,37 @@ + + + + + + + package.html file for p + + + A named package {@link p2} in a name module acme2.mdle. + @author WECoyote + @since 1940 + + diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/overview.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/modules/overview.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,35 @@ + + + + + + + My overview html file + + +The overview html file + + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/packages/p1/doc-files/sub-dir/SubReadme.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/packages/p1/doc-files/sub-dir/SubReadme.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,35 @@ + + + + + + + SubReadme + + + SubReadme.html at second level of doc-file directory. + + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/unnamed/doc-files/doc-file/SubReadme.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/unnamed/doc-files/doc-file/SubReadme.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,35 @@ + + + + + + + Beep Beep + + + SubReadme.html at second level of doc-file directory for unnamed package. + + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testCopyFiles/unnamed/doc-files/inpackage.html --- a/test/langtools/jdk/javadoc/doclet/testCopyFiles/unnamed/doc-files/inpackage.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testCopyFiles/unnamed/doc-files/inpackage.html Tue Dec 05 10:28:45 2017 +0000 @@ -24,9 +24,6 @@ --> - - "Hello World" - In an unnamed package diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java --- a/test/langtools/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testPackageHtml/TestPackageHtml.java Tue Dec 05 10:28:45 2017 +0000 @@ -44,7 +44,7 @@ "-sourcepath", testSrc, "pkg1"); checkExit(Exit.ERROR); - checkOutput(Output.OUT, true, "package.html:10: error: bad use of '>'"); + checkOutput(Output.OUT, true, "package.html:5: error: bad use of '>'"); } // Doclet must handle empty body in package.html, must diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java --- a/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java Tue Dec 05 10:28:45 2017 +0000 @@ -102,7 +102,7 @@ "p2"); checkExit(Exit.OK); - checkOutput(Output.OUT, true, "package.html:5: warning: invalid use of @summary"); + checkOutput(Output.OUT, true, "package.html:3: warning: invalid use of @summary"); checkOutput("index-all.html", true, "

          foo bar
          \n"); diff -r 10b34c929b4f -r 64298b1e890b test/langtools/jdk/jshell/CompilerOptionsTest.java --- a/test/langtools/jdk/jshell/CompilerOptionsTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/jdk/jshell/CompilerOptionsTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -51,6 +51,6 @@ public void testSourceVersion() { assertEval("import java.util.function.*;", added(VALID)); assertDeclareFail("Function f = x -> x*2;", - new ExpectedDiagnostic("compiler.err.lambda.not.supported.in.source", 32, 32, 32, -1, -1, Diagnostic.Kind.ERROR)); + new ExpectedDiagnostic("compiler.err.feature.not.supported.in.source.plural", 32, 32, 32, -1, -1, Diagnostic.Kind.ERROR)); } } diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java --- a/test/langtools/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * 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,28 +29,62 @@ * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main - * @build toolbox.ToolBox - * @run compile -encoding iso-8859-1 -XD-printsource T6302184.java + * @build toolbox.ToolBox toolbox.JavacTask * @run main HiddenOptionsShouldUseGivenEncodingTest */ +import java.nio.charset.Charset; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.List; +import toolbox.JavacTask; import toolbox.ToolBox; // Original test: test/tools/javac/6302184/T6302184.sh public class HiddenOptionsShouldUseGivenEncodingTest { public static void main(String[] args) throws Exception { + String encoding = "iso-8859-1"; + Path src = Paths.get("src"); + Files.createDirectories(src); + Files.write(src.resolve("T6302184.java"), source, Charset.forName(encoding)); + Files.write(src.resolve("T6302184.out"), expect, Charset.forName(encoding)); + + Path out = Paths.get("out"); + Files.createDirectories(out); + ToolBox tb = new ToolBox(); - String encoding = "iso-8859-1"; - Path path1 = Paths.get(ToolBox.testClasses, "T6302184.java"); + new JavacTask(tb) + .outdir("out") + .options("-encoding", encoding, "-XD-printsource") + .files(src.resolve("T6302184.java")) + .run(); + + Path path1 = Paths.get("out").resolve("T6302184.java"); List file1 = tb.readAllLines(path1, encoding); - Path path2 = Paths.get(ToolBox.testSrc, "T6302184.out"); + Path path2 = src.resolve("T6302184.out"); List file2 = tb.readAllLines(path2, encoding); tb.checkEqual(file1, file2); } + static List source = Arrays.asList( + "class T6302184 {", + " int \u00c0\u00c1\u00c2\u00c3\u00c4\u00c5 = 1;", + "}" + ); + + static List expect = Arrays.asList( + "", + "class T6302184 {", + " ", + " T6302184() {", + " super();", + " }", + " int \u00c0\u00c1\u00c2\u00c3\u00c4\u00c5 = 1;", + "}" + ); + } diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/6302184/T6302184.java --- a/test/langtools/tools/javac/6302184/T6302184.java Tue Dec 05 10:21:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please 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 a test that uses ISO 8859 encoding. - */ -class T6302184 { - int ÀÁÂÃÄÅ = 1; -} diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/6302184/T6302184.out --- a/test/langtools/tools/javac/6302184/T6302184.out Tue Dec 05 10:21:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ - -/** - * This is a test that uses ISO 8859 encoding. - */ -class T6302184 { - - T6302184() { - super(); - } - int ÀÁÂÃÄÅ = 1; -} diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel1_6.out --- a/test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel1_6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel1_6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,7 +1,7 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -BadlyTypedLabel1.java:10:15: compiler.err.string.switch.not.supported.in.source: 1.6 +BadlyTypedLabel1.java:10:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7 BadlyTypedLabel1.java:13:14: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: int, java.lang.String) 2 errors 3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel2_6.out --- a/test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel2_6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/StringsInSwitch/BadlyTypedLabel2_6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,7 +1,7 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -BadlyTypedLabel2.java:12:15: compiler.err.string.switch.not.supported.in.source: 1.6 +BadlyTypedLabel2.java:12:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7 BadlyTypedLabel2.java:15:14: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.math.RoundingMode, java.lang.String) 2 errors 3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/StringsInSwitch/NonConstantLabel6.out --- a/test/langtools/tools/javac/StringsInSwitch/NonConstantLabel6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/StringsInSwitch/NonConstantLabel6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,7 +1,7 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -NonConstantLabel.java:11:15: compiler.err.string.switch.not.supported.in.source: 1.6 +NonConstantLabel.java:11:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7 NonConstantLabel.java:14:14: compiler.err.string.const.req 2 errors 3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/StringsInSwitch/OneCaseSwitches.out --- a/test/langtools/tools/javac/StringsInSwitch/OneCaseSwitches.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/StringsInSwitch/OneCaseSwitches.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,6 +1,6 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -OneCaseSwitches.java:23:15: compiler.err.string.switch.not.supported.in.source: 1.6 +OneCaseSwitches.java:23:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7 1 error -3 warnings \ No newline at end of file +3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/StringsInSwitch/RSCL1_6.out --- a/test/langtools/tools/javac/StringsInSwitch/RSCL1_6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/StringsInSwitch/RSCL1_6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,7 +1,7 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -RepeatedStringCaseLabels1.java:10:15: compiler.err.string.switch.not.supported.in.source: 1.6 +RepeatedStringCaseLabels1.java:10:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7 RepeatedStringCaseLabels1.java:13:9: compiler.err.duplicate.case.label 2 errors 3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/StringsInSwitch/RSCL2_6.out --- a/test/langtools/tools/javac/StringsInSwitch/RSCL2_6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/StringsInSwitch/RSCL2_6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,7 +1,7 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -RepeatedStringCaseLabels2.java:11:15: compiler.err.string.switch.not.supported.in.source: 1.6 +RepeatedStringCaseLabels2.java:11:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.string.switch), 6, 7 RepeatedStringCaseLabels2.java:14:9: compiler.err.duplicate.case.label 2 errors 3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/TryWithResources/BadTwr6.out --- a/test/langtools/tools/javac/TryWithResources/BadTwr6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/TryWithResources/BadTwr6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,6 +1,6 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -BadTwr.java:13:12: compiler.err.try.with.resources.not.supported.in.source: 1.6 +BadTwr.java:13:12: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.try.with.resources), 6, 7 1 error 3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/TryWithResources/BadTwrSyntax6.out --- a/test/langtools/tools/javac/TryWithResources/BadTwrSyntax6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/TryWithResources/BadTwrSyntax6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,7 +1,7 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -BadTwrSyntax.java:14:12: compiler.err.try.with.resources.not.supported.in.source: 1.6 +BadTwrSyntax.java:14:12: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.try.with.resources), 6, 7 BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.expr 2 errors 3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/TryWithResources/TwrForVariable1.out --- a/test/langtools/tools/javac/TryWithResources/TwrForVariable1.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/TryWithResources/TwrForVariable1.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -TwrForVariable1.java:13:14: compiler.err.var.in.try.with.resources.not.supported.in.source: 1.8 +TwrForVariable1.java:13:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.var.in.try.with.resources), 8, 9 1 error diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/TryWithResources/TwrOnNonResource6.out --- a/test/langtools/tools/javac/TryWithResources/TwrOnNonResource6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/TryWithResources/TwrOnNonResource6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,6 +1,6 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -TwrOnNonResource.java:12:12: compiler.err.try.with.resources.not.supported.in.source: 1.6 +TwrOnNonResource.java:12:12: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.try.with.resources), 6, 7 1 error 3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/TryWithResources/WeirdTwr.out --- a/test/langtools/tools/javac/TryWithResources/WeirdTwr.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/TryWithResources/WeirdTwr.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,6 +1,6 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.warn.option.obsolete.source: 1.6 +- compiler.warn.source.no.bootclasspath: 6 +- compiler.warn.option.obsolete.source: 6 - compiler.warn.option.obsolete.suppression -WeirdTwr.java:14:12: compiler.err.try.with.resources.not.supported.in.source: 1.6 +WeirdTwr.java:14:12: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.try.with.resources), 6, 7 1 error 3 warnings diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out --- a/test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -WrongVersion.java:12:9: compiler.err.repeatable.annotations.not.supported.in.source: 1.6 +WrongVersion.java:12:9: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.repeatable.annotations), 6, 8 1 error diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out --- a/test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/annotations/repeatingAnnotations/WrongVersion7.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -WrongVersion.java:12:9: compiler.err.repeatable.annotations.not.supported.in.source: 1.7 +WrongVersion.java:12:9: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.repeatable.annotations), 7, 8 1 error diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out --- a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -AnnotationVersion.java:12:27: compiler.err.type.annotations.not.supported.in.source: 1.6 +AnnotationVersion.java:12:27: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.type.annotations), 6, 8 1 error diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out --- a/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/AnnotationVersion7.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -AnnotationVersion.java:12:27: compiler.err.type.annotations.not.supported.in.source: 1.7 +AnnotationVersion.java:12:27: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.type.annotations), 7, 8 1 error diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/annotations/typeAnnotations/failures/CheckErrorsForSource7.java --- a/test/langtools/tools/javac/annotations/typeAnnotations/failures/CheckErrorsForSource7.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/annotations/typeAnnotations/failures/CheckErrorsForSource7.java Tue Dec 05 10:28:45 2017 +0000 @@ -135,7 +135,7 @@ boolean found = false; for (Diagnostic d : errors.getDiagnostics()) { - if (d.getKind() == Diagnostic.Kind.ERROR && EXPECTED_ERRORS.contains(d.getCode())) { + if (d.getKind() == Diagnostic.Kind.ERROR && EXPECTED_ERROR.equals(d.getCode())) { if (found) { throw new IllegalStateException("More than one expected error found."); } @@ -149,10 +149,7 @@ } } - static final Set EXPECTED_ERRORS = new HashSet<>(Arrays.asList( - "compiler.err.type.annotations.not.supported.in.source", - "compiler.err.annotations.after.type.params.not.supported.in.source" - )); + static final String EXPECTED_ERROR = "compiler.err.feature.not.supported.in.source.plural"; class TestFO extends SimpleJavaFileObject { private final String content; diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/conditional/Conditional.out --- a/test/langtools/tools/javac/conditional/Conditional.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/conditional/Conditional.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.7 +- compiler.warn.source.no.bootclasspath: 7 Conditional.java:16:38: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.List, java.util.List) 1 error 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified6.out --- a/test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -StaticInvokeQualified.java:11:32: compiler.err.static.intf.method.invoke.not.supported.in.source: 1.6 +StaticInvokeQualified.java:11:32: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.static.intf.method.invoke), 6, 8 1 error diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified7.out --- a/test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified7.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/defaultMethods/static/StaticInvokeQualified7.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -StaticInvokeQualified.java:11:32: compiler.err.static.intf.method.invoke.not.supported.in.source: 1.7 +StaticInvokeQualified.java:11:32: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.static.intf.method.invoke), 7, 8 1 error diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple6.out --- a/test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -StaticInvokeSimple.java:12:15: compiler.err.static.intf.method.invoke.not.supported.in.source: 1.6 +StaticInvokeSimple.java:12:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.static.intf.method.invoke), 6, 8 1 error diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple7.out --- a/test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple7.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/defaultMethods/static/StaticInvokeSimple7.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -StaticInvokeSimple.java:12:15: compiler.err.static.intf.method.invoke.not.supported.in.source: 1.7 -1 error \ No newline at end of file +StaticInvokeSimple.java:12:15: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.static.intf.method.invoke), 7, 8 +1 error diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/depDocComment/SuppressDeprecation8.out --- a/test/langtools/tools/javac/depDocComment/SuppressDeprecation8.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/depDocComment/SuppressDeprecation8.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.8 +- compiler.warn.source.no.bootclasspath: 8 SuppressDeprecation.java:83:10: compiler.warn.has.been.deprecated: g(), T SuppressDeprecation.java:84:14: compiler.warn.has.been.deprecated: g(), T SuppressDeprecation.java:85:9: compiler.warn.has.been.deprecated: var, T diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples.not-yet.txt --- a/test/langtools/tools/javac/diags/examples.not-yet.txt Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples.not-yet.txt Tue Dec 05 10:28:45 2017 +0000 @@ -61,6 +61,7 @@ compiler.misc.fatal.err.cant.locate.field # Resolve, from Lower compiler.misc.fatal.err.cant.locate.meth # Resolve, from Lower compiler.misc.fatal.err.cant.close # JavaCompiler +compiler.misc.feature.not.supported.in.source.plural # cannot happen (for now) compiler.misc.file.does.not.contain.package compiler.misc.illegal.start.of.class.file compiler.misc.inferred.do.not.conform.to.lower.bounds # cannot happen? diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/AnnotationsAfterTypeParamsNotSupportedInSource.java --- a/test/langtools/tools/javac/diags/examples/AnnotationsAfterTypeParamsNotSupportedInSource.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/AnnotationsAfterTypeParamsNotSupportedInSource.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.annotations.after.type.params.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.annotations.after.type.params // key: compiler.warn.source.no.bootclasspath // options: -source 7 diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/DefaultMethodNotSupported.java --- a/test/langtools/tools/javac/diags/examples/DefaultMethodNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/DefaultMethodNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.default.methods.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.default.methods // options: -source 7 -Xlint:-options interface DefaultMethodNotSupported { diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/DiamondAndAnonClass.java --- a/test/langtools/tools/javac/diags/examples/DiamondAndAnonClass.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/DiamondAndAnonClass.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.misc.diamond.and.anon.class.not.supported.in.source +// key: compiler.misc.feature.not.supported.in.source +// key: compiler.misc.feature.diamond.and.anon.class // key: compiler.err.cant.apply.diamond.1 // key: compiler.warn.source.no.bootclasspath // options: -source 8 diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/DiamondNotSupported.java --- a/test/langtools/tools/javac/diags/examples/DiamondNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/DiamondNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.diamond.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source +// key: compiler.misc.feature.diamond // options: -source 6 -Xlint:-options import java.util.*; diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/IntersectionTypesInCastNotSupported.java --- a/test/langtools/tools/javac/diags/examples/IntersectionTypesInCastNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/IntersectionTypesInCastNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.intersection.types.in.cast.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.intersection.types.in.cast // options: -source 7 -Xlint:-options interface IntersectionTypesInCastNotSupported { diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/LambdaNotSupported.java --- a/test/langtools/tools/javac/diags/examples/LambdaNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/LambdaNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.lambda.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.lambda // options: -source 7 -Xlint:-options class LambdaNotSupported { diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/MethodReferencesNotSupported.java --- a/test/langtools/tools/javac/diags/examples/MethodReferencesNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/MethodReferencesNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.method.references.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.method.references // options: -source 7 -Xlint:-options class MethodReferencesNotSupported { diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java --- a/test/langtools/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.modules.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.modules // key: compiler.warn.source.no.bootclasspath // options: -source 8 -Xlint:-path diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/MulticatchNotSupported.java --- a/test/langtools/tools/javac/diags/examples/MulticatchNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/MulticatchNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.multicatch.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.multicatch // options: -source 1.6 -Xlint:-options class MulticatchNotSupported { diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/PrivateInterfaceMethodsNotSupported.java --- a/test/langtools/tools/javac/diags/examples/PrivateInterfaceMethodsNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/PrivateInterfaceMethodsNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.private.intf.methods.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.private.intf.methods // key: compiler.warn.source.no.bootclasspath // options: -source 8 diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/RepeatableAnnotationsNotSupported.java --- a/test/langtools/tools/javac/diags/examples/RepeatableAnnotationsNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/RepeatableAnnotationsNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.repeatable.annotations.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.repeatable.annotations // key: compiler.warn.source.no.bootclasspath // options: -source 7 diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/StaticIntfMethodInvokeNotSupported.java --- a/test/langtools/tools/javac/diags/examples/StaticIntfMethodInvokeNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/StaticIntfMethodInvokeNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.static.intf.method.invoke.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.static.intf.method.invoke // options: -source 7 -Xlint:-options import java.util.stream.Stream; diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/StaticIntfMethodNotSupported.java --- a/test/langtools/tools/javac/diags/examples/StaticIntfMethodNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/StaticIntfMethodNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.static.intf.methods.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.static.intf.methods // options: -source 7 -Xlint:-options -XDallowStaticInterfaceMethods interface StaticIntfMethodNotSupported { diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/StringSwitchNotSupported.java --- a/test/langtools/tools/javac/diags/examples/StringSwitchNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/StringSwitchNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.string.switch.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.string.switch // options: -source 6 -Xlint:-options class StringSwitchNotSupported { diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/TryResourceNotSupported.java --- a/test/langtools/tools/javac/diags/examples/TryResourceNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/TryResourceNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.try.with.resources.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source +// key: compiler.misc.feature.try.with.resources // options: -source 1.6 -Xlint:-options import java.io.*; diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/TypeAnnotationsNotSupported.java --- a/test/langtools/tools/javac/diags/examples/TypeAnnotationsNotSupported.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/TypeAnnotationsNotSupported.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.type.annotations.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.type.annotations // key: compiler.warn.source.no.bootclasspath // options: -source 7 diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/UnsupportedBinaryLiteral.java --- a/test/langtools/tools/javac/diags/examples/UnsupportedBinaryLiteral.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/UnsupportedBinaryLiteral.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.unsupported.binary.lit +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.binary.lit // options: -source 6 -Xlint:-options class UnsupportedBinaryLiteral { diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/UnsupportedUnderscoreLiteral.java --- a/test/langtools/tools/javac/diags/examples/UnsupportedUnderscoreLiteral.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/UnsupportedUnderscoreLiteral.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.unsupported.underscore.lit +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.underscore.lit // options: -source 6 -Xlint:-options class UnsupportedUnderscoreLiteral { diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java --- a/test/langtools/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/diags/examples/VarInTryWithResourcesNotSupportedInSource.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,7 +21,8 @@ * questions. */ -// key: compiler.err.var.in.try.with.resources.not.supported.in.source +// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.misc.feature.var.in.try.with.resources // key: compiler.warn.source.no.bootclasspath // options: -source 8 diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/DocCommentTester.java --- a/test/langtools/tools/javac/doctree/DocCommentTester.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/DocCommentTester.java Tue Dec 05 10:28:45 2017 +0000 @@ -404,9 +404,18 @@ public Void visitDocComment(DocCommentTree node, Void p) { header(node); indent(+1); + // Applicable only to html files, print iff non-empty + if (!node.getPreamble().isEmpty()) + print("preamble", node.getPreamble()); + print("firstSentence", node.getFirstSentence()); print("body", node.getBody()); print("block tags", node.getBlockTags()); + + // Applicable only to html files, print iff non-empty + if (!node.getPostamble().isEmpty()) + print("postamble", node.getPostamble()); + indent(-1); indent(); out.println("]"); @@ -418,6 +427,11 @@ return null; } + public Void visitDocType(DocTypeTree node, Void p) { + header(node, compress(node.getText())); + return null; + } + public Void visitEndElement(EndElementTree node, Void p) { header(node, node.getName().toString()); return null; diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/SimpleDocTreeVisitorTest.java --- a/test/langtools/tools/javac/doctree/SimpleDocTreeVisitorTest.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/SimpleDocTreeVisitorTest.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import com.sun.source.doctree.DocCommentTree; import com.sun.source.doctree.DocTree; +import com.sun.source.doctree.DocTree.Kind; import com.sun.source.doctree.DocTreeVisitor; import com.sun.source.tree.ClassTree; import com.sun.source.tree.CompilationUnitTree; @@ -84,7 +85,7 @@ } for (DocTree.Kind k: DocTree.Kind.values()) { - if (!found.contains(k) && k != DocTree.Kind.OTHER) + if (!found.contains(k) && k != DocTree.Kind.OTHER && k != DocTree.Kind.DOC_TYPE) error("not found: " + k); } diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/Anchor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/Anchor.java Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Anchor test. + */ +public class Anchor {} diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java --- a/test/langtools/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/DocCommentTreeApiTester.java Tue Dec 05 10:28:45 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * 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 8132096 8157611 + * @bug 8132096 8157611 8190552 * @summary test the APIs in the DocTree interface * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.file @@ -52,6 +52,7 @@ import javax.lang.model.util.Elements; import javax.tools.FileObject; import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; import javax.tools.StandardJavaFileManager; import com.sun.source.doctree.DocTree; @@ -64,8 +65,8 @@ public class DocCommentTreeApiTester { - private static final String MARKER_START = ""; + private static final String MARKER_START = "EXPECT_START"; + private static final String MARKER_END = "EXPECT_END"; private static final String testSrc = System.getProperty("test.src", "."); @@ -85,22 +86,26 @@ DocCommentTreeApiTester test = new DocCommentTreeApiTester(); try { // test getting a DocTree from an element - test.runElementAndBreakIteratorTests("OverviewTest.java", "OverviewTest test."); + test.runElementAndBreakIteratorTests("Anchor.java", "Anchor test."); // test relative paths in a class within a package - test.runRelativePathTest("pkg/Anchor.java", "package.html"); + test.runRelativePathTest("pkg/Anchor.java", "package.html", true); // tests files relative path in an unnamed package - test.runRelativePathTest("OverviewTest.java", "overview0.html"); + test.runRelativePathTest("Anchor.java", "overview0.html", true); - // tests doctreepath using package element and package.html - test.runDocTreePath("pkg/Anchor.java", "package.html"); + // test doctree path and Doc + test.runDocTreePath("Anchor.java", "package.html"); // test for correct parsing using valid and some invalid html tags - for (int i = 0; i < 7; i++) { - String hname = "overview" + i + ".html"; - test.runFileObjectTest(hname); - } + test.runFileObjectTest("overview0.html"); + test.runFileObjectTest("overview1.html"); + test.runFileObjectTest("overview2.html"); + test.runFileObjectTest("overview3.html"); + test.runFileObjectTest("overview4.html"); + test.runFileObjectTest("overview5.html"); + test.runFileObjectTest("overview6.html"); + test.runFileObjectTest("overview7.html"); } finally { test.status(); @@ -166,7 +171,8 @@ * @param fileName the relative html file * @throws java.lang.Exception ouch */ - public void runRelativePathTest(String javaFileName, String fileName) throws Exception { + public void runRelativePathTest(String javaFileName, String fileName, + boolean bodyOnly) throws Exception { List javaFiles = new ArrayList<>(); javaFiles.add(new File(testSrc, javaFileName)); @@ -185,13 +191,17 @@ Element klass = elements.iterator().next(); DocCommentTree dcTree = trees.getDocCommentTree(klass, fileName); + + if (dcTree == null) + throw new Error("invalid input: " + fileName); + StringWriter sw = new StringWriter(); printer.print(dcTree, sw); String found = sw.toString(); FileObject htmlFo = fm.getFileForInput(javax.tools.StandardLocation.SOURCE_PATH, t.getElements().getPackageOf(klass).getQualifiedName().toString(), - fileName); + fileName + ".out"); String expected = getExpected(htmlFo.openReader(true)); astcheck(fileName, expected, found); @@ -209,6 +219,7 @@ List otherFiles = new ArrayList<>(); otherFiles.add(new File(testSrc, htmlfileName)); + otherFiles.add(new File(testSrc, htmlfileName + ".out")); try (StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null)) { Iterable fos = fm.getJavaFileObjectsFromFiles(javaFiles); @@ -218,10 +229,22 @@ final DocTrees trees = DocTrees.instance(t); StringWriter sw = new StringWriter(); + DocCommentTree dct = null; + String expected = null; + for (JavaFileObject jfo : others) { + switch (jfo.getKind()) { + case HTML: + dct = trees.getDocCommentTree(jfo); + if (dct == null) + throw new Exception("invalid input: " + jfo); + break; + default: + expected = getExpected(jfo.openReader(true)); + } + } - printer.print(trees.getDocCommentTree(others.iterator().next()), sw); + printer.print(dct, sw); String found = sw.toString(); - String expected = getExpected(otherFiles.iterator().next().toPath()); astcheck(otherFiles.toString(), expected, found); } } @@ -237,6 +260,9 @@ List javaFiles = new ArrayList<>(); javaFiles.add(new File(testSrc, javaFileName)); + List otherFiles = new ArrayList<>(); + otherFiles.add(new File(testSrc, pkgFileName + ".out")); + List dirs = new ArrayList<>(); dirs.add(new File(testSrc)); @@ -256,15 +282,23 @@ FileObject htmlFo = fm.getFileForInput(javax.tools.StandardLocation.SOURCE_PATH, t.getElements().getPackageOf(klass).getQualifiedName().toString(), "package.html"); - System.out.println(); DocTreePath treePath = trees.getDocTreePath(htmlFo, pkg); + + if (treePath == null) { + throw new Exception("invalid input: " + htmlFo); + } + DocCommentTree dcTree = treePath.getDocComment(); + if (dcTree == null) + throw new Exception("invalid input" + htmlFo); StringWriter sw = new StringWriter(); printer.print(dcTree, sw); String found = sw.toString(); + Iterable oos = fm.getJavaFileObjectsFromFiles(otherFiles); + JavaFileObject otherFo = oos.iterator().next(); + String expected = getExpected(otherFo.openReader(true)); - String expected = getExpected(htmlFo.openReader(true)); astcheck(pkgFileName, expected, found); } } @@ -300,10 +334,6 @@ return getExpected(lines); } - String getExpected(Path p) throws IOException { - return getExpected(Files.readAllLines(p)); - } - String getExpected(List lines) { boolean start = false; StringWriter sw = new StringWriter(); diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/OverviewTest.java --- a/test/langtools/tools/javac/doctree/dcapi/OverviewTest.java Tue Dec 05 10:21:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -/* - * 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. - */ - -/** - * OverviewTest test. - */ -public class OverviewTest {} diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview0.html --- a/test/langtools/tools/javac/doctree/dcapi/overview0.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview0.html Tue Dec 05 10:28:45 2017 +0000 @@ -1,48 +1,8 @@ - - + -A simple well formed html document
          overview0.html
          .
          +A simple well formed html document 
          overview0.html
          . - - + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview0.html.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview0.html.out Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,33 @@ +EXPECT_START +DocComment[DOC_COMMENT, pos:0 + preamble: 5 + Comment[COMMENT, pos:0, ] + StartElement[START_ELEMENT, pos:30 + name:HTML + attributes: empty + ] + StartElement[START_ELEMENT, pos:37 + name:HEAD + attributes: empty + ] + EndElement[END_ELEMENT, pos:44, HEAD] + StartElement[START_ELEMENT, pos:52 + name:BODY + attributes: empty + ] + firstSentence: 1 + Text[TEXT, pos:59, A_simple_well_fo...rmed_html_document] + body: 4 + StartElement[START_ELEMENT, pos:94 + name:pre + attributes: empty + ] + Text[TEXT, pos:99, overview0.html] + EndElement[END_ELEMENT, pos:113, pre] + Text[TEXT, pos:119, .] + block tags: empty + postamble: 2 + EndElement[END_ELEMENT, pos:121, BODY] + EndElement[END_ELEMENT, pos:129, HTML] +] +EXPECT_END diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview1.html --- a/test/langtools/tools/javac/doctree/dcapi/overview1.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview1.html Tue Dec 05 10:28:45 2017 +0000 @@ -1,47 +1,8 @@ - - + -Html document
          overview1.html
          .
          +Html document 
          overview1.html
          . Missing HTML. - + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview1.html.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview1.html.out Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,29 @@ +EXPECT_START +DocComment[DOC_COMMENT, pos:0 + preamble: 4 + Comment[COMMENT, pos:0, ] + StartElement[START_ELEMENT, pos:30 + name:HEAD + attributes: empty + ] + EndElement[END_ELEMENT, pos:37, HEAD] + StartElement[START_ELEMENT, pos:45 + name:BODY + attributes: empty + ] + firstSentence: 1 + Text[TEXT, pos:52, Html_document] + body: 4 + StartElement[START_ELEMENT, pos:66 + name:pre + attributes: empty + ] + Text[TEXT, pos:71, overview1.html] + EndElement[END_ELEMENT, pos:85, pre] + Text[TEXT, pos:91, .|Missing_HTML.] + block tags: empty + postamble: 2 + EndElement[END_ELEMENT, pos:107, BODY] + EndElement[END_ELEMENT, pos:115, HTML] +] +EXPECT_END diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview2.html --- a/test/langtools/tools/javac/doctree/dcapi/overview2.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview2.html Tue Dec 05 10:28:45 2017 +0000 @@ -1,47 +1,8 @@ - - + -Html document
          overview2.html
          .
          +Html document 
          overview2.html
          . Missing HEAD. - + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview2.html.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview2.html.out Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,29 @@ +EXPECT_START +DocComment[DOC_COMMENT, pos:0 + preamble: 4 + Comment[COMMENT, pos:0, ] + StartElement[START_ELEMENT, pos:30 + name:HTML + attributes: empty + ] + EndElement[END_ELEMENT, pos:37, HEAD] + StartElement[START_ELEMENT, pos:45 + name:BODY + attributes: empty + ] + firstSentence: 1 + Text[TEXT, pos:52, Html_document] + body: 4 + StartElement[START_ELEMENT, pos:66 + name:pre + attributes: empty + ] + Text[TEXT, pos:71, overview2.html] + EndElement[END_ELEMENT, pos:85, pre] + Text[TEXT, pos:91, .|Missing_HEAD.] + block tags: empty + postamble: 2 + EndElement[END_ELEMENT, pos:107, BODY] + EndElement[END_ELEMENT, pos:115, HTML] +] +EXPECT_END diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview3.html --- a/test/langtools/tools/javac/doctree/dcapi/overview3.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview3.html Tue Dec 05 10:28:45 2017 +0000 @@ -1,47 +1,8 @@ - - + -Html document
          overview3.html
          .
          +Html document 
          overview3.html
          . Missing enclosing HEAD. - + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview3.html.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview3.html.out Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,32 @@ +EXPECT_START +DocComment[DOC_COMMENT, pos:0 + preamble: 4 + Comment[COMMENT, pos:0, ] + StartElement[START_ELEMENT, pos:30 + name:HTML + attributes: empty + ] + StartElement[START_ELEMENT, pos:37 + name:HEAD + attributes: empty + ] + StartElement[START_ELEMENT, pos:44 + name:BODY + attributes: empty + ] + firstSentence: 1 + Text[TEXT, pos:51, Html_document] + body: 4 + StartElement[START_ELEMENT, pos:65 + name:pre + attributes: empty + ] + Text[TEXT, pos:70, overview3.html] + EndElement[END_ELEMENT, pos:84, pre] + Text[TEXT, pos:90, .|Missing_enclosing_HEAD.] + block tags: empty + postamble: 2 + EndElement[END_ELEMENT, pos:116, BODY] + EndElement[END_ELEMENT, pos:124, HTML] +] +EXPECT_END diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview4.html --- a/test/langtools/tools/javac/doctree/dcapi/overview4.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview4.html Tue Dec 05 10:28:45 2017 +0000 @@ -1,44 +1,6 @@ - - Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - or visit www.oracle.com if you need additional information or have any - questions. ---> - -Html document
          overview4.html
          .
          +Html document 
          overview4.html
          . Only BODY - + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview4.html.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview4.html.out Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,23 @@ +EXPECT_START +DocComment[DOC_COMMENT, pos:0 + preamble: 2 + Comment[COMMENT, pos:0, ] + StartElement[START_ELEMENT, pos:31 + name:BODY + attributes: empty + ] + firstSentence: 1 + Text[TEXT, pos:38, Html_document] + body: 4 + StartElement[START_ELEMENT, pos:52 + name:pre + attributes: empty + ] + Text[TEXT, pos:57, overview4.html] + EndElement[END_ELEMENT, pos:71, pre] + Text[TEXT, pos:77, .|Only_BODY] + block tags: empty + postamble: 1 + EndElement[END_ELEMENT, pos:89, BODY] +] +EXPECT_END diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview5.html --- a/test/langtools/tools/javac/doctree/dcapi/overview5.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview5.html Tue Dec 05 10:28:45 2017 +0000 @@ -1,47 +1,8 @@ - - + -Html document
          overview5.html
          .
          +Html document 
          overview5.html
          . Missing enclosing HTML - + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview5.html.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview5.html.out Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,32 @@ +EXPECT_START +DocComment[DOC_COMMENT, pos:0 + preamble: 5 + Comment[COMMENT, pos:0, ] + StartElement[START_ELEMENT, pos:30 + name:HTML + attributes: empty + ] + StartElement[START_ELEMENT, pos:37 + name:HEAD + attributes: empty + ] + EndElement[END_ELEMENT, pos:44, HEAD] + StartElement[START_ELEMENT, pos:52 + name:BODY + attributes: empty + ] + firstSentence: 1 + Text[TEXT, pos:59, Html_document] + body: 4 + StartElement[START_ELEMENT, pos:73 + name:pre + attributes: empty + ] + Text[TEXT, pos:78, overview5.html] + EndElement[END_ELEMENT, pos:92, pre] + Text[TEXT, pos:98, .|Missing_enclosing_HTML] + block tags: empty + postamble: 1 + EndElement[END_ELEMENT, pos:123, BODY] +] +EXPECT_END diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview6.html --- a/test/langtools/tools/javac/doctree/dcapi/overview6.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview6.html Tue Dec 05 10:28:45 2017 +0000 @@ -1,40 +1,4 @@ - - + @@ -46,4 +10,3 @@ Illegal second body pair, the first body should not be ignored. - diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview6.html.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview6.html.out Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,32 @@ +EXPECT_START +DocComment[DOC_COMMENT, pos:0 + preamble: 5 + Comment[COMMENT, pos:0, ] + StartElement[START_ELEMENT, pos:30 + name:HTML + attributes: empty + ] + StartElement[START_ELEMENT, pos:37 + name:HEAD + attributes: empty + ] + EndElement[END_ELEMENT, pos:44, HEAD] + StartElement[START_ELEMENT, pos:52 + name:BODY + attributes: empty + ] + firstSentence: 1 + Text[TEXT, pos:59, The_first_correct_body_pair.] + body: empty + block tags: empty + postamble: 5 + EndElement[END_ELEMENT, pos:88, BODY] + StartElement[START_ELEMENT, pos:97 + name:BODY + attributes: empty + ] + Text[TEXT, pos:104, Illegal_second_b...ody_pair,_the_first_body_should_not_be_ignored.|] + EndElement[END_ELEMENT, pos:168, BODY] + EndElement[END_ELEMENT, pos:176, HTML] +] +EXPECT_END diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview7.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview7.html Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,6 @@ + + + + +@since 1.0 + diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/overview7.html.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/overview7.html.out Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,29 @@ +EXPECT_START +DocComment[DOC_COMMENT, pos:0 + preamble: 5 + Comment[COMMENT, pos:0, ] + StartElement[START_ELEMENT, pos:30 + name:HTML + attributes: empty + ] + StartElement[START_ELEMENT, pos:37 + name:HEAD + attributes: empty + ] + EndElement[END_ELEMENT, pos:44, HEAD] + StartElement[START_ELEMENT, pos:52 + name:BODY + attributes: empty + ] + firstSentence: empty + body: empty + block tags: 1 + Since[SINCE, pos:58 + body: 1 + Text[TEXT, pos:65, 1.0] + ] + postamble: 2 + EndElement[END_ELEMENT, pos:68, BODY] + EndElement[END_ELEMENT, pos:76, HTML] +] +EXPECT_END diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/package.html --- a/test/langtools/tools/javac/doctree/dcapi/package.html Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/package.html Tue Dec 05 10:28:45 2017 +0000 @@ -1,47 +1,11 @@ - + + + The Crafty Fox A simple well formed html document
          package.html
          .
           
          -
          -
          +
          \ No newline at end of file
          diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/package.html.out
          --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
          +++ b/test/langtools/tools/javac/doctree/dcapi/package.html.out	Tue Dec 05 10:28:45 2017 +0000
          @@ -0,0 +1,43 @@
          +EXPECT_START
          +DocComment[DOC_COMMENT, pos:10
          +  preamble: 9
          +    DocType[DOC_TYPE, pos:10, HTML_PUBLIC_"-//...W3C//DTD_HTML_4.01//EN"|________"http://www.w3.org/TR/html4/strict.dtd"]
          +    Comment[COMMENT, pos:99, ]
          +    StartElement[START_ELEMENT, pos:129
          +      name:HTML
          +      attributes: empty
          +    ]
          +    StartElement[START_ELEMENT, pos:136
          +      name:HEAD
          +      attributes: empty
          +    ]
          +    StartElement[START_ELEMENT, pos:147
          +      name:TITLE
          +      attributes: empty
          +    ]
          +    Text[TEXT, pos:154, The_Crafty_Fox]
          +    EndElement[END_ELEMENT, pos:168, TITLE]
          +    EndElement[END_ELEMENT, pos:177, HEAD]
          +    StartElement[START_ELEMENT, pos:185
          +      name:BODY
          +      attributes: empty
          +    ]
          +  firstSentence: 1
          +    Text[TEXT, pos:192, A_simple_well_fo...rmed_html_document]
          +  body: 4
          +    StartElement[START_ELEMENT, pos:227
          +      name:pre
          +      attributes: empty
          +    ]
          +    Text[TEXT, pos:232, package.html]
          +    StartElement[START_ELEMENT, pos:244
          +      name:pre
          +      attributes: empty
          +    ]
          +    Text[TEXT, pos:249, .]
          +  block tags: empty
          +  postamble: 2
          +    EndElement[END_ELEMENT, pos:251, BODY]
          +    EndElement[END_ELEMENT, pos:259, HTML]
          +]
          +EXPECT_END
          diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/pkg/package.html
          --- a/test/langtools/tools/javac/doctree/dcapi/pkg/package.html	Tue Dec 05 10:21:41 2017 +0000
          +++ b/test/langtools/tools/javac/doctree/dcapi/pkg/package.html	Tue Dec 05 10:28:45 2017 +0000
          @@ -1,48 +1,9 @@
          -
          -
          +
           
           
           
           
          -A simple well formed html document 
          package.html
          .
          +A simple well formed html document 
          package.html
          . In package pkg. - + \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/doctree/dcapi/pkg/package.html.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/doctree/dcapi/pkg/package.html.out Tue Dec 05 10:28:45 2017 +0000 @@ -0,0 +1,33 @@ +EXPECT_START +DocComment[DOC_COMMENT, pos:0 + preamble: 5 + Comment[COMMENT, pos:0, ] + StartElement[START_ELEMENT, pos:31 + name:HTML + attributes: empty + ] + StartElement[START_ELEMENT, pos:38 + name:HEAD + attributes: empty + ] + EndElement[END_ELEMENT, pos:45, HEAD] + StartElement[START_ELEMENT, pos:53 + name:BODY + attributes: empty + ] + firstSentence: 1 + Text[TEXT, pos:60, A_simple_well_fo...rmed_html_document] + body: 4 + StartElement[START_ELEMENT, pos:95 + name:pre + attributes: empty + ] + Text[TEXT, pos:100, package.html] + EndElement[END_ELEMENT, pos:112, pre] + Text[TEXT, pos:118, .|In_package_pkg.] + block tags: empty + postamble: 2 + EndElement[END_ELEMENT, pos:136, BODY] + EndElement[END_ELEMENT, pos:144, HTML] +] +EXPECT_END \ No newline at end of file diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/generics/diamond/neg/Neg09a.out --- a/test/langtools/tools/javac/generics/diamond/neg/Neg09a.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/generics/diamond/neg/Neg09a.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.8 -Neg09a.java:15:34: compiler.err.cant.apply.diamond.1: Neg09a.Member, (compiler.misc.diamond.and.anon.class.not.supported.in.source: 1.8) +- compiler.warn.source.no.bootclasspath: 8 +Neg09a.java:15:34: compiler.err.cant.apply.diamond.1: Neg09a.Member, (compiler.misc.feature.not.supported.in.source: (compiler.misc.feature.diamond.and.anon.class), 8, 9) 1 error 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/generics/diamond/neg/Neg09b.out --- a/test/langtools/tools/javac/generics/diamond/neg/Neg09b.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/generics/diamond/neg/Neg09b.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.8 -Neg09b.java:16:34: compiler.err.cant.apply.diamond.1: Neg09b.Nested, (compiler.misc.diamond.and.anon.class.not.supported.in.source: 1.8) +- compiler.warn.source.no.bootclasspath: 8 +Neg09b.java:16:34: compiler.err.cant.apply.diamond.1: Neg09b.Nested, (compiler.misc.feature.not.supported.in.source: (compiler.misc.feature.diamond.and.anon.class), 8, 9) 1 error 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/generics/diamond/neg/Neg09c.out --- a/test/langtools/tools/javac/generics/diamond/neg/Neg09c.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/generics/diamond/neg/Neg09c.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.8 -Neg09c.java:15:39: compiler.err.cant.apply.diamond.1: Neg09c.Member, (compiler.misc.diamond.and.anon.class.not.supported.in.source: 1.8) +- compiler.warn.source.no.bootclasspath: 8 +Neg09c.java:15:39: compiler.err.cant.apply.diamond.1: Neg09c.Member, (compiler.misc.feature.not.supported.in.source: (compiler.misc.feature.diamond.and.anon.class), 8, 9) 1 error 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/generics/diamond/neg/Neg09d.out --- a/test/langtools/tools/javac/generics/diamond/neg/Neg09d.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/generics/diamond/neg/Neg09d.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.8 +- compiler.warn.source.no.bootclasspath: 8 Neg09d.java:16:33: compiler.err.doesnt.exist: Neg09 1 error 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/generics/inference/6278587/T6278587Neg.out --- a/test/langtools/tools/javac/generics/inference/6278587/T6278587Neg.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/generics/inference/6278587/T6278587Neg.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.7 +- compiler.warn.source.no.bootclasspath: 7 T6278587Neg.java:18:10: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: T, T6278587Neg.C) 1 error 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/generics/odersky/BadTest4.out --- a/test/langtools/tools/javac/generics/odersky/BadTest4.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/generics/odersky/BadTest4.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.7 +- compiler.warn.source.no.bootclasspath: 7 BadTest4.java:38:17: compiler.err.cant.apply.symbol: kindname.method, f, A,B, java.lang.Integer,java.lang.Number, kindname.class, BadTest4.Main, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Number, java.lang.Integer) 1 error 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/lambda/SourceLevelTest.out --- a/test/langtools/tools/javac/lambda/SourceLevelTest.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/lambda/SourceLevelTest.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,6 +1,6 @@ -- compiler.warn.source.no.bootclasspath: 1.7 -SourceLevelTest.java:11:9: compiler.err.default.methods.not.supported.in.source: 1.7 -SourceLevelTest.java:18:17: compiler.err.lambda.not.supported.in.source: 1.7 -SourceLevelTest.java:19:20: compiler.err.method.references.not.supported.in.source: 1.7 +- compiler.warn.source.no.bootclasspath: 7 +SourceLevelTest.java:11:9: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.default.methods), 7, 8 +SourceLevelTest.java:18:17: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.lambda), 7, 8 +SourceLevelTest.java:19:20: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.method.references), 7, 8 3 errors 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/lib/DPrinter.java --- a/test/langtools/tools/javac/lib/DPrinter.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/lib/DPrinter.java Tue Dec 05 10:28:45 2017 +0000 @@ -1028,6 +1028,12 @@ return visitInlineTag(node, null); } + @Override + public Void visitDocType(DocTypeTree node, Void aVoid) { + printLimitedEscapedString("body", node.getText()); + return visitTree(node, null); + } + public Void visitEndElement(EndElementTree node, Void p) { printName("name", node.getName()); return visitTree(node, null); diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/literals/BadBinaryLiterals.6.out --- a/test/langtools/tools/javac/literals/BadBinaryLiterals.6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/literals/BadBinaryLiterals.6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,8 +1,6 @@ -BadBinaryLiterals.java:10:17: compiler.err.unsupported.binary.lit: 1.6 +BadBinaryLiterals.java:10:17: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.binary.lit), 6, 7 BadBinaryLiterals.java:11:24: compiler.err.expected: ';' -BadBinaryLiterals.java:13:21: compiler.err.int.number.too.large: 111111111111111111111111111111111 -BadBinaryLiterals.java:15:21: compiler.err.int.number.too.large: 11111111111111111111111111111111111111111111111111111111111111111 BadBinaryLiterals.java:16:27: compiler.err.expected: ';' BadBinaryLiterals.java:17:27: compiler.err.expected: ';' BadBinaryLiterals.java:17:30: compiler.err.expected: token.identifier -7 errors +5 errors diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/literals/BadUnderscoreLiterals.6.out --- a/test/langtools/tools/javac/literals/BadUnderscoreLiterals.6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/literals/BadUnderscoreLiterals.6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,7 +1,7 @@ -BadUnderscoreLiterals.java:11:17: compiler.err.unsupported.underscore.lit: 1.6 +BadUnderscoreLiterals.java:11:17: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.underscore.lit), 6, 7 BadUnderscoreLiterals.java:15:15: compiler.err.illegal.underscore BadUnderscoreLiterals.java:19:19: compiler.err.illegal.underscore -BadUnderscoreLiterals.java:22:14: compiler.err.unsupported.binary.lit: 1.6 +BadUnderscoreLiterals.java:22:14: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.binary.lit), 6, 7 BadUnderscoreLiterals.java:22:16: compiler.err.illegal.underscore BadUnderscoreLiterals.java:23:17: compiler.err.illegal.underscore BadUnderscoreLiterals.java:26:16: compiler.err.illegal.underscore diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/options/T6900037.out --- a/test/langtools/tools/javac/options/T6900037.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/options/T6900037.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.8 +- compiler.warn.source.no.bootclasspath: 8 - compiler.err.warnings.and.werror 1 error 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/parser/extend/TrialParser.java --- a/test/langtools/tools/javac/parser/extend/TrialParser.java Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/parser/extend/TrialParser.java Tue Dec 05 10:28:45 2017 +0000 @@ -21,6 +21,7 @@ * questions. */ +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.TypeTag; import com.sun.tools.javac.parser.JavacParser; import com.sun.tools.javac.parser.ParserFactory; @@ -186,7 +187,7 @@ List annosAfterParams = annotationsOpt(Tag.ANNOTATION); if (annosAfterParams.nonEmpty()) { - checkAnnotationsAfterTypeParams(annosAfterParams.head.pos); + checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS); mods.annotations = mods.annotations.appendList(annosAfterParams); if (mods.pos == Position.NOPOS) { mods.pos = mods.annotations.head.pos; diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/processing/warnings/gold_sv_warn_5_6.out --- a/test/langtools/tools/javac/processing/warnings/gold_sv_warn_5_6.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/processing/warnings/gold_sv_warn_5_6.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,2 +1,2 @@ -- compiler.warn.proc.processor.incompatible.source.version: RELEASE_5, TestSourceVersionWarnings, 1.6 +- compiler.warn.proc.processor.incompatible.source.version: RELEASE_5, TestSourceVersionWarnings, 6 1 warning diff -r 10b34c929b4f -r 64298b1e890b test/langtools/tools/javac/varargs/6313164/T6313164Source7.out --- a/test/langtools/tools/javac/varargs/6313164/T6313164Source7.out Tue Dec 05 10:21:41 2017 +0000 +++ b/test/langtools/tools/javac/varargs/6313164/T6313164Source7.out Tue Dec 05 10:28:45 2017 +0000 @@ -1,4 +1,4 @@ -- compiler.warn.source.no.bootclasspath: 1.7 +- compiler.warn.source.no.bootclasspath: 7 T6313164.java:14:10: compiler.err.cant.apply.symbol: kindname.method, foo1, p1.A[], p1.B,p1.B, kindname.class, p1.B, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164) T6313164.java:19:15: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164) T6313164.java:20:15: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)