Merge
authorduke
Wed, 05 Jul 2017 17:24:13 +0200
changeset 6707 d4bd99be2de6
parent 6706 645f70db28dc (current diff)
parent 6705 a620046a250b (diff)
child 6725 39b3cef7bd46
Merge
jdk/make/common/Rules-SCCS.gmk
jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedCharEncoding.sh
--- a/.hgtags-top-repo	Thu Oct 07 15:12:12 2010 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 17:24:13 2017 +0200
@@ -87,3 +87,4 @@
 2a02d4a6955c7c078aee9a604cb3be409800d82c jdk7-b110
 9702d6fef68e17533ee7fcf5923b11ead3e912ce jdk7-b111
 b852103caf73da70068473777ae867a457bb3ae1 jdk7-b112
+c1df968c4527bfab5f97662a89245f15d12d378b jdk7-b113
--- a/Makefile	Thu Oct 07 15:12:12 2010 -0700
+++ b/Makefile	Wed Jul 05 17:24:13 2017 +0200
@@ -558,9 +558,12 @@
 # rule to test
 ################################################################
 
-.NOTPARALLEL: test
+.NOTPARALLEL: test_run
 
-test: test_clean test_start test_summary
+test:
+	$(MAKE) test_run
+
+test_run: test_clean test_start test_summary
 
 test_start:
 	@$(ECHO) "Tests started at `$(DATE)`"
@@ -586,7 +589,7 @@
 # Get failure list from log
 $(OUTPUTDIR)/test_failures.txt: $(OUTPUTDIR)/test_log.txt
 	@$(RM) $@
-	@( $(EGREP) '^FAILED:' $< || $(ECHO) "" ) > $@
+	@( $(EGREP) '^FAILED:' $< || $(ECHO) "" ) | $(NAWK) 'length>0' > $@
 
 # Get log file of all tests run
 JDK_TO_TEST := $(shell 							\
@@ -598,10 +601,11 @@
     $(ECHO) "$(PRODUCT_HOME)"; 						\
   fi 									\
 )
+TEST_TARGETS=all
 $(OUTPUTDIR)/test_log.txt:
 	$(RM) $@
-	( $(CD) test &&                                     \
-          $(MAKE) NO_STOPPING=- PRODUCT_HOME=$(JDK_TO_TEST) \
+	( $(CD) test &&                                                     \
+          $(MAKE) NO_STOPPING=- PRODUCT_HOME=$(JDK_TO_TEST) $(TEST_TARGETS) \
         ) | tee $@
 
 ################################################################
@@ -614,7 +618,7 @@
 #  PHONY
 ################################################################
 
-.PHONY: all  test test_start test_summary test_clean \
+.PHONY: all  test test_run test_start test_summary test_clean \
 	generic_build_repo_series \
 	what clobber insane \
         dev dev-build dev-sanity dev-clobber \
--- a/corba/.hgtags	Thu Oct 07 15:12:12 2010 -0700
+++ b/corba/.hgtags	Wed Jul 05 17:24:13 2017 +0200
@@ -87,3 +87,4 @@
 0e1f80fda2271f53d4bbb59ec3f301dfbcef6a0a jdk7-b110
 640fa4d4e2ad4c2d7e4815c955026740d8c52b7a jdk7-b111
 cc67fdc4fee9a5b25caee4e71b51a8ff24ae7d1a jdk7-b112
+a89a6c5be9d1a754868d3d359cbf7ad36aa95631 jdk7-b113
--- a/hotspot/.hgtags	Thu Oct 07 15:12:12 2010 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 17:24:13 2017 +0200
@@ -122,3 +122,4 @@
 2f25f2b8de2700a1822463b1bd3d02b5e218018f jdk7-b110
 07b042e13dde4f3479ba9ec55120fcd5e8623323 jdk7-b111
 5511edd5d719f3fc9fdd04879482026a3d2c8652 jdk7-b112
+beef35b96b81129c375d572357fb9548d9020db1 jdk7-b113
--- a/jaxp/.hgtags	Thu Oct 07 15:12:12 2010 -0700
+++ b/jaxp/.hgtags	Wed Jul 05 17:24:13 2017 +0200
@@ -87,3 +87,4 @@
 d422dbdd09766269344b796b3a46a5b3f74557e1 jdk7-b110
 8106c747067c905d814a737a57fea0e29057b33f jdk7-b111
 1b05254242881527b4d5d711295c0fe708c8823a jdk7-b112
+bc0c84ce54c34d3e8b0604b94da0d7c75c26755e jdk7-b113
--- a/jdk/.hgtags	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/.hgtags	Wed Jul 05 17:24:13 2017 +0200
@@ -87,3 +87,4 @@
 176586cd040e4dd17a5ff6e91f72df10d7442453 jdk7-b110
 fb63a2688db807a73e2a3de7d9bab298f1bff0e8 jdk7-b111
 b53f226b1d91473ac54184afa827be07b87e0319 jdk7-b112
+61d3b9fbb26bdef56cfa41b9af5bc312a22cbeb8 jdk7-b113
--- a/jdk/make/Makefile	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/make/Makefile	Wed Jul 05 17:24:13 2017 +0200
@@ -75,7 +75,6 @@
 import_fastdebug  -- copy in the fastdebug components \n\
 import_debug      -- copy in the debug components \n\
 modules           -- build the jdk and jre module images (experimental) \n\
-sccs_get          -- make sure all SCCS files are up-to-date (need SCCS) \n\
 create_links      -- create softlinks in Solaris 32bit build to 64bit dirs \n\
 "
 
@@ -278,21 +277,6 @@
 $(OUTPUTDIR) $(TEMPDIR):
 	$(MKDIR) -p $@
 
-# cleanup everything. If the workspace is not being built by the control
-# workspace, and if it is a Teamware workspace, then see if there are
-# any files which are not under SCCS control.
-clean clobber:: 
-ifndef EXTERNALSANITYCONTROL
-	@if [ -d $(TOPDIR)/Codemgr_wsdata ]; then \
-	  $(ECHO) '\nPerforming workspace scan for remnant files.\n' \
-		'  Any files listed below are not under SCCS control in the workspace\n' \
-		'  and you should review them and possibly remove them manually:' ; \
-	  $(FIND) $(TOPDIR)/make $(TOPDIR)/src -type f | \
-		$(SED) 's+SCCS/[ps]\.++' | $(SORT) | $(UNIQ) -c | $(NAWK) '$$1<2 {print $$2;}' ; \
-	  $(ECHO) 'End of workspace scan.' ; \
-	fi
-endif
-
 # this should be the last rule in this file:
 all::
 	@if [ -r $(WARNING_FILE) ]; then \
@@ -341,16 +325,70 @@
 include $(BUILDDIR)/common/internal/BinaryPlugs.gmk
 
 #
-# Get top level sccs_get rule
+# Test rule
 #
-include $(BUILDDIR)/common/Rules-SCCS.gmk
+
+.NOTPARALLEL: test_run
+
+test:
+	$(MAKE) test_run
+
+test_run: test_clean test_start test_summary
+
+test_start:
+	@$(ECHO) "Tests started at `$(DATE)`"
+
+test_clean:
+	$(RM) $(OUTPUTDIR)/test_failures.txt $(OUTPUTDIR)/test_log.txt
 
+test_summary: $(OUTPUTDIR)/test_failures.txt
+	@$(ECHO) "#################################################"
+	@$(ECHO) "Tests completed at `$(DATE)`"
+	@( $(EGREP) '^TEST STATS:' $(OUTPUTDIR)/test_log.txt \
+          || $(ECHO) "No TEST STATS seen in log" )
+	@$(ECHO) "For complete details see: $(OUTPUTDIR)/test_log.txt"
+	@$(ECHO) "#################################################"
+	@if [ -s $< ] ; then                                           \
+          $(ECHO) "ERROR: Test failure count: `$(CAT) $< | $(WC) -l`"; \
+          $(CAT) $<;                                                   \
+          exit 1;                                                      \
+        else                                                           \
+          $(ECHO) "Success! No failures detected";                     \
+        fi
+
+# Get failure list from log
+$(OUTPUTDIR)/test_failures.txt: $(OUTPUTDIR)/test_log.txt
+	@$(RM) $@
+	@( $(EGREP) '^FAILED:' $< || $(ECHO) "" ) | $(NAWK) 'length>0' > $@
+
+# Get log file of all tests run
+JDK_TO_TEST := $(shell 							\
+  if [ -d "$(ABS_OUTPUTDIR)/j2sdk-image" ] ; then 			\
+    $(ECHO) "$(ABS_OUTPUTDIR)/j2sdk-image"; 				\
+  elif [ -d "$(ABS_OUTPUTDIR)/bin" ] ; then 				\
+    $(ECHO) "$(ABS_OUTPUTDIR)"; 					\
+  elif [ "$(PRODUCT_HOME)" != "" -a -d "$(PRODUCT_HOME)/bin" ] ; then 	\
+    $(ECHO) "$(PRODUCT_HOME)"; 						\
+  fi 									\
+)
+
+TEST_TARGETS=jdk_all
+$(OUTPUTDIR)/test_log.txt:
+	$(RM) $@
+	( $(CD) ../test &&                                              \
+          $(MAKE) NO_STOPPING=- PRODUCT_HOME=$(JDK_TO_TEST) $(TEST_TARGETS) \
+        ) | tee $@
+
+#
 # JPRT rules
+#
+
 include jprt.gmk
 
 #
 # Phonies to avoid accidents.
 #
 .PHONY: all build clean clobber optimized debug fastdebug create_links \
-	import import_product import_fastdebug import_debug
+	import import_product import_fastdebug import_debug \
+	test test_run test_start test_clean test_summary
 
--- a/jdk/make/common/Cscope.gmk	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/make/common/Cscope.gmk	Wed Jul 05 17:24:13 2017 +0200
@@ -76,7 +76,7 @@
 # What files should we include?  A simple rule might be just those files under
 # SCM control, however this would miss files we create like the opcodes and
 # CClassHeaders.  The following attempts to find everything that is *useful*.
-# (.del files are created by sccsrm, demo directories contain many .java files
+# (demo directories contain many .java files
 # that probably aren't useful for development, and the pkgarchive may contain
 # duplicates of files within the source hierarchy).  The ordering of the .raw
 # file is an attempt to make cscope display the most relevant files first.
--- a/jdk/make/common/Defs.gmk	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/make/common/Defs.gmk	Wed Jul 05 17:24:13 2017 +0200
@@ -334,7 +334,7 @@
 DOCSDIRSUFFIX       =
 
 # The MESSAGE, WARNING and ERROR files are used to store sanityck and 
-# SCCS check messages, warnings and errors. 
+# warnings and errors. 
 ifndef ERROR_FILE
   ERROR_FILE   = $(OUTPUTDIR)/sanityCheckErrors.txt
 endif
@@ -634,38 +634,6 @@
 
 VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
 
-# Note: As a rule, GNU Make rules should not appear in any of the 
-# Defs*.gmk files. These were added for Kestrel-Solaris and do address
-# a TeamWare bug. They should be moved elsewhere for Merlin.
-# 
-#  Override gnumake built-in rules which do sccs get operations badly.
-#  (They put the checked out code in the current directory, not in the
-#  directory of the original file.) 
-# Since this is a symptom of a teamware failure, complain and die on the spot.
-
-# This message immediately goes to stdout and the build terminates.
-define SCCS-trouble
-$(error  \
-"ERROR: File $@ referenced while building in $(CURRENT_DIRECTORY) \
- is out of date with respect to its SCCS file $<. \
- This can happen from an unresolved Teamware conflict, a file movement, or \
- a failure in which SCCS files are updated but the 'sccs get' was not done. \
- You should double check for other out of date files in your workspace. \
- Or run: cd $(TOPDIR) && $(MAKE) sccs_get")
-endef
-
-%:: s.%
-	@$(SCCS-trouble)
-%:: SCCS/s.%
-	@$(SCCS-trouble)
-	@$(ECHO) "         is out of date with respect to its SCCS file." >> $(WARNING_FILE)
-	@$(ECHO) "         This file may be from an unresolved Teamware conflict." >> $(WARNING_FILE)
-	@$(ECHO) "         This is also a symptom of a Teamware bringover/putback failure" >> $(WARNING_FILE)
-	@$(ECHO) "         in which SCCS files are updated but not checked out." >> $(WARNING_FILE)
-	@$(ECHO) "         Check for other out of date files in your workspace." >> $(WARNING_FILE)
-	@$(ECHO) "" >> $(WARNING_FILE)
-	@#exit 666
-
 ifdef INSANE
   export INSANE
 endif
--- a/jdk/make/common/Rules-SCCS.gmk	Thu Oct 07 15:12:12 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +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.  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.
-#
-
-#
-# Only get these rules if SCCS is available
-#
-
-ifdef SCCS
-
-# SCCS command to extract out latest source
-SCCS_GET=$(SCCS) get -s
-
-#
-# Make sure all files in workspace are fresh
-#
-TEMP_ALL_FILES=$(JDK_TOPDIR)/temp_filelist
-$(TEMP_ALL_FILES): $(JDK_TOPDIR)/Codemgr_wsdata/nametable
-	$(prep-target)
-	@$(CUT) -d' ' -f1 $< \
-	    | $(GREP) -v '^VERSION' \
-	    | $(GREP) -v '^deleted_files' \
-	    | $(GREP) -v '^Codemgr_wsdata' > $@
-
-sccs_get: $(TEMP_ALL_FILES)
-	@$(PRINTF) "Workspace has %d files\n"  `$(CAT) $< | $(WC) -l`
-	@count=0; \
-	for i in `$(CAT) $<` ; do \
-	    f=$(JDK_TOPDIR)/$$i; \
-	    count=`$(EXPR) $$count '+' 1`; \
-	    if [ `$(EXPR) $$count '%' 100` = 0 ] ; then \
-		$(PRINTF) "\rChecked $$count files"; \
-	    fi; \
-	    if [ ! -f $$f ] ; then \
-		$(PRINTF) "\r$(SCCS_GET) $$f\n"; \
-		(cd `$(DIRNAME) $$f` && $(SCCS_GET) `$(BASENAME) $$f`); \
-	    elif /usr/bin/test $$f -ot `$(DIRNAME) $$f`/SCCS/s.`$(BASENAME) $$f` ; then \
-		$(PRINTF) "\r$(SCCS_GET) $$f\n"; \
-		(cd `$(DIRNAME) $$f` && $(SCCS_GET) `$(BASENAME) $$f`); \
-	    fi; \
-	done; \
-	$(PRINTF) "\rChecked $$count files\n"
-
-#
-# Phonies to avoid accidents.
-#
-.PHONY: sccs_get
-
-endif
--- a/jdk/make/common/shared/Defs-utils.gmk	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/make/common/shared/Defs-utils.gmk	Wed Jul 05 17:24:13 2017 +0200
@@ -33,7 +33,7 @@
 #            UTILS_COMMAND_PATH
 #         /usr/bin/ 
 #            UTILS_USR_BIN_PATH
-#         /usr/ccs/bin/ (sccs, m4, lex, yacc, as, ar, strip, mcs)
+#         /usr/ccs/bin/ (m4, lex, yacc, as, ar, strip, mcs)
 #            UTILS_CCS_BIN_PATH
 #         Dev Tools: zip, unzip, etc that we may have special versions of
 #            UTILS_DEVTOOL_PATH
@@ -117,7 +117,6 @@
 RMDIR          = $(UTILS_COMMAND_PATH)rmdir
 RPM            = $(UTILS_COMMAND_PATH)rpm
 RPMBUILD       = $(UTILS_COMMAND_PATH)rpmbuild
-SCCS           = $(UTILS_CCS_BIN_PATH)sccs
 SED            = $(UTILS_COMMAND_PATH)sed
 SH             = $(UTILS_COMMAND_PATH)sh
 SHOWREV        = $(UTILS_USR_BIN_PATH)showrev
@@ -183,7 +182,7 @@
   NAWK           = $(USRBIN_PATH)gawk
   # Intrinsic unix command, with backslash-escaped character interpretation
   ECHO           = /bin/echo -e
-  # These are really in UTILS_USR_BIN_PATH on Linux (only sccs is not)
+  # These are really in UTILS_USR_BIN_PATH on Linux
   AR             = $(UTILS_USR_BIN_PATH)ar
   AS             = $(UTILS_USR_BIN_PATH)as
   LD             = $(UTILS_USR_BIN_PATH)ld
--- a/jdk/make/common/shared/Defs.gmk	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/make/common/shared/Defs.gmk	Wed Jul 05 17:24:13 2017 +0200
@@ -219,7 +219,7 @@
   PRODUCT_NAME = Java(TM)
   PRODUCT_SUFFIX = SE Runtime Environment
   JDK_RC_PLATFORM_NAME = Platform SE
-  COMPANY_NAME = Oracle
+  COMPANY_NAME = Oracle Corporation
 endif
 
 RUNTIME_NAME = $(PRODUCT_NAME) $(PRODUCT_SUFFIX)
--- a/jdk/make/java/java/FILES_java.gmk	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/make/java/java/FILES_java.gmk	Wed Jul 05 17:24:13 2017 +0200
@@ -284,6 +284,7 @@
     java/util/concurrent/CancellationException.java \
     java/util/concurrent/CompletionService.java \
     java/util/concurrent/ConcurrentHashMap.java \
+    java/util/concurrent/ConcurrentLinkedDeque.java \
     java/util/concurrent/ConcurrentLinkedQueue.java \
     java/util/concurrent/ConcurrentMap.java \
     java/util/concurrent/ConcurrentNavigableMap.java \
--- a/jdk/make/jprt.properties	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/make/jprt.properties	Wed Jul 05 17:24:13 2017 +0200
@@ -25,43 +25,265 @@
 
 # Properties for jprt
 
-# Use whatever release that the submitted job requests
+# At submit time, the release supplied will be in jprt.submit.release
+#    and will be one of the official release names defined in jprt.
+#    jprt supports property value expansion using ${property.name} syntax.
+
+# This tells jprt what default release we want to build
 jprt.tools.default.release=${jprt.submit.release}
 
 # The different build flavors we want, we override here so we just get these 2
 jprt.build.flavors=product,fastdebug
 
-# Standard test target for everybody
-jprt.test.targets=*-*-*-jvm98
+# Define the Windows we want (temporary)
+jprt.my.windows.i586.jdk7b107=windows_i586_5.0
+jprt.my.windows.i586.jdk7temp=windows_i586_5.0
+jprt.my.windows.i586.jdk7=windows_i586_5.1
+jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}}
+
+# Standard list of jprt build targets for this source tree
+jprt.build.targets= 						\
+    solaris_sparc_5.10-{product|fastdebug}, 			\
+    solaris_sparcv9_5.10-{product|fastdebug}, 			\
+    solaris_i586_5.10-{product|fastdebug}, 			\
+    solaris_x64_5.10-{product|fastdebug}, 			\
+    linux_i586_2.6-{product|fastdebug}, 			\
+    linux_x64_2.6-{product|fastdebug}, 				\
+    ${jprt.my.windows.i586}-{product|fastdebug}, 		\
+    windows_x64_5.2-{product|fastdebug}
+
+# Standard vm test target
+jprt.test.targets=						\
+    solaris_sparc_5.10-product-c1-jvm98, 			\
+    solaris_sparcv9_5.10-product-c2-jvm98, 			\
+    solaris_i586_5.10-product-c1-jvm98, 			\
+    solaris_x64_5.10-product-c2-jvm98, 				\
+    linux_i586_2.6-product-{c1|c2}-jvm98, 			\
+    linux_x64_2.6-product-c2-jvm98, 				\
+    ${jprt.my.windows.i586}-product-c1-jvm98, 			\
+    windows_x64_5.2-product-c2-jvm98
+
+# User can select the test set with jprt submit "-testset name" option
+jprt.my.test.set=${jprt.test.set}
 
-# Test targets in test/Makefile (some longer running tests only test c2)
-jprt.make.rule.test.targets=    \
-   *-product-*-jdk_beans1,      \
-   *-product-*-jdk_beans2,      \
-   *-product-*-jdk_beans3,      \
-   *-product-*-jdk_io,          \
-   *-product-*-jdk_lang,        \
-   *-product-*-jdk_management1, \
-   *-product-*-jdk_management2, \
-   *-product-*-jdk_math,        \
-   *-product-*-jdk_misc,        \
-   *-product-*-jdk_net,         \
-   *-product-*-jdk_nio1,        \
-   *-product-*-jdk_nio2,        \
-   *-product-*-jdk_nio3,        \
-   *-product-*-jdk_security1,   \
-   *-product-*-jdk_security2,   \
-   *-product-*-jdk_security3,   \
-   *-product-*-jdk_text,        \
-   *-product-*-jdk_tools1,      \
-   *-product-*-jdk_tools2,      \
-   *-product-*-jdk_util
+# Default jdk test targets in test/Makefile (no fastdebug & limited c2)
+jprt.make.rule.default.test.targets=				\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_beans1, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_beans1, 		\
+    solaris_i586_5.10-product-c1-jdk_beans1, 			\
+    solaris_x64_5.10-product-c2-jdk_beans1, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_beans1, 			\
+    linux_x64_2.6-product-c2-jdk_beans1, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_beans1, 		\
+    windows_x64_5.2-product-c2-jdk_beans1, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_io, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_io, 			\
+    solaris_i586_5.10-product-c1-jdk_io, 			\
+    solaris_x64_5.10-product-c2-jdk_io, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_io, 			\
+    linux_x64_2.6-product-c2-jdk_io, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_io, 			\
+    windows_x64_5.2-product-c2-jdk_io, 				\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_lang, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_lang, 			\
+    solaris_i586_5.10-product-c1-jdk_lang, 			\
+    solaris_x64_5.10-product-c2-jdk_lang, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_lang, 			\
+    linux_x64_2.6-product-c2-jdk_lang, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_lang, 		\
+    windows_x64_5.2-product-c2-jdk_lang, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_math, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_math, 			\
+    solaris_i586_5.10-product-c1-jdk_math, 			\
+    solaris_x64_5.10-product-c2-jdk_math, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_math, 			\
+    linux_x64_2.6-product-c2-jdk_math, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_math, 		\
+    windows_x64_5.2-product-c2-jdk_math, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_misc, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_misc, 			\
+    solaris_i586_5.10-product-c1-jdk_misc, 			\
+    solaris_x64_5.10-product-c2-jdk_misc, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_misc, 			\
+    linux_x64_2.6-product-c2-jdk_misc, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_misc, 		\
+    windows_x64_5.2-product-c2-jdk_misc, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_net, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_net, 			\
+    solaris_i586_5.10-product-c1-jdk_net, 			\
+    solaris_x64_5.10-product-c2-jdk_net, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_net, 			\
+    linux_x64_2.6-product-c2-jdk_net, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_net, 		\
+    windows_x64_5.2-product-c2-jdk_net, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_nio1, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_nio1, 			\
+    solaris_i586_5.10-product-c1-jdk_nio1, 			\
+    solaris_x64_5.10-product-c2-jdk_nio1, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_nio1, 			\
+    linux_x64_2.6-product-c2-jdk_nio1, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_nio1, 		\
+    windows_x64_5.2-product-c2-jdk_nio1, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_nio2, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_nio2, 			\
+    solaris_i586_5.10-product-c1-jdk_nio2, 			\
+    solaris_x64_5.10-product-c2-jdk_nio2, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_nio2, 			\
+    linux_x64_2.6-product-c2-jdk_nio2, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_nio2, 		\
+    windows_x64_5.2-product-c2-jdk_nio2, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_nio3, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_nio3, 			\
+    solaris_i586_5.10-product-c1-jdk_nio3, 			\
+    solaris_x64_5.10-product-c2-jdk_nio3, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_nio3, 			\
+    linux_x64_2.6-product-c2-jdk_nio3, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_nio3, 		\
+    windows_x64_5.2-product-c2-jdk_nio3, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_security1, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_security1, 		\
+    solaris_i586_5.10-product-c1-jdk_security1, 		\
+    solaris_x64_5.10-product-c2-jdk_security1, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_security1, 		\
+    linux_x64_2.6-product-c2-jdk_security1, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_security1, 		\
+    windows_x64_5.2-product-c2-jdk_security1, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_text, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_text, 			\
+    solaris_i586_5.10-product-c1-jdk_text, 			\
+    solaris_x64_5.10-product-c2-jdk_text, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_text, 			\
+    linux_x64_2.6-product-c2-jdk_text, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_text, 		\
+    windows_x64_5.2-product-c2-jdk_text, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_tools1, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_tools1, 		\
+    solaris_i586_5.10-product-c1-jdk_tools1, 			\
+    solaris_x64_5.10-product-c2-jdk_tools1, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_tools1, 			\
+    linux_x64_2.6-product-c2-jdk_tools1, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_tools1, 		\
+    windows_x64_5.2-product-c2-jdk_tools1, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_util, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_util, 			\
+    solaris_i586_5.10-product-c1-jdk_util, 			\
+    solaris_x64_5.10-product-c2-jdk_util, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_util, 			\
+    linux_x64_2.6-product-c2-jdk_util, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_util, 		\
+    windows_x64_5.2-product-c2-jdk_util
 
-# Some of these are crashing Xvfb or windows manager, need dedicated DISPLAY per test batch
-jprt2.make.rule.test.targets=    \
-   *-product-*-jdk_awt,         \
-   *-product-*-jdk_rmi,         \
-   *-product-*-jdk_swing,       \
+# All jdk test targets in test/Makefile (still no fastdebug & limited c2)
+jprt.make.rule.all.test.targets=    				\
+    								\
+   ${jprt.make.rule.default.test.targets}, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_awt, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_awt, 			\
+    solaris_i586_5.10-product-c1-jdk_awt, 			\
+    solaris_x64_5.10-product-c2-jdk_awt, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_awt, 			\
+    linux_x64_2.6-product-c2-jdk_awt, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_awt, 		\
+    windows_x64_5.2-product-c2-jdk_awt, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_beans2, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_beans2, 		\
+    solaris_i586_5.10-product-c1-jdk_beans2, 			\
+    solaris_x64_5.10-product-c2-jdk_beans2, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_beans2, 			\
+    linux_x64_2.6-product-c2-jdk_beans2, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_beans2, 		\
+    windows_x64_5.2-product-c2-jdk_beans2, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_beans3, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_beans3, 		\
+    solaris_i586_5.10-product-c1-jdk_beans3, 			\
+    solaris_x64_5.10-product-c2-jdk_beans3, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_beans3, 			\
+    linux_x64_2.6-product-c2-jdk_beans3, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_beans3, 		\
+    windows_x64_5.2-product-c2-jdk_beans3, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_management1, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_management1, 		\
+    solaris_i586_5.10-product-c1-jdk_management1, 		\
+    solaris_x64_5.10-product-c2-jdk_management1, 		\
+    linux_i586_2.6-product-{c1|c2}-jdk_management1, 		\
+    linux_x64_2.6-product-c2-jdk_management1, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_management1, 	\
+    windows_x64_5.2-product-c2-jdk_management1, 		\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_management2, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_management2, 		\
+    solaris_i586_5.10-product-c1-jdk_management2, 		\
+    solaris_x64_5.10-product-c2-jdk_management2, 		\
+    linux_i586_2.6-product-{c1|c2}-jdk_management2, 		\
+    linux_x64_2.6-product-c2-jdk_management2, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_management2, 	\
+    windows_x64_5.2-product-c2-jdk_management2, 		\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_rmi, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_rmi, 			\
+    solaris_i586_5.10-product-c1-jdk_rmi, 			\
+    solaris_x64_5.10-product-c2-jdk_rmi, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_rmi, 			\
+    linux_x64_2.6-product-c2-jdk_rmi, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_rmi, 		\
+    windows_x64_5.2-product-c2-jdk_rmi, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_security2, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_security2, 		\
+    solaris_i586_5.10-product-c1-jdk_security2, 		\
+    solaris_x64_5.10-product-c2-jdk_security2, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_security2, 		\
+    linux_x64_2.6-product-c2-jdk_security2, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_security2, 		\
+    windows_x64_5.2-product-c2-jdk_security2, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_security3, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_security3, 		\
+    solaris_i586_5.10-product-c1-jdk_security3, 		\
+    solaris_x64_5.10-product-c2-jdk_security3, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_security3, 		\
+    linux_x64_2.6-product-c2-jdk_security3, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_security3, 		\
+    windows_x64_5.2-product-c2-jdk_security3, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_swing, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_swing, 			\
+    solaris_i586_5.10-product-c1-jdk_swing, 			\
+    solaris_x64_5.10-product-c2-jdk_swing, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_swing, 			\
+    linux_x64_2.6-product-c2-jdk_swing, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_swing, 		\
+    windows_x64_5.2-product-c2-jdk_swing, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_tools2, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_tools2, 		\
+    solaris_i586_5.10-product-c1-jdk_tools2, 			\
+    solaris_x64_5.10-product-c2-jdk_tools2, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_tools2, 			\
+    linux_x64_2.6-product-c2-jdk_tools2, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_tools2, 		\
+    windows_x64_5.2-product-c2-jdk_tools2
+
+# Select list to use (allow for testset to be empty too)
+jprt.make.rule..test.targets=${jprt.make.rule.default.test.targets} 
+jprt.make.rule.test.targets=${jprt.make.rule.${jprt.my.test.set}.test.targets} 
 
 # Directories to be excluded from the source bundles
 jprt.bundle.exclude.src.dirs=build dist webrev
--- a/jdk/make/mkdemo/Makefile	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/make/mkdemo/Makefile	Wed Jul 05 17:24:13 2017 +0200
@@ -31,7 +31,7 @@
 PRODUCT = demos
 include $(BUILDDIR)/common/Defs.gmk
 
-SUBDIRS            = jni
+SUBDIRS            = jni nio
 SUBDIRS_desktop    = applets jfc
 SUBDIRS_management = management
 SUBDIRS_misc       = scripting
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/mkdemo/nio/Makefile	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  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.
+#
+
+#
+# Makefile for building the jfc demos
+#
+
+BUILDDIR = ../..
+PRODUCT = demos
+include $(BUILDDIR)/common/Defs.gmk
+
+SUBDIRS = zipfs
+include $(BUILDDIR)/common/Subdirs.gmk
+
+all build clean clobber::
+	$(SUBDIRS-loop)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/mkdemo/nio/zipfs/Makefile	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute 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.
+#
+
+#
+# Makefile to build the ZipFileSystem demo.
+#
+
+BUILDDIR = ../../..
+PRODUCT = demo/zipfs
+DEMONAME = zipfs
+include $(BUILDDIR)/common/Defs.gmk
+
+DEMO_ROOT       = $(SHARE_SRC)/demo/nio/$(DEMONAME)
+DEMO_TOPFILES   = ./README.txt
+DEMO_SRCDIR     = $(DEMO_ROOT)
+DEMO_DESTDIR    = $(DEMODIR)/nio/$(DEMONAME)
+
+#
+# Demo jar building rules.
+#
+include $(BUILDDIR)/common/Demo.gmk
+
--- a/jdk/make/sun/cmm/lcms/Makefile	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/make/sun/cmm/lcms/Makefile	Wed Jul 05 17:24:13 2017 +0200
@@ -80,7 +80,12 @@
 vpath %.c   $(SHARE_SRC)/native/sun/java2d
 
 ifeq ($(PLATFORM), windows)
-OTHER_CFLAGS += -DCMS_IS_WINDOWS_ -Dsqrtf=sqrt
+OTHER_CFLAGS += -DCMS_IS_WINDOWS_
+
+ifeq ($(COMPILER_VERSION), VS2003)
+OTHER_CFLAGS += -Dsqrtf=sqrt
+endif
+
 OTHER_LDLIBS = $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib
 OTHER_INCLUDES += -I$(SHARE_SRC)/native/sun/java2d \
                   -I$(SHARE_SRC)/native/sun/awt/debug
--- a/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Wed Jul 05 17:24:13 2017 +0200
@@ -525,7 +525,7 @@
 
         iMatchColumns = new Vector(10);
         for(int i = 0; i < 10 ; i++) {
-           iMatchColumns.add(i,new Integer(-1));
+           iMatchColumns.add(i,Integer.valueOf(-1));
         }
 
         strMatchColumns = new Vector(10);
@@ -889,7 +889,12 @@
                     success = false;
                 } else {
                     tWriter = (TransactionalWriter)rowSetWriter;
-                    ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert);
+                    if (tWriter instanceof CachedRowSetWriter) {
+                        ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert);
+                    } else {
+                        tWriter.commit();
+                    }
+
                     success = true;
                 }
             }
@@ -1294,7 +1299,7 @@
         tMap = new TreeMap();
 
         for (int i = 0; i<numRows; i++) {
-            tMap.put(new Integer(i), rvh.get(i));
+            tMap.put(Integer.valueOf(i), rvh.get(i));
         }
 
         return (tMap.values());
@@ -1806,7 +1811,7 @@
             return (byte)0;
         }
         try {
-            return ((new Byte(value.toString())).byteValue());
+            return ((Byte.valueOf(value.toString())).byteValue());
         } catch (NumberFormatException ex) {
             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.bytefail").toString(),
                   new Object[] {value.toString().trim(), columnIndex}));
@@ -1850,7 +1855,7 @@
         }
 
         try {
-            return ((new Short(value.toString().trim())).shortValue());
+            return ((Short.valueOf(value.toString().trim())).shortValue());
         } catch (NumberFormatException ex) {
             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.shortfail").toString(),
                   new Object[] {value.toString().trim(), columnIndex}));
@@ -1893,7 +1898,7 @@
         }
 
         try {
-            return ((new Integer(value.toString().trim())).intValue());
+            return ((Integer.valueOf(value.toString().trim())).intValue());
         } catch (NumberFormatException ex) {
             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.intfail").toString(),
                   new Object[] {value.toString().trim(), columnIndex}));
@@ -1936,7 +1941,7 @@
             return (long)0;
         }
         try {
-            return ((new Long(value.toString().trim())).longValue());
+            return ((Long.valueOf(value.toString().trim())).longValue());
         } catch (NumberFormatException ex) {
             throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.longfail").toString(),
                   new Object[] {value.toString().trim(), columnIndex}));
@@ -4014,18 +4019,18 @@
         try {
             switch (trgType) {
                 case java.sql.Types.BIT:
-                    Integer i = new Integer(srcObj.toString().trim());
-                    return i.equals(new Integer((int)0)) ?
-                    new Boolean(false) :
-                        new Boolean(true);
+                    Integer i = Integer.valueOf(srcObj.toString().trim());
+                    return i.equals(Integer.valueOf((int)0)) ?
+                    Boolean.valueOf(false) :
+                        Boolean.valueOf(true);
                 case java.sql.Types.TINYINT:
-                    return new Byte(srcObj.toString().trim());
+                    return Byte.valueOf(srcObj.toString().trim());
                 case java.sql.Types.SMALLINT:
-                    return new Short(srcObj.toString().trim());
+                    return Short.valueOf(srcObj.toString().trim());
                 case java.sql.Types.INTEGER:
-                    return new Integer(srcObj.toString().trim());
+                    return Integer.valueOf(srcObj.toString().trim());
                 case java.sql.Types.BIGINT:
-                    return new Long(srcObj.toString().trim());
+                    return Long.valueOf(srcObj.toString().trim());
                 case java.sql.Types.NUMERIC:
                 case java.sql.Types.DECIMAL:
                     return new BigDecimal(srcObj.toString().trim());
@@ -4037,7 +4042,7 @@
                 case java.sql.Types.CHAR:
                 case java.sql.Types.VARCHAR:
                 case java.sql.Types.LONGVARCHAR:
-                    return new String(srcObj.toString());
+                    return srcObj.toString();
                 default:
                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
             }
@@ -4134,7 +4139,7 @@
                 case java.sql.Types.CHAR:
                 case java.sql.Types.VARCHAR:
                 case java.sql.Types.LONGVARCHAR:
-                    return new String(srcObj.toString());
+                    return srcObj.toString();
                 default:
                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString());
             }
@@ -4181,12 +4186,12 @@
         try {
             switch (trgType) {
                 case java.sql.Types.BIT:
-                    Integer i = new Integer(srcObj.toString().trim());
-                    return i.equals(new Integer((int)0)) ?
-                    new Boolean(false) :
-                        new Boolean(true);
+                    Integer i = Integer.valueOf(srcObj.toString().trim());
+                    return i.equals(Integer.valueOf((int)0)) ?
+                    Boolean.valueOf(false) :
+                        Boolean.valueOf(true);
                 case java.sql.Types.BOOLEAN:
-                    return new Boolean(srcObj.toString().trim());
+                    return Boolean.valueOf(srcObj.toString().trim());
                 default:
                     throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()+ trgType);
             }
@@ -4260,7 +4265,7 @@
         checkIndex(columnIndex);
         // make sure the cursor is on a valid row
         checkCursor();
-        Object obj = convertBoolean(new Boolean(x),
+        Object obj = convertBoolean(Boolean.valueOf(x),
         java.sql.Types.BIT,
         RowSetMD.getColumnType(columnIndex));
 
@@ -4296,7 +4301,7 @@
         // make sure the cursor is on a valid row
         checkCursor();
 
-        Object obj = convertNumeric(new Byte(x),
+        Object obj = convertNumeric(Byte.valueOf(x),
         java.sql.Types.TINYINT,
         RowSetMD.getColumnType(columnIndex));
 
@@ -4332,7 +4337,7 @@
         // make sure the cursor is on a valid row
         checkCursor();
 
-        Object obj = convertNumeric(new Short(x),
+        Object obj = convertNumeric(Short.valueOf(x),
         java.sql.Types.SMALLINT,
         RowSetMD.getColumnType(columnIndex));
 
@@ -4367,7 +4372,7 @@
         checkIndex(columnIndex);
         // make sure the cursor is on a valid row
         checkCursor();
-        Object obj = convertNumeric(new Integer(x),
+        Object obj = convertNumeric(Integer.valueOf(x),
         java.sql.Types.INTEGER,
         RowSetMD.getColumnType(columnIndex));
 
@@ -4403,7 +4408,7 @@
         // make sure the cursor is on a valid row
         checkCursor();
 
-        Object obj = convertNumeric(new Long(x),
+        Object obj = convertNumeric(Long.valueOf(x),
         java.sql.Types.BIGINT,
         RowSetMD.getColumnType(columnIndex));
 
@@ -6429,7 +6434,7 @@
         if (tabName == null)
             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.tablename").toString());
         else
-            tableName = new String(tabName);
+            tableName = tabName;
     }
 
     /**
@@ -6940,7 +6945,7 @@
          }
 
          for( int i = 0;i < columnIdxes.length ;i++) {
-            iMatchColumns.set(i,new Integer(-1));
+            iMatchColumns.set(i,Integer.valueOf(-1));
          }
     }
 
@@ -7049,7 +7054,7 @@
            }
         }
         for(int i = 0 ;i < columnIdxes.length; i++) {
-           iMatchColumns.add(i,new Integer(columnIdxes[i]));
+           iMatchColumns.add(i,Integer.valueOf(columnIdxes[i]));
         }
     }
 
@@ -7104,7 +7109,7 @@
             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols1").toString());
         } else {
             // set iMatchColumn
-            iMatchColumns.set(0, new Integer(columnIdx));
+            iMatchColumns.set(0, Integer.valueOf(columnIdx));
             //strMatchColumn = null;
         }
     }
@@ -7126,7 +7131,7 @@
      */
     public void setMatchColumn(String columnName) throws SQLException {
         // validate, if col is ok to be set
-        if(columnName.equals(null) || ((columnName = columnName.trim()) == "" )) {
+        if(columnName == null || (columnName= columnName.trim()).equals("") ) {
             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString());
         } else {
             // set strMatchColumn
@@ -7151,13 +7156,13 @@
      */
     public void unsetMatchColumn(int columnIdx) throws SQLException {
         // check if we are unsetting the SAME column
-        if(! iMatchColumns.get(0).equals(new Integer(columnIdx) )  ) {
+        if(! iMatchColumns.get(0).equals(Integer.valueOf(columnIdx) )  ) {
             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch").toString());
         } else if(strMatchColumns.get(0) != null) {
             throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unsetmatch1").toString());
         } else {
                 // that is, we are unsetting it.
-               iMatchColumns.set(0, new Integer(-1));
+               iMatchColumns.set(0, Integer.valueOf(-1));
         }
     }
 
--- a/jdk/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java	Wed Jul 05 17:24:13 2017 +0200
@@ -499,7 +499,7 @@
 
      if(onInsertRow) {
         if(p != null) {
-           bool = p.evaluate(new Integer(x),columnIndex);
+           bool = p.evaluate(Integer.valueOf(x),columnIndex);
 
            if(!bool) {
               throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
@@ -566,7 +566,7 @@
 
       if(onInsertRow) {
          if(p != null) {
-            bool = p.evaluate(new Boolean(x) , columnIndex);
+            bool = p.evaluate(Boolean.valueOf(x) , columnIndex);
 
             if(!bool) {
                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
@@ -634,7 +634,7 @@
 
       if(onInsertRow) {
          if(p != null) {
-            bool = p.evaluate(new Byte(x),columnIndex);
+            bool = p.evaluate(Byte.valueOf(x),columnIndex);
 
             if(!bool) {
                 throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
@@ -703,7 +703,7 @@
 
       if(onInsertRow) {
          if(p != null) {
-            bool = p.evaluate(new Short(x), columnIndex);
+            bool = p.evaluate(Short.valueOf(x), columnIndex);
 
             if(!bool) {
                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
@@ -771,7 +771,7 @@
 
       if(onInsertRow) {
          if(p != null) {
-            bool = p.evaluate(new Long(x), columnIndex);
+            bool = p.evaluate(Long.valueOf(x), columnIndex);
 
             if(!bool) {
                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
@@ -1106,12 +1106,12 @@
    public void updateBytes(int columnIndex , byte []x) throws SQLException {
 
       boolean bool;
-      String val = new String();
+      String val = "";
 
       Byte [] obj_arr = new Byte[x.length];
 
       for(int i = 0; i < x.length; i++) {
-         obj_arr[i] = new Byte(x[i]);
+         obj_arr[i] = Byte.valueOf(x[i]);
          val = val.concat(obj_arr[i].toString());
      }
 
--- a/jdk/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Wed Jul 05 17:24:13 2017 +0200
@@ -215,7 +215,7 @@
 
         iMatchColumns = new Vector(10);
         for(int i = 0; i < 10 ; i++) {
-           iMatchColumns.add(i,new Integer(-1));
+           iMatchColumns.add(i,Integer.valueOf(-1));
         }
 
         strMatchColumns = new Vector(10);
@@ -288,7 +288,7 @@
 
         iMatchColumns = new Vector(10);
         for(int i = 0; i < 10 ; i++) {
-           iMatchColumns.add(i,new Integer(-1));
+           iMatchColumns.add(i,Integer.valueOf(-1));
         }
 
         strMatchColumns = new Vector(10);
@@ -375,7 +375,7 @@
 
         iMatchColumns = new Vector(10);
         for(int i = 0; i < 10 ; i++) {
-           iMatchColumns.add(i,new Integer(-1));
+           iMatchColumns.add(i,Integer.valueOf(-1));
         }
 
         strMatchColumns = new Vector(10);
@@ -465,7 +465,7 @@
 
         iMatchColumns = new Vector(10);
         for(int i = 0; i < 10 ; i++) {
-           iMatchColumns.add(i,new Integer(-1));
+           iMatchColumns.add(i,Integer.valueOf(-1));
         }
 
         strMatchColumns = new Vector(10);
@@ -3754,7 +3754,7 @@
          }
 
          for( int i = 0;i < columnIdxes.length ;i++) {
-            iMatchColumns.set(i,new Integer(-1));
+            iMatchColumns.set(i,Integer.valueOf(-1));
          }
     }
 
@@ -3863,7 +3863,7 @@
            }
         }
         for(int i = 0 ;i < columnIdxes.length; i++) {
-           iMatchColumns.add(i,new Integer(columnIdxes[i]));
+           iMatchColumns.add(i,Integer.valueOf(columnIdxes[i]));
         }
     }
 
@@ -3918,7 +3918,7 @@
             throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols1").toString());
         } else {
             // set iMatchColumn
-            iMatchColumns.set(0, new Integer(columnIdx));
+            iMatchColumns.set(0, Integer.valueOf(columnIdx));
             //strMatchColumn = null;
         }
     }
@@ -3940,7 +3940,7 @@
      */
     public void setMatchColumn(String columnName) throws SQLException {
         // validate, if col is ok to be set
-        if(columnName.equals(null) || ((columnName = columnName.trim()) == "" )) {
+        if(columnName == null || (columnName= columnName.trim()).equals("")) {
             throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString());
         } else {
             // set strMatchColumn
@@ -3965,13 +3965,13 @@
      */
     public void unsetMatchColumn(int columnIdx) throws SQLException {
         // check if we are unsetting the SAME column
-        if(! iMatchColumns.get(0).equals(new Integer(columnIdx) )  ) {
+        if(! iMatchColumns.get(0).equals(Integer.valueOf(columnIdx) )  ) {
             throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.unsetmatch").toString());
         } else if(strMatchColumns.get(0) != null) {
             throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.usecolname").toString());
         } else {
                 // that is, we are unsetting it.
-               iMatchColumns.set(0, new Integer(-1));
+               iMatchColumns.set(0, Integer.valueOf(-1));
         }
     }
 
--- a/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Wed Jul 05 17:24:13 2017 +0200
@@ -33,6 +33,8 @@
 import java.util.*;
 
 import javax.sql.rowset.*;
+import javax.sql.rowset.spi.SyncProvider;
+import javax.sql.rowset.spi.SyncProviderException;
 
 /**
  * The standard implementation of the <code>JoinRowSet</code>
@@ -550,7 +552,7 @@
                // This 'if' will be removed after all joins are implemented.
                throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.notsupported").toString());
            } else {
-              Integer Intgr = new Integer(JoinRowSet.INNER_JOIN);
+              Integer Intgr = Integer.valueOf(JoinRowSet.INNER_JOIN);
               vecJoinType.add(Intgr);
            }
        } else {
@@ -874,8 +876,8 @@
 
        String strWhereClause = "Select ";
        String whereClause;
-       String tabName= null;
-       String strTabName = null;
+       String tabName= "";
+       String strTabName = "";
        int sz,cols;
        int j;
        CachedRowSetImpl crs;
@@ -889,8 +891,6 @@
        // tableNameX.(rowsetX.getMatchColumnName()) ==
        // tableNameZ.(rowsetZ.getMatchColumnName()));
 
-       tabName = new String();
-       strTabName  = new String();
        sz = vecRowSetsInJOIN.size();
        for(int i=0;i<sz; i++) {
           crs = (CachedRowSetImpl)vecRowSetsInJOIN.get(i);
@@ -4311,6 +4311,27 @@
          return crsInternal.createCopySchema();
      }
 
+     /**
+      * {@inheritDoc}
+      */
+     public void setSyncProvider(String providerStr) throws SQLException {
+         crsInternal.setSyncProvider(providerStr);
+     }
+
+     /**
+      * {@inheritDoc}
+      */
+     public void acceptChanges() throws SyncProviderException {
+         crsInternal.acceptChanges();
+     }
+
+     /**
+      * {@inheritDoc}
+      */
+     public SyncProvider getSyncProvider() throws SQLException {
+        return crsInternal.getSyncProvider();
+     }
+
     /**
      * This method re populates the resBundle
      * during the deserialization process
--- a/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java	Wed Jul 05 17:24:13 2017 +0200
@@ -338,11 +338,11 @@
             if (crs.rowDeleted()) {
                 // The row has been deleted.
                 if (conflict = (deleteOriginalRow(crs, this.crsResolve)) == true) {
-                       status.add(rows, new Integer(SyncResolver.DELETE_ROW_CONFLICT));
+                       status.add(rows, Integer.valueOf(SyncResolver.DELETE_ROW_CONFLICT));
                 } else {
                       // delete happened without any occurrence of conflicts
                       // so update status accordingly
-                       status.add(rows, new Integer(SyncResolver.NO_ROW_CONFLICT));
+                       status.add(rows, Integer.valueOf(SyncResolver.NO_ROW_CONFLICT));
                 }
 
            } else if (crs.rowInserted()) {
@@ -350,20 +350,20 @@
 
                 pstmtIns = con.prepareStatement(insertCmd);
                 if ( (conflict = insertNewRow(crs, pstmtIns, this.crsResolve)) == true) {
-                          status.add(rows, new Integer(SyncResolver.INSERT_ROW_CONFLICT));
+                          status.add(rows, Integer.valueOf(SyncResolver.INSERT_ROW_CONFLICT));
                 } else {
                       // insert happened without any occurrence of conflicts
                       // so update status accordingly
-                       status.add(rows, new Integer(SyncResolver.NO_ROW_CONFLICT));
+                       status.add(rows, Integer.valueOf(SyncResolver.NO_ROW_CONFLICT));
                 }
             } else  if (crs.rowUpdated()) {
                   // The row has been updated.
                        if ( conflict = (updateOriginalRow(crs)) == true) {
-                             status.add(rows, new Integer(SyncResolver.UPDATE_ROW_CONFLICT));
+                             status.add(rows, Integer.valueOf(SyncResolver.UPDATE_ROW_CONFLICT));
                } else {
                       // update happened without any occurrence of conflicts
                       // so update status accordingly
-                      status.add(rows, new Integer(SyncResolver.NO_ROW_CONFLICT));
+                      status.add(rows, Integer.valueOf(SyncResolver.NO_ROW_CONFLICT));
                }
 
             } else {
@@ -375,7 +375,7 @@
                 *  that is fine.
                 **/
                 int icolCount = crs.getMetaData().getColumnCount();
-                status.add(rows, new Integer(SyncResolver.NO_ROW_CONFLICT));
+                status.add(rows, Integer.valueOf(SyncResolver.NO_ROW_CONFLICT));
 
                 this.crsResolve.moveToInsertRow();
                 for(int cols=0;cols<iColCount;cols++) {
@@ -398,7 +398,7 @@
       boolean boolConf = false;
       for (int j=1;j<status.size();j++){
           // ignore status for index = 0 which is set to null
-          if(! ((status.get(j)).equals(new Integer(SyncResolver.NO_ROW_CONFLICT)))) {
+          if(! ((status.get(j)).equals(Integer.valueOf(SyncResolver.NO_ROW_CONFLICT)))) {
               // there is at least one conflict which needs to be resolved
               boolConf = true;
              break;
@@ -541,7 +541,7 @@
                 // how many fields need to be updated
                 int colsNotChanged = 0;
                 Vector cols = new Vector();
-                String updateExec = new String(updateCmd);
+                String updateExec = updateCmd;
                 Object orig;
                 Object curr;
                 Object rsval;
@@ -652,7 +652,7 @@
                           updateExec += ", ";
                          }
                         updateExec += crs.getMetaData().getColumnName(i);
-                        cols.add(new Integer(i));
+                        cols.add(Integer.valueOf(i));
                         updateExec += " = ? ";
                         first = false;
 
@@ -698,7 +698,7 @@
                                     updateExec += ", ";
                                  }
                                 updateExec += crs.getMetaData().getColumnName(i);
-                                cols.add(new Integer(i));
+                                cols.add(Integer.valueOf(i));
                                 updateExec += " = ? ";
                                 flag = false;
                              } else {
@@ -1184,7 +1184,7 @@
        // trim all the leading and trailing whitespaces,
        // white spaces can never be catalog, schema or a table name.
 
-        String cmd = new String();
+        String cmd = "";
 
         catalog = catalog.trim();
         schema = schema.trim();
--- a/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java	Wed Jul 05 17:24:13 2017 +0200
@@ -248,7 +248,7 @@
             String strProvider = strProviderInstance.substring(0, (caller.getSyncProvider()).toString().indexOf("@"));
 
             propString("sync-provider-name", strProvider);
-            propString("sync-provider-vendor", "Sun Microsystems Inc.");
+            propString("sync-provider-vendor", "Oracle Corporation");
             propString("sync-provider-version", "1.0");
             propInteger("sync-provider-grade", caller.getSyncProvider().getProviderGrade());
             propInteger("data-source-lock", caller.getSyncProvider().getDataSourceLock());
@@ -387,7 +387,7 @@
                     if (caller.wasNull())
                         writeNull();
                     else
-                        writeInteger(caller.getInt(idx));
+                        writeInteger(i);
                     break;
                 case java.sql.Types.BIGINT:
                     long l = caller.getLong(idx);
@@ -574,7 +574,7 @@
     }
 
     private void writeBoolean(boolean b) throws java.io.IOException {
-        writer.write(new Boolean(b).toString());
+        writer.write(Boolean.valueOf(b).toString());
     }
 
     private void writeFloat(float f) throws java.io.IOException {
@@ -641,7 +641,7 @@
             return null;
         }
         char []charStr = s.toCharArray();
-        String specialStr = new String();
+        String specialStr = "";
 
         for(int i = 0; i < charStr.length; i++) {
             if(charStr[i] == '&') {
--- a/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java	Wed Jul 05 17:24:13 2017 +0200
@@ -441,9 +441,9 @@
         updates = new Vector();
 
         // start out with the empty string
-        columnValue = new String("");
-        propertyValue = new String("");
-        metaDataValue = new String("");
+        columnValue = "";
+        propertyValue = "";
+        metaDataValue = "";
 
         nullVal = false;
         idx = 0;
@@ -481,21 +481,21 @@
         items = properties.length;
 
         for (i=0;i<items;i++) {
-            propMap.put(properties[i], new Integer(i));
+            propMap.put(properties[i], Integer.valueOf(i));
         }
 
         colDefMap = new HashMap();
         items = colDef.length;
 
         for (i=0;i<items;i++) {
-            colDefMap.put(colDef[i], new Integer(i));
+            colDefMap.put(colDef[i], Integer.valueOf(i));
         }
 
         dataMap = new HashMap();
         items = data.length;
 
         for (i=0;i<items;i++) {
-            dataMap.put(data[i], new Integer(i));
+            dataMap.put(data[i], Integer.valueOf(i));
         }
 
         //Initialize connection map here
@@ -686,7 +686,7 @@
             }
 
             // propertyValue need to be reset to an empty string
-            propertyValue = new String("");
+            propertyValue = "";
             setTag(-1);
             break;
         case METADATA:
@@ -710,7 +710,7 @@
 
                 }
                 // metaDataValue needs to be reset to an empty string
-                metaDataValue = new String("");
+                metaDataValue = "";
             }
             setTag(-1);
             break;
@@ -736,7 +736,7 @@
                         insertValue(tempStr);
                     }
                     // columnValue now need to be reset to the empty string
-                    columnValue = new String("");
+                    columnValue = "";
                 } catch (SQLException ex) {
                     throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errinsert").toString(), ex.getMessage()));
                 }
@@ -981,7 +981,7 @@
 
     private boolean getBooleanValue(String s) {
 
-        return new Boolean(s).booleanValue();
+        return Boolean.valueOf(s).booleanValue();
     }
 
     private java.math.BigDecimal getBigDecimalValue(String s) {
@@ -1316,7 +1316,7 @@
               **/
 
             tempUpdate = tempUpdate.concat(new String(ch,start,len));
-            upd[0] = new Integer(idx);
+            upd[0] = Integer.valueOf(idx);
             upd[1] = tempUpdate;
             //updates.add(upd);
 
--- a/jdk/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java	Wed Jul 05 17:24:13 2017 +0200
@@ -93,14 +93,14 @@
     private CachedRowSetWriter writer;
 
     /**
-     * The unique provider indentifier.
+     * The unique provider identifier.
      */
     private String providerID = "com.sun.rowset.providers.RIOptimisticProvider";
 
     /**
      * The vendor name of this SyncProvider implementation
      */
-    private String vendorName = "Sun Microsystems Inc.";
+    private String vendorName = "Oracle Corporation";
 
     /**
      * The version number of this SyncProvider implementation
@@ -236,8 +236,8 @@
     }
 
     /**
-     * Returns the vendor name of the Reference Implemntation Optimistic
-     * Syncchronication Provider
+     * Returns the vendor name of the Reference Implementation Optimistic
+     * Synchronization Provider
      *
      * @return the <code>String</code> detailing the vendor name of this
      *      SyncProvider
--- a/jdk/src/share/classes/com/sun/rowset/providers/RIXMLProvider.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/providers/RIXMLProvider.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -85,7 +85,7 @@
     /**
      * The vendor name of this SyncProvider implementation.
      */
-    private String vendorName = "Sun Microsystems Inc.";
+    private String vendorName = "Oracle Corporation";
 
     /**
      * The version number of this SyncProvider implementation.
--- a/jdk/src/share/classes/com/sun/servicetag/Installer.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/Installer.java	Wed Jul 05 17:24:13 2017 +0200
@@ -43,7 +43,8 @@
         "servicetag.dir.path";
     private static String SVCTAG_ENABLE_REGISTRATION =
         "servicetag.registration.enabled";
-    private final static String SUN_VENDOR = "Sun Microsystems";
+    private final static String ORACLE = "Oracle";
+    private final static String SUN = "Sun Microsystems";
     private final static String REGISTRATION_XML = "registration.xml";
     private final static String SERVICE_TAG_FILE = "servicetag";
     private final static String REGISTRATION_HTML_NAME = "register";
@@ -84,9 +85,10 @@
 
     // Implementation of ServiceTag.getJavaServiceTag(String) method
     static ServiceTag getJavaServiceTag(String source) throws IOException {
-        if (!System.getProperty("java.vendor").startsWith(SUN_VENDOR)) {
+        String vendor = System.getProperty("java.vendor", "");
+        if (!vendor.startsWith(SUN) && !vendor.startsWith(ORACLE)) {
             // Products bundling this implementation may run on
-            // Mac OS which is not a Sun JDK
+            // Mac OS which is not a Sun/Oracle JDK
             return null;
         }
         boolean cleanup = false;
@@ -365,7 +367,7 @@
                                       props.getProperty("servicetag.parent.name"),
                                       props.getProperty("servicetag.parent.urn"),
                                       getProductDefinedId(),
-                                      SUN_VENDOR,
+                                      System.getProperty("java.vendor"),
                                       System.getProperty("os.arch"),
                                       getZoneName(),
                                       svcTagSource);
--- a/jdk/src/share/classes/com/sun/servicetag/RegistrationData.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/RegistrationData.java	Wed Jul 05 17:24:13 2017 +0200
@@ -80,12 +80,12 @@
  *       <tr>
  *          <td><tt>systemManufacturer</tt></td>
  *          <td>System manufacturer</td>
- *          <td> e.g. Sun Microsystems</td>
+ *          <td> e.g. Oracle Corporation</td>
  *       </tr>
  *       <tr>
  *          <td><tt>cpuManufacturer</tt></td>
  *          <td>CPU manufacturer</td>
- *          <td> e.g. Sun Microsystems</td>
+ *          <td> e.g. Oracle Corporation</td>
  *       </tr>
  *       <tr>
  *          <td><tt>serialNumber</tt></td>
--- a/jdk/src/share/classes/com/sun/servicetag/Registry.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/Registry.java	Wed Jul 05 17:24:13 2017 +0200
@@ -90,7 +90,7 @@
                 stclient = getWindowsStClientFile();
             } else {
                 if (isVerbose()) {
-                    System.out.println("Running on non-Sun JDK");
+                    System.out.println("Running on unsupported platform");
                 }
             }
             initialized = true;
--- a/jdk/src/share/classes/com/sun/servicetag/SolarisSystemEnvironment.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/SolarisSystemEnvironment.java	Wed Jul 05 17:24:13 2017 +0200
@@ -44,6 +44,7 @@
  * Solaris implementation of the SystemEnvironment class.
  */
 class SolarisSystemEnvironment extends SystemEnvironment {
+    private static final String ORACLE = "Oracle Corporation";
     SolarisSystemEnvironment() {
         setHostId(getCommandOutput("/usr/bin/hostid"));
         setSystemModel(getCommandOutput("/usr/bin/uname", "-i"));
@@ -59,7 +60,7 @@
     private String getSolarisCpuManufacturer() {
         // not fully accurate, this could be another manufacturer (fujitsu for example)
         if ("sparc".equalsIgnoreCase(System.getProperty("os.arch"))) {
-            return "Sun Microsystems, Inc";
+            return ORACLE;
         }
 
         // if we're here, then we'll try smbios (type 4)
@@ -73,7 +74,7 @@
     private String getSolarisSystemManufacturer() {
         // not fully accurate, this could be another manufacturer (fujitsu for example)
         if ("sparc".equalsIgnoreCase(System.getProperty("os.arch"))) {
-            return "Sun Microsystems, Inc";
+            return ORACLE;
         }
 
         // if we're here, then we'll try smbios (type 1)
@@ -117,7 +118,7 @@
     // ID    SIZE TYPE
     // 1     150  SMB_TYPE_SYSTEM (system information)
     //
-    //   Manufacturer: Sun Microsystems
+    //   Manufacturer: Oracle Corporation
     //   Product: Sun Fire X4600
     //   Version: To Be Filled By O.E.M.
     //   Serial Number: 00:14:4F:45:0C:2A
--- a/jdk/src/share/classes/java/awt/Dialog.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/awt/Dialog.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1068,7 +1068,7 @@
                     modalityPushed();
                     try {
                         EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
-                        secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 5000);
+                        secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 0);
                         if (!secondaryLoop.enter()) {
                             secondaryLoop = null;
                         }
--- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java	Wed Jul 05 17:24:13 2017 +0200
@@ -142,6 +142,9 @@
                 public void removeLastFocusRequest(Component heavyweight) {
                     KeyboardFocusManager.removeLastFocusRequest(heavyweight);
                 }
+                public void setMostRecentFocusOwner(Window window, Component component) {
+                    KeyboardFocusManager.setMostRecentFocusOwner(window, component);
+                }
             }
         );
     }
--- a/jdk/src/share/classes/java/awt/event/ActionEvent.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/awt/event/ActionEvent.java	Wed Jul 05 17:24:13 2017 +0200
@@ -51,7 +51,7 @@
  * in the range from {@code ACTION_FIRST} to {@code ACTION_LAST}.
  *
  * @see ActionListener
- * @see <a href="http://java.sun.com/docs/books/tutorial/post1.0/ui/eventmodel.html">Tutorial: Java 1.1 Event Model</a>
+ * @see <a href="http://java.sun.com/docs/books/tutorial/uiswing/events/actionlistener.html">Tutorial: How to Write an Action Listener</a>
  *
  * @author Carl Quinn
  * @since 1.1
--- a/jdk/src/share/classes/java/awt/image/SampleModel.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/awt/image/SampleModel.java	Wed Jul 05 17:24:13 2017 +0200
@@ -937,14 +937,22 @@
                             int iArray[], DataBuffer data) {
         int pixels[];
         int Offset=0;
+        int x1 = x + w;
+        int y1 = y + h;
+
+        if (x < 0 || x1 < x || x1 > width ||
+            y < 0 || y1 < y || y1 > height)
+        {
+            throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
+        }
 
         if (iArray != null)
             pixels = iArray;
         else
             pixels = new int[w * h];
 
-        for(int i=y; i<(h+y); i++) {
-            for (int j=x; j<(w+x); j++) {
+        for(int i=y; i<y1; i++) {
+            for (int j=x; j<x1; j++) {
                 pixels[Offset++] = getSample(j, i, b, data);
             }
         }
@@ -978,14 +986,22 @@
                               DataBuffer data) {
         float pixels[];
         int   Offset=0;
+        int x1 = x + w;
+        int y1 = y + h;
+
+        if (x < 0 || x1 < x || x1 > width ||
+            y < 0 || y1 < y || y1 > height)
+        {
+            throw new ArrayIndexOutOfBoundsException("Invalid coordinates");
+        }
 
         if (fArray != null)
             pixels = fArray;
         else
             pixels = new float[w * h];
 
-        for (int i=y; i<(h+y); i++) {
-            for (int j=x; j<(w+x); j++) {
+        for (int i=y; i<y1; i++) {
+            for (int j=x; j<x1; j++) {
                 pixels[Offset++] = getSampleFloat(j, i, b, data);
             }
         }
@@ -1019,14 +1035,22 @@
                                DataBuffer data) {
         double pixels[];
         int    Offset=0;
+        int x1 = x + w;
+        int y1 = y + h;
+
+        if (x < 0 || x1 < x || x1 > width ||
+            y < 0 || y1 < y || y1 > height)
+        {
+            throw new ArrayIndexOutOfBoundsException("Invalid coordinates");
+        }
 
         if (dArray != null)
             pixels = dArray;
         else
             pixels = new double[w * h];
 
-        for (int i=y; i<(y+h); i++) {
-            for (int j=x; j<(x+w); j++) {
+        for (int i=y; i<y1; i++) {
+            for (int j=x; j<x1; j++) {
                 pixels[Offset++] = getSampleDouble(j, i, b, data);
             }
         }
--- a/jdk/src/share/classes/java/beans/EventSetDescriptor.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/beans/EventSetDescriptor.java	Wed Jul 05 17:24:13 2017 +0200
@@ -176,8 +176,9 @@
         setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1));
 
         // Be more forgiving of not finding the getListener method.
-        if (getListenerMethodName != null) {
-            setGetListenerMethod(Introspector.findInstanceMethod(sourceClass, getListenerMethodName));
+        Method method = Introspector.findMethod(sourceClass, getListenerMethodName, 0);
+        if (method != null) {
+            setGetListenerMethod(method);
         }
     }
 
--- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java	Wed Jul 05 17:24:13 2017 +0200
@@ -189,11 +189,13 @@
                     indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();
                 }
             }
-            indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class);
+
+            Class[] args = { int.class };
+            indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
             if (indexedReadMethod == null) {
                 // no "is" method, so look for a "get" method.
                 indexedReadMethodName = Introspector.GET_PREFIX + getBaseName();
-                indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class);
+                indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args);
             }
             setIndexedReadMethod0(indexedReadMethod);
         }
@@ -265,7 +267,9 @@
             if (indexedWriteMethodName == null) {
                 indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName();
             }
-            indexedWriteMethod = Introspector.findInstanceMethod(cls, indexedWriteMethodName, int.class, type);
+
+            Class[] args = (type == null) ? null : new Class[] { int.class, type };
+            indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 2, args);
             if (indexedWriteMethod != null) {
                 if (!indexedWriteMethod.getReturnType().equals(void.class)) {
                     indexedWriteMethod = null;
--- a/jdk/src/share/classes/java/beans/Introspector.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/beans/Introspector.java	Wed Jul 05 17:24:13 2017 +0200
@@ -28,7 +28,6 @@
 import com.sun.beans.WeakCache;
 import com.sun.beans.finder.BeanInfoFinder;
 import com.sun.beans.finder.ClassFinder;
-import com.sun.beans.finder.MethodFinder;
 
 import java.lang.ref.Reference;
 import java.lang.ref.SoftReference;
@@ -843,8 +842,8 @@
                 Method read = result.getReadMethod();
 
                 if (read == null && write != null) {
-                    read = findInstanceMethod(result.getClass0(),
-                                              GET_PREFIX + NameGenerator.capitalize(result.getName()));
+                    read = findMethod(result.getClass0(),
+                                      GET_PREFIX + NameGenerator.capitalize(result.getName()), 0);
                     if (read != null) {
                         try {
                             result.setReadMethod(read);
@@ -854,9 +853,9 @@
                     }
                 }
                 if (write == null && read != null) {
-                    write = findInstanceMethod(result.getClass0(),
-                                               SET_PREFIX + NameGenerator.capitalize(result.getName()),
-                                               FeatureDescriptor.getReturnType(result.getClass0(), read));
+                    write = findMethod(result.getClass0(),
+                                       SET_PREFIX + NameGenerator.capitalize(result.getName()), 1,
+                                       new Class[] { FeatureDescriptor.getReturnType(result.getClass0(), read) });
                     if (write != null) {
                         try {
                             result.setWriteMethod(write);
@@ -1280,27 +1279,90 @@
     // Package private support methods.
     //======================================================================
 
-    static Method findMethod(Class<?> type, String name, int args) {
-        for (Method method : type.getMethods()) {
-            if (method.getName().equals(name) && (args == method.getParameterTypes().length)) {
-                try {
-                    return MethodFinder.findAccessibleMethod(method);
+    /**
+     * Internal support for finding a target methodName with a given
+     * parameter list on a given class.
+     */
+    private static Method internalFindMethod(Class start, String methodName,
+                                                 int argCount, Class args[]) {
+        // For overriden methods we need to find the most derived version.
+        // So we start with the given class and walk up the superclass chain.
+
+        Method method = null;
+
+        for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
+            Method methods[] = getPublicDeclaredMethods(cl);
+            for (int i = 0; i < methods.length; i++) {
+                method = methods[i];
+                if (method == null) {
+                    continue;
                 }
-                catch (NoSuchMethodException exception) {
-                    // continue search for a method with the specified count of parameters
+
+                // make sure method signature matches.
+                Class params[] = FeatureDescriptor.getParameterTypes(start, method);
+                if (method.getName().equals(methodName) &&
+                    params.length == argCount) {
+                    if (args != null) {
+                        boolean different = false;
+                        if (argCount > 0) {
+                            for (int j = 0; j < argCount; j++) {
+                                if (params[j] != args[j]) {
+                                    different = true;
+                                    continue;
+                                }
+                            }
+                            if (different) {
+                                continue;
+                            }
+                        }
+                    }
+                    return method;
                 }
             }
         }
-        return null;
+        method = null;
+
+        // Now check any inherited interfaces.  This is necessary both when
+        // the argument class is itself an interface, and when the argument
+        // class is an abstract class.
+        Class ifcs[] = start.getInterfaces();
+        for (int i = 0 ; i < ifcs.length; i++) {
+            // Note: The original implementation had both methods calling
+            // the 3 arg method. This is preserved but perhaps it should
+            // pass the args array instead of null.
+            method = internalFindMethod(ifcs[i], methodName, argCount, null);
+            if (method != null) {
+                break;
+            }
+        }
+        return method;
     }
 
-    static Method findInstanceMethod(Class<?> type, String name, Class<?>... args) {
-        try {
-            return MethodFinder.findInstanceMethod(type, name, args);
-        }
-        catch (NoSuchMethodException exception) {
+    /**
+     * Find a target methodName on a given class.
+     */
+    static Method findMethod(Class cls, String methodName, int argCount) {
+        return findMethod(cls, methodName, argCount, null);
+    }
+
+    /**
+     * Find a target methodName with specific parameter list on a given class.
+     * <p>
+     * Used in the contructors of the EventSetDescriptor,
+     * PropertyDescriptor and the IndexedPropertyDescriptor.
+     * <p>
+     * @param cls The Class object on which to retrieve the method.
+     * @param methodName Name of the method.
+     * @param argCount Number of arguments for the desired method.
+     * @param args Array of argument types for the method.
+     * @return the method or null if not found
+     */
+    static Method findMethod(Class cls, String methodName, int argCount,
+                             Class args[]) {
+        if (methodName == null) {
             return null;
         }
+        return internalFindMethod(cls, methodName, argCount, args);
     }
 
     /**
--- a/jdk/src/share/classes/java/beans/MethodDescriptor.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/beans/MethodDescriptor.java	Wed Jul 05 17:24:13 2017 +0200
@@ -90,13 +90,13 @@
                         // Find methods for up to 2 params. We are guessing here.
                         // This block should never execute unless the classloader
                         // that loaded the argument classes disappears.
-                        method = Introspector.findMethod(cls, name, i);
+                        method = Introspector.findMethod(cls, name, i, null);
                         if (method != null) {
                             break;
                         }
                     }
                 } else {
-                    method = Statement.getMethod(cls, name, params);
+                    method = Introspector.findMethod(cls, name, params.length, params);
                 }
                 setMethod(method);
             }
--- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java	Wed Jul 05 17:24:13 2017 +0200
@@ -112,7 +112,8 @@
         // If this class or one of its base classes allow PropertyChangeListener,
         // then we assume that any properties we discover are "bound".
         // See Introspector.getTargetPropertyInfo() method.
-        this.bound = null != Introspector.findInstanceMethod(beanClass, "addPropertyChangeListener", PropertyChangeListener.class);
+        Class[] args = { PropertyChangeListener.class };
+        this.bound = null != Introspector.findMethod(beanClass, "addPropertyChangeListener", args.length, args);
     }
 
     /**
@@ -223,10 +224,10 @@
             // property type is.  For booleans, there can be "is" and "get"
             // methods.  If an "is" method exists, this is the official
             // reader method so look for this one first.
-            readMethod = Introspector.findInstanceMethod(cls, readMethodName);
+            readMethod = Introspector.findMethod(cls, readMethodName, 0);
             if (readMethod == null) {
                 readMethodName = Introspector.GET_PREFIX + getBaseName();
-                readMethod = Introspector.findInstanceMethod(cls, readMethodName);
+                readMethod = Introspector.findMethod(cls, readMethodName, 0);
             }
             try {
                 setReadMethod(readMethod);
@@ -291,7 +292,8 @@
                 writeMethodName = Introspector.SET_PREFIX + getBaseName();
             }
 
-            writeMethod = Introspector.findInstanceMethod(cls, writeMethodName, type);
+            Class[] args = (type == null) ? null : new Class[] { type };
+            writeMethod = Introspector.findMethod(cls, writeMethodName, 1, args);
             if (writeMethod != null) {
                 if (!writeMethod.getReturnType().equals(void.class)) {
                     writeMethod = null;
--- a/jdk/src/share/classes/java/lang/System.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/lang/System.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1101,22 +1101,12 @@
         lineSeparator = props.getProperty("line.separator");
         sun.misc.Version.init();
 
-        // Workaround until DownloadManager initialization is revisited.
-        // Make JavaLangAccess available early enough for internal
-        // Shutdown hooks to be registered
-        setJavaLangAccess();
-
         // Gets and removes system properties that configure the Integer
         // cache used to support the object identity semantics of autoboxing.
         // At this time, the size of the cache may be controlled by the
         // vm option -XX:AutoBoxCacheMax=<size>.
         Integer.getAndRemoveCacheProperties();
 
-        // Load the zip library now in order to keep java.util.zip.ZipFile
-        // from trying to use itself to load this library later.
-        loadLibrary("zip");
-
-
         FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
         FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
         FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
@@ -1124,6 +1114,10 @@
         setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
         setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true));
 
+        // Load the zip library now in order to keep java.util.zip.ZipFile
+        // from trying to use itself to load this library later.
+        loadLibrary("zip");
+
         // Setup Java signal handlers for HUP, TERM, and INT (where available).
         Terminator.setup();
 
@@ -1153,6 +1147,9 @@
         // way as other threads; we must do it ourselves here.
         Thread current = Thread.currentThread();
         current.getThreadGroup().add(current);
+
+        // register shared secrets
+        setJavaLangAccess();
     }
 
     private static void setJavaLangAccess() {
--- a/jdk/src/share/classes/java/net/InetAddress.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/net/InetAddress.java	Wed Jul 05 17:24:13 2017 +0200
@@ -677,19 +677,20 @@
 
     static InetAddressImpl  impl;
 
-    private static HashMap          lookupTable = new HashMap();
+    private static HashMap<String, InetAddress[]> lookupTable
+        = new HashMap<String, InetAddress[]>();
 
     /**
      * Represents a cache entry
      */
     static final class CacheEntry {
 
-        CacheEntry(Object address, long expiration) {
-            this.address = address;
+        CacheEntry(InetAddress[] addresses, long expiration) {
+            this.addresses = addresses;
             this.expiration = expiration;
         }
 
-        Object address;
+        InetAddress[] addresses;
         long expiration;
     }
 
@@ -698,7 +699,7 @@
      * at creation time.
      */
     static final class Cache {
-        private LinkedHashMap cache;
+        private LinkedHashMap<String, CacheEntry> cache;
         private Type type;
 
         enum Type {Positive, Negative};
@@ -708,7 +709,7 @@
          */
         public Cache(Type type) {
             this.type = type;
-            cache = new LinkedHashMap();
+            cache = new LinkedHashMap<String, CacheEntry>();
         }
 
         private int getPolicy() {
@@ -724,7 +725,7 @@
          * entry then for this host then the entry will be
          * replaced.
          */
-        public Cache put(String host, Object address) {
+        public Cache put(String host, InetAddress[] addresses) {
             int policy = getPolicy();
             if (policy == InetAddressCachePolicy.NEVER) {
                 return this;
@@ -736,12 +737,10 @@
 
                 // As we iterate in insertion order we can
                 // terminate when a non-expired entry is found.
-                LinkedList expired = new LinkedList();
-                Iterator i = cache.keySet().iterator();
+                LinkedList<String> expired = new LinkedList<String>();
                 long now = System.currentTimeMillis();
-                while (i.hasNext()) {
-                    String key = (String)i.next();
-                    CacheEntry entry = (CacheEntry)cache.get(key);
+                for (String key : cache.keySet()) {
+                    CacheEntry entry = cache.get(key);
 
                     if (entry.expiration >= 0 && entry.expiration < now) {
                         expired.add(key);
@@ -750,9 +749,8 @@
                     }
                 }
 
-                i = expired.iterator();
-                while (i.hasNext()) {
-                    cache.remove(i.next());
+                for (String key : expired) {
+                    cache.remove(key);
                 }
             }
 
@@ -766,7 +764,7 @@
             } else {
                 expiration = System.currentTimeMillis() + (policy * 1000);
             }
-            CacheEntry entry = new CacheEntry(address, expiration);
+            CacheEntry entry = new CacheEntry(addresses, expiration);
             cache.put(host, entry);
             return this;
         }
@@ -780,7 +778,7 @@
             if (policy == InetAddressCachePolicy.NEVER) {
                 return null;
             }
-            CacheEntry entry = (CacheEntry)cache.get(host);
+            CacheEntry entry = cache.get(host);
 
             // check if entry has expired
             if (entry != null && policy != InetAddressCachePolicy.FOREVER) {
@@ -814,42 +812,41 @@
     }
 
     /*
-     * Cache the given hostname and address.
+     * Cache the given hostname and addresses.
      */
-    private static void cacheAddress(String hostname, Object address,
-                                     boolean success) {
+    private static void cacheAddresses(String hostname,
+                                       InetAddress[] addresses,
+                                       boolean success) {
         hostname = hostname.toLowerCase();
         synchronized (addressCache) {
             cacheInitIfNeeded();
             if (success) {
-                addressCache.put(hostname, address);
+                addressCache.put(hostname, addresses);
             } else {
-                negativeCache.put(hostname, address);
+                negativeCache.put(hostname, addresses);
             }
         }
     }
 
     /*
      * Lookup hostname in cache (positive & negative cache). If
-     * found return address, null if not found.
+     * found return addresses, null if not found.
      */
-    private static Object getCachedAddress(String hostname) {
+    private static InetAddress[] getCachedAddresses(String hostname) {
         hostname = hostname.toLowerCase();
 
         // search both positive & negative caches
 
         synchronized (addressCache) {
-            CacheEntry entry;
-
             cacheInitIfNeeded();
 
-            entry = addressCache.get(hostname);
+            CacheEntry entry = addressCache.get(hostname);
             if (entry == null) {
                 entry = negativeCache.get(hostname);
             }
 
             if (entry != null) {
-                return entry.address;
+                return entry.addresses;
             }
         }
 
@@ -911,7 +908,7 @@
 
     static {
         // create the impl
-        impl = (new InetAddressImplFactory()).create();
+        impl = InetAddressImplFactory.create();
 
         // get name service if provided and requested
         String provider = null;;
@@ -931,7 +928,7 @@
         }
 
         // if not designate any name services provider,
-        // creat a default one
+        // create a default one
         if (nameServices.size() == 0) {
             NameService ns = createNSProvider("default");
             nameServices.add(ns);
@@ -939,7 +936,7 @@
     }
 
     /**
-     * Create an InetAddress based on the provided host name and IP address
+     * Creates an InetAddress based on the provided host name and IP address.
      * No name service is checked for the validity of the address.
      *
      * <p> The host name can either be a machine name, such as
@@ -1067,13 +1064,13 @@
 
         boolean ipv6Expected = false;
         if (host.charAt(0) == '[') {
-            // This is supposed to be an IPv6 litteral
+            // This is supposed to be an IPv6 literal
             if (host.length() > 2 && host.charAt(host.length()-1) == ']') {
                 host = host.substring(1, host.length() -1);
                 ipv6Expected = true;
             } else {
                 // This was supposed to be a IPv6 address, but it's not!
-                throw new UnknownHostException(host);
+                throw new UnknownHostException(host + ": invalid IPv6 address");
             }
         }
 
@@ -1180,8 +1177,6 @@
         throws UnknownHostException  {
         /* If it gets here it is presumed to be a hostname */
         /* Cache.get can return: null, unknownAddress, or InetAddress[] */
-        Object obj = null;
-        Object objcopy = null;
 
         /* make sure the connection to the host is allowed, before we
          * give out a hostname
@@ -1193,26 +1188,23 @@
             }
         }
 
-        obj = getCachedAddress(host);
+        InetAddress[] addresses = getCachedAddresses(host);
 
         /* If no entry in cache, then do the host lookup */
-        if (obj == null) {
-            obj = getAddressFromNameService(host);
+        if (addresses == null) {
+            addresses = getAddressesFromNameService(host);
         }
 
-        if (obj == unknown_array)
+        if (addresses == unknown_array)
             throw new UnknownHostException(host);
 
-        /* Make a copy of the InetAddress array */
-        objcopy = ((InetAddress [])obj).clone();
-
-        return (InetAddress [])objcopy;
+        return addresses.clone();
     }
 
-    private static Object getAddressFromNameService(String host)
+    private static InetAddress[] getAddressesFromNameService(String host)
         throws UnknownHostException
     {
-        Object obj = null;
+        InetAddress[] addresses = null;
         boolean success = false;
         UnknownHostException ex = null;
 
@@ -1226,16 +1218,16 @@
         //    would be blocked until the host is removed
         //    from the lookupTable. Then this thread
         //    should try to look up the addressCache.
-        //     i) if it found the address in the
+        //     i) if it found the addresses in the
         //        addressCache, checkLookupTable()  would
-        //        return the address.
-        //     ii) if it didn't find the address in the
+        //        return the addresses.
+        //     ii) if it didn't find the addresses in the
         //         addressCache for any reason,
         //         it should add the host in the
         //         lookupTable and return null so the
         //         following code would do  a lookup itself.
-        if ((obj = checkLookupTable(host)) == null) {
-            // This is the first thread which looks up the address
+        if ((addresses = checkLookupTable(host)) == null) {
+            // This is the first thread which looks up the addresses
             // this host or the cache entry for this host has been
             // expired so this thread should do the lookup.
             for (NameService nameService : nameServices) {
@@ -1246,26 +1238,26 @@
                      * allocating space when the lookup fails.
                      */
 
-                    obj = nameService.lookupAllHostAddr(host);
+                    addresses = nameService.lookupAllHostAddr(host);
                     success = true;
                     break;
                 } catch (UnknownHostException uhe) {
                     if (host.equalsIgnoreCase("localhost")) {
                         InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
-                        obj = local;
+                        addresses = local;
                         success = true;
                         break;
                     }
                     else {
-                        obj  = unknown_array;
+                        addresses = unknown_array;
                         success = false;
                         ex = uhe;
                     }
                 }
             }
 
-            // Cache the address.
-            cacheAddress(host, obj, success);
+            // Cache the addresses.
+            cacheAddresses(host, addresses, success);
             // Delete the host from the lookupTable, and
             // notify all threads waiting for the monitor
             // for lookupTable.
@@ -1274,13 +1266,13 @@
                 throw ex;
         }
 
-        return obj;
+        return addresses;
     }
 
 
-    private static Object checkLookupTable(String host) {
-        // make sure obj  is null.
-        Object obj = null;
+    private static InetAddress[] checkLookupTable(String host) {
+        // make sure addresses is null.
+        InetAddress[] addresses = null;
 
         synchronized (lookupTable) {
             // If the host isn't in the lookupTable, add it in the
@@ -1288,11 +1280,11 @@
             // the lookup.
             if (lookupTable.containsKey(host) == false) {
                 lookupTable.put(host, null);
-                return obj;
+                return addresses;
             }
 
             // If the host is in the lookupTable, it means that another
-            // thread is trying to look up the address of this host.
+            // thread is trying to look up the addresses of this host.
             // This thread should wait.
             while (lookupTable.containsKey(host)) {
                 try {
@@ -1302,18 +1294,18 @@
             }
         }
 
-        // The other thread has finished looking up the address of
-        // the host. This thread should retry to get the address
-        // from the addressCache. If it doesn't get the address from
-        // the cache,  it will try to look up the address itself.
-        obj = getCachedAddress(host);
-        if (obj == null) {
+        // The other thread has finished looking up the addresses of
+        // the host. This thread should retry to get the addresses
+        // from the addressCache. If it doesn't get the addresses from
+        // the cache, it will try to look up the addresses itself.
+        addresses = getCachedAddresses(host);
+        if (addresses == null) {
             synchronized (lookupTable) {
                 lookupTable.put(host, null);
             }
         }
 
-        return obj;
+        return addresses;
     }
 
     private static void updateLookupTable(String host) {
@@ -1396,15 +1388,20 @@
                         cachedLocalHost = null;
                 }
 
-                // we are calling getAddressFromNameService directly
+                // we are calling getAddressesFromNameService directly
                 // to avoid getting localHost from cache
                 if (ret == null) {
                     InetAddress[] localAddrs;
                     try {
                         localAddrs =
-                            (InetAddress[]) InetAddress.getAddressFromNameService(local);
+                            InetAddress.getAddressesFromNameService(local);
                     } catch (UnknownHostException uhe) {
-                        throw new UnknownHostException(local + ": " + uhe.getMessage());
+                        // Rethrow with a more informative error message.
+                        UnknownHostException uhe2 =
+                            new UnknownHostException(local + ": " +
+                                                     uhe.getMessage());
+                        uhe2.initCause(uhe);
+                        throw uhe2;
                     }
                     cachedLocalHost = localAddrs[0];
                     cacheTime = now;
@@ -1434,8 +1431,8 @@
     /*
      * Load and instantiate an underlying impl class
      */
-    static Object loadImpl(String implName) {
-        Object impl;
+    static InetAddressImpl loadImpl(String implName) {
+        Object impl = null;
 
         /*
          * Property "impl.prefix" will be prepended to the classname
@@ -1446,7 +1443,6 @@
          */
         String prefix = AccessController.doPrivileged(
                       new GetPropertyAction("impl.prefix", ""));
-        impl = null;
         try {
             impl = Class.forName("java.net." + prefix + implName).newInstance();
         } catch (ClassNotFoundException e) {
@@ -1471,7 +1467,7 @@
             }
         }
 
-        return impl;
+        return (InetAddressImpl) impl;
     }
 
     private void readObjectNoData (ObjectInputStream s) throws
@@ -1498,13 +1494,8 @@
 class InetAddressImplFactory {
 
     static InetAddressImpl create() {
-        Object o;
-        if (isIPv6Supported()) {
-            o = InetAddress.loadImpl("Inet6AddressImpl");
-        } else {
-            o = InetAddress.loadImpl("Inet4AddressImpl");
-        }
-        return (InetAddressImpl)o;
+        return InetAddress.loadImpl(isIPv6Supported() ?
+                                    "Inet6AddressImpl" : "Inet4AddressImpl");
     }
 
     static native boolean isIPv6Supported();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/nio/file/FileSystemLoopException.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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 java.nio.file;
+
+/**
+ * Checked exception thrown when a file system loop, or cycle, is encountered.
+ *
+ * @since 1.7
+ * @see Files#walkFileTree
+ */
+
+public class FileSystemLoopException
+    extends FileSystemException
+{
+    private static final long serialVersionUID = 4843039591949217617L;
+
+    /**
+     * Constructs an instance of this class.
+     *
+     * @param   file
+     *          a string identifying the file causing the cycle or {@code null} if
+     *          not known
+     */
+    public FileSystemLoopException(String file) {
+        super(file);
+    }
+}
--- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java	Wed Jul 05 17:24:13 2017 +0200
@@ -38,7 +38,6 @@
 
 class FileTreeWalker {
     private final boolean followLinks;
-    private final boolean detectCycles;
     private final LinkOption[] linkOptions;
     private final FileVisitor<? super Path> visitor;
     private final int maxDepth;
@@ -48,17 +47,15 @@
                    int maxDepth)
     {
         boolean fl = false;
-        boolean dc = false;
         for (FileVisitOption option: options) {
+            // will throw NPE if options contains null
             switch (option) {
-                case FOLLOW_LINKS  : fl = true; break;
-                case DETECT_CYCLES : dc = true; break;
+                case FOLLOW_LINKS : fl = true; break;
                 default:
                     throw new AssertionError("Should not get here");
             }
         }
         this.followLinks = fl;
-        this.detectCycles = fl | dc;
         this.linkOptions = (fl) ? new LinkOption[0] :
             new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
         this.visitor = visitor;
@@ -68,13 +65,11 @@
     /**
      * Walk file tree starting at the given file
      */
-    void walk(Path start) {
+    void walk(Path start) throws IOException {
         FileVisitResult result = walk(start,
                                       0,
                                       new ArrayList<AncestorDirectory>());
-        if (result == null) {
-            throw new NullPointerException("Visitor returned 'null'");
-        }
+        Objects.nonNull(result, "FileVisitor returned null");
     }
 
     /**
@@ -88,11 +83,8 @@
     private FileVisitResult walk(Path file,
                                  int depth,
                                  List<AncestorDirectory> ancestors)
+        throws IOException
     {
-        // depth check
-        if (depth > maxDepth)
-            return FileVisitResult.CONTINUE;
-
         // if attributes are cached then use them if possible
         BasicFileAttributes attrs = null;
         if ((depth > 0) &&
@@ -137,13 +129,13 @@
             return visitor.visitFileFailed(file, exc);
         }
 
-        // file is not a directory so invoke visitFile method
-        if (!attrs.isDirectory()) {
+        // at maximum depth or file is not a directory
+        if (depth >= maxDepth || !attrs.isDirectory()) {
             return visitor.visitFile(file, attrs);
         }
 
-        // check for cycles
-        if (detectCycles) {
+        // check for cycles when following links
+        if (followLinks) {
             Object key = attrs.fileKey();
 
             // if this directory and ancestor has a file key then we compare
@@ -153,19 +145,23 @@
                 if (key != null && ancestorKey != null) {
                     if (key.equals(ancestorKey)) {
                         // cycle detected
-                        return visitor.visitFile(file, attrs);
+                        return visitor.visitFileFailed(file,
+                            new FileSystemLoopException(file.toString()));
                     }
                 } else {
+                    boolean isSameFile = false;
                     try {
-                        if (file.isSameFile(ancestor.file())) {
-                            // cycle detected
-                            return visitor.visitFile(file, attrs);
-                        }
+                        isSameFile = file.isSameFile(ancestor.file());
                     } catch (IOException x) {
                         // ignore
                     } catch (SecurityException x) {
                         // ignore
                     }
+                    if (isSameFile) {
+                        // cycle detected
+                        return visitor.visitFileFailed(file,
+                            new FileSystemLoopException(file.toString()));
+                    }
                 }
             }
 
@@ -181,7 +177,7 @@
             try {
                 stream = file.newDirectoryStream();
             } catch (IOException x) {
-                return visitor.preVisitDirectoryFailed(file, x);
+                return visitor.visitFileFailed(file, x);
             } catch (SecurityException x) {
                 // ignore, as per spec
                 return FileVisitResult.CONTINUE;
@@ -192,20 +188,14 @@
 
             // invoke preVisitDirectory and then visit each entry
             try {
-                result = visitor.preVisitDirectory(file);
+                result = visitor.preVisitDirectory(file, attrs);
                 if (result != FileVisitResult.CONTINUE) {
                     return result;
                 }
 
-                // if an I/O occurs during iteration then a CME is thrown. We
-                // need to distinguish this from a CME thrown by the visitor.
-                boolean inAction = false;
-
                 try {
                     for (Path entry: stream) {
-                        inAction = true;
                         result = walk(entry, depth+1, ancestors);
-                        inAction = false;
 
                         // returning null will cause NPE to be thrown
                         if (result == null || result == FileVisitResult.TERMINATE)
@@ -215,17 +205,9 @@
                         if (result == FileVisitResult.SKIP_SIBLINGS)
                             break;
                     }
-                } catch (ConcurrentModificationException x) {
-                    // if CME thrown because the iteration failed then remember
-                    // the IOException so that it is notified to postVisitDirectory
-                    if (!inAction) {
-                        // iteration failed
-                        Throwable t = x.getCause();
-                        if (t instanceof IOException)
-                            ioe = (IOException)t;
-                    }
-                    if (ioe == null)
-                        throw x;
+                } catch (DirectoryIteratorException e) {
+                    // IOException will be notified to postVisitDirectory
+                    ioe = e.getCause();
                 }
             } finally {
                 try {
@@ -238,7 +220,7 @@
 
         } finally {
             // remove key from trail if doing cycle detection
-            if (detectCycles) {
+            if (followLinks) {
                 ancestors.remove(ancestors.size()-1);
             }
         }
--- a/jdk/src/share/classes/java/nio/file/FileVisitOption.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileVisitOption.java	Wed Jul 05 17:24:13 2017 +0200
@@ -37,9 +37,5 @@
     /**
      * Follow symbolic links.
      */
-    FOLLOW_LINKS,
-    /**
-     * Detect cycles in the file tree.
-     */
-    DETECT_CYCLES;
+    FOLLOW_LINKS;
 }
--- a/jdk/src/share/classes/java/nio/file/FileVisitor.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileVisitor.java	Wed Jul 05 17:24:13 2017 +0200
@@ -40,33 +40,28 @@
  *     Path start = ...
  *     Files.walkFileTree(start, new SimpleFileVisitor&lt;Path&gt;() {
  *         &#64;Override
- *         public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
- *             try {
- *                 file.delete();
- *             } catch (IOException exc) {
- *                 // failed to delete, do error handling here
- *             }
+ *         public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ *             throws IOException
+ *         {
+ *             file.delete();
  *             return FileVisitResult.CONTINUE;
  *         }
  *         &#64;Override
- *         public FileVisitResult postVisitDirectory(Path dir, IOException e) {
- *             if (e == null) {
- *                 try {
- *                     dir.delete();
- *                 } catch (IOException exc) {
- *                     // failed to delete, do error handling here
- *                 }
- *             } else {
+ *         public FileVisitResult postVisitDirectory(Path dir, IOException e)
+ *             throws IOException
+ *         {
+ *             if (e != null) {
  *                 // directory iteration failed
+ *                 throw e;
  *             }
+ *             dir.delete();
  *             return FileVisitResult.CONTINUE;
  *         }
  *     });
  * </pre>
- * <p> Furthermore, suppose we want to copy a file tree rooted at a source
- * directory to a target location. In that case, symbolic links should be
- * followed and the target directory should be created before the entries in
- * the directory are copied.
+ * <p> Furthermore, suppose we want to copy a file tree to a target location.
+ * In that case, symbolic links should be followed and the target directory
+ * should be created before the entries in the directory are copied.
  * <pre>
  *     final Path source = ...
  *     final Path target = ...
@@ -74,25 +69,21 @@
  *     Files.walkFileTree(source, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
  *         new SimpleFileVisitor&lt;Path&gt;() {
  *             &#64;Override
- *             public FileVisitResult preVisitDirectory(Path dir) {
+ *             public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+ *                 throws IOException
+ *             {
  *                 try {
  *                     dir.copyTo(target.resolve(source.relativize(dir)));
  *                 } catch (FileAlreadyExistsException e) {
  *                      // ignore
- *                 } catch (IOException e) {
- *                     // copy failed, do error handling here
- *                     // skip rest of directory and descendants
- *                     return SKIP_SUBTREE;
  *                 }
  *                 return CONTINUE;
  *             }
  *             &#64;Override
- *             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
- *                 try {
- *                     file.copyTo(target.resolve(source.relativize(file)));
- *                 } catch (IOException e) {
- *                     // copy failed, do error handling here
- *                 }
+ *             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ *                 throws IOException
+ *             {
+ *                 file.copyTo(target.resolve(source.relativize(file)));
  *                 return CONTINUE;
  *             }
  *         });
@@ -114,22 +105,16 @@
      *
      * @param   dir
      *          a reference to the directory
+     * @param   attrs
+     *          the directory's basic attributes
      *
      * @return  the visit result
+     *
+     * @throws  IOException
+     *          if an I/O error occurs
      */
-    FileVisitResult preVisitDirectory(T dir);
-
-    /**
-     * Invoked for a directory that could not be opened.
-     *
-     * @param   dir
-     *          a reference to the directory
-     * @param   exc
-     *          the I/O exception thrown from the attempt to open the directory
-     *
-     * @return  the visit result
-     */
-    FileVisitResult preVisitDirectoryFailed(T dir, IOException exc);
+    FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)
+        throws IOException;
 
     /**
      * Invoked for a file in a directory.
@@ -140,21 +125,30 @@
      *          the file's basic attributes
      *
      * @return  the visit result
+     *
+     * @throws  IOException
+     *          if an I/O error occurs
      */
-    FileVisitResult visitFile(T file, BasicFileAttributes attrs);
+    FileVisitResult visitFile(T file, BasicFileAttributes attrs)
+        throws IOException;
 
     /**
-     * Invoked for a file when its basic file attributes could not be read.
+     * Invoked for a file that could not be visited. This method is invoked
+     * if the file's attributes could not be read, the file is a directory
+     * that could not be opened, and other reasons.
      *
      * @param   file
      *          a reference to the file
      * @param   exc
-     *          the I/O exception thrown from the attempt to read the file
-     *          attributes
+     *          the I/O exception that prevented the file from being visited
      *
      * @return  the visit result
+     *
+     * @throws  IOException
+     *          if an I/O error occurs
      */
-    FileVisitResult visitFileFailed(T file, IOException exc);
+    FileVisitResult visitFileFailed(T file, IOException exc)
+        throws IOException;
 
     /**
      * Invoked for a directory after entries in the directory, and all of their
@@ -171,6 +165,10 @@
      *          of the directory to complete prematurely
      *
      * @return  the visit result
+     *
+     * @throws  IOException
+     *          if an I/O error occurs
      */
-    FileVisitResult postVisitDirectory(T dir, IOException exc);
+    FileVisitResult postVisitDirectory(T dir, IOException exc)
+        throws IOException;
 }
--- a/jdk/src/share/classes/java/nio/file/Files.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/Files.java	Wed Jul 05 17:24:13 2017 +0200
@@ -135,9 +135,9 @@
      * FileVisitor} invoked for each file encountered. File tree traversal
      * completes when all accessible files in the tree have been visited, or a
      * visit method returns a result of {@link FileVisitResult#TERMINATE
-     * TERMINATE}. Where a visit method terminates due an uncaught error or
-     * runtime exception then the traversal is terminated and the error or
-     * exception is propagated to the caller of this method.
+     * TERMINATE}. Where a visit method terminates due an {@code IOException},
+     * an uncaught error, or runtime exception, then the traversal is terminated
+     * and the error or exception is propagated to the caller of this method.
      *
      * <p> For each file encountered this method attempts to gets its {@link
      * java.nio.file.attribute.BasicFileAttributes}. If the file is not a
@@ -146,12 +146,10 @@
      * due to an I/O exception, then the {@link FileVisitor#visitFileFailed
      * visitFileFailed} method is invoked with the I/O exception.
      *
-     * <p> Where the file is a directory, this method attempts to open it by
-     * invoking its {@link Path#newDirectoryStream newDirectoryStream} method.
-     * Where the directory could not be opened, due to an {@code IOException},
-     * then the {@link FileVisitor#preVisitDirectoryFailed preVisitDirectoryFailed}
-     * method is invoked with the I/O exception, after which, the file tree walk
-     * continues, by default, at the next <em>sibling</em> of the directory.
+     * <p> Where the file is a directory, and the directory could not be opened,
+     * then the {@code visitFileFailed} method is invoked with the I/O exception,
+     * after which, the file tree walk continues, by default, at the next
+     * <em>sibling</em> of the directory.
      *
      * <p> Where the directory is opened successfully, then the entries in the
      * directory, and their <em>descendants</em> are visited. When all entries
@@ -171,26 +169,25 @@
      * method is invoked as specified above).
      *
      * <p> If the {@code options} parameter contains the {@link
-     * FileVisitOption#DETECT_CYCLES DETECT_CYCLES} or {@link
-     * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} options then this method keeps
+     * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then this method keeps
      * track of directories visited so that cycles can be detected. A cycle
      * arises when there is an entry in a directory that is an ancestor of the
      * directory. Cycle detection is done by recording the {@link
      * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
      * or if file keys are not available, by invoking the {@link Path#isSameFile
      * isSameFile} method to test if a directory is the same file as an
-     * ancestor. When a cycle is detected the {@link FileVisitor#visitFile
-     * visitFile} is invoked with the attributes of the directory. The {@link
-     * java.nio.file.attribute.BasicFileAttributes#isDirectory isDirectory}
-     * method may be used to test if the file is a directory and that a cycle is
-     * detected. The {@code preVisitDirectory} and {@code postVisitDirectory}
-     * methods are not invoked.
+     * ancestor. When a cycle is detected it is treated as an I/O error, and the
+     * {@link FileVisitor#visitFileFailed visitFileFailed} method is invoked with
+     * an instance of {@link FileSystemLoopException}.
      *
      * <p> The {@code maxDepth} parameter is the maximum number of levels of
      * directories to visit. A value of {@code 0} means that only the starting
      * file is visited, unless denied by the security manager. A value of
      * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
-     * levels should be visited.
+     * levels should be visited. The {@code visitFile} method is invoked for all
+     * files, including directories, encountered at {@code maxDepth}, unless the
+     * basic file attributes cannot be read, in which case the {@code
+     * visitFileFailed} method is invoked.
      *
      * <p> If a visitor returns a result of {@code null} then {@code
      * NullPointerException} is thrown.
@@ -215,11 +212,14 @@
      *          In the case of the default provider, the {@link
      *          SecurityManager#checkRead(String) checkRead} method is invoked
      *          to check read access to the directory.
+     * @throws  IOException
+     *          If an I/O error is thrown by a visitor method
      */
     public static void walkFileTree(Path start,
                                     Set<FileVisitOption> options,
                                     int maxDepth,
                                     FileVisitor<? super Path> visitor)
+        throws IOException
     {
         if (maxDepth < 0)
             throw new IllegalArgumentException("'maxDepth' is negative");
@@ -245,8 +245,12 @@
      *          In the case of the default provider, the {@link
      *          SecurityManager#checkRead(String) checkRead} method is invoked
      *          to check read access to the directory.
+     * @throws  IOException
+     *          If an I/O error is thrown by a visitor method
      */
-    public static void walkFileTree(Path start, FileVisitor<? super Path> visitor) {
+    public static void walkFileTree(Path start, FileVisitor<? super Path> visitor)
+        throws IOException
+    {
         walkFileTree(start,
                      EnumSet.noneOf(FileVisitOption.class),
                      Integer.MAX_VALUE,
--- a/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java	Wed Jul 05 17:24:13 2017 +0200
@@ -27,7 +27,7 @@
 
 import java.nio.file.attribute.BasicFileAttributes;
 import java.io.IOException;
-import java.io.IOError;
+import java.util.Objects;
 
 /**
  * A simple visitor of files with default behavior to visit all files and to
@@ -48,70 +48,47 @@
     }
 
     /**
-     * Throws NullPointerException if obj is null.
-     */
-    private static void checkNotNull(Object obj) {
-        if (obj == null)
-            throw new NullPointerException();
-    }
-
-    /**
      * Invoked for a directory before entries in the directory are visited.
      *
      * <p> Unless overridden, this method returns {@link FileVisitResult#CONTINUE
      * CONTINUE}.
      */
     @Override
-    public FileVisitResult preVisitDirectory(T dir) {
-        checkNotNull(dir);
+    public FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)
+        throws IOException
+    {
+        Objects.nonNull(dir);
+        Objects.nonNull(attrs);
         return FileVisitResult.CONTINUE;
     }
 
     /**
-     * Invoked for a directory that could not be opened.
-     *
-     * <p> Unless overridden, this method throws {@link IOError} with the I/O
-     * exception as cause.
-     *
-     * @throws  IOError
-     *          with the I/O exception thrown when the attempt to open the
-     *          directory failed
-     */
-    @Override
-    public FileVisitResult preVisitDirectoryFailed(T dir, IOException exc) {
-        checkNotNull(dir);
-        checkNotNull(exc);
-        throw new IOError(exc);
-    }
-
-    /**
      * Invoked for a file in a directory.
      *
      * <p> Unless overridden, this method returns {@link FileVisitResult#CONTINUE
      * CONTINUE}.
      */
     @Override
-    public FileVisitResult visitFile(T file, BasicFileAttributes attrs) {
-        checkNotNull(file);
-        checkNotNull(attrs);
+    public FileVisitResult visitFile(T file, BasicFileAttributes attrs)
+        throws IOException
+    {
+        Objects.nonNull(file);
+        Objects.nonNull(attrs);
         return FileVisitResult.CONTINUE;
     }
 
     /**
-     * Invoked for a file when its basic file attributes could not be read.
+     * Invoked for a file that could not be visited.
      *
-     * <p> Unless overridden, this method throws {@link IOError} with the I/O
-     * exception as cause.
-     *
-     * @throws  IOError
-     *          with the I/O exception thrown when the attempt to read the file
-     *          attributes failed
+     * <p> Unless overridden, this method re-throws the I/O exception that prevented
+     * the file from being visited.
      */
     @Override
-    public FileVisitResult visitFileFailed(T file, IOException exc) {
-        checkNotNull(file);
-        checkNotNull(exc);
-        throw new IOError(exc);
+    public FileVisitResult visitFileFailed(T file, IOException exc)
+        throws IOException
+    {
+        Objects.nonNull(file);
+        throw exc;
     }
 
     /**
@@ -120,18 +97,16 @@
      *
      * <p> Unless overridden, this method returns {@link FileVisitResult#CONTINUE
      * CONTINUE} if the directory iteration completes without an I/O exception;
-     * otherwise this method throws {@link IOError} with the I/O exception as
-     * cause.
-     *
-     * @throws  IOError
-     *          with the I/O exception thrown when iteration of the directory
-     *          completed prematurely due to an I/O error
+     * otherwise this method re-throws the I/O exception that caused the iteration
+     * of the directory to terminate prematurely.
      */
     @Override
-    public FileVisitResult postVisitDirectory(T dir, IOException exc) {
-        checkNotNull(dir);
+    public FileVisitResult postVisitDirectory(T dir, IOException exc)
+        throws IOException
+    {
+        Objects.nonNull(dir);
         if (exc != null)
-            throw new IOError(exc);
+            throw exc;
         return FileVisitResult.CONTINUE;
     }
 }
--- a/jdk/src/share/classes/java/sql/DatabaseMetaData.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/sql/DatabaseMetaData.java	Wed Jul 05 17:24:13 2017 +0200
@@ -3643,7 +3643,7 @@
 
     /**
      * Retrieves whether a generated key will always be returned if the column
-     * name(s) or indexe(s) specified for the auto generated key column(s)
+     * name(s) or index(es) specified for the auto generated key column(s)
      * are valid and the statement succeeds.  The key that is returned may or
      * may not be based on the column(s) for the auto generated key.
      * Consult your JDBC driver documentation for additional details.
--- a/jdk/src/share/classes/java/sql/Statement.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/sql/Statement.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1051,9 +1051,9 @@
 
     /**
      * Returns a value indicating whether this {@code Statement} will be
-     * closed when all dependent objects such as resultsets are closed.
+     * closed when all its dependent result sets are closed.
      * @return {@code true} if the {@code Statement} will be closed when all
-     * of its dependent objects are closed; {@code false} otherwise
+     * of its dependent result sets are closed; {@code false} otherwise
      * @throws SQLException if this method is called on a closed
      * {@code Statement}
      * @since 1.7
--- a/jdk/src/share/classes/java/util/Locale.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/util/Locale.java	Wed Jul 05 17:24:13 2017 +0200
@@ -569,6 +569,9 @@
      * @exception NullPointerException thrown if any argument is null.
      */
     public Locale(String language, String country, String variant) {
+        if (language== null || country == null || variant == null) {
+            throw new NullPointerException();
+        }
         _baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
         _extensions = getCompatibilityExtensions(language, "", country, variant);
     }
--- a/jdk/src/share/classes/java/util/ResourceBundle.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/util/ResourceBundle.java	Wed Jul 05 17:24:13 2017 +0200
@@ -293,16 +293,6 @@
         = new ConcurrentHashMap<CacheKey, BundleReference>(INITIAL_CACHE_SIZE);
 
     /**
-     * This ConcurrentMap is used to keep multiple threads from loading the
-     * same bundle concurrently.  The table entries are <CacheKey, Thread>
-     * where CacheKey is the key for the bundle that is under construction
-     * and Thread is the thread that is constructing the bundle.
-     * This list is manipulated in findBundleInCache and putBundleInCache.
-     */
-    private static final ConcurrentMap<CacheKey, Thread> underConstruction
-        = new ConcurrentHashMap<CacheKey, Thread>();
-
-    /**
      * Queue for reference objects referring to class loaders or bundles.
      */
     private static final ReferenceQueue referenceQueue = new ReferenceQueue();
@@ -1381,7 +1371,7 @@
         boolean expiredBundle = false;
 
         // First, look up the cache to see if it's in the cache, without
-        // declaring beginLoading.
+        // attempting to load bundle.
         cacheKey.setLocale(targetLocale);
         ResourceBundle bundle = findBundleInCache(cacheKey, control);
         if (isValidBundle(bundle)) {
@@ -1408,56 +1398,25 @@
             CacheKey constKey = (CacheKey) cacheKey.clone();
 
             try {
-                // Try declaring loading. If beginLoading() returns true,
-                // then we can proceed. Otherwise, we need to take a look
-                // at the cache again to see if someone else has loaded
-                // the bundle and put it in the cache while we've been
-                // waiting for other loading work to complete.
-                while (!beginLoading(constKey)) {
-                    bundle = findBundleInCache(cacheKey, control);
-                    if (bundle == null) {
-                        continue;
+                bundle = loadBundle(cacheKey, formats, control, expiredBundle);
+                if (bundle != null) {
+                    if (bundle.parent == null) {
+                        bundle.setParent(parent);
                     }
-                    if (bundle == NONEXISTENT_BUNDLE) {
-                        // If the bundle is NONEXISTENT_BUNDLE, the bundle doesn't exist.
-                        return parent;
-                    }
-                    expiredBundle = bundle.expired;
-                    if (!expiredBundle) {
-                        if (bundle.parent == parent) {
-                            return bundle;
-                        }
-                        BundleReference bundleRef = cacheList.get(cacheKey);
-                        if (bundleRef != null && bundleRef.get() == bundle) {
-                            cacheList.remove(cacheKey, bundleRef);
-                        }
-                    }
+                    bundle.locale = targetLocale;
+                    bundle = putBundleInCache(cacheKey, bundle, control);
+                    return bundle;
                 }
 
-                try {
-                    bundle = loadBundle(cacheKey, formats, control, expiredBundle);
-                    if (bundle != null) {
-                        if (bundle.parent == null) {
-                            bundle.setParent(parent);
-                        }
-                        bundle.locale = targetLocale;
-                        bundle = putBundleInCache(cacheKey, bundle, control);
-                        return bundle;
-                    }
-
-                    // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
-                    // instance for the locale.
-                    putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control);
-                } finally {
-                    endLoading(constKey);
-                }
+                // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
+                // instance for the locale.
+                putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control);
             } finally {
                 if (constKey.getCause() instanceof InterruptedException) {
                     Thread.currentThread().interrupt();
                 }
             }
         }
-        assert underConstruction.get(cacheKey) != Thread.currentThread();
         return parent;
     }
 
@@ -1465,7 +1424,6 @@
                                                    List<String> formats,
                                                    Control control,
                                                    boolean reload) {
-        assert underConstruction.get(cacheKey) == Thread.currentThread();
 
         // Here we actually load the bundle in the order of formats
         // specified by the getFormats() value.
@@ -1498,7 +1456,6 @@
                 break;
             }
         }
-        assert underConstruction.get(cacheKey) == Thread.currentThread();
 
         return bundle;
     }
@@ -1530,57 +1487,6 @@
     }
 
     /**
-     * Declares the beginning of actual resource bundle loading. This method
-     * returns true if the declaration is successful and the current thread has
-     * been put in underConstruction. If someone else has already begun
-     * loading, this method waits until that loading work is complete and
-     * returns false.
-     */
-    private static final boolean beginLoading(CacheKey constKey) {
-        Thread me = Thread.currentThread();
-        Thread worker;
-        // We need to declare by putting the current Thread (me) to
-        // underConstruction that we are working on loading the specified
-        // resource bundle. If we are already working the loading, it means
-        // that the resource loading requires a recursive call. In that case,
-        // we have to proceed. (4300693)
-        if (((worker = underConstruction.putIfAbsent(constKey, me)) == null)
-            || worker == me) {
-            return true;
-        }
-
-        // If someone else is working on the loading, wait until
-        // the Thread finishes the bundle loading.
-        synchronized (worker) {
-            while (underConstruction.get(constKey) == worker) {
-                try {
-                    worker.wait();
-                } catch (InterruptedException e) {
-                    // record the interruption
-                    constKey.setCause(e);
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Declares the end of the bundle loading. This method calls notifyAll
-     * for those who are waiting for this completion.
-     */
-    private static final void endLoading(CacheKey constKey) {
-        // Remove this Thread from the underConstruction map and wake up
-        // those who have been waiting for me to complete this bundle
-        // loading.
-        Thread me = Thread.currentThread();
-        assert (underConstruction.get(constKey) == me);
-        underConstruction.remove(constKey);
-        synchronized (me) {
-            me.notifyAll();
-        }
-    }
-
-    /**
      * Throw a MissingResourceException with proper message
      */
     private static final void throwMissingResourceException(String baseName,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,1445 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from members of
+ * JCP JSR-166 Expert Group and released to the public domain, as explained
+ * at http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.AbstractCollection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+
+/**
+ * An unbounded concurrent {@linkplain Deque deque} based on linked nodes.
+ * Concurrent insertion, removal, and access operations execute safely
+ * across multiple threads.
+ * A {@code ConcurrentLinkedDeque} is an appropriate choice when
+ * many threads will share access to a common collection.
+ * Like most other concurrent collection implementations, this class
+ * does not permit the use of {@code null} elements.
+ *
+ * <p>Iterators are <i>weakly consistent</i>, returning elements
+ * reflecting the state of the deque at some point at or since the
+ * creation of the iterator.  They do <em>not</em> throw {@link
+ * java.util.ConcurrentModificationException
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations.
+ *
+ * <p>Beware that, unlike in most collections, the {@code size}
+ * method is <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these deques, determining the current number
+ * of elements requires a traversal of the elements.
+ *
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Deque} and {@link Iterator} interfaces.
+ *
+ * <p>Memory consistency effects: As with other concurrent collections,
+ * actions in a thread prior to placing an object into a
+ * {@code ConcurrentLinkedDeque}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code ConcurrentLinkedDeque} in another thread.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ * @author Martin Buchholz
+ * @param <E> the type of elements held in this collection
+ */
+
+public class ConcurrentLinkedDeque<E>
+    extends AbstractCollection<E>
+    implements Deque<E>, java.io.Serializable {
+
+    /*
+     * This is an implementation of a concurrent lock-free deque
+     * supporting interior removes but not interior insertions, as
+     * required to support the entire Deque interface.
+     *
+     * We extend the techniques developed for ConcurrentLinkedQueue and
+     * LinkedTransferQueue (see the internal docs for those classes).
+     * Understanding the ConcurrentLinkedQueue implementation is a
+     * prerequisite for understanding the implementation of this class.
+     *
+     * The data structure is a symmetrical doubly-linked "GC-robust"
+     * linked list of nodes.  We minimize the number of volatile writes
+     * using two techniques: advancing multiple hops with a single CAS
+     * and mixing volatile and non-volatile writes of the same memory
+     * locations.
+     *
+     * A node contains the expected E ("item") and links to predecessor
+     * ("prev") and successor ("next") nodes:
+     *
+     * class Node<E> { volatile Node<E> prev, next; volatile E item; }
+     *
+     * A node p is considered "live" if it contains a non-null item
+     * (p.item != null).  When an item is CASed to null, the item is
+     * atomically logically deleted from the collection.
+     *
+     * At any time, there is precisely one "first" node with a null
+     * prev reference that terminates any chain of prev references
+     * starting at a live node.  Similarly there is precisely one
+     * "last" node terminating any chain of next references starting at
+     * a live node.  The "first" and "last" nodes may or may not be live.
+     * The "first" and "last" nodes are always mutually reachable.
+     *
+     * A new element is added atomically by CASing the null prev or
+     * next reference in the first or last node to a fresh node
+     * containing the element.  The element's node atomically becomes
+     * "live" at that point.
+     *
+     * A node is considered "active" if it is a live node, or the
+     * first or last node.  Active nodes cannot be unlinked.
+     *
+     * A "self-link" is a next or prev reference that is the same node:
+     *   p.prev == p  or  p.next == p
+     * Self-links are used in the node unlinking process.  Active nodes
+     * never have self-links.
+     *
+     * A node p is active if and only if:
+     *
+     * p.item != null ||
+     * (p.prev == null && p.next != p) ||
+     * (p.next == null && p.prev != p)
+     *
+     * The deque object has two node references, "head" and "tail".
+     * The head and tail are only approximations to the first and last
+     * nodes of the deque.  The first node can always be found by
+     * following prev pointers from head; likewise for tail.  However,
+     * it is permissible for head and tail to be referring to deleted
+     * nodes that have been unlinked and so may not be reachable from
+     * any live node.
+     *
+     * There are 3 stages of node deletion;
+     * "logical deletion", "unlinking", and "gc-unlinking".
+     *
+     * 1. "logical deletion" by CASing item to null atomically removes
+     * the element from the collection, and makes the containing node
+     * eligible for unlinking.
+     *
+     * 2. "unlinking" makes a deleted node unreachable from active
+     * nodes, and thus eventually reclaimable by GC.  Unlinked nodes
+     * may remain reachable indefinitely from an iterator.
+     *
+     * Physical node unlinking is merely an optimization (albeit a
+     * critical one), and so can be performed at our convenience.  At
+     * any time, the set of live nodes maintained by prev and next
+     * links are identical, that is, the live nodes found via next
+     * links from the first node is equal to the elements found via
+     * prev links from the last node.  However, this is not true for
+     * nodes that have already been logically deleted - such nodes may
+     * be reachable in one direction only.
+     *
+     * 3. "gc-unlinking" takes unlinking further by making active
+     * nodes unreachable from deleted nodes, making it easier for the
+     * GC to reclaim future deleted nodes.  This step makes the data
+     * structure "gc-robust", as first described in detail by Boehm
+     * (http://portal.acm.org/citation.cfm?doid=503272.503282).
+     *
+     * GC-unlinked nodes may remain reachable indefinitely from an
+     * iterator, but unlike unlinked nodes, are never reachable from
+     * head or tail.
+     *
+     * Making the data structure GC-robust will eliminate the risk of
+     * unbounded memory retention with conservative GCs and is likely
+     * to improve performance with generational GCs.
+     *
+     * When a node is dequeued at either end, e.g. via poll(), we would
+     * like to break any references from the node to active nodes.  We
+     * develop further the use of self-links that was very effective in
+     * other concurrent collection classes.  The idea is to replace
+     * prev and next pointers with special values that are interpreted
+     * to mean off-the-list-at-one-end.  These are approximations, but
+     * good enough to preserve the properties we want in our
+     * traversals, e.g. we guarantee that a traversal will never visit
+     * the same element twice, but we don't guarantee whether a
+     * traversal that runs out of elements will be able to see more
+     * elements later after enqueues at that end.  Doing gc-unlinking
+     * safely is particularly tricky, since any node can be in use
+     * indefinitely (for example by an iterator).  We must ensure that
+     * the nodes pointed at by head/tail never get gc-unlinked, since
+     * head/tail are needed to get "back on track" by other nodes that
+     * are gc-unlinked.  gc-unlinking accounts for much of the
+     * implementation complexity.
+     *
+     * Since neither unlinking nor gc-unlinking are necessary for
+     * correctness, there are many implementation choices regarding
+     * frequency (eagerness) of these operations.  Since volatile
+     * reads are likely to be much cheaper than CASes, saving CASes by
+     * unlinking multiple adjacent nodes at a time may be a win.
+     * gc-unlinking can be performed rarely and still be effective,
+     * since it is most important that long chains of deleted nodes
+     * are occasionally broken.
+     *
+     * The actual representation we use is that p.next == p means to
+     * goto the first node (which in turn is reached by following prev
+     * pointers from head), and p.next == null && p.prev == p means
+     * that the iteration is at an end and that p is a (final static)
+     * dummy node, NEXT_TERMINATOR, and not the last active node.
+     * Finishing the iteration when encountering such a TERMINATOR is
+     * good enough for read-only traversals, so such traversals can use
+     * p.next == null as the termination condition.  When we need to
+     * find the last (active) node, for enqueueing a new node, we need
+     * to check whether we have reached a TERMINATOR node; if so,
+     * restart traversal from tail.
+     *
+     * The implementation is completely directionally symmetrical,
+     * except that most public methods that iterate through the list
+     * follow next pointers ("forward" direction).
+     *
+     * We believe (without full proof) that all single-element deque
+     * operations (e.g., addFirst, peekLast, pollLast) are linearizable
+     * (see Herlihy and Shavit's book).  However, some combinations of
+     * operations are known not to be linearizable.  In particular,
+     * when an addFirst(A) is racing with pollFirst() removing B, it is
+     * possible for an observer iterating over the elements to observe
+     * A B C and subsequently observe A C, even though no interior
+     * removes are ever performed.  Nevertheless, iterators behave
+     * reasonably, providing the "weakly consistent" guarantees.
+     *
+     * Empirically, microbenchmarks suggest that this class adds about
+     * 40% overhead relative to ConcurrentLinkedQueue, which feels as
+     * good as we can hope for.
+     */
+
+    private static final long serialVersionUID = 876323262645176354L;
+
+    /**
+     * A node from which the first node on list (that is, the unique node p
+     * with p.prev == null && p.next != p) can be reached in O(1) time.
+     * Invariants:
+     * - the first node is always O(1) reachable from head via prev links
+     * - all live nodes are reachable from the first node via succ()
+     * - head != null
+     * - (tmp = head).next != tmp || tmp != head
+     * - head is never gc-unlinked (but may be unlinked)
+     * Non-invariants:
+     * - head.item may or may not be null
+     * - head may not be reachable from the first or last node, or from tail
+     */
+    private transient volatile Node<E> head;
+
+    /**
+     * A node from which the last node on list (that is, the unique node p
+     * with p.next == null && p.prev != p) can be reached in O(1) time.
+     * Invariants:
+     * - the last node is always O(1) reachable from tail via next links
+     * - all live nodes are reachable from the last node via pred()
+     * - tail != null
+     * - tail is never gc-unlinked (but may be unlinked)
+     * Non-invariants:
+     * - tail.item may or may not be null
+     * - tail may not be reachable from the first or last node, or from head
+     */
+    private transient volatile Node<E> tail;
+
+    private final static Node<Object> PREV_TERMINATOR, NEXT_TERMINATOR;
+
+    static {
+        PREV_TERMINATOR = new Node<Object>(null);
+        PREV_TERMINATOR.next = PREV_TERMINATOR;
+        NEXT_TERMINATOR = new Node<Object>(null);
+        NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
+    }
+
+    @SuppressWarnings("unchecked")
+    Node<E> prevTerminator() {
+        return (Node<E>) PREV_TERMINATOR;
+    }
+
+    @SuppressWarnings("unchecked")
+    Node<E> nextTerminator() {
+        return (Node<E>) NEXT_TERMINATOR;
+    }
+
+    static final class Node<E> {
+        volatile Node<E> prev;
+        volatile E item;
+        volatile Node<E> next;
+
+        /**
+         * Constructs a new node.  Uses relaxed write because item can
+         * only be seen after publication via casNext or casPrev.
+         */
+        Node(E item) {
+            UNSAFE.putObject(this, itemOffset, item);
+        }
+
+        boolean casItem(E cmp, E val) {
+            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+        }
+
+        void lazySetNext(Node<E> val) {
+            UNSAFE.putOrderedObject(this, nextOffset, val);
+        }
+
+        boolean casNext(Node<E> cmp, Node<E> val) {
+            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+        }
+
+        void lazySetPrev(Node<E> val) {
+            UNSAFE.putOrderedObject(this, prevOffset, val);
+        }
+
+        boolean casPrev(Node<E> cmp, Node<E> val) {
+            return UNSAFE.compareAndSwapObject(this, prevOffset, cmp, val);
+        }
+
+        // Unsafe mechanics
+
+        private static final sun.misc.Unsafe UNSAFE =
+            sun.misc.Unsafe.getUnsafe();
+        private static final long prevOffset =
+            objectFieldOffset(UNSAFE, "prev", Node.class);
+        private static final long itemOffset =
+            objectFieldOffset(UNSAFE, "item", Node.class);
+        private static final long nextOffset =
+            objectFieldOffset(UNSAFE, "next", Node.class);
+    }
+
+    /**
+     * Links e as first element.
+     */
+    private void linkFirst(E e) {
+        checkNotNull(e);
+        final Node<E> newNode = new Node<E>(e);
+
+        restartFromHead:
+        for (;;)
+            for (Node<E> h = head, p = h, q;;) {
+                if ((q = p.prev) != null &&
+                    (q = (p = q).prev) != null)
+                    // Check for head updates every other hop.
+                    // If p == q, we are sure to follow head instead.
+                    p = (h != (h = head)) ? h : q;
+                else if (p.next == p) // PREV_TERMINATOR
+                    continue restartFromHead;
+                else {
+                    // p is first node
+                    newNode.lazySetNext(p); // CAS piggyback
+                    if (p.casPrev(null, newNode)) {
+                        // Successful CAS is the linearization point
+                        // for e to become an element of this deque,
+                        // and for newNode to become "live".
+                        if (p != h) // hop two nodes at a time
+                            casHead(h, newNode);  // Failure is OK.
+                        return;
+                    }
+                    // Lost CAS race to another thread; re-read prev
+                }
+            }
+    }
+
+    /**
+     * Links e as last element.
+     */
+    private void linkLast(E e) {
+        checkNotNull(e);
+        final Node<E> newNode = new Node<E>(e);
+
+        restartFromTail:
+        for (;;)
+            for (Node<E> t = tail, p = t, q;;) {
+                if ((q = p.next) != null &&
+                    (q = (p = q).next) != null)
+                    // Check for tail updates every other hop.
+                    // If p == q, we are sure to follow tail instead.
+                    p = (t != (t = tail)) ? t : q;
+                else if (p.prev == p) // NEXT_TERMINATOR
+                    continue restartFromTail;
+                else {
+                    // p is last node
+                    newNode.lazySetPrev(p); // CAS piggyback
+                    if (p.casNext(null, newNode)) {
+                        // Successful CAS is the linearization point
+                        // for e to become an element of this deque,
+                        // and for newNode to become "live".
+                        if (p != t) // hop two nodes at a time
+                            casTail(t, newNode);  // Failure is OK.
+                        return;
+                    }
+                    // Lost CAS race to another thread; re-read next
+                }
+            }
+    }
+
+    private final static int HOPS = 2;
+
+    /**
+     * Unlinks non-null node x.
+     */
+    void unlink(Node<E> x) {
+        // assert x != null;
+        // assert x.item == null;
+        // assert x != PREV_TERMINATOR;
+        // assert x != NEXT_TERMINATOR;
+
+        final Node<E> prev = x.prev;
+        final Node<E> next = x.next;
+        if (prev == null) {
+            unlinkFirst(x, next);
+        } else if (next == null) {
+            unlinkLast(x, prev);
+        } else {
+            // Unlink interior node.
+            //
+            // This is the common case, since a series of polls at the
+            // same end will be "interior" removes, except perhaps for
+            // the first one, since end nodes cannot be unlinked.
+            //
+            // At any time, all active nodes are mutually reachable by
+            // following a sequence of either next or prev pointers.
+            //
+            // Our strategy is to find the unique active predecessor
+            // and successor of x.  Try to fix up their links so that
+            // they point to each other, leaving x unreachable from
+            // active nodes.  If successful, and if x has no live
+            // predecessor/successor, we additionally try to gc-unlink,
+            // leaving active nodes unreachable from x, by rechecking
+            // that the status of predecessor and successor are
+            // unchanged and ensuring that x is not reachable from
+            // tail/head, before setting x's prev/next links to their
+            // logical approximate replacements, self/TERMINATOR.
+            Node<E> activePred, activeSucc;
+            boolean isFirst, isLast;
+            int hops = 1;
+
+            // Find active predecessor
+            for (Node<E> p = prev; ; ++hops) {
+                if (p.item != null) {
+                    activePred = p;
+                    isFirst = false;
+                    break;
+                }
+                Node<E> q = p.prev;
+                if (q == null) {
+                    if (p.next == p)
+                        return;
+                    activePred = p;
+                    isFirst = true;
+                    break;
+                }
+                else if (p == q)
+                    return;
+                else
+                    p = q;
+            }
+
+            // Find active successor
+            for (Node<E> p = next; ; ++hops) {
+                if (p.item != null) {
+                    activeSucc = p;
+                    isLast = false;
+                    break;
+                }
+                Node<E> q = p.next;
+                if (q == null) {
+                    if (p.prev == p)
+                        return;
+                    activeSucc = p;
+                    isLast = true;
+                    break;
+                }
+                else if (p == q)
+                    return;
+                else
+                    p = q;
+            }
+
+            // TODO: better HOP heuristics
+            if (hops < HOPS
+                // always squeeze out interior deleted nodes
+                && (isFirst | isLast))
+                return;
+
+            // Squeeze out deleted nodes between activePred and
+            // activeSucc, including x.
+            skipDeletedSuccessors(activePred);
+            skipDeletedPredecessors(activeSucc);
+
+            // Try to gc-unlink, if possible
+            if ((isFirst | isLast) &&
+
+                // Recheck expected state of predecessor and successor
+                (activePred.next == activeSucc) &&
+                (activeSucc.prev == activePred) &&
+                (isFirst ? activePred.prev == null : activePred.item != null) &&
+                (isLast  ? activeSucc.next == null : activeSucc.item != null)) {
+
+                updateHead(); // Ensure x is not reachable from head
+                updateTail(); // Ensure x is not reachable from tail
+
+                // Finally, actually gc-unlink
+                x.lazySetPrev(isFirst ? prevTerminator() : x);
+                x.lazySetNext(isLast  ? nextTerminator() : x);
+            }
+        }
+    }
+
+    /**
+     * Unlinks non-null first node.
+     */
+    private void unlinkFirst(Node<E> first, Node<E> next) {
+        // assert first != null;
+        // assert next != null;
+        // assert first.item == null;
+        for (Node<E> o = null, p = next, q;;) {
+            if (p.item != null || (q = p.next) == null) {
+                if (o != null && p.prev != p && first.casNext(next, p)) {
+                    skipDeletedPredecessors(p);
+                    if (first.prev == null &&
+                        (p.next == null || p.item != null) &&
+                        p.prev == first) {
+
+                        updateHead(); // Ensure o is not reachable from head
+                        updateTail(); // Ensure o is not reachable from tail
+
+                        // Finally, actually gc-unlink
+                        o.lazySetNext(o);
+                        o.lazySetPrev(prevTerminator());
+                    }
+                }
+                return;
+            }
+            else if (p == q)
+                return;
+            else {
+                o = p;
+                p = q;
+            }
+        }
+    }
+
+    /**
+     * Unlinks non-null last node.
+     */
+    private void unlinkLast(Node<E> last, Node<E> prev) {
+        // assert last != null;
+        // assert prev != null;
+        // assert last.item == null;
+        for (Node<E> o = null, p = prev, q;;) {
+            if (p.item != null || (q = p.prev) == null) {
+                if (o != null && p.next != p && last.casPrev(prev, p)) {
+                    skipDeletedSuccessors(p);
+                    if (last.next == null &&
+                        (p.prev == null || p.item != null) &&
+                        p.next == last) {
+
+                        updateHead(); // Ensure o is not reachable from head
+                        updateTail(); // Ensure o is not reachable from tail
+
+                        // Finally, actually gc-unlink
+                        o.lazySetPrev(o);
+                        o.lazySetNext(nextTerminator());
+                    }
+                }
+                return;
+            }
+            else if (p == q)
+                return;
+            else {
+                o = p;
+                p = q;
+            }
+        }
+    }
+
+    /**
+     * Guarantees that any node which was unlinked before a call to
+     * this method will be unreachable from head after it returns.
+     * Does not guarantee to eliminate slack, only that head will
+     * point to a node that was active while this method was running.
+     */
+    private final void updateHead() {
+        // Either head already points to an active node, or we keep
+        // trying to cas it to the first node until it does.
+        Node<E> h, p, q;
+        restartFromHead:
+        while ((h = head).item == null && (p = h.prev) != null) {
+            for (;;) {
+                if ((q = p.prev) == null ||
+                    (q = (p = q).prev) == null) {
+                    // It is possible that p is PREV_TERMINATOR,
+                    // but if so, the CAS is guaranteed to fail.
+                    if (casHead(h, p))
+                        return;
+                    else
+                        continue restartFromHead;
+                }
+                else if (h != head)
+                    continue restartFromHead;
+                else
+                    p = q;
+            }
+        }
+    }
+
+    /**
+     * Guarantees that any node which was unlinked before a call to
+     * this method will be unreachable from tail after it returns.
+     * Does not guarantee to eliminate slack, only that tail will
+     * point to a node that was active while this method was running.
+     */
+    private final void updateTail() {
+        // Either tail already points to an active node, or we keep
+        // trying to cas it to the last node until it does.
+        Node<E> t, p, q;
+        restartFromTail:
+        while ((t = tail).item == null && (p = t.next) != null) {
+            for (;;) {
+                if ((q = p.next) == null ||
+                    (q = (p = q).next) == null) {
+                    // It is possible that p is NEXT_TERMINATOR,
+                    // but if so, the CAS is guaranteed to fail.
+                    if (casTail(t, p))
+                        return;
+                    else
+                        continue restartFromTail;
+                }
+                else if (t != tail)
+                    continue restartFromTail;
+                else
+                    p = q;
+            }
+        }
+    }
+
+    private void skipDeletedPredecessors(Node<E> x) {
+        whileActive:
+        do {
+            Node<E> prev = x.prev;
+            // assert prev != null;
+            // assert x != NEXT_TERMINATOR;
+            // assert x != PREV_TERMINATOR;
+            Node<E> p = prev;
+            findActive:
+            for (;;) {
+                if (p.item != null)
+                    break findActive;
+                Node<E> q = p.prev;
+                if (q == null) {
+                    if (p.next == p)
+                        continue whileActive;
+                    break findActive;
+                }
+                else if (p == q)
+                    continue whileActive;
+                else
+                    p = q;
+            }
+
+            // found active CAS target
+            if (prev == p || x.casPrev(prev, p))
+                return;
+
+        } while (x.item != null || x.next == null);
+    }
+
+    private void skipDeletedSuccessors(Node<E> x) {
+        whileActive:
+        do {
+            Node<E> next = x.next;
+            // assert next != null;
+            // assert x != NEXT_TERMINATOR;
+            // assert x != PREV_TERMINATOR;
+            Node<E> p = next;
+            findActive:
+            for (;;) {
+                if (p.item != null)
+                    break findActive;
+                Node<E> q = p.next;
+                if (q == null) {
+                    if (p.prev == p)
+                        continue whileActive;
+                    break findActive;
+                }
+                else if (p == q)
+                    continue whileActive;
+                else
+                    p = q;
+            }
+
+            // found active CAS target
+            if (next == p || x.casNext(next, p))
+                return;
+
+        } while (x.item != null || x.prev == null);
+    }
+
+    /**
+     * Returns the successor of p, or the first node if p.next has been
+     * linked to self, which will only be true if traversing with a
+     * stale pointer that is now off the list.
+     */
+    final Node<E> succ(Node<E> p) {
+        // TODO: should we skip deleted nodes here?
+        Node<E> q = p.next;
+        return (p == q) ? first() : q;
+    }
+
+    /**
+     * Returns the predecessor of p, or the last node if p.prev has been
+     * linked to self, which will only be true if traversing with a
+     * stale pointer that is now off the list.
+     */
+    final Node<E> pred(Node<E> p) {
+        Node<E> q = p.prev;
+        return (p == q) ? last() : q;
+    }
+
+    /**
+     * Returns the first node, the unique node p for which:
+     *     p.prev == null && p.next != p
+     * The returned node may or may not be logically deleted.
+     * Guarantees that head is set to the returned node.
+     */
+    Node<E> first() {
+        restartFromHead:
+        for (;;)
+            for (Node<E> h = head, p = h, q;;) {
+                if ((q = p.prev) != null &&
+                    (q = (p = q).prev) != null)
+                    // Check for head updates every other hop.
+                    // If p == q, we are sure to follow head instead.
+                    p = (h != (h = head)) ? h : q;
+                else if (p == h
+                         // It is possible that p is PREV_TERMINATOR,
+                         // but if so, the CAS is guaranteed to fail.
+                         || casHead(h, p))
+                    return p;
+                else
+                    continue restartFromHead;
+            }
+    }
+
+    /**
+     * Returns the last node, the unique node p for which:
+     *     p.next == null && p.prev != p
+     * The returned node may or may not be logically deleted.
+     * Guarantees that tail is set to the returned node.
+     */
+    Node<E> last() {
+        restartFromTail:
+        for (;;)
+            for (Node<E> t = tail, p = t, q;;) {
+                if ((q = p.next) != null &&
+                    (q = (p = q).next) != null)
+                    // Check for tail updates every other hop.
+                    // If p == q, we are sure to follow tail instead.
+                    p = (t != (t = tail)) ? t : q;
+                else if (p == t
+                         // It is possible that p is NEXT_TERMINATOR,
+                         // but if so, the CAS is guaranteed to fail.
+                         || casTail(t, p))
+                    return p;
+                else
+                    continue restartFromTail;
+            }
+    }
+
+    // Minor convenience utilities
+
+    /**
+     * Throws NullPointerException if argument is null.
+     *
+     * @param v the element
+     */
+    private static void checkNotNull(Object v) {
+        if (v == null)
+            throw new NullPointerException();
+    }
+
+    /**
+     * Returns element unless it is null, in which case throws
+     * NoSuchElementException.
+     *
+     * @param v the element
+     * @return the element
+     */
+    private E screenNullResult(E v) {
+        if (v == null)
+            throw new NoSuchElementException();
+        return v;
+    }
+
+    /**
+     * Creates an array list and fills it with elements of this list.
+     * Used by toArray.
+     *
+     * @return the arrayList
+     */
+    private ArrayList<E> toArrayList() {
+        ArrayList<E> list = new ArrayList<E>();
+        for (Node<E> p = first(); p != null; p = succ(p)) {
+            E item = p.item;
+            if (item != null)
+                list.add(item);
+        }
+        return list;
+    }
+
+    /**
+     * Constructs an empty deque.
+     */
+    public ConcurrentLinkedDeque() {
+        head = tail = new Node<E>(null);
+    }
+
+    /**
+     * Constructs a deque initially containing the elements of
+     * the given collection, added in traversal order of the
+     * collection's iterator.
+     *
+     * @param c the collection of elements to initially contain
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
+     */
+    public ConcurrentLinkedDeque(Collection<? extends E> c) {
+        // Copy c into a private chain of Nodes
+        Node<E> h = null, t = null;
+        for (E e : c) {
+            checkNotNull(e);
+            Node<E> newNode = new Node<E>(e);
+            if (h == null)
+                h = t = newNode;
+            else {
+                t.lazySetNext(newNode);
+                newNode.lazySetPrev(t);
+                t = newNode;
+            }
+        }
+        initHeadTail(h, t);
+    }
+
+    /**
+     * Initializes head and tail, ensuring invariants hold.
+     */
+    private void initHeadTail(Node<E> h, Node<E> t) {
+        if (h == t) {
+            if (h == null)
+                h = t = new Node<E>(null);
+            else {
+                // Avoid edge case of a single Node with non-null item.
+                Node<E> newNode = new Node<E>(null);
+                t.lazySetNext(newNode);
+                newNode.lazySetPrev(t);
+                t = newNode;
+            }
+        }
+        head = h;
+        tail = t;
+    }
+
+    /**
+     * Inserts the specified element at the front of this deque.
+     *
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void addFirst(E e) {
+        linkFirst(e);
+    }
+
+    /**
+     * Inserts the specified element at the end of this deque.
+     *
+     * <p>This method is equivalent to {@link #add}.
+     *
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void addLast(E e) {
+        linkLast(e);
+    }
+
+    /**
+     * Inserts the specified element at the front of this deque.
+     *
+     * @return {@code true} always
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean offerFirst(E e) {
+        linkFirst(e);
+        return true;
+    }
+
+    /**
+     * Inserts the specified element at the end of this deque.
+     *
+     * <p>This method is equivalent to {@link #add}.
+     *
+     * @return {@code true} always
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean offerLast(E e) {
+        linkLast(e);
+        return true;
+    }
+
+    public E peekFirst() {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
+            E item = p.item;
+            if (item != null)
+                return item;
+        }
+        return null;
+    }
+
+    public E peekLast() {
+        for (Node<E> p = last(); p != null; p = pred(p)) {
+            E item = p.item;
+            if (item != null)
+                return item;
+        }
+        return null;
+    }
+
+    /**
+     * @throws NoSuchElementException {@inheritDoc}
+     */
+    public E getFirst() {
+        return screenNullResult(peekFirst());
+    }
+
+    /**
+     * @throws NoSuchElementException {@inheritDoc}
+     */
+    public E getLast()  {
+        return screenNullResult(peekLast());
+    }
+
+    public E pollFirst() {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
+            E item = p.item;
+            if (item != null && p.casItem(item, null)) {
+                unlink(p);
+                return item;
+            }
+        }
+        return null;
+    }
+
+    public E pollLast() {
+        for (Node<E> p = last(); p != null; p = pred(p)) {
+            E item = p.item;
+            if (item != null && p.casItem(item, null)) {
+                unlink(p);
+                return item;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @throws NoSuchElementException {@inheritDoc}
+     */
+    public E removeFirst() {
+        return screenNullResult(pollFirst());
+    }
+
+    /**
+     * @throws NoSuchElementException {@inheritDoc}
+     */
+    public E removeLast() {
+        return screenNullResult(pollLast());
+    }
+
+    // *** Queue and stack methods ***
+
+    /**
+     * Inserts the specified element at the tail of this deque.
+     *
+     * @return {@code true} (as specified by {@link Queue#offer})
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean offer(E e) {
+        return offerLast(e);
+    }
+
+    /**
+     * Inserts the specified element at the tail of this deque.
+     *
+     * @return {@code true} (as specified by {@link Collection#add})
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean add(E e) {
+        return offerLast(e);
+    }
+
+    public E poll()           { return pollFirst(); }
+    public E remove()         { return removeFirst(); }
+    public E peek()           { return peekFirst(); }
+    public E element()        { return getFirst(); }
+    public void push(E e)     { addFirst(e); }
+    public E pop()            { return removeFirst(); }
+
+    /**
+     * Removes the first element {@code e} such that
+     * {@code o.equals(e)}, if such an element exists in this deque.
+     * If the deque does not contain the element, it is unchanged.
+     *
+     * @param o element to be removed from this deque, if present
+     * @return {@code true} if the deque contained the specified element
+     * @throws NullPointerException if the specified element is {@code null}
+     */
+    public boolean removeFirstOccurrence(Object o) {
+        checkNotNull(o);
+        for (Node<E> p = first(); p != null; p = succ(p)) {
+            E item = p.item;
+            if (item != null && o.equals(item) && p.casItem(item, null)) {
+                unlink(p);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Removes the last element {@code e} such that
+     * {@code o.equals(e)}, if such an element exists in this deque.
+     * If the deque does not contain the element, it is unchanged.
+     *
+     * @param o element to be removed from this deque, if present
+     * @return {@code true} if the deque contained the specified element
+     * @throws NullPointerException if the specified element is {@code null}
+     */
+    public boolean removeLastOccurrence(Object o) {
+        checkNotNull(o);
+        for (Node<E> p = last(); p != null; p = pred(p)) {
+            E item = p.item;
+            if (item != null && o.equals(item) && p.casItem(item, null)) {
+                unlink(p);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if this deque contains at least one
+     * element {@code e} such that {@code o.equals(e)}.
+     *
+     * @param o element whose presence in this deque is to be tested
+     * @return {@code true} if this deque contains the specified element
+     */
+    public boolean contains(Object o) {
+        if (o == null) return false;
+        for (Node<E> p = first(); p != null; p = succ(p)) {
+            E item = p.item;
+            if (item != null && o.equals(item))
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if this collection contains no elements.
+     *
+     * @return {@code true} if this collection contains no elements
+     */
+    public boolean isEmpty() {
+        return peekFirst() == null;
+    }
+
+    /**
+     * Returns the number of elements in this deque.  If this deque
+     * contains more than {@code Integer.MAX_VALUE} elements, it
+     * returns {@code Integer.MAX_VALUE}.
+     *
+     * <p>Beware that, unlike in most collections, this method is
+     * <em>NOT</em> a constant-time operation. Because of the
+     * asynchronous nature of these deques, determining the current
+     * number of elements requires traversing them all to count them.
+     * Additionally, it is possible for the size to change during
+     * execution of this method, in which case the returned result
+     * will be inaccurate. Thus, this method is typically not very
+     * useful in concurrent applications.
+     *
+     * @return the number of elements in this deque
+     */
+    public int size() {
+        int count = 0;
+        for (Node<E> p = first(); p != null; p = succ(p))
+            if (p.item != null)
+                // Collection.size() spec says to max out
+                if (++count == Integer.MAX_VALUE)
+                    break;
+        return count;
+    }
+
+    /**
+     * Removes the first element {@code e} such that
+     * {@code o.equals(e)}, if such an element exists in this deque.
+     * If the deque does not contain the element, it is unchanged.
+     *
+     * @param o element to be removed from this deque, if present
+     * @return {@code true} if the deque contained the specified element
+     * @throws NullPointerException if the specified element is {@code null}
+     */
+    public boolean remove(Object o) {
+        return removeFirstOccurrence(o);
+    }
+
+    /**
+     * Appends all of the elements in the specified collection to the end of
+     * this deque, in the order that they are returned by the specified
+     * collection's iterator.  Attempts to {@code addAll} of a deque to
+     * itself result in {@code IllegalArgumentException}.
+     *
+     * @param c the elements to be inserted into this deque
+     * @return {@code true} if this deque changed as a result of the call
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
+     * @throws IllegalArgumentException if the collection is this deque
+     */
+    public boolean addAll(Collection<? extends E> c) {
+        if (c == this)
+            // As historically specified in AbstractQueue#addAll
+            throw new IllegalArgumentException();
+
+        // Copy c into a private chain of Nodes
+        Node<E> beginningOfTheEnd = null, last = null;
+        for (E e : c) {
+            checkNotNull(e);
+            Node<E> newNode = new Node<E>(e);
+            if (beginningOfTheEnd == null)
+                beginningOfTheEnd = last = newNode;
+            else {
+                last.lazySetNext(newNode);
+                newNode.lazySetPrev(last);
+                last = newNode;
+            }
+        }
+        if (beginningOfTheEnd == null)
+            return false;
+
+        // Atomically append the chain at the tail of this collection
+        restartFromTail:
+        for (;;)
+            for (Node<E> t = tail, p = t, q;;) {
+                if ((q = p.next) != null &&
+                    (q = (p = q).next) != null)
+                    // Check for tail updates every other hop.
+                    // If p == q, we are sure to follow tail instead.
+                    p = (t != (t = tail)) ? t : q;
+                else if (p.prev == p) // NEXT_TERMINATOR
+                    continue restartFromTail;
+                else {
+                    // p is last node
+                    beginningOfTheEnd.lazySetPrev(p); // CAS piggyback
+                    if (p.casNext(null, beginningOfTheEnd)) {
+                        // Successful CAS is the linearization point
+                        // for all elements to be added to this queue.
+                        if (!casTail(t, last)) {
+                            // Try a little harder to update tail,
+                            // since we may be adding many elements.
+                            t = tail;
+                            if (last.next == null)
+                                casTail(t, last);
+                        }
+                        return true;
+                    }
+                    // Lost CAS race to another thread; re-read next
+                }
+            }
+    }
+
+    /**
+     * Removes all of the elements from this deque.
+     */
+    public void clear() {
+        while (pollFirst() != null)
+            ;
+    }
+
+    /**
+     * Returns an array containing all of the elements in this deque, in
+     * proper sequence (from first to last element).
+     *
+     * <p>The returned array will be "safe" in that no references to it are
+     * maintained by this deque.  (In other words, this method must allocate
+     * a new array).  The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all of the elements in this deque
+     */
+    public Object[] toArray() {
+        return toArrayList().toArray();
+    }
+
+    /**
+     * Returns an array containing all of the elements in this deque,
+     * in proper sequence (from first to last element); the runtime
+     * type of the returned array is that of the specified array.  If
+     * the deque fits in the specified array, it is returned therein.
+     * Otherwise, a new array is allocated with the runtime type of
+     * the specified array and the size of this deque.
+     *
+     * <p>If this deque fits in the specified array with room to spare
+     * (i.e., the array has more elements than this deque), the element in
+     * the array immediately following the end of the deque is set to
+     * {@code null}.
+     *
+     * <p>Like the {@link #toArray()} method, this method acts as
+     * bridge between array-based and collection-based APIs.  Further,
+     * this method allows precise control over the runtime type of the
+     * output array, and may, under certain circumstances, be used to
+     * save allocation costs.
+     *
+     * <p>Suppose {@code x} is a deque known to contain only strings.
+     * The following code can be used to dump the deque into a newly
+     * allocated array of {@code String}:
+     *
+     * <pre>
+     *     String[] y = x.toArray(new String[0]);</pre>
+     *
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
+     *
+     * @param a the array into which the elements of the deque 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 deque
+     * @throws ArrayStoreException if the runtime type of the specified array
+     *         is not a supertype of the runtime type of every element in
+     *         this deque
+     * @throws NullPointerException if the specified array is null
+     */
+    public <T> T[] toArray(T[] a) {
+        return toArrayList().toArray(a);
+    }
+
+    /**
+     * Returns an iterator over the elements in this deque in proper sequence.
+     * The elements will be returned in order from first (head) to last (tail).
+     *
+     * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
+     *
+     * @return an iterator over the elements in this deque in proper sequence
+     */
+    public Iterator<E> iterator() {
+        return new Itr();
+    }
+
+    /**
+     * Returns an iterator over the elements in this deque in reverse
+     * sequential order.  The elements will be returned in order from
+     * last (tail) to first (head).
+     *
+     * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException},
+     * and guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed to)
+     * reflect any modifications subsequent to construction.
+     *
+     * @return an iterator over the elements in this deque in reverse order
+     */
+    public Iterator<E> descendingIterator() {
+        return new DescendingItr();
+    }
+
+    private abstract class AbstractItr implements Iterator<E> {
+        /**
+         * Next node to return item for.
+         */
+        private Node<E> nextNode;
+
+        /**
+         * nextItem holds on to item fields because once we claim
+         * that an element exists in hasNext(), we must return it in
+         * the following next() call even if it was in the process of
+         * being removed when hasNext() was called.
+         */
+        private E nextItem;
+
+        /**
+         * Node returned by most recent call to next. Needed by remove.
+         * Reset to null if this element is deleted by a call to remove.
+         */
+        private Node<E> lastRet;
+
+        abstract Node<E> startNode();
+        abstract Node<E> nextNode(Node<E> p);
+
+        AbstractItr() {
+            advance();
+        }
+
+        /**
+         * Sets nextNode and nextItem to next valid node, or to null
+         * if no such.
+         */
+        private void advance() {
+            lastRet = nextNode;
+
+            Node<E> p = (nextNode == null) ? startNode() : nextNode(nextNode);
+            for (;; p = nextNode(p)) {
+                if (p == null) {
+                    // p might be active end or TERMINATOR node; both are OK
+                    nextNode = null;
+                    nextItem = null;
+                    break;
+                }
+                E item = p.item;
+                if (item != null) {
+                    nextNode = p;
+                    nextItem = item;
+                    break;
+                }
+            }
+        }
+
+        public boolean hasNext() {
+            return nextItem != null;
+        }
+
+        public E next() {
+            E item = nextItem;
+            if (item == null) throw new NoSuchElementException();
+            advance();
+            return item;
+        }
+
+        public void remove() {
+            Node<E> l = lastRet;
+            if (l == null) throw new IllegalStateException();
+            l.item = null;
+            unlink(l);
+            lastRet = null;
+        }
+    }
+
+    /** Forward iterator */
+    private class Itr extends AbstractItr {
+        Node<E> startNode() { return first(); }
+        Node<E> nextNode(Node<E> p) { return succ(p); }
+    }
+
+    /** Descending iterator */
+    private class DescendingItr extends AbstractItr {
+        Node<E> startNode() { return last(); }
+        Node<E> nextNode(Node<E> p) { return pred(p); }
+    }
+
+    /**
+     * Saves the state to a stream (that is, serializes it).
+     *
+     * @serialData All of the elements (each an {@code E}) in
+     * the proper order, followed by a null
+     * @param s the stream
+     */
+    private void writeObject(java.io.ObjectOutputStream s)
+        throws java.io.IOException {
+
+        // Write out any hidden stuff
+        s.defaultWriteObject();
+
+        // Write out all elements in the proper order.
+        for (Node<E> p = first(); p != null; p = succ(p)) {
+            E item = p.item;
+            if (item != null)
+                s.writeObject(item);
+        }
+
+        // Use trailing null as sentinel
+        s.writeObject(null);
+    }
+
+    /**
+     * Reconstitutes the instance from a stream (that is, deserializes it).
+     * @param s the stream
+     */
+    private void readObject(java.io.ObjectInputStream s)
+        throws java.io.IOException, ClassNotFoundException {
+        s.defaultReadObject();
+
+        // Read in elements until trailing null sentinel found
+        Node<E> h = null, t = null;
+        Object item;
+        while ((item = s.readObject()) != null) {
+            @SuppressWarnings("unchecked")
+            Node<E> newNode = new Node<E>((E) item);
+            if (h == null)
+                h = t = newNode;
+            else {
+                t.lazySetNext(newNode);
+                newNode.lazySetPrev(t);
+                t = newNode;
+            }
+        }
+        initHeadTail(h, t);
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE =
+        sun.misc.Unsafe.getUnsafe();
+    private static final long headOffset =
+        objectFieldOffset(UNSAFE, "head", ConcurrentLinkedDeque.class);
+    private static final long tailOffset =
+        objectFieldOffset(UNSAFE, "tail", ConcurrentLinkedDeque.class);
+
+    private boolean casHead(Node<E> cmp, Node<E> val) {
+        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+    }
+
+    private boolean casTail(Node<E> cmp, Node<E> val) {
+        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+    }
+
+    static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+                                  String field, Class<?> klazz) {
+        try {
+            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+        } catch (NoSuchFieldException e) {
+            // Convert Exception to corresponding Error
+            NoSuchFieldError error = new NoSuchFieldError(field);
+            error.initCause(e);
+            throw error;
+        }
+    }
+}
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Wed Jul 05 17:24:13 2017 +0200
@@ -28,9 +28,9 @@
  * However, the following notice accompanied the original version of this
  * file:
  *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/licenses/publicdomain
+ * Written by Doug Lea and Martin Buchholz with assistance from members of
+ * JCP JSR-166 Expert Group and released to the public domain, as explained
+ * at http://creativecommons.org/licenses/publicdomain
  */
 
 package java.util.concurrent;
@@ -53,7 +53,8 @@
  * operations obtain elements at the head of the queue.
  * A {@code ConcurrentLinkedQueue} is an appropriate choice when
  * many threads will share access to a common collection.
- * This queue does not permit {@code null} elements.
+ * Like most other concurrent collection implementations, this class
+ * does not permit the use of {@code null} elements.
  *
  * <p>This implementation employs an efficient &quot;wait-free&quot;
  * algorithm based on one described in <a
@@ -61,14 +62,20 @@
  * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
  * Algorithms</a> by Maged M. Michael and Michael L. Scott.
  *
+ * <p>Iterators are <i>weakly consistent</i>, returning elements
+ * reflecting the state of the queue at some point at or since the
+ * creation of the iterator.  They do <em>not</em> throw {@link
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations.  Elements contained in the queue since the creation
+ * of the iterator will be returned exactly once.
+ *
  * <p>Beware that, unlike in most collections, the {@code size} method
  * is <em>NOT</em> a constant-time operation. Because of the
  * asynchronous nature of these queues, determining the current number
  * of elements requires a traversal of the elements.
  *
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Queue} and {@link Iterator} interfaces.
  *
  * <p>Memory consistency effects: As with other concurrent
  * collections, actions in a thread prior to placing an object into a
@@ -132,9 +139,10 @@
      *
      * Both head and tail are permitted to lag.  In fact, failing to
      * update them every time one could is a significant optimization
-     * (fewer CASes). This is controlled by local "hops" variables
-     * that only trigger helping-CASes after experiencing multiple
-     * lags.
+     * (fewer CASes). As with LinkedTransferQueue (see the internal
+     * documentation for that class), we use a slack threshold of two;
+     * that is, we update head/tail when the current pointer appears
+     * to be two or more steps away from the first/last node.
      *
      * Since head and tail are updated concurrently and independently,
      * it is possible for tail to lag behind head (why not)?
@@ -148,8 +156,8 @@
      * this is merely an optimization.
      *
      * When constructing a Node (before enqueuing it) we avoid paying
-     * for a volatile write to item by using lazySet instead of a
-     * normal write.  This allows the cost of enqueue to be
+     * for a volatile write to item by using Unsafe.putObject instead
+     * of a normal write.  This allows the cost of enqueue to be
      * "one-and-a-half" CASes.
      *
      * Both head and tail may or may not point to a Node with a
@@ -161,38 +169,25 @@
      */
 
     private static class Node<E> {
-        private volatile E item;
-        private volatile Node<E> next;
+        volatile E item;
+        volatile Node<E> next;
 
+        /**
+         * Constructs a new node.  Uses relaxed write because item can
+         * only be seen after publication via casNext.
+         */
         Node(E item) {
-            // Piggyback on imminent casNext()
-            lazySetItem(item);
-        }
-
-        E getItem() {
-            return item;
+            UNSAFE.putObject(this, itemOffset, item);
         }
 
         boolean casItem(E cmp, E val) {
             return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
         }
 
-        void setItem(E val) {
-            item = val;
-        }
-
-        void lazySetItem(E val) {
-            UNSAFE.putOrderedObject(this, itemOffset, val);
-        }
-
         void lazySetNext(Node<E> val) {
             UNSAFE.putOrderedObject(this, nextOffset, val);
         }
 
-        Node<E> getNext() {
-            return next;
-        }
-
         boolean casNext(Node<E> cmp, Node<E> val) {
             return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
         }
@@ -219,7 +214,7 @@
      * - it is permitted for tail to lag behind head, that is, for tail
      *   to not be reachable from head!
      */
-    private transient volatile Node<E> head = new Node<E>(null);
+    private transient volatile Node<E> head;
 
     /**
      * A node from which the last node on list (that is, the unique
@@ -233,25 +228,41 @@
      *   to not be reachable from head!
      * - tail.next may or may not be self-pointing to tail.
      */
-    private transient volatile Node<E> tail = head;
+    private transient volatile Node<E> tail;
 
 
     /**
      * Creates a {@code ConcurrentLinkedQueue} that is initially empty.
      */
-    public ConcurrentLinkedQueue() {}
+    public ConcurrentLinkedQueue() {
+        head = tail = new Node<E>(null);
+    }
 
     /**
      * Creates a {@code ConcurrentLinkedQueue}
      * initially containing the elements of the given collection,
      * added in traversal order of the collection's iterator.
+     *
      * @param c the collection of elements to initially contain
      * @throws NullPointerException if the specified collection or any
      *         of its elements are null
      */
     public ConcurrentLinkedQueue(Collection<? extends E> c) {
-        for (E e : c)
-            add(e);
+        Node<E> h = null, t = null;
+        for (E e : c) {
+            checkNotNull(e);
+            Node<E> newNode = new Node<E>(e);
+            if (h == null)
+                h = t = newNode;
+            else {
+                t.lazySetNext(newNode);
+                t = newNode;
+            }
+        }
+        if (h == null)
+            h = t = new Node<E>(null);
+        head = h;
+        tail = t;
     }
 
     // Have to override just to update the javadoc
@@ -267,13 +278,6 @@
     }
 
     /**
-     * We don't bother to update head or tail pointers if fewer than
-     * HOPS links from "true" location.  We assume that volatile
-     * writes are significantly more expensive than volatile reads.
-     */
-    private static final int HOPS = 1;
-
-    /**
      * Try to CAS head to p. If successful, repoint old head to itself
      * as sentinel for succ(), below.
      */
@@ -288,7 +292,7 @@
      * stale pointer that is now off the list.
      */
     final Node<E> succ(Node<E> p) {
-        Node<E> next = p.getNext();
+        Node<E> next = p.next;
         return (p == next) ? head : next;
     }
 
@@ -299,68 +303,75 @@
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
-        if (e == null) throw new NullPointerException();
-        Node<E> n = new Node<E>(e);
-        retry:
-        for (;;) {
-            Node<E> t = tail;
-            Node<E> p = t;
-            for (int hops = 0; ; hops++) {
-                Node<E> next = succ(p);
-                if (next != null) {
-                    if (hops > HOPS && t != tail)
-                        continue retry;
-                    p = next;
-                } else if (p.casNext(null, n)) {
-                    if (hops >= HOPS)
-                        casTail(t, n);  // Failure is OK.
+        checkNotNull(e);
+        final Node<E> newNode = new Node<E>(e);
+
+        for (Node<E> t = tail, p = t;;) {
+            Node<E> q = p.next;
+            if (q == null) {
+                // p is last node
+                if (p.casNext(null, newNode)) {
+                    // Successful CAS is the linearization point
+                    // for e to become an element of this queue,
+                    // and for newNode to become "live".
+                    if (p != t) // hop two nodes at a time
+                        casTail(t, newNode);  // Failure is OK.
                     return true;
-                } else {
-                    p = succ(p);
                 }
+                // Lost CAS race to another thread; re-read next
             }
+            else if (p == q)
+                // We have fallen off list.  If tail is unchanged, it
+                // will also be off-list, in which case we need to
+                // jump to head, from which all live nodes are always
+                // reachable.  Else the new tail is a better bet.
+                p = (t != (t = tail)) ? t : head;
+            else
+                // Check for tail updates after two hops.
+                p = (p != t && t != (t = tail)) ? t : q;
         }
     }
 
     public E poll() {
-        Node<E> h = head;
-        Node<E> p = h;
-        for (int hops = 0; ; hops++) {
-            E item = p.getItem();
+        restartFromHead:
+        for (;;) {
+            for (Node<E> h = head, p = h, q;;) {
+                E item = p.item;
 
-            if (item != null && p.casItem(item, null)) {
-                if (hops >= HOPS) {
-                    Node<E> q = p.getNext();
-                    updateHead(h, (q != null) ? q : p);
+                if (item != null && p.casItem(item, null)) {
+                    // Successful CAS is the linearization point
+                    // for item to be removed from this queue.
+                    if (p != h) // hop two nodes at a time
+                        updateHead(h, ((q = p.next) != null) ? q : p);
+                    return item;
                 }
-                return item;
+                else if ((q = p.next) == null) {
+                    updateHead(h, p);
+                    return null;
+                }
+                else if (p == q)
+                    continue restartFromHead;
+                else
+                    p = q;
             }
-            Node<E> next = succ(p);
-            if (next == null) {
-                updateHead(h, p);
-                break;
-            }
-            p = next;
         }
-        return null;
     }
 
     public E peek() {
-        Node<E> h = head;
-        Node<E> p = h;
-        E item;
+        restartFromHead:
         for (;;) {
-            item = p.getItem();
-            if (item != null)
-                break;
-            Node<E> next = succ(p);
-            if (next == null) {
-                break;
+            for (Node<E> h = head, p = h, q;;) {
+                E item = p.item;
+                if (item != null || (q = p.next) == null) {
+                    updateHead(h, p);
+                    return item;
+                }
+                else if (p == q)
+                    continue restartFromHead;
+                else
+                    p = q;
             }
-            p = next;
         }
-        updateHead(h, p);
-        return item;
     }
 
     /**
@@ -372,24 +383,20 @@
      * of losing a race to a concurrent poll().
      */
     Node<E> first() {
-        Node<E> h = head;
-        Node<E> p = h;
-        Node<E> result;
+        restartFromHead:
         for (;;) {
-            E item = p.getItem();
-            if (item != null) {
-                result = p;
-                break;
+            for (Node<E> h = head, p = h, q;;) {
+                boolean hasItem = (p.item != null);
+                if (hasItem || (q = p.next) == null) {
+                    updateHead(h, p);
+                    return hasItem ? p : null;
+                }
+                else if (p == q)
+                    continue restartFromHead;
+                else
+                    p = q;
             }
-            Node<E> next = succ(p);
-            if (next == null) {
-                result = null;
-                break;
-            }
-            p = next;
         }
-        updateHead(h, p);
-        return result;
     }
 
     /**
@@ -410,18 +417,20 @@
      * <em>NOT</em> a constant-time operation. Because of the
      * asynchronous nature of these queues, determining the current
      * number of elements requires an O(n) traversal.
+     * Additionally, if elements are added or removed during execution
+     * of this method, the returned result may be inaccurate.  Thus,
+     * this method is typically not very useful in concurrent
+     * applications.
      *
      * @return the number of elements in this queue
      */
     public int size() {
         int count = 0;
-        for (Node<E> p = first(); p != null; p = succ(p)) {
-            if (p.getItem() != null) {
-                // Collections.size() spec says to max out
+        for (Node<E> p = first(); p != null; p = succ(p))
+            if (p.item != null)
+                // Collection.size() spec says to max out
                 if (++count == Integer.MAX_VALUE)
                     break;
-            }
-        }
         return count;
     }
 
@@ -436,9 +445,8 @@
     public boolean contains(Object o) {
         if (o == null) return false;
         for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.getItem();
-            if (item != null &&
-                o.equals(item))
+            E item = p.item;
+            if (item != null && o.equals(item))
                 return true;
         }
         return false;
@@ -459,7 +467,7 @@
         if (o == null) return false;
         Node<E> pred = null;
         for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.getItem();
+            E item = p.item;
             if (item != null &&
                 o.equals(item) &&
                 p.casItem(item, null)) {
@@ -474,6 +482,69 @@
     }
 
     /**
+     * Appends all of the elements in the specified collection to the end of
+     * this queue, in the order that they are returned by the specified
+     * collection's iterator.  Attempts to {@code addAll} of a queue to
+     * itself result in {@code IllegalArgumentException}.
+     *
+     * @param c the elements to be inserted into this queue
+     * @return {@code true} if this queue changed as a result of the call
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
+     * @throws IllegalArgumentException if the collection is this queue
+     */
+    public boolean addAll(Collection<? extends E> c) {
+        if (c == this)
+            // As historically specified in AbstractQueue#addAll
+            throw new IllegalArgumentException();
+
+        // Copy c into a private chain of Nodes
+        Node<E> beginningOfTheEnd = null, last = null;
+        for (E e : c) {
+            checkNotNull(e);
+            Node<E> newNode = new Node<E>(e);
+            if (beginningOfTheEnd == null)
+                beginningOfTheEnd = last = newNode;
+            else {
+                last.lazySetNext(newNode);
+                last = newNode;
+            }
+        }
+        if (beginningOfTheEnd == null)
+            return false;
+
+        // Atomically append the chain at the tail of this collection
+        for (Node<E> t = tail, p = t;;) {
+            Node<E> q = p.next;
+            if (q == null) {
+                // p is last node
+                if (p.casNext(null, beginningOfTheEnd)) {
+                    // Successful CAS is the linearization point
+                    // for all elements to be added to this queue.
+                    if (!casTail(t, last)) {
+                        // Try a little harder to update tail,
+                        // since we may be adding many elements.
+                        t = tail;
+                        if (last.next == null)
+                            casTail(t, last);
+                    }
+                    return true;
+                }
+                // Lost CAS race to another thread; re-read next
+            }
+            else if (p == q)
+                // We have fallen off list.  If tail is unchanged, it
+                // will also be off-list, in which case we need to
+                // jump to head, from which all live nodes are always
+                // reachable.  Else the new tail is a better bet.
+                p = (t != (t = tail)) ? t : head;
+            else
+                // Check for tail updates after two hops.
+                p = (p != t && t != (t = tail)) ? t : q;
+        }
+    }
+
+    /**
      * Returns an array containing all of the elements in this queue, in
      * proper sequence.
      *
@@ -490,7 +561,7 @@
         // Use ArrayList to deal with resizing.
         ArrayList<E> al = new ArrayList<E>();
         for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.getItem();
+            E item = p.item;
             if (item != null)
                 al.add(item);
         }
@@ -539,7 +610,7 @@
         int k = 0;
         Node<E> p;
         for (p = first(); p != null && k < a.length; p = succ(p)) {
-            E item = p.getItem();
+            E item = p.item;
             if (item != null)
                 a[k++] = (T)item;
         }
@@ -552,7 +623,7 @@
         // If won't fit, use ArrayList version
         ArrayList<E> al = new ArrayList<E>();
         for (Node<E> q = first(); q != null; q = succ(q)) {
-            E item = q.getItem();
+            E item = q.item;
             if (item != null)
                 al.add(item);
         }
@@ -561,7 +632,9 @@
 
     /**
      * Returns an iterator over the elements in this queue in proper sequence.
-     * The returned iterator is a "weakly consistent" iterator that
+     * The elements will be returned in order from first (head) to last (tail).
+     *
+     * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
      * will never throw {@link java.util.ConcurrentModificationException
      * ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
@@ -620,7 +693,7 @@
                     nextItem = null;
                     return x;
                 }
-                E item = p.getItem();
+                E item = p.item;
                 if (item != null) {
                     nextNode = p;
                     nextItem = item;
@@ -648,13 +721,13 @@
             Node<E> l = lastRet;
             if (l == null) throw new IllegalStateException();
             // rely on a future traversal to relink.
-            l.setItem(null);
+            l.item = null;
             lastRet = null;
         }
     }
 
     /**
-     * Save the state to a stream (that is, serialize it).
+     * Saves the state to a stream (that is, serializes it).
      *
      * @serialData All of the elements (each an {@code E}) in
      * the proper order, followed by a null
@@ -668,7 +741,7 @@
 
         // Write out all elements in the proper order.
         for (Node<E> p = first(); p != null; p = succ(p)) {
-            Object item = p.getItem();
+            Object item = p.item;
             if (item != null)
                 s.writeObject(item);
         }
@@ -678,25 +751,40 @@
     }
 
     /**
-     * Reconstitute the Queue instance from a stream (that is,
-     * deserialize it).
+     * Reconstitutes the instance from a stream (that is, deserializes it).
      * @param s the stream
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
-        // Read in capacity, and any hidden stuff
         s.defaultReadObject();
-        head = new Node<E>(null);
-        tail = head;
-        // Read in all elements and place in queue
-        for (;;) {
+
+        // Read in elements until trailing null sentinel found
+        Node<E> h = null, t = null;
+        Object item;
+        while ((item = s.readObject()) != null) {
             @SuppressWarnings("unchecked")
-            E item = (E)s.readObject();
-            if (item == null)
-                break;
-            else
-                offer(item);
+            Node<E> newNode = new Node<E>((E) item);
+            if (h == null)
+                h = t = newNode;
+            else {
+                t.lazySetNext(newNode);
+                t = newNode;
+            }
         }
+        if (h == null)
+            h = t = new Node<E>(null);
+        head = h;
+        tail = t;
+    }
+
+    /**
+     * Throws NullPointerException if argument is null.
+     *
+     * @param v the element
+     */
+    private static void checkNotNull(Object v) {
+        if (v == null)
+            throw new NullPointerException();
     }
 
     // Unsafe mechanics
@@ -715,10 +803,6 @@
         return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
     }
 
-    private void lazySetHead(Node<E> val) {
-        UNSAFE.putOrderedObject(this, headOffset, val);
-    }
-
     static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
                                   String field, Class<?> klazz) {
         try {
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Jul 05 17:24:13 2017 +0200
@@ -42,7 +42,6 @@
 import java.util.List;
 import java.util.concurrent.AbstractExecutorService;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.RejectedExecutionException;
@@ -823,15 +822,13 @@
                                    (workerCounts & RUNNING_COUNT_MASK) <= 1);
                 long startTime = untimed? 0 : System.nanoTime();
                 Thread.interrupted();         // clear/ignore interrupt
-                if (eventCount != ec || w.runState != 0 ||
-                    runState >= TERMINATING)  // recheck after clear
-                    break;
+                if (eventCount != ec || w.isTerminating())
+                    break;                    // recheck after clear
                 if (untimed)
                     LockSupport.park(w);
                 else {
                     LockSupport.parkNanos(w, SHRINK_RATE_NANOS);
-                    if (eventCount != ec || w.runState != 0 ||
-                        runState >= TERMINATING)
+                    if (eventCount != ec || w.isTerminating())
                         break;
                     if (System.nanoTime() - startTime >= SHRINK_RATE_NANOS)
                         tryShutdownUnusedWorker(ec);
@@ -899,16 +896,23 @@
                      UNSAFE.compareAndSwapInt(this, workerCountsOffset, wc,
                                               wc + (ONE_RUNNING|ONE_TOTAL))) {
                 ForkJoinWorkerThread w = null;
+                Throwable fail = null;
                 try {
                     w = factory.newThread(this);
-                } finally { // adjust on null or exceptional factory return
-                    if (w == null) {
-                        decrementWorkerCounts(ONE_RUNNING, ONE_TOTAL);
-                        tryTerminate(false); // handle failure during shutdown
-                    }
+                } catch (Throwable ex) {
+                    fail = ex;
                 }
-                if (w == null)
+                if (w == null) { // null or exceptional factory return
+                    decrementWorkerCounts(ONE_RUNNING, ONE_TOTAL);
+                    tryTerminate(false); // handle failure during shutdown
+                    // If originating from an external caller,
+                    // propagate exception, else ignore
+                    if (fail != null && runState < TERMINATING &&
+                        !(Thread.currentThread() instanceof
+                          ForkJoinWorkerThread))
+                        UNSAFE.throwException(fail);
                     break;
+                }
                 w.start(recordWorker(w), ueh);
                 if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc) {
                     int c; // advance event count
@@ -997,8 +1001,12 @@
         boolean active = w.active;
         boolean inactivate = false;
         int pc = parallelism;
-        int rs;
-        while (w.runState == 0 && (rs = runState) < TERMINATING) {
+        while (w.runState == 0) {
+            int rs = runState;
+            if (rs >= TERMINATING) { // propagate shutdown
+                w.shutdown();
+                break;
+            }
             if ((inactivate || (active && (rs & ACTIVE_COUNT_MASK) >= pc)) &&
                 UNSAFE.compareAndSwapInt(this, runStateOffset, rs, rs - 1))
                 inactivate = active = w.active = false;
@@ -1126,6 +1134,7 @@
         return true;
     }
 
+
     /**
      * Actions on transition to TERMINATING
      *
@@ -1149,7 +1158,7 @@
                     if (passes > 0 && !w.isTerminated()) {
                         w.cancelTasks();
                         LockSupport.unpark(w);
-                        if (passes > 1) {
+                        if (passes > 1 && !w.isInterrupted()) {
                             try {
                                 w.interrupt();
                             } catch (SecurityException ignore) {
@@ -1726,6 +1735,13 @@
     }
 
     /**
+     * Returns true if terminating or terminated. Used by ForkJoinWorkerThread.
+     */
+    final boolean isAtLeastTerminating() {
+        return runState >= TERMINATING;
+    }
+
+    /**
      * Returns {@code true} if this pool has been shut down.
      *
      * @return {@code true} if this pool has been shut down
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java	Wed Jul 05 17:24:13 2017 +0200
@@ -55,10 +55,10 @@
  * start other subtasks.  As indicated by the name of this class,
  * many programs using {@code ForkJoinTask} employ only methods
  * {@link #fork} and {@link #join}, or derivatives such as {@link
- * #invokeAll}.  However, this class also provides a number of other
- * methods that can come into play in advanced usages, as well as
- * extension mechanics that allow support of new forms of fork/join
- * processing.
+ * #invokeAll(ForkJoinTask...) invokeAll}.  However, this class also
+ * provides a number of other methods that can come into play in
+ * advanced usages, as well as extension mechanics that allow
+ * support of new forms of fork/join processing.
  *
  * <p>A {@code ForkJoinTask} is a lightweight form of {@link Future}.
  * The efficiency of {@code ForkJoinTask}s stems from a set of
@@ -250,7 +250,7 @@
         int s;         // the odd construction reduces lock bias effects
         while ((s = status) >= 0) {
             try {
-                synchronized(this) {
+                synchronized (this) {
                     if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
                         wait();
                 }
@@ -270,7 +270,7 @@
         int s;
         if ((s = status) >= 0) {
             try {
-                synchronized(this) {
+                synchronized (this) {
                     if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
                         wait(millis, 0);
                 }
@@ -288,7 +288,7 @@
     private void externalAwaitDone() {
         int s;
         while ((s = status) >= 0) {
-            synchronized(this) {
+            synchronized (this) {
                 if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)){
                     boolean interrupted = false;
                     while (status >= 0) {
@@ -669,11 +669,34 @@
         setCompletion(NORMAL);
     }
 
+    /**
+     * Waits if necessary for the computation to complete, and then
+     * retrieves its result.
+     *
+     * @return the computed result
+     * @throws CancellationException if the computation was cancelled
+     * @throws ExecutionException if the computation threw an
+     * exception
+     * @throws InterruptedException if the current thread is not a
+     * member of a ForkJoinPool and was interrupted while waiting
+     */
     public final V get() throws InterruptedException, ExecutionException {
-        quietlyJoin();
-        if (Thread.interrupted())
-            throw new InterruptedException();
-        int s = status;
+        int s;
+        if (Thread.currentThread() instanceof ForkJoinWorkerThread) {
+            quietlyJoin();
+            s = status;
+        }
+        else {
+            while ((s = status) >= 0) {
+                synchronized (this) { // interruptible form of awaitDone
+                    if (UNSAFE.compareAndSwapInt(this, statusOffset,
+                                                 s, SIGNAL)) {
+                        while (status >= 0)
+                            wait();
+                    }
+                }
+            }
+        }
         if (s < NORMAL) {
             Throwable ex;
             if (s == CANCELLED)
@@ -684,6 +707,20 @@
         return getRawResult();
     }
 
+    /**
+     * Waits if necessary for at most the given time for the computation
+     * to complete, and then retrieves its result, if available.
+     *
+     * @param timeout the maximum time to wait
+     * @param unit the time unit of the timeout argument
+     * @return the computed result
+     * @throws CancellationException if the computation was cancelled
+     * @throws ExecutionException if the computation threw an
+     * exception
+     * @throws InterruptedException if the current thread is not a
+     * member of a ForkJoinPool and was interrupted while waiting
+     * @throws TimeoutException if the wait timed out
+     */
     public final V get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
         Thread t = Thread.currentThread();
@@ -725,7 +762,7 @@
                         long ms = nt / 1000000;
                         int ns = (int) (nt % 1000000);
                         try {
-                            synchronized(this) {
+                            synchronized (this) {
                                 if (status >= 0)
                                     wait(ms, ns);
                             }
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Wed Jul 05 17:24:13 2017 +0200
@@ -778,11 +778,20 @@
 
     // status check methods used mainly by ForkJoinPool
     final boolean isRunning()     { return runState == 0; }
-    final boolean isTerminating() { return (runState & TERMINATING) != 0; }
     final boolean isTerminated()  { return (runState & TERMINATED) != 0; }
     final boolean isSuspended()   { return (runState & SUSPENDED) != 0; }
     final boolean isTrimmed()     { return (runState & TRIMMED) != 0; }
 
+    final boolean isTerminating() {
+        if ((runState & TERMINATING) != 0)
+            return true;
+        if (pool.isAtLeastTerminating()) { // propagate pool state
+            shutdown();
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Sets state to TERMINATING. Does NOT unpark or interrupt
      * to wake up if currently blocked. Callers must do so if desired.
--- a/jdk/src/share/classes/java/util/concurrent/RecursiveAction.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/RecursiveAction.java	Wed Jul 05 17:24:13 2017 +0200
@@ -138,7 +138,7 @@
  *        if (right.tryUnfork()) // directly calculate if not stolen
  *          sum += right.atLeaf(right.lo, right.hi);
  *       else {
- *          right.helpJoin();
+ *          right.join();
  *          sum += right.result;
  *        }
  *        right = right.next;
--- a/jdk/src/share/classes/java/util/logging/LogManager.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java	Wed Jul 05 17:24:13 2017 +0200
@@ -690,6 +690,11 @@
      * Note that since untrusted code may create loggers with
      * arbitrary names this method should not be relied on to
      * find Loggers for security sensitive logging.
+     * It is also important to note that the Logger associated with the
+     * String {@code name} may be garbage collected at any time if there
+     * is no strong reference to the Logger. The caller of this method
+     * must check the return value for null in order to properly handle
+     * the case where the Logger has been garbage collected.
      * <p>
      * @param name name of the logger
      * @return  matching logger or null if none is found
@@ -713,6 +718,14 @@
      * <p>
      * Note:  Loggers may be added dynamically as new classes are loaded.
      * This method only reports on the loggers that are currently registered.
+     * It is also important to note that this method only returns the name
+     * of a Logger, not a strong reference to the Logger itself.
+     * The returned String does nothing to prevent the Logger from being
+     * garbage collected. In particular, if the returned name is passed
+     * to {@code LogManager.getLogger()}, then the caller must check the
+     * return value from {@code LogManager.getLogger()} for null to properly
+     * handle the case where the Logger has been garbage collected in the
+     * time since its name was returned by this method.
      * <p>
      * @return  enumeration of logger name strings
      */
--- a/jdk/src/share/classes/java/util/logging/Logger.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java	Wed Jul 05 17:24:13 2017 +0200
@@ -42,7 +42,10 @@
  * <p>
  * Logger objects may be obtained by calls on one of the getLogger
  * factory methods.  These will either create a new Logger or
- * return a suitable existing Logger.
+ * return a suitable existing Logger. It is important to note that
+ * the Logger returned by one of the {@code getLogger} factory methods
+ * may be garbage collected at any time if a strong reference to the
+ * Logger is not kept.
  * <p>
  * Logging messages will be forwarded to registered Handler
  * objects, which can forward the messages to a variety of
@@ -210,7 +213,9 @@
      * who are making serious use of the logging package (for example
      * in products) should create and use their own Logger objects,
      * with appropriate names, so that logging can be controlled on a
-     * suitable per-Logger granularity.
+     * suitable per-Logger granularity. Developers also need to keep a
+     * strong reference to their Logger objects to prevent them from
+     * being garbage collected.
      * <p>
      * @deprecated Initialization of this field is prone to deadlocks.
      * The field must be initialized by the Logger class initialization
@@ -287,6 +292,15 @@
      * based on the LogManager configuration and it will configured
      * to also send logging output to its parent's Handlers.  It will
      * be registered in the LogManager global namespace.
+     * <p>
+     * Note: The LogManager may only retain a weak reference to the newly
+     * created Logger. It is important to understand that a previously
+     * created Logger with the given name may be garbage collected at any
+     * time if there is no strong reference to the Logger. In particular,
+     * this means that two back-to-back calls like
+     * {@code getLogger("MyLogger").log(...)} may use different Logger
+     * objects named "MyLogger" if there is no strong reference to the
+     * Logger named "MyLogger" elsewhere in the program.
      *
      * @param   name            A name for the logger.  This should
      *                          be a dot-separated name and should normally
@@ -311,6 +325,15 @@
      * output to its parent's Handlers.  It will be registered in
      * the LogManager global namespace.
      * <p>
+     * Note: The LogManager may only retain a weak reference to the newly
+     * created Logger. It is important to understand that a previously
+     * created Logger with the given name may be garbage collected at any
+     * time if there is no strong reference to the Logger. In particular,
+     * this means that two back-to-back calls like
+     * {@code getLogger("MyLogger", ...).log(...)} may use different Logger
+     * objects named "MyLogger" if there is no strong reference to the
+     * Logger named "MyLogger" elsewhere in the program.
+     * <p>
      * If the named Logger already exists and does not yet have a
      * localization resource bundle then the given resource bundle
      * name is used.  If the named Logger already exists and has
--- a/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -734,7 +734,7 @@
                  throw new SQLException("Set initParams() before setCommand");
             }
             params.clear();
-            command = new String(cmd);
+            command = cmd;
         }
 
     }
@@ -797,7 +797,7 @@
             throw new SQLException("Invalid url string detected. " +
             "Cannot be of length less than 1");
         } else {
-            URL = new String(url);
+            URL = url;
         }
 
         dataSource = null;
@@ -854,7 +854,7 @@
         } else if (name.equals("")) {
            throw new SQLException("DataSource name cannot be empty string");
         } else {
-           dataSource = new String(name);
+           dataSource = name;
         }
 
         URL = null;
@@ -889,7 +889,7 @@
         {
            username = null;
         } else {
-           username = new String(name);
+           username = name;
         }
     }
 
@@ -924,7 +924,7 @@
         {
            password = null;
         } else {
-           password = new String(pass);
+           password = pass;
         }
     }
 
@@ -1563,13 +1563,13 @@
 
         nullVal = new Object[2];
         nullVal[0] = null;
-        nullVal[1] = new Integer(sqlType);
+        nullVal[1] = Integer.valueOf(sqlType);
 
        if (params == null){
             throw new SQLException("Set initParams() before setNull");
        }
 
-        params.put(new Integer(parameterIndex - 1), nullVal);
+        params.put(Integer.valueOf(parameterIndex - 1), nullVal);
     }
 
     /**
@@ -1644,14 +1644,14 @@
 
         nullVal = new Object[3];
         nullVal[0] = null;
-        nullVal[1] = new Integer(sqlType);
-        nullVal[2] = new String(typeName);
+        nullVal[1] = Integer.valueOf(sqlType);
+        nullVal[2] = typeName;
 
        if(params == null){
             throw new SQLException("Set initParams() before setNull");
        }
 
-        params.put(new Integer(parameterIndex - 1), nullVal);
+        params.put(Integer.valueOf(parameterIndex - 1), nullVal);
     }
 
 
@@ -1686,7 +1686,7 @@
             throw new SQLException("Set initParams() before setNull");
        }
 
-        params.put(new Integer(parameterIndex - 1), new Boolean(x));
+        params.put(Integer.valueOf(parameterIndex - 1), Boolean.valueOf(x));
     }
 
     /**
@@ -1720,7 +1720,7 @@
             throw new SQLException("Set initParams() before setByte");
        }
 
-        params.put(new Integer(parameterIndex - 1), new Byte(x));
+        params.put(Integer.valueOf(parameterIndex - 1), Byte.valueOf(x));
     }
 
     /**
@@ -1754,7 +1754,7 @@
              throw new SQLException("Set initParams() before setShort");
         }
 
-        params.put(new Integer(parameterIndex - 1), new Short(x));
+        params.put(Integer.valueOf(parameterIndex - 1), Short.valueOf(x));
     }
 
     /**
@@ -1786,7 +1786,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setInt");
         }
-        params.put(new Integer(parameterIndex - 1), new Integer(x));
+        params.put(Integer.valueOf(parameterIndex - 1), Integer.valueOf(x));
     }
 
     /**
@@ -1818,7 +1818,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setLong");
         }
-        params.put(new Integer(parameterIndex - 1), new Long(x));
+        params.put(Integer.valueOf(parameterIndex - 1), Long.valueOf(x));
     }
 
     /**
@@ -1850,7 +1850,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setFloat");
         }
-        params.put(new Integer(parameterIndex - 1), new Float(x));
+        params.put(Integer.valueOf(parameterIndex - 1), new Float(x));
     }
 
     /**
@@ -1882,7 +1882,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setDouble");
         }
-        params.put(new Integer(parameterIndex - 1), new Double(x));
+        params.put(Integer.valueOf(parameterIndex - 1), new Double(x));
     }
 
     /**
@@ -1914,7 +1914,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setBigDecimal");
         }
-        params.put(new Integer(parameterIndex - 1), x);
+        params.put(Integer.valueOf(parameterIndex - 1), x);
     }
 
     /**
@@ -1948,7 +1948,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setString");
         }
-        params.put(new Integer(parameterIndex - 1), x);
+        params.put(Integer.valueOf(parameterIndex - 1), x);
     }
 
     /**
@@ -1982,7 +1982,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setBytes");
         }
-        params.put(new Integer(parameterIndex - 1), x);
+        params.put(Integer.valueOf(parameterIndex - 1), x);
     }
 
     /**
@@ -2024,7 +2024,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setDate");
         }
-        params.put(new Integer(parameterIndex - 1), x);
+        params.put(Integer.valueOf(parameterIndex - 1), x);
     }
 
     /**
@@ -2069,7 +2069,7 @@
              throw new SQLException("Set initParams() before setTime");
         }
 
-        params.put(new Integer(parameterIndex - 1), x);
+        params.put(Integer.valueOf(parameterIndex - 1), x);
     }
 
     /**
@@ -2112,7 +2112,7 @@
              throw new SQLException("Set initParams() before setTimestamp");
         }
 
-        params.put(new Integer(parameterIndex - 1), x);
+        params.put(Integer.valueOf(parameterIndex - 1), x);
     }
 
     /**
@@ -2185,14 +2185,14 @@
 
         asciiStream = new Object[3];
         asciiStream[0] = x;
-        asciiStream[1] = new Integer(length);
-        asciiStream[2] = new Integer(ASCII_STREAM_PARAM);
+        asciiStream[1] = Integer.valueOf(length);
+        asciiStream[2] = Integer.valueOf(ASCII_STREAM_PARAM);
 
         if(params == null){
              throw new SQLException("Set initParams() before setAsciiStream");
         }
 
-        params.put(new Integer(parameterIndex - 1), asciiStream);
+        params.put(Integer.valueOf(parameterIndex - 1), asciiStream);
     }
 
   /**
@@ -2290,13 +2290,13 @@
 
         binaryStream = new Object[3];
         binaryStream[0] = x;
-        binaryStream[1] = new Integer(length);
-        binaryStream[2] = new Integer(BINARY_STREAM_PARAM);
+        binaryStream[1] = Integer.valueOf(length);
+        binaryStream[2] = Integer.valueOf(BINARY_STREAM_PARAM);
         if(params == null){
              throw new SQLException("Set initParams() before setBinaryStream");
         }
 
-        params.put(new Integer(parameterIndex - 1), binaryStream);
+        params.put(Integer.valueOf(parameterIndex - 1), binaryStream);
     }
 
 
@@ -2396,12 +2396,12 @@
 
         unicodeStream = new Object[3];
         unicodeStream[0] = x;
-        unicodeStream[1] = new Integer(length);
-        unicodeStream[2] = new Integer(UNICODE_STREAM_PARAM);
+        unicodeStream[1] = Integer.valueOf(length);
+        unicodeStream[2] = Integer.valueOf(UNICODE_STREAM_PARAM);
         if(params == null){
              throw new SQLException("Set initParams() before setUnicodeStream");
         }
-        params.put(new Integer(parameterIndex - 1), unicodeStream);
+        params.put(Integer.valueOf(parameterIndex - 1), unicodeStream);
     }
 
     /**
@@ -2475,11 +2475,11 @@
 
         charStream = new Object[2];
         charStream[0] = reader;
-        charStream[1] = new Integer(length);
+        charStream[1] = Integer.valueOf(length);
         if(params == null){
              throw new SQLException("Set initParams() before setCharacterStream");
         }
-        params.put(new Integer(parameterIndex - 1), charStream);
+        params.put(Integer.valueOf(parameterIndex - 1), charStream);
     }
 
    /**
@@ -2591,12 +2591,12 @@
 
         obj = new Object[3];
         obj[0] = x;
-        obj[1] = new Integer(targetSqlType);
-        obj[2] = new Integer(scale);
+        obj[1] = Integer.valueOf(targetSqlType);
+        obj[2] = Integer.valueOf(scale);
         if(params == null){
              throw new SQLException("Set initParams() before setObject");
         }
-        params.put(new Integer(parameterIndex - 1), obj);
+        params.put(Integer.valueOf(parameterIndex - 1), obj);
     }
 
     /**
@@ -2654,11 +2654,11 @@
 
         obj = new Object[2];
         obj[0] = x;
-        obj[1] = new Integer(targetSqlType);
+        obj[1] = Integer.valueOf(targetSqlType);
         if (params == null){
              throw new SQLException("Set initParams() before setObject");
         }
-        params.put(new Integer(parameterIndex - 1), obj);
+        params.put(Integer.valueOf(parameterIndex - 1), obj);
     }
 
     /**
@@ -2726,7 +2726,7 @@
         if (params == null) {
              throw new SQLException("Set initParams() before setObject");
         }
-        params.put(new Integer(parameterIndex - 1), x);
+        params.put(Integer.valueOf(parameterIndex - 1), x);
     }
 
     /**
@@ -2773,7 +2773,7 @@
         if (params == null) {
              throw new SQLException("Set initParams() before setRef");
         }
-        params.put(new Integer(parameterIndex - 1), new SerialRef(ref));
+        params.put(Integer.valueOf(parameterIndex - 1), new SerialRef(ref));
     }
 
     /**
@@ -2817,7 +2817,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setBlob");
         }
-        params.put(new Integer(parameterIndex - 1), new SerialBlob(x));
+        params.put(Integer.valueOf(parameterIndex - 1), new SerialBlob(x));
     }
 
     /**
@@ -2862,7 +2862,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setClob");
         }
-        params.put(new Integer(parameterIndex - 1), new SerialClob(x));
+        params.put(Integer.valueOf(parameterIndex - 1), new SerialClob(x));
     }
 
     /**
@@ -2910,7 +2910,7 @@
         if (params == null){
              throw new SQLException("Set initParams() before setArray");
         }
-        params.put(new Integer(parameterIndex - 1), new SerialArray(array));
+        params.put(Integer.valueOf(parameterIndex - 1), new SerialArray(array));
     }
 
     /**
@@ -2975,7 +2975,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setDate");
         }
-        params.put(new Integer(parameterIndex - 1), date);
+        params.put(Integer.valueOf(parameterIndex - 1), date);
     }
 
     /**
@@ -3041,7 +3041,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setTime");
         }
-        params.put(new Integer(parameterIndex - 1), time);
+        params.put(Integer.valueOf(parameterIndex - 1), time);
     }
 
     /**
@@ -3107,7 +3107,7 @@
         if(params == null){
              throw new SQLException("Set initParams() before setTimestamp");
         }
-        params.put(new Integer(parameterIndex - 1), timestamp);
+        params.put(Integer.valueOf(parameterIndex - 1), timestamp);
     }
 
     /**
@@ -3181,7 +3181,7 @@
 
             Object[] paramsArray = new Object[params.size()];
             for (int i = 0; i < params.size(); i++) {
-               paramsArray[i] = params.get(new Integer(i));
+               paramsArray[i] = params.get(Integer.valueOf(i));
                if (paramsArray[i] == null) {
                  throw new SQLException("missing parameter: " + (i + 1));
                } //end if
--- a/jdk/src/share/classes/javax/sql/rowset/CachedRowSet.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/CachedRowSet.java	Wed Jul 05 17:24:13 2017 +0200
@@ -39,7 +39,7 @@
  * <code>CachedRowSet</code> must implement.
  * <P>
  * The reference implementation of the <code>CachedRowSet</code> interface provided
- * by Sun Microsystems is a standard implementation. Developers may use this implementation
+ * by Oracle Corporation is a standard implementation. Developers may use this implementation
  * just as it is, they may extend it, or they may choose to write their own implementations
  * of this interface.
  * <P>
@@ -1623,4 +1623,3 @@
     public boolean previousPage() throws SQLException;
 
 }
-
--- a/jdk/src/share/classes/javax/sql/rowset/RowSetMetaDataImpl.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/RowSetMetaDataImpl.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -306,9 +306,9 @@
     public void setColumnLabel(int columnIndex, String label) throws SQLException {
         checkColRange(columnIndex);
         if (label != null) {
-            colInfo[columnIndex].columnLabel = new String(label);
+            colInfo[columnIndex].columnLabel = label;
         } else {
-            colInfo[columnIndex].columnLabel = new String("");
+            colInfo[columnIndex].columnLabel = "";
         }
     }
 
@@ -326,9 +326,9 @@
     public void setColumnName(int columnIndex, String columnName) throws SQLException {
         checkColRange(columnIndex);
         if (columnName != null) {
-            colInfo[columnIndex].columnName = new String(columnName);
+            colInfo[columnIndex].columnName = columnName;
         } else {
-            colInfo[columnIndex].columnName = new String("");
+            colInfo[columnIndex].columnName = "";
         }
     }
 
@@ -348,9 +348,9 @@
     public void setSchemaName(int columnIndex, String schemaName) throws SQLException {
         checkColRange(columnIndex);
         if (schemaName != null ) {
-            colInfo[columnIndex].schemaName = new String(schemaName);
+            colInfo[columnIndex].schemaName = schemaName;
         } else {
-            colInfo[columnIndex].schemaName = new String("");
+            colInfo[columnIndex].schemaName = "";
         }
     }
 
@@ -411,9 +411,9 @@
     public void setTableName(int columnIndex, String tableName) throws SQLException {
         checkColRange(columnIndex);
         if (tableName != null) {
-            colInfo[columnIndex].tableName = new String(tableName);
+            colInfo[columnIndex].tableName = tableName;
         } else {
-            colInfo[columnIndex].tableName = new String("");
+            colInfo[columnIndex].tableName = "";
         }
     }
 
@@ -432,9 +432,9 @@
     public void setCatalogName(int columnIndex, String catalogName) throws SQLException {
         checkColRange(columnIndex);
         if (catalogName != null)
-            colInfo[columnIndex].catName = new String(catalogName);
+            colInfo[columnIndex].catName = catalogName;
         else
-            colInfo[columnIndex].catName = new String("");
+            colInfo[columnIndex].catName = "";
     }
 
     /**
@@ -474,9 +474,9 @@
         throws SQLException {
         checkColRange(columnIndex);
         if (typeName != null) {
-            colInfo[columnIndex].colTypeName = new String(typeName);
+            colInfo[columnIndex].colTypeName = typeName;
         } else {
-            colInfo[columnIndex].colTypeName = new String("");
+            colInfo[columnIndex].colTypeName = "";
         }
     }
 
@@ -827,7 +827,7 @@
      *         or the given column number is out of bounds
      */
     public String getColumnClassName(int columnIndex) throws SQLException {
-        String className = (new String()).getClass().getName();
+        String className = String.class.getName();
 
         int sqlType = getColumnType(columnIndex);
 
@@ -835,65 +835,62 @@
 
         case Types.NUMERIC:
         case Types.DECIMAL:
-            className = (new java.math.BigDecimal(0)).getClass().getName ();
+            className = java.math.BigDecimal.class.getName();
             break;
 
         case Types.BIT:
-            className = (new Boolean(false)).getClass().getName ();
+            className = java.lang.Boolean.class.getName();
             break;
 
         case Types.TINYINT:
-            className = (new Byte("0")).getClass().getName ();
+            className = java.lang.Byte.class.getName();
             break;
 
         case Types.SMALLINT:
-            className = (new Short("0")).getClass().getName ();
+            className = java.lang.Short.class.getName();
             break;
 
         case Types.INTEGER:
-            className = (new Integer(0)).getClass().getName ();
+            className = java.lang.Integer.class.getName();
             break;
 
         case Types.BIGINT:
-            className = (new Long(0)).getClass().getName ();
+            className = java.lang.Long.class.getName();
             break;
 
         case Types.REAL:
-            className = (new Float(0)).getClass().getName ();
+            className = java.lang.Float.class.getName();
             break;
 
         case Types.FLOAT:
         case Types.DOUBLE:
-            className = (new Double(0)).getClass().getName();
+            className = java.lang.Double.class.getName();
             break;
 
         case Types.BINARY:
         case Types.VARBINARY:
         case Types.LONGVARBINARY:
-            byte[] b = {};
-            className = (b.getClass()).getName();
+            className = "byte[]";
             break;
 
         case Types.DATE:
-            className = (new java.sql.Date(123456)).getClass().getName ();
+            className = java.sql.Date.class.getName();
             break;
 
         case Types.TIME:
-            className = (new java.sql.Time(123456)).getClass().getName ();
+            className = java.sql.Time.class.getName();
             break;
 
         case Types.TIMESTAMP:
-            className = (new java.sql.Timestamp(123456)).getClass().getName ();
+            className = java.sql.Timestamp.class.getName();
             break;
 
         case Types.BLOB:
-            byte[] blob = {};
-            className = (blob.getClass()).getName();
+            className = java.sql.Blob.class.getName();
             break;
 
         case Types.CLOB:
-            char[] c = {};
-            className = (c.getClass()).getName();
+            className = java.sql.Clob.class.getName();
             break;
         }
 
--- a/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java	Wed Jul 05 17:24:13 2017 +0200
@@ -29,7 +29,6 @@
 import java.security.PrivilegedAction;
 import java.sql.SQLException;
 import java.util.ServiceLoader;
-import javax.sql.rowset.RowSetFactory;
 
 /**
  * A factory API that enables applications to obtain a
@@ -82,15 +81,15 @@
      * the <code>RowSetFactory</code> implementation class to load:</p>
      * <ul>
      * <li>
-     * The System property {@code javax.sql.rowset.RowsetFactory}.  For example:
+     * The System property {@code javax.sql.rowset.RowSetFactory}.  For example:
      * <ul>
      * <li>
-     * -Djavax.sql.rowset.RowsetFactory=com.sun.rowset.RowSetFactoryImpl
+     * -Djavax.sql.rowset.RowSetFactory=com.sun.rowset.RowSetFactoryImpl
      * </li>
      * </ul>
      * <li>
-     * The ServiceLocator API. The ServiceLocator API will look
-     * for a classname in the file
+     * The {@link ServiceLoader} API. The {@code ServiceLoader} API will look
+     * for a class name in the file
      * {@code META-INF/services/javax.sql.rowset.RowSetFactory}
      * in jars available to the runtime. For example, to have the the RowSetFactory
      * implementation {@code com.sun.rowset.RowSetFactoryImpl } loaded, the
@@ -271,7 +270,7 @@
     /**
      * Returns the requested System Property.  If a {@code SecurityException}
      * occurs, just return NULL
-     * @param propName - System property to retreive
+     * @param propName - System property to retrieve
      * @return The System property value or NULL if the property does not exist
      * or a {@code SecurityException} occurs.
      */
--- a/jdk/src/share/classes/javax/sql/rowset/WebRowSet.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/WebRowSet.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -115,7 +115,7 @@
  *      &lt;<font color=red>url</font>&gt;jdbc:thin:oracle&lt;<font color=red>/url</font>&gt;
  *      &lt;<font color=red>sync-provider</font>&gt;
  *              &lt;<font color=red>sync-provider-name</font>&gt;.com.rowset.provider.RIOptimisticProvider&lt;<font color=red>/sync-provider-name</font>&gt;
- *              &lt;<font color=red>sync-provider-vendor</font>&gt;Sun Microsystems&lt;<font color=red>/sync-provider-vendor</font>&gt;
+ *              &lt;<font color=red>sync-provider-vendor</font>&gt;Oracle Corporation&lt;<font color=red>/sync-provider-vendor</font>&gt;
  *              &lt;<font color=red>sync-provider-version</font>&gt;1.0&lt;<font color=red>/sync-provider-name</font>&gt;
  *              &lt;<font color=red>sync-provider-grade</font>&gt;LOW&lt;<font color=red>/sync-provider-grade</font>&gt;
  *              &lt;<font color=red>data-source-lock</font>&gt;NONE&lt;<font color=red>/data-source-lock</font>&gt;
@@ -489,7 +489,7 @@
      * tags and their valid values for a <code>WebRowSet</code> implementation.
      */
     public static String PUBLIC_XML_SCHEMA =
-        "--//Sun Microsystems, Inc.//XSD Schema//EN";
+        "--//Oracle Corporation//XSD Schema//EN";
 
     /**
      * The URL for the XML Schema definition file that defines the XML tags and
--- a/jdk/src/share/classes/javax/sql/rowset/rowset.properties	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/rowset.properties	Wed Jul 05 17:24:13 2017 +0200
@@ -3,10 +3,10 @@
 
 # Optimistic synchonriztaion provider
 rowset.provider.classname.0=com.sun.rowset.providers.RIOptimisticProvider
-rowset.provider.vendor.0=Sun Microsystems Inc
+rowset.provider.vendor.0=Oracle Corporation
 rowset.provider.version.0=1.0
 
 # XML Provider using standard XML schema
 rowset.provider.classname.1=com.sun.rowset.providers.RIXMLProvider
-rowset.provider.vendor.1=Sun Microsystems Inc.
+rowset.provider.vendor.1=Oracle Corporation
 rowset.provider.version.1=1.0
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -137,7 +137,7 @@
      *        values of a UDT to the database.
      */
     public void writeBoolean(boolean x) throws SQLException {
-        attribs.add(new Boolean(x));
+        attribs.add(Boolean.valueOf(x));
     }
 
     /**
@@ -151,7 +151,7 @@
      *        values of a UDT to the database.
      */
     public void writeByte(byte x) throws SQLException {
-        attribs.add(new Byte(x));
+        attribs.add(Byte.valueOf(x));
     }
 
     /**
@@ -165,7 +165,7 @@
      *        values of a UDT to the database.
      */
     public void writeShort(short x) throws SQLException {
-        attribs.add(new Short(x));
+        attribs.add(Short.valueOf(x));
     }
 
     /**
@@ -179,7 +179,7 @@
      *        values of a UDT to the database.
      */
     public void writeInt(int x) throws SQLException {
-        attribs.add(new Integer(x));
+        attribs.add(Integer.valueOf(x));
     }
 
     /**
@@ -193,7 +193,7 @@
      *        values of a UDT to the database.
      */
     public void writeLong(long x) throws SQLException {
-        attribs.add(new Long(x));
+        attribs.add(Long.valueOf(x));
     }
 
     /**
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialRef.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialRef.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -77,7 +77,7 @@
             throw new SQLException("Cannot instantiate a SerialRef object " +
                 "that returns a null base type name");
         } else {
-            baseTypeName = new String(ref.getBaseTypeName());
+            baseTypeName = ref.getBaseTypeName();
         }
     }
 
@@ -110,7 +110,7 @@
         throws SerialException
     {
         map = new Hashtable(map);
-        if (!object.equals(null)) {
+        if (object != null) {
             return map.get(object);
         } else {
             throw new SerialException("The object is not set");
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialStruct.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialStruct.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -94,7 +94,7 @@
         try {
 
         // get the type name
-        SQLTypeName = new String(in.getSQLTypeName());
+        SQLTypeName = in.getSQLTypeName();
         System.out.println("SQLTypeName: " + SQLTypeName);
 
         // get the attributes of the struct
@@ -137,7 +137,7 @@
         try {
 
         //set the type name
-        SQLTypeName = new String(in.getSQLTypeName());
+        SQLTypeName = in.getSQLTypeName();
 
         Vector tmp = new Vector();
         in.writeSQL(new SQLOutputImpl(tmp, map));
@@ -247,7 +247,7 @@
     }
 
     /**
-         * The identifier that assists in the serialization of this
+     * The identifier that assists in the serialization of this
      * <code>SerialStruct</code> object.
      */
     static final long serialVersionUID = -8322445504027483372L;
--- a/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java	Wed Jul 05 17:24:13 2017 +0200
@@ -125,12 +125,12 @@
  *
  *   # Optimistic synchronization provider
  *   rowset.provider.classname.0=com.sun.rowset.providers.RIOptimisticProvider
- *   rowset.provider.vendor.0=Sun Microsystems Inc
+ *   rowset.provider.vendor.0=Oracle Corporation
  *   rowset.provider.version.0=1.0
  *
  *   # XML Provider using standard XML schema
  *   rowset.provider.classname.1=com.sun.rowset.providers.RIXMLProvider
- *   rowset.provider.vendor.1=Sun Microsystems Inc.
+ *   rowset.provider.vendor.1=Oracle Corporation
  *   rowset.provider.version.1=1.0
  * </PRE>
  * The <code>SyncFactory</code> checks this file and registers the
@@ -369,7 +369,7 @@
             try {
 
                 // check if user is supplying his Synchronisation Provider
-                // Implementation  if not use Sun's implementation.
+                // Implementation if not using Oracle's implementation.
                 // properties.load(new FileInputStream(ROWSET_PROPERTIES));
 
                 // The rowset.properties needs to be in jdk/jre/lib when
--- a/jdk/src/share/classes/javax/sql/rowset/spi/SyncProvider.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/spi/SyncProvider.java	Wed Jul 05 17:24:13 2017 +0200
@@ -91,8 +91,8 @@
  * </pre>
  * <p>
  * A vendor can register a <code>SyncProvider</code> implementation class name
- * with Sun Microsystems, Inc. by sending email to jdbc@sun.com.
- * Sun will maintain a database listing the
+ * with Oracle Corporation by sending email to jdbc@sun.com.
+ * Oracle will maintain a database listing the
  * available <code>SyncProvider</code> implementations for use with compliant
  * <code>RowSet</code> implementations.  This database will be similar to the
  * one already maintained to list available JDBC drivers.
--- a/jdk/src/share/classes/javax/sql/rowset/spi/package.html	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/spi/package.html	Wed Jul 05 17:24:13 2017 +0200
@@ -8,7 +8,7 @@
   <meta name="GENERATOR"
  content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
 <!--
-Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2003, 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
@@ -199,7 +199,7 @@
 Vendors may develop a <tt>SyncProvider</tt> implementation with any one of the possible
 levels of synchronization, thus giving <code>RowSet</code> objects a choice of
 synchronization mechanisms.  A vendor can make its implementation available by 
-registering the fully qualified class name with Sun Microsystems at 
+registering the fully qualified class name with Oracle Corporation at
 <code>jdbc@sun.com</code>. This process is discussed in further detail below. 
 <P>
 
--- a/jdk/src/share/classes/javax/swing/GroupLayout.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/GroupLayout.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1464,8 +1464,8 @@
      * &lt;= {@code pref} &lt;= {@code max}.
      * <p>
      * Similarly any methods that take a {@code Component} throw a
-     * {@code NullPointerException} if passed {@code null} and any methods
-     * that take a {@code Group} throw an {@code IllegalArgumentException} if
+     * {@code IllegalArgumentException} if passed {@code null} and any methods
+     * that take a {@code Group} throw an {@code NullPointerException} if
      * passed {@code null}.
      *
      * @see #createSequentialGroup
--- a/jdk/src/share/classes/javax/swing/JComponent.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JComponent.java	Wed Jul 05 17:24:13 2017 +0200
@@ -4787,6 +4787,17 @@
      * @see RepaintManager#addDirtyRegion
      */
     public void repaint(long tm, int x, int y, int width, int height) {
+        Container p = this;
+        while ((p = p.getParent()) instanceof JComponent) {
+            JComponent jp = (JComponent) p;
+            if (jp.isPaintingOrigin()) {
+                Rectangle rectangle = SwingUtilities.convertRectangle(
+                        this, new Rectangle(x, y, width, height), jp);
+                jp.repaint(tm,
+                        rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+                return;
+            }
+        }
         RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
     }
 
--- a/jdk/src/share/classes/javax/swing/JDesktopPane.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JDesktopPane.java	Wed Jul 05 17:24:13 2017 +0200
@@ -215,7 +215,8 @@
 
     /**
      * Sets the <code>DesktopManger</code> that will handle
-     * desktop-specific UI actions.
+     * desktop-specific UI actions. This may be overridden by
+     * {@code LookAndFeel}.
      *
      * @param d the <code>DesktopManager</code> to use
      *
--- a/jdk/src/share/classes/javax/swing/JLayer.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JLayer.java	Wed Jul 05 17:24:13 2017 +0200
@@ -25,17 +25,17 @@
 
 package javax.swing;
 
+import sun.awt.AWTAccessor;
+
 import javax.swing.plaf.LayerUI;
+import javax.swing.border.Border;
 import java.awt.*;
 import java.awt.event.*;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.io.IOException;
 import java.io.ObjectInputStream;
-import java.io.Serializable;
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
@@ -156,8 +156,6 @@
     private LayerUI<? super V> layerUI;
     private JPanel glassPane;
     private boolean isPainting;
-    private static final DefaultLayerLayout sharedLayoutInstance =
-            new DefaultLayerLayout();
     private long eventMask;
 
     private static final LayerEventController eventController =
@@ -165,7 +163,7 @@
 
     /**
      * Creates a new {@code JLayer} object with a {@code null} view component
-     * and {@code null} {@link javax.swing.plaf.LayerUI}.
+     * and default {@link javax.swing.plaf.LayerUI}.
      *
      * @see #setView
      * @see #setUI
@@ -176,14 +174,14 @@
 
     /**
      * Creates a new {@code JLayer} object
-     * with {@code null} {@link javax.swing.plaf.LayerUI}.
+     * with default {@link javax.swing.plaf.LayerUI}.
      *
      * @param view the component to be decorated by this {@code JLayer}
      *
      * @see #setUI
      */
     public JLayer(V view) {
-        this(view, null);
+        this(view, new LayerUI<V>());
     }
 
     /**
@@ -195,7 +193,6 @@
      * to be used by this {@code JLayer}
      */
     public JLayer(V view, LayerUI<V> ui) {
-        setLayout(sharedLayoutInstance);
         setGlassPane(createGlassPane());
         setView(view);
         setUI(ui);
@@ -279,10 +276,15 @@
      */
     public void setGlassPane(JPanel glassPane) {
         Component oldGlassPane = getGlassPane();
+        boolean isGlassPaneVisible = false;
         if (oldGlassPane != null) {
+            isGlassPaneVisible = oldGlassPane.isVisible();
             super.remove(oldGlassPane);
         }
         if (glassPane != null) {
+            AWTAccessor.getComponentAccessor().setMixingCutoutShape(glassPane,
+                    new Rectangle());
+            glassPane.setVisible(isGlassPaneVisible);
             super.addImpl(glassPane, null, 0);
         }
         this.glassPane = glassPane;
@@ -303,6 +305,40 @@
     }
 
     /**
+     * Sets the layout manager for this container.  This method is
+     * overridden to prevent the layout manager from being set.
+     * <p/>Note:  If {@code mgr} is non-{@code null}, this
+     * method will throw an exception as layout managers are not supported on
+     * a {@code JLayer}.
+     *
+     * @param mgr the specified layout manager
+     * @exception IllegalArgumentException this method is not supported
+     */
+    public void setLayout(LayoutManager mgr) {
+        if (mgr != null) {
+            throw new IllegalArgumentException("JLayer.setLayout() not supported");
+        }
+    }
+
+    /**
+     * A non-{@code null] border, or non-zero insets, isn't supported, to prevent the geometry
+     * of this component from becoming complex enough to inhibit
+     * subclassing of {@code LayerUI} class.  To create a {@code JLayer} with a border,
+     * add it to a {@code JPanel} that has a border.
+     * <p/>Note:  If {@code border} is non-{@code null}, this
+     * method will throw an exception as borders are not supported on
+     * a {@code JLayer}.
+     *
+     * @param border the {@code Border} to set
+     * @exception IllegalArgumentException this method is not supported
+     */
+    public void setBorder(Border border) {
+        if (border != null) {
+            throw new IllegalArgumentException("JLayer.setBorder() not supported");
+        }
+    }
+
+    /**
      * This method is not supported by {@code JLayer}
      * and always throws {@code UnsupportedOperationException}
      *
@@ -341,6 +377,32 @@
     }
 
     /**
+     * Always returns {@code true} to cause painting to originate from {@code JLayer},
+     * or one of its ancestors.
+     *
+     * @return true
+     * @see JComponent#isPaintingOrigin()
+     */
+    boolean isPaintingOrigin() {
+        return true;
+    }
+
+    /**
+     * Delegates repainting to {@link javax.swing.plaf.LayerUI#repaint} method.
+     *
+     * @param tm  this parameter is not used
+     * @param x  the x value of the dirty region
+     * @param y  the y value of the dirty region
+     * @param width  the width of the dirty region
+     * @param height  the height of the dirty region
+     */
+    public void repaint(long tm, int x, int y, int width, int height) {
+        if (getUI() != null) {
+            getUI().repaint(tm, x, y, width, height, this);
+        }
+    }
+
+    /**
      * Delegates all painting to the {@link javax.swing.plaf.LayerUI} object.
      *
      * @param g the {@code Graphics} to render to
@@ -364,14 +426,18 @@
     }
 
     /**
-     * To enable the correct painting of the {@code glassPane} and view component,
-     * the {@code JLayer} overrides the default implementation of
-     * this method to return {@code false} when the {@code glassPane} is visible.
+     * The {@code JLayer} overrides the default implementation of
+     * this method (in {@code JComponent}) to return {@code false}.
+     * This ensures
+     * that the drawing machinery will call the {@code JLayer}'s
+     * {@code paint}
+     * implementation rather than messaging the {@code JLayer}'s
+     * children directly.
      *
-     * @return false if {@code JLayer}'s {@code glassPane} is visible
+     * @return false
      */
     public boolean isOptimizedDrawingEnabled() {
-        return glassPane == null || !glassPane.isVisible();
+        return false;
     }
 
     /**
@@ -461,17 +527,16 @@
     /**
      * Returns the preferred size of the viewport for a view component.
      * <p/>
-     * If the ui delegate of this layer is not {@code null}, this method delegates its
-     * implementation to the {@code LayerUI.getPreferredScrollableViewportSize(JLayer)}
+     * If the view component of this layer implements {@link Scrollable}, this method delegates its
+     * implementation to the view component.
      *
      * @return the preferred size of the viewport for a view component
      *
      * @see Scrollable
-     * @see LayerUI#getPreferredScrollableViewportSize(JLayer)
      */
     public Dimension getPreferredScrollableViewportSize() {
-        if (getUI() != null) {
-            return getUI().getPreferredScrollableViewportSize(this);
+        if (getView() instanceof Scrollable) {
+            return ((Scrollable)getView()).getPreferredScrollableViewportSize();
         }
         return getPreferredSize();
     }
@@ -481,18 +546,17 @@
      * that display logical rows or columns in order to completely expose
      * one block of rows or columns, depending on the value of orientation.
      * <p/>
-     * If the ui delegate of this layer is not {@code null}, this method delegates its
-     * implementation to the {@code LayerUI.getScrollableBlockIncrement(JLayer,Rectangle,int,int)}
+     * If the view component of this layer implements {@link Scrollable}, this method delegates its
+     * implementation to the view component.
      *
      * @return the "block" increment for scrolling in the specified direction
      *
      * @see Scrollable
-     * @see LayerUI#getScrollableBlockIncrement(JLayer, Rectangle, int, int)
      */
     public int getScrollableBlockIncrement(Rectangle visibleRect,
                                            int orientation, int direction) {
-        if (getUI() != null) {
-            return getUI().getScrollableBlockIncrement(this, visibleRect,
+        if (getView() instanceof Scrollable) {
+            return ((Scrollable)getView()).getScrollableBlockIncrement(visibleRect,
                     orientation, direction);
         }
         return (orientation == SwingConstants.VERTICAL) ? visibleRect.height :
@@ -504,17 +568,16 @@
      * determine the height of the layer, unless the preferred height
      * of the layer is smaller than the height of the viewport.
      * <p/>
-     * If the ui delegate of this layer is not null, this method delegates its
-     * implementation to the {@code LayerUI.getScrollableTracksViewportHeight(JLayer)}
+     * If the view component of this layer implements {@link Scrollable}, this method delegates its
+     * implementation to the view component.
      *
      * @return whether the layer should track the height of the viewport
      *
      * @see Scrollable
-     * @see LayerUI#getScrollableTracksViewportHeight(JLayer)
      */
     public boolean getScrollableTracksViewportHeight() {
-        if (getUI() != null) {
-            return getUI().getScrollableTracksViewportHeight(this);
+        if (getView() instanceof Scrollable) {
+            return ((Scrollable)getView()).getScrollableTracksViewportHeight();
         }
         return false;
     }
@@ -524,17 +587,16 @@
      * determine the width of the layer, unless the preferred width
      * of the layer is smaller than the width of the viewport.
      * <p/>
-     * If the ui delegate of this layer is not null, this method delegates its
-     * implementation to the {@code LayerUI.getScrollableTracksViewportWidth(JLayer)}
+     * If the view component of this layer implements {@link Scrollable}, this method delegates its
+     * implementation to the view component.
      *
      * @return whether the layer should track the width of the viewport
      *
      * @see Scrollable
-     * @see LayerUI#getScrollableTracksViewportWidth(JLayer)
      */
     public boolean getScrollableTracksViewportWidth() {
-        if (getUI() != null) {
-            return getUI().getScrollableTracksViewportWidth(this);
+        if (getView() instanceof Scrollable) {
+            return ((Scrollable)getView()).getScrollableTracksViewportWidth();
         }
         return false;
     }
@@ -549,20 +611,19 @@
      * Scrolling containers, like {@code JScrollPane}, will use this method
      * each time the user requests a unit scroll.
      * <p/>
-     * If the ui delegate of this layer is not {@code null}, this method delegates its
-     * implementation to the {@code LayerUI.getScrollableUnitIncrement(JLayer,Rectangle,int,int)}
+     * If the view component of this layer implements {@link Scrollable}, this method delegates its
+     * implementation to the view component.
      *
      * @return The "unit" increment for scrolling in the specified direction.
      *         This value should always be positive.
      *
      * @see Scrollable
-     * @see LayerUI#getScrollableUnitIncrement(JLayer, Rectangle, int, int)
      */
     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
                                           int direction) {
-        if (getUI() != null) {
-            return getUI().getScrollableUnitIncrement(
-                    this, visibleRect, orientation, direction);
+        if (getView() instanceof Scrollable) {
+            return ((Scrollable) getView()).getScrollableUnitIncrement(
+                    visibleRect, orientation, direction);
         }
         return 1;
     }
@@ -595,6 +656,16 @@
     }
 
     /**
+     * Delegates its functionality to the {@link javax.swing.plaf.LayerUI#doLayout(JLayer)} method,
+     * if {@code LayerUI} is set.
+     */
+    public void doLayout() {
+        if (getUI() != null) {
+            getUI().doLayout(this);
+        }
+    }
+
+    /**
      * static AWTEventListener to be shared with all AbstractLayerUIs
      */
     private static class LayerEventController implements AWTEventListener {
@@ -625,8 +696,8 @@
                         JLayer l = (JLayer) component;
                         LayerUI ui = l.getUI();
                         if (ui != null &&
-                                isEventEnabled(l.getLayerEventMask(),
-                                        event.getID())) {
+                                isEventEnabled(l.getLayerEventMask(), event.getID()) &&
+                                (!(event instanceof InputEvent) || !((InputEvent)event).isConsumed())) {
                             ui.eventDispatched(event, l);
                         }
                     }
@@ -758,82 +829,4 @@
             return super.contains(x, y);
         }
     }
-
-    /**
-     * The default layout manager for the {@link javax.swing.JLayer}.<br/>
-     * It places the glassPane on top of the view component
-     * and makes it the same size as {@code JLayer},
-     * it also makes the view component the same size but minus layer's insets<br/>
-     */
-    private static class DefaultLayerLayout implements LayoutManager, Serializable {
-        /**
-         * {@inheritDoc}
-         */
-        public void layoutContainer(Container parent) {
-            JLayer layer = (JLayer) parent;
-            Component view = layer.getView();
-            Component glassPane = layer.getGlassPane();
-            if (view != null) {
-                Insets insets = layer.getInsets();
-                view.setLocation(insets.left, insets.top);
-                view.setSize(layer.getWidth() - insets.left - insets.right,
-                        layer.getHeight() - insets.top - insets.bottom);
-            }
-            if (glassPane != null) {
-                glassPane.setLocation(0, 0);
-                glassPane.setSize(layer.getWidth(), layer.getHeight());
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Dimension minimumLayoutSize(Container parent) {
-            JLayer layer = (JLayer) parent;
-            Insets insets = layer.getInsets();
-            Dimension ret = new Dimension(insets.left + insets.right,
-                    insets.top + insets.bottom);
-            Component view = layer.getView();
-            if (view != null) {
-                Dimension size = view.getMinimumSize();
-                ret.width += size.width;
-                ret.height += size.height;
-            }
-            if (ret.width == 0 || ret.height == 0) {
-                ret.width = ret.height = 4;
-            }
-            return ret;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Dimension preferredLayoutSize(Container parent) {
-            JLayer layer = (JLayer) parent;
-            Insets insets = layer.getInsets();
-            Dimension ret = new Dimension(insets.left + insets.right,
-                    insets.top + insets.bottom);
-            Component view = layer.getView();
-            if (view != null) {
-                Dimension size = view.getPreferredSize();
-                if (size.width > 0 && size.height > 0) {
-                    ret.width += size.width;
-                    ret.height += size.height;
-                }
-            }
-            return ret;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void addLayoutComponent(String name, Component comp) {
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void removeLayoutComponent(Component comp) {
-        }
-    }
 }
--- a/jdk/src/share/classes/javax/swing/JTable.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JTable.java	Wed Jul 05 17:24:13 2017 +0200
@@ -4574,9 +4574,8 @@
      * @see TableColumnModelListener
      */
     public void columnMoved(TableColumnModelEvent e) {
-        // If I'm currently editing, then I should stop editing
-        if (isEditing()) {
-            removeEditor();
+        if (isEditing() && !getCellEditor().stopCellEditing()) {
+            getCellEditor().cancelCellEditing();
         }
         repaint();
     }
@@ -4593,8 +4592,8 @@
      * @see TableColumnModelListener
      */
     public void columnMarginChanged(ChangeEvent e) {
-        if (isEditing()) {
-            removeEditor();
+        if (isEditing() && !getCellEditor().stopCellEditing()) {
+            getCellEditor().cancelCellEditing();
         }
         TableColumn resizingColumn = getResizingColumn();
         // Need to do this here, before the parent's
--- a/jdk/src/share/classes/javax/swing/ToolTipManager.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/ToolTipManager.java	Wed Jul 05 17:24:13 2017 +0200
@@ -459,7 +459,7 @@
         if (insideComponent == null) {
             // Drag exit
         }
-        if (window != null && event.getSource() == window) {
+        if (window != null && event.getSource() == window && insideComponent != null) {
           // if we get an exit and have a heavy window
           // we need to check if it if overlapping the inside component
             Container insideComponentWindow = insideComponent.getTopLevelAncestor();
--- a/jdk/src/share/classes/javax/swing/plaf/LayerUI.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/LayerUI.java	Wed Jul 05 17:24:13 2017 +0200
@@ -600,104 +600,6 @@
     }
 
     /**
-     * Returns the preferred size of the viewport for a view component.
-     *
-     * @param l the {@code JLayer} component where this UI delegate is being installed
-     * @return the preferred size of the viewport for a view component
-     * @see Scrollable#getPreferredScrollableViewportSize()
-     */
-    public Dimension getPreferredScrollableViewportSize(JLayer<? extends V> l) {
-        if (l.getView() instanceof Scrollable) {
-            return ((Scrollable)l.getView()).getPreferredScrollableViewportSize();
-        }
-        return l.getPreferredSize();
-    }
-
-    /**
-     * Returns a scroll increment, which is required for components
-     * that display logical rows or columns in order to completely expose
-     * one block of rows or columns, depending on the value of orientation.
-     *
-     * @param l the {@code JLayer} component where this UI delegate is being installed
-     * @param visibleRect The view area visible within the viewport
-     * @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
-     * @param direction Less than zero to scroll up/left, greater than zero for down/right.
-     * @return the "block" increment for scrolling in the specified direction
-     * @see Scrollable#getScrollableBlockIncrement(Rectangle, int, int)
-     */
-     public int getScrollableBlockIncrement(JLayer<? extends V> l,
-                                           Rectangle visibleRect,
-                                           int orientation, int direction) {
-        if (l.getView() instanceof Scrollable) {
-            return ((Scrollable)l.getView()).getScrollableBlockIncrement(
-                    visibleRect,orientation, direction);
-        }
-        return (orientation == SwingConstants.VERTICAL) ? visibleRect.height :
-            visibleRect.width;
-    }
-
-    /**
-     * Returns {@code false} to indicate that the height of the viewport does not
-     * determine the height of the layer, unless the preferred height
-     * of the layer is smaller than the height of the viewport.
-     *
-     * @param l the {@code JLayer} component where this UI delegate is being installed
-     * @return whether the layer should track the height of the viewport
-     * @see Scrollable#getScrollableTracksViewportHeight()
-     */
-    public boolean getScrollableTracksViewportHeight(JLayer<? extends V> l) {
-        if (l.getView() instanceof Scrollable) {
-            return ((Scrollable)l.getView()).getScrollableTracksViewportHeight();
-        }
-        return false;
-    }
-
-    /**
-     * Returns {@code false} to indicate that the width of the viewport does not
-     * determine the width of the layer, unless the preferred width
-     * of the layer is smaller than the width of the viewport.
-     *
-     * @param l the {@code JLayer} component where this UI delegate is being installed
-     * @return whether the layer should track the width of the viewport
-     * @see Scrollable
-     * @see LayerUI#getScrollableTracksViewportWidth(JLayer)
-     */
-    public boolean getScrollableTracksViewportWidth(JLayer<? extends V> l) {
-        if (l.getView() instanceof Scrollable) {
-            return ((Scrollable)l.getView()).getScrollableTracksViewportWidth();
-        }
-        return false;
-    }
-
-    /**
-     * Returns a scroll increment, which is required for components
-     * that display logical rows or columns in order to completely expose
-     * one new row or column, depending on the value of orientation.
-     * Ideally, components should handle a partially exposed row or column
-     * by returning the distance required to completely expose the item.
-     * <p>
-     * Scrolling containers, like JScrollPane, will use this method
-     * each time the user requests a unit scroll.
-     *
-     * @param l the {@code JLayer} component where this UI delegate is being installed
-     * @param visibleRect The view area visible within the viewport
-     * @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
-     * @param direction Less than zero to scroll up/left, greater than zero for down/right.
-     * @return The "unit" increment for scrolling in the specified direction.
-     *         This value should always be positive.
-     * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int)
-     */
-    public int getScrollableUnitIncrement(JLayer<? extends V> l,
-                                          Rectangle visibleRect,
-                                          int orientation, int direction) {
-        if (l.getView() instanceof Scrollable) {
-            return ((Scrollable)l.getView()).getScrollableUnitIncrement(
-                    visibleRect, orientation, direction);
-        }
-        return 1;
-    }
-
-    /**
      * If the {@code JLayer}'s view component is not {@code null},
      * this calls the view's {@code getBaseline()} method.
      * Otherwise, the default implementation is called.
@@ -718,7 +620,7 @@
 
     /**
      * If the {@code JLayer}'s view component is not {@code null},
-     * this calls the view's {@code getBaselineResizeBehavior()} method.
+     * this returns the result of the view's {@code getBaselineResizeBehavior()} method.
      * Otherwise, the default implementation is called.
      *
      * @param c {@code JLayer} to return baseline resize behavior for
@@ -732,4 +634,90 @@
         }
         return super.getBaselineResizeBehavior(c);
     }
+
+    /**
+     * Causes the passed instance of {@code JLayer} to lay out its components.
+     *
+     * @param l the {@code JLayer} component where this UI delegate is being installed
+     */
+    public void doLayout(JLayer<? extends V> l) {
+        Component view = l.getView();
+        if (view != null) {
+            view.setBounds(0, 0, l.getWidth(), l.getHeight());
+        }
+        Component glassPane = l.getGlassPane();
+        if (glassPane != null) {
+            glassPane.setBounds(0, 0, l.getWidth(), l.getHeight());
+        }
+    }
+
+    /**
+     * If the {@code JLayer}'s view component is not {@code null},
+     * this returns the result of  the view's {@code getPreferredSize()} method.
+     * Otherwise, the default implementation is used.
+     *
+     * @param c {@code JLayer} to return preferred size for
+     * @return preferred size for the passed {@code JLayer}
+     */
+    public Dimension getPreferredSize(JComponent c) {
+        JLayer l = (JLayer) c;
+        Component view = l.getView();
+        if (view != null) {
+            return view.getPreferredSize();
+        }
+        return super.getPreferredSize(c);
+    }
+
+    /**
+     * If the {@code JLayer}'s view component is not {@code null},
+     * this returns the result of  the view's {@code getMinimalSize()} method.
+     * Otherwise, the default implementation is used.
+     *
+     * @param c {@code JLayer} to return preferred size for
+     * @return minimal size for the passed {@code JLayer}
+     */
+    public Dimension getMinimumSize(JComponent c) {
+        JLayer l = (JLayer) c;
+        Component view = l.getView();
+        if (view != null) {
+            return view.getMinimumSize();
+        }
+        return super.getMinimumSize(c);
+    }
+
+    /**
+     * If the {@code JLayer}'s view component is not {@code null},
+     * this returns the result of  the view's {@code getMaximumSize()} method.
+     * Otherwise, the default implementation is used.
+     *
+     * @param c {@code JLayer} to return preferred size for
+     * @return maximun size for the passed {@code JLayer}
+     */
+    public Dimension getMaximumSize(JComponent c) {
+        JLayer l = (JLayer) c;
+        Component view = l.getView();
+        if (view != null) {
+            return view.getMaximumSize();
+        }
+        return super.getMaximumSize(c);
+    }
+
+    /**
+     * Adds the specified region to the dirty region list if the component
+     * is showing.  The component will be repainted after all of the
+     * currently pending events have been dispatched.
+     * <p/>
+     * This method is to be overridden when the dirty region needs to be changed.
+     *
+     * @param tm  this parameter is not used
+     * @param x  the x value of the dirty region
+     * @param y  the y value of the dirty region
+     * @param width  the width of the dirty region
+     * @param height  the height of the dirty region
+     * @see java.awt.Component#isShowing
+     * @see RepaintManager#addDirtyRegion
+     */
+    public void repaint(long tm, int x, int y, int width, int height, JLayer<? extends V> l) {
+        RepaintManager.currentManager(l).addDirtyRegion(l, x, y, width, height);
+    }
 }
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1603,6 +1603,7 @@
                 BoundedRangeModel newModel = (BoundedRangeModel)e.getNewValue();
                 oldModel.removeChangeListener(modelListener);
                 newModel.addChangeListener(modelListener);
+                scrollBarValue = scrollbar.getValue();
                 scrollbar.repaint();
                 scrollbar.revalidate();
             } else if ("orientation" == propertyName) {
--- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalComboBoxUI.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalComboBoxUI.java	Wed Jul 05 17:24:13 2017 +0200
@@ -144,7 +144,7 @@
      */
     public int getBaseline(JComponent c, int width, int height) {
         int baseline;
-        if (MetalLookAndFeel.usingOcean()) {
+        if (MetalLookAndFeel.usingOcean() && height >= 4) {
             height -= 4;
             baseline = super.getBaseline(c, width, height);
             if (baseline >= 0) {
--- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Wed Jul 05 17:24:13 2017 +0200
@@ -115,6 +115,9 @@
         return new SynthTabbedPaneUI();
     }
 
+    private SynthTabbedPaneUI() {
+    }
+
     private boolean scrollableTabLayoutEnabled() {
         return (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT);
     }
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java	Wed Jul 05 17:24:13 2017 +0200
@@ -344,6 +344,11 @@
          * Removes the last focus request for the heavyweight from the queue.
          */
         void removeLastFocusRequest(Component heavyweight);
+
+        /*
+         * Sets the most recent focus owner in the window.
+         */
+        void setMostRecentFocusOwner(Window window, Component component);
     }
 
     /*
--- a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java	Wed Jul 05 17:24:13 2017 +0200
@@ -70,7 +70,10 @@
     // JDK 1.1 compatibility
     private static final long serialVersionUID = 2967042741780317130L;
 
-    // Use these in traverseOut method to determine directions
+    /*
+     * The constants define focus traversal directions.
+     * Use them in {@code traverseIn}, {@code traverseOut} methods.
+     */
     protected static final boolean FORWARD = true;
     protected static final boolean BACKWARD = false;
 
@@ -284,6 +287,41 @@
     }
 
     /**
+     * This method is called by the embedder when we should receive focus as element
+     * of the traversal chain.  The method requests focus on:
+     * 1. the first Component of this EmbeddedFrame if user moves focus forward
+     *    in the focus traversal cycle.
+     * 2. the last Component of this EmbeddedFrame if user moves focus backward
+     *    in the focus traversal cycle.
+     *
+     * The direction parameter specifies which of the two mentioned cases is
+     * happening. Use FORWARD and BACKWARD constants defined in the EmbeddedFrame class
+     * to avoid confusing boolean values.
+     *
+     * A concrete implementation of this method is defined in the platform-dependent
+     * subclasses.
+     *
+     * @param direction FORWARD or BACKWARD
+     * @return true, if the EmbeddedFrame wants to get focus, false otherwise.
+     */
+    public boolean traverseIn(boolean direction) {
+        Component comp = null;
+
+        if (direction == FORWARD) {
+            comp = getFocusTraversalPolicy().getFirstComponent(this);
+        } else {
+            comp = getFocusTraversalPolicy().getLastComponent(this);
+        }
+        if (comp != null) {
+            // comp.requestFocus(); - Leads to a hung.
+
+            AWTAccessor.getKeyboardFocusManagerAccessor().setMostRecentFocusOwner(this, comp);
+            synthesizeWindowActivation(true);
+        }
+        return (null != comp);
+    }
+
+    /**
      * This method is called from dispatchKeyEvent in the following two cases:
      * 1. The focus is on the first Component of this EmbeddedFrame and we are
      *    about to transfer the focus backward.
--- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java	Wed Jul 05 17:24:13 2017 +0200
@@ -55,6 +55,9 @@
     // Http data we send with the headers
     PosterOutputStream poster = null;
 
+    // true if we are in streaming mode (fixed length or chunked)
+    boolean streaming;
+
     // if we've had one io error
     boolean failedOnce = false;
 
@@ -275,6 +278,10 @@
                         ret.cachedHttpClient = true;
                         assert ret.inCache;
                         ret.inCache = false;
+                        PlatformLogger logger = HttpURLConnection.getHttpLogger();
+                        if (logger.isLoggable(PlatformLogger.FINEST)) {
+                            logger.finest("KeepAlive stream retrieved from the cache, " + ret);
+                        }
                     }
                 } else {
                     // We cannot return this connection to the cache as it's
@@ -545,6 +552,13 @@
         serverOutput.flush();
     }
 
+    public void writeRequests(MessageHeader head,
+                              PosterOutputStream pos,
+                              boolean streaming) throws IOException {
+        this.streaming = streaming;
+        writeRequests(head, pos);
+    }
+
     /** Parse the first line of the HTTP request.  It usually looks
         something like: "HTTP/1.0 <number> comment\r\n". */
 
@@ -577,11 +591,11 @@
             closeServer();
             cachedHttpClient = false;
             if (!failedOnce && requests != null) {
-                if (httpuc.getRequestMethod().equals("POST") && !retryPostProp) {
+                failedOnce = true;
+                if (httpuc.getRequestMethod().equals("POST") && (!retryPostProp || streaming)) {
                     // do not retry the request
                 }  else {
                     // try once more
-                    failedOnce = true;
                     openServer();
                     if (needsTunneling()) {
                         httpuc.doTunneling();
@@ -684,10 +698,10 @@
                 }
             } else if (nread != 8) {
                 if (!failedOnce && requests != null) {
-                    if (httpuc.getRequestMethod().equals("POST") && !retryPostProp) {
+                    failedOnce = true;
+                    if (httpuc.getRequestMethod().equals("POST") && (!retryPostProp || streaming)) {
                         // do not retry the request
                     } else {
-                        failedOnce = true;
                         closeServer();
                         cachedHttpClient = false;
                         openServer();
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Wed Jul 05 17:24:13 2017 +0200
@@ -494,7 +494,7 @@
         if (logger.isLoggable(PlatformLogger.FINE)) {
             logger.fine(requests.toString());
         }
-        http.writeRequests(requests, poster);
+        http.writeRequests(requests, poster, streaming());
         if (ps.checkError()) {
             String proxyHost = http.getProxyHostUsed();
             int proxyPort = http.getProxyPortUsed();
@@ -2825,6 +2825,38 @@
             }
         }
 
+        /* skip() calls read() in order to ensure that entire response gets
+         * cached. same implementation as InputStream.skip */
+
+        private byte[] skipBuffer;
+        private static final int SKIP_BUFFER_SIZE = 8096;
+
+        @Override
+        public long skip (long n) throws IOException {
+
+            long remaining = n;
+            int nr;
+            if (skipBuffer == null)
+                skipBuffer = new byte[SKIP_BUFFER_SIZE];
+
+            byte[] localSkipBuffer = skipBuffer;
+
+            if (n <= 0) {
+                return 0;
+            }
+
+            while (remaining > 0) {
+                nr = read(localSkipBuffer, 0,
+                          (int) Math.min(SKIP_BUFFER_SIZE, remaining));
+                if (nr < 0) {
+                    break;
+                }
+                remaining -= nr;
+            }
+
+            return n - remaining;
+        }
+
         @Override
         public void close () throws IOException {
             try {
--- a/jdk/src/share/classes/sun/security/tools/KeyTool.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java	Wed Jul 05 17:24:13 2017 +0200
@@ -281,7 +281,7 @@
         RFC("rfc", null, "output in RFC style"),
         SIGALG("sigalg", "<sigalg>", "signature algorithm name"),
         SRCALIAS("srcalias", "<srcalias>", "source alias"),
-        SRCKEYPASS("srckeypass", "<arg>", "source keystore password"),
+        SRCKEYPASS("srckeypass", "<arg>", "source key password"),
         SRCKEYSTORE("srckeystore", "<srckeystore>", "source keystore name"),
         SRCPROTECTED("srcprotected", null, "source keystore password protected"),
         SRCPROVIDERNAME("srcprovidername", "<srcprovidername>", "source keystore provider name"),
--- a/jdk/src/share/classes/sun/security/util/Resources.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/sun/security/util/Resources.java	Wed Jul 05 17:24:13 2017 +0200
@@ -116,11 +116,9 @@
         {"X.509 extension",
                 "X.509 extension"}, //-ext
         {"output file name",
-                "output file name"}, //-file
+                "output file name"}, //-file and -outfile
         {"input file name",
-                "input file name"}, //-file
-        {"input file name",
-                "input file name"}, //-infile
+                "input file name"}, //-file and -infile
         {"key algorithm name",
                 "key algorithm name"}, //-keyalg
         {"key password",
@@ -133,8 +131,6 @@
                 "new password"}, //-new
         {"do not prompt",
                 "do not prompt"}, //-noprompt
-        {"output file name",
-                "output file name"}, //-outfile
         {"password through protected mechanism",
                 "password through protected mechanism"}, //-protected
         {"provider argument",
@@ -151,8 +147,8 @@
                 "signature algorithm name"}, //-sigalg
         {"source alias",
                 "source alias"}, //-srcalias
-        {"source keystore password",
-                "source keystore password"}, //-srckeypass
+        {"source key password",
+                "source key password"}, //-srckeypass
         {"source keystore name",
                 "source keystore name"}, //-srckeystore
         {"source keystore password protected",
@@ -276,8 +272,6 @@
                 "Alias <{0}> has no certificate"},
         {"Key pair not generated, alias <alias> already exists",
                 "Key pair not generated, alias <{0}> already exists"},
-        {"Cannot derive signature algorithm",
-                "Cannot derive signature algorithm"},
         {"Generating keysize bit keyAlgName key pair and self-signed certificate (sigAlgName) with a validity of validality days\n\tfor: x500Name",
                 "Generating {0} bit {1} key pair and self-signed certificate ({2}) with a validity of {3} days\n\tfor: {4}"},
         {"Enter key password for <alias>", "Enter key password for <{0}>"},
@@ -321,8 +315,6 @@
         {"Failed to parse input", "Failed to parse input"},
         {"Empty input", "Empty input"},
         {"Not X.509 certificate", "Not X.509 certificate"},
-        {"Cannot derive signature algorithm",
-                "Cannot derive signature algorithm"},
         {"alias has no public key", "{0} has no public key"},
         {"alias has no X.509 certificate", "{0} has no X.509 certificate"},
         {"New certificate (self-signed):", "New certificate (self-signed):"},
@@ -552,7 +544,6 @@
         {"package name", "package name"},
         {"policy type", "policy type"},
         {"property name", "property name"},
-        {"provider name", "provider name"},
         {"Principal List", "Principal List"},
         {"Permission List", "Permission List"},
         {"Code Base", "Code Base"},
--- a/jdk/src/share/classes/sun/util/locale/BaseLocale.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/classes/sun/util/locale/BaseLocale.java	Wed Jul 05 17:24:13 2017 +0200
@@ -64,12 +64,14 @@
 
     public static BaseLocale getInstance(String language, String script, String region, String variant) {
         // JDK uses deprecated ISO639.1 language codes for he, yi and id
-        if (AsciiUtil.caseIgnoreMatch(language, "he")) {
-            language = "iw";
-        } else if (AsciiUtil.caseIgnoreMatch(language, "yi")) {
-            language = "ji";
-        } else if (AsciiUtil.caseIgnoreMatch(language, "id")) {
-            language = "in";
+        if (language != null) {
+            if (AsciiUtil.caseIgnoreMatch(language, "he")) {
+                language = "iw";
+            } else if (AsciiUtil.caseIgnoreMatch(language, "yi")) {
+                language = "ji";
+            } else if (AsciiUtil.caseIgnoreMatch(language, "id")) {
+                language = "in";
+            }
         }
 
         Key key = new Key(language, script, region, variant);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/Demo.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,664 @@
+/*
+ * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.net.*;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/*
+ * ZipFileSystem usage demo
+ *
+ * java [-cp .../zipfs.jar:./] Demo action ZipfileName [...]
+ *
+ * To deploy the provider, either copy the zipfs.jar into JDK/JRE
+ * extensions directory or add
+ *      <JDK_HOME>/demo/nio/ZipFileSystem/zipfs.jar
+ * into your class path as showed above.
+ *
+ * @author Xueming Shen
+ */
+
+public class Demo {
+
+    static enum Action {
+        rename,          // <java Demo rename zipfile src dst>
+                         // rename entry src to dst inside zipfile
+
+        movein,          // <java Demo movein zipfile src dst>
+                         // move an external src file into zipfile
+                         // as entry dst
+
+        moveout,         // <java Demo moveout zipfile src dst>
+                         // move a zipfile entry src out to dst
+
+        copy,            // <java Demo copy zipfile src dst>
+                         // copy entry src to dst inside zipfile
+
+        copyin,          // <java Demo copyin zipfile src dst>
+                         // copy an external src file into zipfile
+                         // as entry dst
+
+        copyout,         // <java Demo copyout zipfile src dst>
+                         // copy zipfile entry src" out to file dst
+
+        zzmove,          // <java Demo zzmove zfsrc zfdst path>
+                         // move entry path/dir from zfsrc to zfdst
+
+        zzcopy,          // <java Demo zzcopy zfsrc zfdst path>
+                         // copy path from zipfile zfsrc to zipfile
+                         // zfdst
+
+        attrs,           // <java Demo attrs zipfile path>
+                         // printout the attributes of entry path
+
+        attrsspace,      // <java Demo attrsspace zipfile path>
+                         // printout the storespace attrs of entry path
+
+        setmtime,        // <java Demo setmtime zipfile "MM/dd/yy-HH:mm:ss" path...>
+                         // set the lastModifiedTime of entry path
+
+        lsdir,           // <java Demo lsdir zipfile dir>
+                         // list dir's direct child files/dirs
+
+        mkdir,           // <java Demo mkdir zipfile dir>
+
+        mkdirs,          // <java Demo mkdirs zipfile dir>
+
+        rmdirs,          // <java Demo rmdirs zipfile dir>
+
+        list,            // <java Demo list zipfile [dir]>
+                         // recursively list all entries of dir
+                         // via DirectoryStream
+
+        tlist,           // <java Demo tlist zipfile [dir]>
+                         // list with buildDirTree=true
+
+        vlist,           // <java Demo vlist zipfile [dir]>
+                         // recursively verbose list all entries of
+                         // dir via DirectoryStream
+
+        walk,            // <java Demo walk zipfile [dir]>
+                         // recursively walk all entries of dir
+                         // via Files.walkFileTree
+
+        twalk,           // <java Demo twalk zipfile [dir]>
+                         // walk with buildDirTree=true
+
+        extract,         // <java Demo extract zipfile file [...]>
+
+        update,          // <java Demo extract zipfile file [...]>
+
+        delete,          // <java Demo delete zipfile file [...]>
+
+        add,             // <java Demo add zipfile file [...]>
+
+        create,          // <java Demo create zipfile file [...]>
+                         // create a new zipfile if it doesn't exit
+                         // and then add the file(s) into it.
+
+        attrs2,          // <java Demo attrs2 zipfile file [...]>
+                         // test different ways to print attrs
+    }
+
+    public static void main(String[] args) throws Throwable {
+
+        Action action = Action.valueOf(args[0]);;
+        Map<String, Object> env = env = new HashMap<String, Object>();
+        if (action == Action.create)
+            env.put("createNew", true);
+        if (action == Action.tlist || action == Action.twalk)
+            env.put("buildDirTree", true);
+
+        FileSystem fs = FileSystems.newFileSystem(
+                            URI.create("zip" + Paths.get(args[1]).toUri().toString().substring(4)),
+                            env,
+                            null);
+        try {
+            FileSystem fs2;
+            Path path, src, dst;
+            boolean isRename = false;
+            switch (action) {
+            case rename:
+                src = fs.getPath(args[2]);
+                dst = fs.getPath(args[3]);
+                src.moveTo(dst);
+                break;
+            case moveout:
+                src = fs.getPath(args[2]);
+                dst = Paths.get(args[3]);
+                src.moveTo(dst);
+                break;
+            case movein:
+                src = Paths.get(args[2]);
+                dst = fs.getPath(args[3]);
+                src.moveTo(dst);
+                break;
+            case copy:
+                src = fs.getPath(args[2]);
+                dst = fs.getPath(args[3]);
+                src.copyTo(dst);
+                break;
+            case copyout:
+                src = fs.getPath(args[2]);
+                dst = Paths.get(args[3]);
+                src.copyTo(dst);
+                break;
+            case copyin:
+                src = Paths.get(args[2]);
+                dst = fs.getPath(args[3]);
+                src.copyTo(dst);
+                break;
+            case zzmove:
+                fs2 = FileSystems.newFileSystem(
+                    URI.create("zip" + Paths.get(args[2]).toUri().toString().substring(4)),
+                    env,
+                    null);
+                //sf1.getPath(args[3]).moveTo(fs2.getPath(args[3]));
+                z2zmove(fs, fs2, args[3]);
+                fs2.close();
+                break;
+            case zzcopy:
+                fs2 = FileSystems.newFileSystem(
+                    URI.create("zip" + Paths.get(args[2]).toUri().toString().substring(4)),
+                    env,
+                    null);
+                //sf1.getPath(args[3]).copyTo(fs2.getPath(args[3]));
+                z2zcopy(fs, fs2, args[3]);
+                fs2.close();
+                break;
+            case attrs:
+                for (int i = 2; i < args.length; i++) {
+                    path = fs.getPath(args[i]);
+                    System.out.println(
+                        Attributes.readBasicFileAttributes(path).toString());
+                }
+                break;
+            case setmtime:
+                DateFormat df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
+                Date newDatetime = df.parse(args[2]);
+                for (int i = 3; i < args.length; i++) {
+                    path = fs.getPath(args[i]);
+                    path.setAttribute("lastModifiedTime",
+                                      FileTime.fromMillis(newDatetime.getTime()));
+                    System.out.println(
+                        Attributes.readBasicFileAttributes(path).toString());
+                }
+                break;
+            case attrsspace:
+                path = fs.getPath("/");
+                FileStore fstore = path.getFileStore();
+                //System.out.println(fstore.getFileStoreAttributeView(FileStoreSpaceAttributeView.class)
+                //                         .readAttributes());
+                // or
+                System.out.printf("filestore[%s]%n", fstore.name());
+                System.out.printf("    totalSpace: %d%n",
+                                  (Long)fstore.getAttribute("space:totalSpace"));
+                System.out.printf("   usableSpace: %d%n",
+                                  (Long)fstore.getAttribute("space:usableSpace"));
+                System.out.printf("  unallocSpace: %d%n",
+                                  (Long)fstore.getAttribute("space:unallocatedSpace"));
+                break;
+            case list:
+            case tlist:
+                if (args.length < 3)
+                    list(fs.getPath("/"), false);
+                else
+                    list(fs.getPath(args[2]), false);
+                break;
+            case vlist:
+                if (args.length < 3)
+                    list(fs.getPath("/"), true);
+                else
+                    list(fs.getPath(args[2]), true);
+                break;
+            case twalk:
+            case walk:
+                walk(fs.getPath((args.length > 2)? args[2] : "/"));
+                break;
+            case extract:
+                if (args.length == 2) {
+                     extract(fs, "/");
+                } else {
+                    for (int i = 2; i < args.length; i++) {
+                        extract(fs, args[i]);
+                    }
+                }
+                break;
+            case delete:
+                for (int i = 2; i < args.length; i++)
+                    fs.getPath(args[i]).delete();
+                break;
+            case create:
+            case add:
+            case update:
+                for (int i = 2; i < args.length; i++) {
+                    update(fs, args[i]);
+                }
+                break;
+            case lsdir:
+                path = fs.getPath(args[2]);
+                final String fStr = (args.length > 3)?args[3]:"";
+                DirectoryStream<Path> ds = path.newDirectoryStream(
+                    new DirectoryStream.Filter<Path>() {
+                        public boolean accept(Path path) {
+                            return path.toString().contains(fStr);
+                        }
+                    });
+                for (Path p : ds)
+                    System.out.println(p);
+                break;
+            case mkdir:
+                fs.getPath(args[2]).createDirectory();
+                break;
+            case mkdirs:
+                mkdirs(fs.getPath(args[2]));
+                break;
+            case attrs2:
+                for (int i = 2; i < args.length; i++) {
+                    path = fs.getPath(args[i]);
+                    System.out.println("-------(1)---------");
+                    System.out.println(
+                        Attributes.readBasicFileAttributes(path).toString());
+                    System.out.println("-------(2)---------");
+                    Map<String, ?> map = path.readAttributes("zip:*");
+                    for (Map.Entry<String, ?> e : map.entrySet()) {
+                        System.out.printf("    %s : %s%n", e.getKey(), e.getValue());
+                    }
+                    System.out.println("-------(3)---------");
+                    map = path.readAttributes("size,lastModifiedTime,isDirectory");
+                    for (Map.Entry<String, ?> e : map.entrySet()) {
+                        System.out.printf("    %s : %s%n", e.getKey(), e.getValue());
+                    }
+                }
+                break;
+            }
+        } catch (Exception x) {
+            x.printStackTrace();
+        } finally {
+            if (fs != null)
+                fs.close();
+        }
+    }
+
+    private static byte[] getBytes(String name) {
+        return name.getBytes();
+    }
+
+    private static String getString(byte[] name) {
+        return new String(name);
+    }
+
+    private static void walk(Path path) throws IOException
+    {
+        Files.walkFileTree(
+            path,
+            new SimpleFileVisitor<Path>() {
+                private int indent = 0;
+                private void indent() {
+                    int n = 0;
+                    while (n++ < indent)
+                        System.out.printf(" ");
+                }
+
+                @Override
+                public FileVisitResult visitFile(Path file,
+                                                 BasicFileAttributes attrs)
+                {
+                    indent();
+                    System.out.printf("%s%n", file.getName().toString());
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult preVisitDirectory(Path dir,
+                                                         BasicFileAttributes attrs)
+                {
+                    indent();
+                    System.out.printf("[%s]%n", dir.toString());
+                    indent += 2;
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult postVisitDirectory(Path dir,
+                                                          IOException ioe)
+                {
+                    indent -= 2;
+                    return FileVisitResult.CONTINUE;
+                }
+        });
+    }
+
+    private static void update(FileSystem fs, String path) throws Throwable{
+        Path src = FileSystems.getDefault().getPath(path);
+        if (Boolean.TRUE.equals(src.getAttribute("isDirectory"))) {
+            DirectoryStream<Path> ds = src.newDirectoryStream();
+            for (Path child : ds)
+                update(fs, child.toString());
+            ds.close();
+        } else {
+            Path dst = fs.getPath(path);
+            Path parent = dst.getParent();
+            if (parent != null && parent.notExists())
+                mkdirs(parent);
+            src.copyTo(dst, REPLACE_EXISTING);
+        }
+    }
+
+    private static void extract(FileSystem fs, String path) throws Throwable{
+        Path src = fs.getPath(path);
+        if (Boolean.TRUE.equals(src.getAttribute("isDirectory"))) {
+            DirectoryStream<Path> ds = src.newDirectoryStream();
+            for (Path child : ds)
+                extract(fs, child.toString());
+            ds.close();
+        } else {
+            if (path.startsWith("/"))
+                path = path.substring(1);
+            Path dst = FileSystems.getDefault().getPath(path);
+            Path parent = dst.getParent();
+            if (parent.notExists())
+                mkdirs(parent);
+            src.copyTo(dst, REPLACE_EXISTING);
+        }
+    }
+
+    // use DirectoryStream
+    private static void z2zcopy(FileSystem src, FileSystem dst, String path)
+        throws IOException
+    {
+        Path srcPath = src.getPath(path);
+        Path dstPath = dst.getPath(path);
+
+        if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) {
+            if (!dstPath.exists()) {
+                try {
+                    mkdirs(dstPath);
+                } catch (FileAlreadyExistsException x) {}
+            }
+            DirectoryStream<Path> ds = srcPath.newDirectoryStream();
+            for (Path child : ds) {
+                z2zcopy(src, dst,
+                        path + (path.endsWith("/")?"":"/") + child.getName());
+            }
+            ds.close();
+        } else {
+            //System.out.println("copying..." + path);
+            srcPath.copyTo(dstPath);
+        }
+    }
+
+    // use TreeWalk to move
+    private static void z2zmove(FileSystem src, FileSystem dst, String path)
+        throws IOException
+    {
+        final Path srcPath = src.getPath(path).toAbsolutePath();
+        final Path dstPath = dst.getPath(path).toAbsolutePath();
+
+        Files.walkFileTree(srcPath, new SimpleFileVisitor<Path>() {
+
+            @Override
+            public FileVisitResult visitFile(Path file,
+                                            BasicFileAttributes attrs)
+            {
+                Path dst = srcPath.relativize(file);
+                dst = dstPath.resolve(dst);
+                try {
+                    Path parent = dstPath.getParent();
+                    if (parent != null && parent.notExists())
+                        mkdirs(parent);
+                    file.moveTo(dst);
+                } catch (IOException x) {
+                    x.printStackTrace();
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult preVisitDirectory(Path dir,
+                                                     BasicFileAttributes attrs)
+            {
+                Path dst = srcPath.relativize(dir);
+                dst = dstPath.resolve(dst);
+                try {
+
+                    if (dst.notExists())
+                        mkdirs(dst);
+                } catch (IOException x) {
+                    x.printStackTrace();
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir,
+                                                      IOException ioe)
+                throws IOException
+            {
+                try {
+                    dir.delete();
+                } catch (IOException x) {
+                    //x.printStackTrace();
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+
+    }
+
+    private static void mkdirs(Path path) throws IOException {
+        path = path.toAbsolutePath();
+        Path parent = path.getParent();
+        if (parent != null) {
+            if (parent.notExists())
+                mkdirs(parent);
+        }
+        path.createDirectory();
+    }
+
+    private static void rmdirs(Path path) throws IOException {
+        while (path != null && path.getNameCount() != 0) {
+            path.delete();
+            path = path.getParent();
+        }
+    }
+
+    private static void list(Path path, boolean verbose ) throws IOException {
+        if (verbose)
+            System.out.println(Attributes.readBasicFileAttributes(path).toString());
+        else
+            System.out.printf("  %s%n", path.toString());
+        if (path.notExists())
+            return;
+        if (Attributes.readBasicFileAttributes(path).isDirectory()) {
+            DirectoryStream<Path> ds = path.newDirectoryStream();
+            for (Path child : ds)
+                list(child, verbose);
+            ds.close();
+        }
+    }
+
+    // check the content of two paths are equal
+    private static void checkEqual(Path src, Path dst) throws IOException
+    {
+        //System.out.printf("checking <%s> vs <%s>...%n",
+        //                  src.toString(), dst.toString());
+
+        //streams
+        InputStream isSrc = src.newInputStream();
+        InputStream isDst = dst.newInputStream();
+        byte[] bufSrc = new byte[8192];
+        byte[] bufDst = new byte[8192];
+
+        try {
+            int nSrc = 0;
+            while ((nSrc = isSrc.read(bufSrc)) != -1) {
+                int nDst = 0;
+                while (nDst < nSrc) {
+                    int n = isDst.read(bufDst, nDst, nSrc - nDst);
+                    if (n == -1) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nDst += n;
+                }
+                while (--nSrc >= 0) {
+                    if (bufSrc[nSrc] != bufDst[nSrc]) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nSrc--;
+                }
+            }
+        } finally {
+            isSrc.close();
+            isDst.close();
+        }
+
+        // channels
+        SeekableByteChannel chSrc = src.newByteChannel();
+        SeekableByteChannel chDst = dst.newByteChannel();
+        if (chSrc.size() != chDst.size()) {
+            System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
+                              chSrc.toString(), chSrc.size(),
+                              chDst.toString(), chDst.size());
+            throw new RuntimeException("CHECK FAILED!");
+        }
+        ByteBuffer bbSrc = ByteBuffer.allocate(8192);
+        ByteBuffer bbDst = ByteBuffer.allocate(8192);
+
+        try {
+            int nSrc = 0;
+            while ((nSrc = chSrc.read(bbSrc)) != -1) {
+                int nDst = chDst.read(bbDst);
+                if (nSrc != nDst) {
+                    System.out.printf("checking <%s> vs <%s>...%n",
+                                      src.toString(), dst.toString());
+                    throw new RuntimeException("CHECK FAILED!");
+                }
+                while (--nSrc >= 0) {
+                    if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nSrc--;
+                }
+                bbSrc.flip();
+                bbDst.flip();
+            }
+        } catch (IOException x) {
+            x.printStackTrace();
+        } finally {
+            chSrc.close();
+            chDst.close();
+        }
+    }
+
+    private static void fchCopy(Path src, Path dst) throws IOException
+    {
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        Set<OpenOption> openwrite = new HashSet<>();
+        openwrite.add(CREATE_NEW);
+        openwrite.add(WRITE);
+
+        FileChannel srcFc = src.getFileSystem()
+                               .provider()
+                               .newFileChannel(src, read);
+        FileChannel dstFc = dst.getFileSystem()
+                               .provider()
+                               .newFileChannel(dst, openwrite);
+
+        try {
+            ByteBuffer bb = ByteBuffer.allocate(8192);
+            while (srcFc.read(bb) >= 0) {
+                bb.flip();
+                dstFc.write(bb);
+                bb.clear();
+            }
+        } finally {
+            srcFc.close();
+            dstFc.close();
+        }
+    }
+
+    private static void chCopy(Path src, Path dst) throws IOException
+    {
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        Set<OpenOption> openwrite = new HashSet<>();
+        openwrite.add(CREATE_NEW);
+        openwrite.add(WRITE);
+
+        SeekableByteChannel srcCh = src.newByteChannel(read);
+        SeekableByteChannel dstCh = dst.newByteChannel(openwrite);
+
+        try {
+            ByteBuffer bb = ByteBuffer.allocate(8192);
+            while (srcCh.read(bb) >= 0) {
+                bb.flip();
+                dstCh.write(bb);
+                bb.clear();
+            }
+        } finally {
+            srcCh.close();
+            dstCh.close();
+        }
+    }
+
+    private static void streamCopy(Path src, Path dst) throws IOException
+    {
+        InputStream isSrc = src.newInputStream();
+        OutputStream osDst = dst.newOutputStream();
+        byte[] buf = new byte[8192];
+        try {
+            int n = 0;
+            while ((n = isSrc.read(buf)) != -1) {
+                osDst.write(buf, 0, n);
+            }
+        } finally {
+            isSrc.close();
+            osDst.close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/META-INF/services/java.nio.file.spi.FileSystemProvider	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,3 @@
+com.sun.nio.zipfs.ZipFileSystemProvider
+com.sun.nio.zipfs.JarFileSystemProvider
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/README.txt	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,29 @@
+ZipFileSystem is a file system provider that treats the contents of a zip or
+JAR file as a java.nio.file.FileSystem.
+
+To deploy the provider you must copy zipfs.jar into your extensions
+directory or else add <JDK_HOME>/demo/nio/ZipFileSystem/zipfs.jar
+to your class path.
+
+The factory methods defined by the java.nio.file.FileSystems class can be
+used to create a FileSystem, eg:
+
+   // use file type detection
+   Map<String,?> env = Collections.emptyMap();
+   Path jarfile = Path.get("foo.jar");
+   FileSystem fs = FileSystems.newFileSystem(jarfile, env);
+
+-or
+
+   // locate file system by URI
+   Map<String,?> env = Collections.emptyMap();
+   URI uri = URI.create("zip:///mydir/foo.jar");
+   FileSystem fs = FileSystems.newFileSystem(uri, env);
+
+Once a FileSystem is created then classes in the java.nio.file package
+can be used to access files in the zip/JAR file, eg:
+
+   Path mf = fs.getPath("/META-INF/MANIFEST.MF");
+   InputStream in = mf.newInputStream();
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/JarFileSystemProvider.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Sun Microsystems nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.sun.nio.zipfs;
+
+import java.nio.file.*;
+import java.nio.file.spi.*;
+import java.nio.file.attribute.*;
+import java.nio.file.spi.FileSystemProvider;
+
+import java.net.URI;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.channels.FileChannel;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class JarFileSystemProvider extends ZipFileSystemProvider
+{
+
+    @Override
+    public String getScheme() {
+        return "jar";
+    }
+
+    @Override
+    protected Path uriToPath(URI uri) {
+        String scheme = uri.getScheme();
+        if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
+            throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
+        }
+        try {
+            String uristr = uri.toString();
+            int end = uristr.indexOf("!/");
+            uristr = uristr.substring(4, (end == -1) ? uristr.length() : end);
+            uri = new URI(uristr);
+            return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null))
+                        .toAbsolutePath();
+        } catch (URISyntaxException e) {
+            throw new AssertionError(e); //never thrown
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipCoder.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.util.Arrays;
+
+/**
+ * Utility class for zipfile name and comment decoding and encoding
+ *
+ * @author  Xueming Shen
+ */
+
+final class ZipCoder {
+
+    String toString(byte[] ba, int length) {
+        CharsetDecoder cd = decoder().reset();
+        int len = (int)(length * cd.maxCharsPerByte());
+        char[] ca = new char[len];
+        if (len == 0)
+            return new String(ca);
+        ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
+        CharBuffer cb = CharBuffer.wrap(ca);
+        CoderResult cr = cd.decode(bb, cb, true);
+        if (!cr.isUnderflow())
+            throw new IllegalArgumentException(cr.toString());
+        cr = cd.flush(cb);
+        if (!cr.isUnderflow())
+            throw new IllegalArgumentException(cr.toString());
+        return new String(ca, 0, cb.position());
+    }
+
+    String toString(byte[] ba) {
+        return toString(ba, ba.length);
+    }
+
+    byte[] getBytes(String s) {
+        CharsetEncoder ce = encoder().reset();
+        char[] ca = s.toCharArray();
+        int len = (int)(ca.length * ce.maxBytesPerChar());
+        byte[] ba = new byte[len];
+        if (len == 0)
+            return ba;
+        ByteBuffer bb = ByteBuffer.wrap(ba);
+        CharBuffer cb = CharBuffer.wrap(ca);
+        CoderResult cr = ce.encode(cb, bb, true);
+        if (!cr.isUnderflow())
+            throw new IllegalArgumentException(cr.toString());
+        cr = ce.flush(bb);
+        if (!cr.isUnderflow())
+            throw new IllegalArgumentException(cr.toString());
+        if (bb.position() == ba.length)  // defensive copy?
+            return ba;
+        else
+            return Arrays.copyOf(ba, bb.position());
+    }
+
+    // assume invoked only if "this" is not utf8
+    byte[] getBytesUTF8(String s) {
+        if (isutf8)
+            return getBytes(s);
+        if (utf8 == null)
+            utf8 = new ZipCoder(Charset.forName("UTF-8"));
+        return utf8.getBytes(s);
+    }
+
+    String toStringUTF8(byte[] ba, int len) {
+        if (isutf8)
+            return toString(ba, len);
+        if (utf8 == null)
+            utf8 = new ZipCoder(Charset.forName("UTF-8"));
+        return utf8.toString(ba, len);
+    }
+
+    boolean isUTF8() {
+        return isutf8;
+    }
+
+    private Charset cs;
+    private boolean isutf8;
+    private ZipCoder utf8;
+
+    private ZipCoder(Charset cs) {
+        this.cs = cs;
+        this.isutf8 = cs.name().equals("UTF-8");
+    }
+
+    static ZipCoder get(Charset charset) {
+        return new ZipCoder(charset);
+    }
+
+    static ZipCoder get(String csn) {
+        try {
+            return new ZipCoder(Charset.forName(csn));
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+        return new ZipCoder(Charset.defaultCharset());
+    }
+
+    private final ThreadLocal<CharsetDecoder> decTL = new ThreadLocal<>();
+    private final ThreadLocal<CharsetEncoder> encTL = new ThreadLocal<>();
+
+    private CharsetDecoder decoder() {
+        CharsetDecoder dec = decTL.get();
+        if (dec == null) {
+            dec = cs.newDecoder()
+              .onMalformedInput(CodingErrorAction.REPORT)
+              .onUnmappableCharacter(CodingErrorAction.REPORT);
+            decTL.set(dec);
+        }
+        return dec;
+    }
+
+    private CharsetEncoder encoder() {
+        CharsetEncoder enc = encTL.get();
+        if (enc == null) {
+            enc = cs.newEncoder()
+              .onMalformedInput(CodingErrorAction.REPORT)
+              .onUnmappableCharacter(CodingErrorAction.REPORT);
+            encTL.set(enc);
+        }
+        return enc;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipConstants.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Xueming Shen
+ */
+
+class ZipConstants {
+    /*
+     * Compression methods
+     */
+    static final int METHOD_STORED     = 0;
+    static final int METHOD_DEFLATED   = 8;
+    static final int METHOD_DEFLATED64 = 9;
+    static final int METHOD_BZIP2      = 12;
+    static final int METHOD_LZMA       = 14;
+    static final int METHOD_LZ77       = 19;
+
+    /*
+     * General purpose big flag
+     */
+    static final int FLAG_ENCRYPTED  = 0x01;
+    static final int FLAG_DATADESCR  = 0x08;    // crc, size and csize in dd
+    static final int FLAG_EFS        = 0x800;   // If this bit is set the filename and
+                                                // comment fields for this file must be
+                                                // encoded using UTF-8.
+    /*
+     * Header signatures
+     */
+    static long LOCSIG = 0x04034b50L;   // "PK\003\004"
+    static long EXTSIG = 0x08074b50L;   // "PK\007\008"
+    static long CENSIG = 0x02014b50L;   // "PK\001\002"
+    static long ENDSIG = 0x06054b50L;   // "PK\005\006"
+
+    /*
+     * Header sizes in bytes (including signatures)
+     */
+    static final int LOCHDR = 30;       // LOC header size
+    static final int EXTHDR = 16;       // EXT header size
+    static final int CENHDR = 46;       // CEN header size
+    static final int ENDHDR = 22;       // END header size
+
+    /*
+     * Local file (LOC) header field offsets
+     */
+    static final int LOCVER = 4;        // version needed to extract
+    static final int LOCFLG = 6;        // general purpose bit flag
+    static final int LOCHOW = 8;        // compression method
+    static final int LOCTIM = 10;       // modification time
+    static final int LOCCRC = 14;       // uncompressed file crc-32 value
+    static final int LOCSIZ = 18;       // compressed size
+    static final int LOCLEN = 22;       // uncompressed size
+    static final int LOCNAM = 26;       // filename length
+    static final int LOCEXT = 28;       // extra field length
+
+    /*
+     * Extra local (EXT) header field offsets
+     */
+    static final int EXTCRC = 4;        // uncompressed file crc-32 value
+    static final int EXTSIZ = 8;        // compressed size
+    static final int EXTLEN = 12;       // uncompressed size
+
+    /*
+     * Central directory (CEN) header field offsets
+     */
+    static final int CENVEM = 4;        // version made by
+    static final int CENVER = 6;        // version needed to extract
+    static final int CENFLG = 8;        // encrypt, decrypt flags
+    static final int CENHOW = 10;       // compression method
+    static final int CENTIM = 12;       // modification time
+    static final int CENCRC = 16;       // uncompressed file crc-32 value
+    static final int CENSIZ = 20;       // compressed size
+    static final int CENLEN = 24;       // uncompressed size
+    static final int CENNAM = 28;       // filename length
+    static final int CENEXT = 30;       // extra field length
+    static final int CENCOM = 32;       // comment length
+    static final int CENDSK = 34;       // disk number start
+    static final int CENATT = 36;       // internal file attributes
+    static final int CENATX = 38;       // external file attributes
+    static final int CENOFF = 42;       // LOC header offset
+
+    /*
+     * End of central directory (END) header field offsets
+     */
+    static final int ENDSUB = 8;        // number of entries on this disk
+    static final int ENDTOT = 10;       // total number of entries
+    static final int ENDSIZ = 12;       // central directory size in bytes
+    static final int ENDOFF = 16;       // offset of first CEN header
+    static final int ENDCOM = 20;       // zip file comment length
+
+    /*
+     * ZIP64 constants
+     */
+    static final long ZIP64_ENDSIG = 0x06064b50L;  // "PK\006\006"
+    static final long ZIP64_LOCSIG = 0x07064b50L;  // "PK\006\007"
+    static final int  ZIP64_ENDHDR = 56;           // ZIP64 end header size
+    static final int  ZIP64_LOCHDR = 20;           // ZIP64 end loc header size
+    static final int  ZIP64_EXTHDR = 24;           // EXT header size
+    static final int  ZIP64_EXTID  = 0x0001;       // Extra field Zip64 header ID
+
+    static final int  ZIP64_MINVAL32 = 0xFFFF;
+    static final long ZIP64_MINVAL = 0xFFFFFFFFL;
+
+    /*
+     * Zip64 End of central directory (END) header field offsets
+     */
+    static final int  ZIP64_ENDLEN = 4;       // size of zip64 end of central dir
+    static final int  ZIP64_ENDVEM = 12;      // version made by
+    static final int  ZIP64_ENDVER = 14;      // version needed to extract
+    static final int  ZIP64_ENDNMD = 16;      // number of this disk
+    static final int  ZIP64_ENDDSK = 20;      // disk number of start
+    static final int  ZIP64_ENDTOD = 24;      // total number of entries on this disk
+    static final int  ZIP64_ENDTOT = 32;      // total number of entries
+    static final int  ZIP64_ENDSIZ = 40;      // central directory size in bytes
+    static final int  ZIP64_ENDOFF = 48;      // offset of first CEN header
+    static final int  ZIP64_ENDEXT = 56;      // zip64 extensible data sector
+
+    /*
+     * Zip64 End of central directory locator field offsets
+     */
+    static final int  ZIP64_LOCDSK = 4;       // disk number start
+    static final int  ZIP64_LOCOFF = 8;       // offset of zip64 end
+    static final int  ZIP64_LOCTOT = 16;      // total number of disks
+
+    /*
+     * Zip64 Extra local (EXT) header field offsets
+     */
+    static final int  ZIP64_EXTCRC = 4;       // uncompressed file crc-32 value
+    static final int  ZIP64_EXTSIZ = 8;       // compressed size, 8-byte
+    static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
+
+    /*
+     * Extra field header ID
+     */
+    static final int  EXTID_ZIP64 = 0x0001;      // ZIP64
+    static final int  EXTID_NTFS  = 0x000a;      // NTFS
+    static final int  EXTID_UNIX  = 0x000d;      // UNIX
+
+
+    /*
+     * fields access methods
+     */
+    ///////////////////////////////////////////////////////
+    static final int CH(byte[] b, int n) {
+       return b[n] & 0xff;
+    }
+
+    static final int SH(byte[] b, int n) {
+        return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8);
+    }
+
+    static final long LG(byte[] b, int n) {
+        return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL;
+    }
+
+    static final long LL(byte[] b, int n) {
+        return (LG(b, n)) | (LG(b, n + 4) << 32);
+    }
+
+    static final long GETSIG(byte[] b) {
+        return LG(b, 0);
+    }
+
+    // local file (LOC) header fields
+    static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature
+    static final int  LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract
+    static final int  LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags
+    static final int  LOCHOW(byte[] b) { return SH(b, 8); } // compression method
+    static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time
+    static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data
+    static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size
+    static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size
+    static final int  LOCNAM(byte[] b) { return SH(b, 26);} // filename length
+    static final int  LOCEXT(byte[] b) { return SH(b, 28);} // extra field length
+
+    // extra local (EXT) header fields
+    static final long EXTCRC(byte[] b) { return LG(b, 4);}  // crc of uncompressed data
+    static final long EXTSIZ(byte[] b) { return LG(b, 8);}  // compressed size
+    static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size
+
+    // end of central directory header (END) fields
+    static final int  ENDSUB(byte[] b) { return SH(b, 8); }  // number of entries on this disk
+    static final int  ENDTOT(byte[] b) { return SH(b, 10);}  // total number of entries
+    static final long ENDSIZ(byte[] b) { return LG(b, 12);}  // central directory size
+    static final long ENDOFF(byte[] b) { return LG(b, 16);}  // central directory offset
+    static final int  ENDCOM(byte[] b) { return SH(b, 20);}  // size of zip file comment
+    static final int  ENDCOM(byte[] b, int off) { return SH(b, off + 20);}
+
+    // zip64 end of central directory recoder fields
+    static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);}  // total number of entries on disk
+    static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);}  // total number of entries
+    static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);}  // central directory size
+    static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);}  // central directory offset
+    static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);}   // zip64 end offset
+
+    //////////////////////////////////////////
+    static final int CH(ByteBuffer b, int pos) {
+       return b.get(pos) & 0xff;
+    }
+    static final int SH(ByteBuffer b, int pos) {
+        return b.getShort(pos) & 0xffff;
+    }
+    static final long LG(ByteBuffer b, int pos) {
+        return b.getInt(pos) & 0xffffffffL;
+    }
+
+    // central directory header (END) fields
+    static final long CENSIG(ByteBuffer b, int pos) { return LG(b, pos + 0); }
+    static final int  CENVEM(ByteBuffer b, int pos) { return SH(b, pos + 4); }
+    static final int  CENVER(ByteBuffer b, int pos) { return SH(b, pos + 6); }
+    static final int  CENFLG(ByteBuffer b, int pos) { return SH(b, pos + 8); }
+    static final int  CENHOW(ByteBuffer b, int pos) { return SH(b, pos + 10);}
+    static final long CENTIM(ByteBuffer b, int pos) { return LG(b, pos + 12);}
+    static final long CENCRC(ByteBuffer b, int pos) { return LG(b, pos + 16);}
+    static final long CENSIZ(ByteBuffer b, int pos) { return LG(b, pos + 20);}
+    static final long CENLEN(ByteBuffer b, int pos) { return LG(b, pos + 24);}
+    static final int  CENNAM(ByteBuffer b, int pos) { return SH(b, pos + 28);}
+    static final int  CENEXT(ByteBuffer b, int pos) { return SH(b, pos + 30);}
+    static final int  CENCOM(ByteBuffer b, int pos) { return SH(b, pos + 32);}
+    static final int  CENDSK(ByteBuffer b, int pos) { return SH(b, pos + 34);}
+    static final int  CENATT(ByteBuffer b, int pos) { return SH(b, pos + 36);}
+    static final long CENATX(ByteBuffer b, int pos) { return LG(b, pos + 38);}
+    static final long CENOFF(ByteBuffer b, int pos) { return LG(b, pos + 42);}
+
+    /* The END header is followed by a variable length comment of size < 64k. */
+    static final long END_MAXLEN = 0xFFFF + ENDHDR;
+    static final int READBLOCKSZ = 128;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipDirectoryStream.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.nio.file.DirectoryStream;
+import java.nio.file.ClosedDirectoryStreamException;
+import java.nio.file.NotDirectoryException;
+import java.nio.file.Path;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.io.IOException;
+import static com.sun.nio.zipfs.ZipUtils.*;
+
+/**
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+public class ZipDirectoryStream implements DirectoryStream<Path> {
+
+    private final ZipFileSystem zipfs;
+    private final byte[] path;
+    private final DirectoryStream.Filter<? super Path> filter;
+    private volatile boolean isClosed;
+    private volatile Iterator<Path> itr;
+
+    ZipDirectoryStream(ZipPath zipPath,
+                       DirectoryStream.Filter<? super java.nio.file.Path> filter)
+        throws IOException
+    {
+        this.zipfs = zipPath.getFileSystem();
+        this.path = zipPath.getResolvedPath();
+        this.filter = filter;
+        // sanity check
+        if (!zipfs.isDirectory(path))
+            throw new NotDirectoryException(zipPath.toString());
+    }
+
+    @Override
+    public synchronized Iterator<Path> iterator() {
+        if (isClosed)
+            throw new ClosedDirectoryStreamException();
+        if (itr != null)
+            throw new IllegalStateException("Iterator has already been returned");
+
+        try {
+            itr = zipfs.iteratorOf(path, filter);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+        return new Iterator<Path>() {
+            private Path next;
+            @Override
+            public boolean hasNext() {
+                if (isClosed)
+                    return false;
+                return itr.hasNext();
+            }
+
+            @Override
+            public synchronized Path next() {
+                if (isClosed)
+                    throw new NoSuchElementException();
+                return itr.next();
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    @Override
+    public synchronized void close() throws IOException {
+        isClosed = true;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributeView.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+package com.sun.nio.zipfs;
+
+import java.nio.file.ReadOnlyFileSystemException;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.FileTime;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+
+/*
+ * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+public class ZipFileAttributeView implements BasicFileAttributeView
+{
+    private static enum AttrID {
+        size,
+        creationTime,
+        lastAccessTime,
+        lastModifiedTime,
+        isDirectory,
+        isRegularFile,
+        isSymbolicLink,
+        isOther,
+        fileKey,
+        compressedSize,
+        crc,
+        method
+    };
+
+    private final ZipPath path;
+    private final boolean isZipView;
+
+    private ZipFileAttributeView(ZipPath path, boolean isZipView) {
+        this.path = path;
+        this.isZipView = isZipView;
+    }
+
+    static <V extends FileAttributeView> V get(ZipPath path, Class<V> type) {
+        if (type == null)
+            throw new NullPointerException();
+        if (type == BasicFileAttributeView.class)
+            return (V)new ZipFileAttributeView(path, false);
+        if (type == ZipFileAttributeView.class)
+            return (V)new ZipFileAttributeView(path, true);
+        return null;
+    }
+
+    static ZipFileAttributeView get(ZipPath path, String type) {
+        if (type == null)
+            throw new NullPointerException();
+        if (type.equals("basic"))
+            return new ZipFileAttributeView(path, false);
+        if (type.equals("zip"))
+            return new ZipFileAttributeView(path, true);
+        return null;
+    }
+
+    @Override
+    public String name() {
+        return isZipView ? "zip" : "basic";
+    }
+
+    public ZipFileAttributes readAttributes() throws IOException
+    {
+        return path.getAttributes();
+    }
+
+    @Override
+    public void setTimes(FileTime lastModifiedTime,
+                         FileTime lastAccessTime,
+                         FileTime createTime)
+        throws IOException
+    {
+        path.setTimes(lastModifiedTime, lastAccessTime, createTime);
+    }
+
+    void setAttribute(String attribute, Object value)
+        throws IOException
+    {
+        try {
+            if (AttrID.valueOf(attribute) == AttrID.lastModifiedTime)
+                setTimes ((FileTime)value, null, null);
+            return;
+        } catch (IllegalArgumentException x) {}
+        throw new UnsupportedOperationException("'" + attribute +
+            "' is unknown or read-only attribute");
+    }
+
+    public Object getAttribute(String attribute, boolean domap)
+        throws IOException
+    {
+        ZipFileAttributes zfas = readAttributes();
+        if (!domap) {
+            try {
+                return attribute(AttrID.valueOf(attribute), zfas);
+            } catch (IllegalArgumentException x) {}
+            return null;
+        }
+        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
+        if ("*".equals(attribute)) {
+            for (AttrID id : AttrID.values()) {
+                try {
+                    map.put(id.name(), attribute(id, zfas));
+                } catch (IllegalArgumentException x) {}
+            }
+        } else {
+            String[] as = attribute.split(",");
+            for (String a : as) {
+                try {
+                    map.put(a, attribute(AttrID.valueOf(a), zfas));
+                } catch (IllegalArgumentException x) {}
+            }
+        }
+        return map;
+    }
+
+    Object attribute(AttrID id, ZipFileAttributes zfas) {
+        switch (id) {
+        case size:
+            return zfas.size();
+        case creationTime:
+            return zfas.creationTime();
+        case lastAccessTime:
+            return zfas.lastAccessTime();
+        case lastModifiedTime:
+            return zfas.lastModifiedTime();
+        case isDirectory:
+            return zfas.isDirectory();
+        case isRegularFile:
+            return zfas.isRegularFile();
+        case isSymbolicLink:
+            return zfas.isSymbolicLink();
+        case isOther:
+            return zfas.isOther();
+        case fileKey:
+            return zfas.fileKey();
+        case compressedSize:
+            if (isZipView)
+                return zfas.compressedSize();
+            break;
+        case crc:
+            if (isZipView)
+                return zfas.crc();
+            break;
+        case method:
+            if (isZipView)
+                return zfas.method();
+            break;
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributes.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+package com.sun.nio.zipfs;
+
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.Arrays;
+import java.util.Formatter;
+import static com.sun.nio.zipfs.ZipUtils.*;
+
+/**
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli,Jaya Hangal
+ */
+
+public class ZipFileAttributes implements BasicFileAttributes
+
+{
+    private final ZipFileSystem.Entry e;
+
+    ZipFileAttributes(ZipFileSystem.Entry e) {
+        this.e = e;
+    }
+
+    ///////// basic attributes ///////////
+    @Override
+    public FileTime creationTime() {
+        if (e.ctime != -1)
+            return FileTime.fromMillis(dosToJavaTime(e.ctime));
+        return null;
+    }
+
+    @Override
+    public boolean isDirectory() {
+        return e.isDir();
+    }
+
+    @Override
+    public boolean isOther() {
+        return false;
+    }
+
+    @Override
+    public boolean isRegularFile() {
+        return !e.isDir();
+    }
+
+    @Override
+    public FileTime lastAccessTime() {
+        if (e.atime != -1)
+            return FileTime.fromMillis(dosToJavaTime(e.atime));
+        return null;
+    }
+
+    @Override
+    public FileTime lastModifiedTime() {
+        return FileTime.fromMillis(dosToJavaTime(e.mtime));
+    }
+
+    @Override
+    public long size() {
+        return e.size;
+    }
+
+    @Override
+    public boolean isSymbolicLink() {
+        return false;
+    }
+
+    @Override
+    public Object fileKey() {
+        return null;
+    }
+
+    ///////// zip entry attributes ///////////
+    public byte[] name() {
+        return Arrays.copyOf(e.name, e.name.length);
+    }
+
+    public long compressedSize() {
+        return e.csize;
+    }
+
+    public long crc() {
+        return e.crc;
+    }
+
+    public int method() {
+        return e.method;
+    }
+
+    public byte[] extra() {
+        if (e.extra != null)
+            return Arrays.copyOf(e.extra, e.extra.length);
+        return null;
+    }
+
+    public byte[] comment() {
+        if (e.comment != null)
+            return Arrays.copyOf(e.comment, e.comment.length);
+        return null;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        Formatter fm = new Formatter(sb);
+        fm.format("[/%s]%n", new String(e.name));  // TBD encoding
+        fm.format("    creationTime    : %s%n", creationTime());
+        if (lastAccessTime() != null)
+            fm.format("    lastAccessTime  : %tc%n", lastAccessTime().toMillis());
+        else
+            fm.format("    lastAccessTime  : null%n");
+        fm.format("    lastModifiedTime: %tc%n", lastModifiedTime().toMillis());
+        fm.format("    isRegularFile   : %b%n", isRegularFile());
+        fm.format("    isDirectory     : %b%n", isDirectory());
+        fm.format("    isSymbolicLink  : %b%n", isSymbolicLink());
+        fm.format("    isOther         : %b%n", isOther());
+        fm.format("    fileKey         : %s%n", fileKey());
+        fm.format("    size            : %d%n", size());
+        fm.format("    compressedSize  : %d%n", compressedSize());
+        fm.format("    crc             : %x%n", crc());
+        fm.format("    method          : %d%n", method());
+        fm.close();
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileStore.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.io.IOException;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.FileStoreAttributeView;
+import java.nio.file.attribute.FileStoreSpaceAttributeView;
+import java.nio.file.attribute.FileStoreSpaceAttributes;
+import java.nio.file.attribute.Attributes;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.util.Formatter;
+
+/*
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+public class ZipFileStore extends FileStore {
+
+    private final ZipFileSystem zfs;
+
+    ZipFileStore(ZipPath zpath) {
+        this.zfs = (ZipFileSystem)zpath.getFileSystem();
+    }
+
+    @Override
+    public String name() {
+        return zfs.toString() + "/";
+    }
+
+    @Override
+    public String type() {
+        return "zipfs";
+    }
+
+    @Override
+    public boolean isReadOnly() {
+        return zfs.isReadOnly();
+    }
+
+    @Override
+    public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
+        return (type == BasicFileAttributeView.class ||
+                type == ZipFileAttributeView.class);
+    }
+
+    @Override
+    public boolean supportsFileAttributeView(String name) {
+        return name.equals("basic") || name.equals("zip");
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) {
+        if (type == null)
+            throw new NullPointerException();
+        if (type == FileStoreSpaceAttributeView.class)
+            return (V) new ZipFileStoreAttributeView(this);
+        return null;
+    }
+
+    @Override
+    public Object getAttribute(String attribute) throws IOException {
+         if (attribute.equals("space:totalSpace"))
+               return new ZipFileStoreAttributeView(this).readAttributes().totalSpace();
+         if (attribute.equals("space:usableSpace"))
+               return new ZipFileStoreAttributeView(this).readAttributes().usableSpace();
+         if (attribute.equals("space:unallocatedSpace"))
+               return new ZipFileStoreAttributeView(this).readAttributes().unallocatedSpace();
+         throw new UnsupportedOperationException("does not support the given attribute");
+    }
+
+    private static class ZipFileStoreAttributeView implements FileStoreSpaceAttributeView {
+
+        private final ZipFileStore fileStore;
+
+        public ZipFileStoreAttributeView(ZipFileStore fileStore) {
+            this.fileStore = fileStore;
+        }
+
+        @Override
+        public String name() {
+            return "space";
+        }
+
+        @Override
+        public FileStoreSpaceAttributes readAttributes() throws IOException {
+            final String file = fileStore.name();
+            Path path = FileSystems.getDefault().getPath(file);
+            final long size = Attributes.readBasicFileAttributes(path).size();
+            final FileStore fstore = path.getFileStore();
+            final FileStoreSpaceAttributes fstoreAttrs =
+                Attributes.readFileStoreSpaceAttributes(fstore);
+            return new FileStoreSpaceAttributes() {
+                public long totalSpace() {
+                    return size;
+                }
+
+                public long usableSpace() {
+                    if (!fstore.isReadOnly())
+                        return fstoreAttrs.usableSpace();
+                    return 0;
+                }
+
+                public long unallocatedSpace() {
+                    if (!fstore.isReadOnly())
+                        return fstoreAttrs.unallocatedSpace();
+                    return 0;
+                }
+
+                public String toString() {
+                    StringBuilder sb = new StringBuilder();
+                    Formatter fm = new Formatter(sb);
+                    fm.format("FileStoreSpaceAttributes[%s]%n", file);
+                    fm.format("      totalSpace: %d%n", totalSpace());
+                    fm.format("     usableSpace: %d%n", usableSpace());
+                    fm.format("    unallocSpace: %d%n", unallocatedSpace());
+                    fm.close();
+                    return sb.toString();
+                }
+            };
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystem.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,2257 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.nio.file.spi.*;
+import java.net.URI;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.zip.CRC32;
+import java.util.zip.Inflater;
+import java.util.zip.Deflater;
+import java.util.zip.InflaterInputStream;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.ZipException;
+import java.util.zip.ZipError;
+import static java.lang.Boolean.*;
+import static com.sun.nio.zipfs.ZipConstants.*;
+import static com.sun.nio.zipfs.ZipUtils.*;
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/**
+ * A FileSystem built on a zip file
+ *
+ * @author Xueming Shen
+ */
+
+public class ZipFileSystem extends FileSystem {
+
+    private final ZipFileSystemProvider provider;
+    private final ZipPath defaultdir;
+    private boolean readOnly = false;
+    private final Path zfpath;
+    private final ZipCoder zc;
+
+    private final Object lock = new Object();
+
+    // configurable by env map
+    private final String  defaultDir;    // default dir for the file system
+    private final String  nameEncoding;  // default encoding for name/comment
+    private final boolean buildDirTree;  // build a dir tree for directoryStream ops
+    private final boolean useTempFile;   // use a temp file for newOS, default
+                                         // is to use BAOS for better performance
+    private final boolean createNew;     // create a new zip if not exists
+
+    ZipFileSystem(ZipFileSystemProvider provider,
+                  Path zfpath,
+                  Map<String, ?> env)
+        throws IOException
+    {
+        // configurable env setup
+        this.buildDirTree = TRUE.equals(env.get("buildDirTree"));
+        this.useTempFile = TRUE.equals(env.get("useTempFile"));
+        this.createNew = TRUE.equals(env.get("createNew"));
+        this.nameEncoding = env.containsKey("nameEncoding") ?
+                            (String)env.get("nameEncoding") : "UTF-8";
+        this.defaultDir = env.containsKey("default.dir") ?
+                          (String)env.get("default.dir") : "/";
+        if (this.defaultDir.charAt(0) != '/')
+            throw new IllegalArgumentException("default dir should be absolute");
+
+        this.provider = provider;
+        this.zfpath = zfpath;
+        if (zfpath.notExists()) {
+            if (createNew) {
+                OutputStream os = zfpath.newOutputStream(CREATE_NEW, WRITE);
+                new END().write(os, 0);
+                os.close();
+            } else {
+                throw new FileSystemNotFoundException(zfpath.toString());
+            }
+        }
+        zfpath.checkAccess(AccessMode.READ); // sm and existence check
+        try {
+            zfpath.checkAccess(AccessMode.WRITE);
+        } catch (AccessDeniedException x) {
+            this.readOnly = true;
+        }
+        this.zc = ZipCoder.get(nameEncoding);
+        this.defaultdir = new ZipPath(this, getBytes(defaultDir));
+        initZipFile();
+    }
+
+    @Override
+    public FileSystemProvider provider() {
+        return provider;
+    }
+
+    @Override
+    public String getSeparator() {
+        return "/";
+    }
+
+    @Override
+    public boolean isOpen() {
+        return isOpen;
+    }
+
+    @Override
+    public boolean isReadOnly() {
+        return readOnly;
+    }
+
+    private void checkWritable() throws IOException {
+        if (readOnly)
+            throw new ReadOnlyFileSystemException();
+    }
+
+    @Override
+    public Iterable<Path> getRootDirectories() {
+        ArrayList<Path> pathArr = new ArrayList<>();
+        pathArr.add(new ZipPath(this, new byte[]{'/'}));
+        return pathArr;
+    }
+
+    ZipPath getDefaultDir() {  // package private
+        return defaultdir;
+    }
+
+    @Override
+    public ZipPath getPath(String path) {
+        if (path.length() == 0)
+            throw new InvalidPathException(path, "path should not be empty");
+        return new ZipPath(this, getBytes(path));
+    }
+
+    @Override
+    public UserPrincipalLookupService getUserPrincipalLookupService() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public WatchService newWatchService() {
+        throw new UnsupportedOperationException();
+    }
+
+    FileStore getFileStore(ZipPath path) {
+        return new ZipFileStore(path);
+    }
+
+    @Override
+    public Iterable<FileStore> getFileStores() {
+        ArrayList<FileStore> list = new ArrayList<FileStore>(1);
+        list.add(new ZipFileStore(new ZipPath(this, new byte[]{'/'})));
+        return list;
+    }
+
+    private static final Set<String> supportedFileAttributeViews =
+            Collections.unmodifiableSet(
+                new HashSet<String>(Arrays.asList("basic", "zip")));
+
+    @Override
+    public Set<String> supportedFileAttributeViews() {
+        return supportedFileAttributeViews;
+    }
+
+    @Override
+    public String toString() {
+        return zfpath.toString();
+    }
+
+    Path getZipFile() {
+        return zfpath;
+    }
+
+    private static final String GLOB_SYNTAX = "glob";
+    private static final String REGEX_SYNTAX = "regex";
+
+    @Override
+    public PathMatcher getPathMatcher(String syntaxAndInput) {
+        int pos = syntaxAndInput.indexOf(':');
+        if (pos <= 0 || pos == syntaxAndInput.length()) {
+            throw new IllegalArgumentException();
+        }
+        String syntax = syntaxAndInput.substring(0, pos);
+        String input = syntaxAndInput.substring(pos + 1);
+        String expr;
+        if (syntax.equals(GLOB_SYNTAX)) {
+            expr = toRegexPattern(input);
+        } else {
+            if (syntax.equals(REGEX_SYNTAX)) {
+                expr = input;
+            } else {
+                throw new UnsupportedOperationException("Syntax '" + syntax +
+                    "' not recognized");
+            }
+        }
+        // return matcher
+        final Pattern pattern = Pattern.compile(expr);
+        return new PathMatcher() {
+            @Override
+            public boolean matches(Path path) {
+                return pattern.matcher(path.toString()).matches();
+            }
+        };
+    }
+
+    @Override
+    public void close() throws IOException {
+        synchronized (lock) {
+            if (!isOpen)
+                return;
+            isOpen = false;
+            if (!streams.isEmpty()) {
+                synchronized(streams) {
+                    for (InputStream is: streams)
+                    is.close();
+                }
+            }
+            sync();
+            ch.close();
+        }
+        synchronized (inflaters) {
+            for (Inflater inf : inflaters)
+                inf.end();
+        }
+        synchronized (deflaters) {
+            for (Deflater def : deflaters)
+                def.end();
+        }
+        for (Path p: tmppaths) {
+            try {
+                p.deleteIfExists();
+            } catch (IOException x) {
+                x.printStackTrace();
+            }
+        }
+        provider.removeFileSystem(zfpath);
+    }
+
+    ZipFileAttributes[] getAllAttributes() throws IOException {
+        ensureOpen();
+        int n = inodes.size();
+        ZipFileAttributes[] zes = new ZipFileAttributes[n];
+        Iterator<IndexNode> itr = inodes.values().iterator();
+        int i = 0;
+        while(itr.hasNext()) {
+            zes[i++] = new ZipFileAttributes(Entry.readCEN(cen, itr.next().pos));
+        }
+        return zes;
+    }
+
+    EntryName[] getEntryNames() throws IOException {
+        ensureOpen();
+        return inodes.keySet().toArray(new EntryName[0]);
+    }
+
+    ZipFileAttributes getFileAttributes(byte[] path)
+        throws IOException
+    {
+        synchronized (lock) {
+            Entry e = getEntry0(path);
+            if (e == null) {
+                if (path.length == 0) {
+                    e = new Entry(new byte[0]);  // root
+                } else if (buildDirTree) {
+                    IndexNode inode = getDirs().get(new EntryName(path));
+                    if (inode == null)
+                        return null;
+                    e = new Entry(inode.name);
+                } else {
+                    return null;
+                }
+                e.method = METHOD_STORED;        // STORED for dir
+                BasicFileAttributes bfas = Attributes.readBasicFileAttributes(zfpath);
+                if (bfas.lastModifiedTime() != null)
+                    e.mtime = javaToDosTime(bfas.lastModifiedTime().toMillis());
+                if (bfas.lastAccessTime() != null)
+                    e.atime = javaToDosTime(bfas.lastAccessTime().toMillis());
+                if (bfas.creationTime() != null)
+                    e.ctime = javaToDosTime(bfas.creationTime().toMillis());
+            }
+            return new ZipFileAttributes(e);
+        }
+    }
+
+    void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime)
+        throws IOException
+    {
+        checkWritable();
+        synchronized (lock) {
+            Entry e = getEntry0(path);    // ensureOpen checked
+            if (e == null)
+                throw new NoSuchFileException(getString(path));
+            if (e.type == Entry.CEN)
+                e.type = Entry.COPY;      // copy e
+            if (mtime != null)
+                e.mtime = javaToDosTime(mtime.toMillis());
+            if (atime != null)
+                e.atime = javaToDosTime(atime.toMillis());
+            if (ctime != null)
+                e.ctime = javaToDosTime(ctime.toMillis());
+            update(e);
+        }
+    }
+
+    boolean exists(byte[] path)
+        throws IOException
+    {
+        return getEntry0(path) != null;
+    }
+
+    boolean isDirectory(byte[] path)
+        throws IOException
+    {
+        synchronized (lock) {
+            if (buildDirTree) {
+                return getDirs().containsKey(new EntryName(path));
+            }
+            Entry e = getEntry0(path);
+            return (e != null && e.isDir()) || path.length == 0;
+        }
+    }
+
+    private ZipPath toZipPath(byte[] path) {
+        // make it absolute
+        byte[] p = new byte[path.length + 1];
+        p[0] = '/';
+        System.arraycopy(path, 0, p, 1, path.length);
+        return new ZipPath(this, p);
+    }
+
+    // returns the list of child paths of "path"
+    Iterator<Path> iteratorOf(byte[] path,
+                              DirectoryStream.Filter<? super Path> filter)
+        throws IOException
+    {
+        synchronized (lock) {
+            if (buildDirTree) {
+                IndexNode inode = getDirs().get(new EntryName(path));
+                if (inode == null)
+                    throw new NotDirectoryException(getString(path));
+                List<Path> list = new ArrayList<Path>();
+                IndexNode child = inode.child;
+                while (child != null) {
+                    ZipPath zp = toZipPath(child.name);
+                    if (filter == null || filter.accept(zp))
+                        list.add(zp);
+                    child = child.sibling;
+                }
+                return list.iterator();
+            }
+
+            if (!isDirectory(path))
+                throw new NotDirectoryException(getString(path));
+            List<Path> list = new ArrayList<Path>();
+            EntryName[] entries = getEntryNames();
+            path = toDirectoryPath(path);
+            for (EntryName en :entries) {
+                if (!isParentOf(path, en.name))  // is "path" the parent of "name"
+                    continue;
+                int off = path.length;
+                while (off < en.name.length) {
+                    if (en.name[off] == '/')
+                        break;
+                    off++;
+                }
+                if (off < (en.name.length - 1))
+                    continue;
+                ZipPath zp = toZipPath(en.name);
+                if (filter == null || filter.accept(zp))
+                    list.add(zp);
+            }
+            return list.iterator();
+        }
+    }
+
+    void createDirectory(byte[] dir, FileAttribute<?>... attrs)
+        throws IOException
+    {
+        checkWritable();
+        dir = toDirectoryPath(dir);
+        synchronized (lock) {
+            ensureOpen();
+            // pseudo root dir, or exiting dir
+            if (dir.length == 0 || exists(dir))
+                throw new FileAlreadyExistsException(getString(dir));
+            checkParents(dir);
+
+            Entry e = new Entry(dir, Entry.NEW);
+            e.method = METHOD_STORED;  // STORED for dir
+            update(e);
+        }
+    }
+
+    void copyFile(boolean deletesrc, byte[]src, byte[] dst, CopyOption... options)
+        throws IOException
+    {
+        checkWritable();
+        if (Arrays.equals(src, dst))
+            return;    // do nothing, src and dst are the same
+        synchronized (lock) {
+            Entry eSrc = getEntry0(src);  // ensureOpen checked
+            if (eSrc == null)
+                throw new NoSuchFileException(getString(src));
+            if (eSrc.isDir()) {    // spec says to create dst dir
+                createDirectory(dst);
+                return;
+            }
+            boolean hasReplace = false;
+            boolean hasCopyAttrs = false;
+            for (CopyOption opt : options) {
+                if (opt == REPLACE_EXISTING)
+                    hasReplace = true;
+                else if (opt == COPY_ATTRIBUTES)
+                    hasCopyAttrs = true;
+            }
+            Entry eDst = getEntry0(dst);
+            if (eDst != null) {
+                if (!hasReplace)
+                    throw new FileAlreadyExistsException(getString(dst));
+            } else {
+                checkParents(dst);
+            }
+            Entry u = new Entry(eSrc, Entry.COPY);    // copy eSrc entry
+            u.name = dst;                             // change name
+            // don't touch the "nlen and elen" here. writeLOC() always
+            // re-calculate from "name" and "extra" for the correct length,
+            // copyLOCEntry however needs the original lengths to skip the
+            // loc header.
+            // u.nlen = dst.length;
+            if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
+            {
+                u.type = eSrc.type;    // make it the same type
+                if (!deletesrc) {      // if it's not "rename", just take the data
+                    if (eSrc.bytes != null)
+                        u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length);
+                    else if (eSrc.file != null) {
+                        u.file = getTempPathForEntry(null);
+                        eSrc.file.copyTo(u.file, REPLACE_EXISTING);
+                    }
+                }
+            }
+            if (!hasCopyAttrs)
+                u.mtime = u.atime= u.ctime = javaToDosTime(System.currentTimeMillis());
+            update(u);
+            if (deletesrc)
+                updateDelete(eSrc);
+        }
+    }
+
+    // Returns an output stream for writing the contents into the specified
+    // entry.
+    OutputStream newOutputStream(byte[] path, OpenOption... options)
+        throws IOException
+    {
+        checkWritable();
+        boolean hasCreateNew = false;
+        boolean hasCreate = false;
+        boolean hasAppend = false;
+        for (OpenOption opt: options) {
+            if (opt == READ)
+                throw new IllegalArgumentException("READ not allowed");
+            if (opt == CREATE_NEW)
+                hasCreateNew = true;
+            if (opt == CREATE)
+                hasCreate = true;
+            if (opt == APPEND)
+                hasAppend = true;
+        }
+        synchronized (lock) {
+            Entry e = getEntry0(path);
+            if (e != null) {
+                if (e.isDir() || hasCreateNew)
+                    throw new FileAlreadyExistsException(getString(path));
+                if (hasAppend) {
+                    InputStream is = getInputStream(e);
+                    OutputStream os = getOutputStream(new Entry(e, Entry.NEW));
+                    copyStream(is, os);
+                    is.close();
+                    return os;
+                 }
+                 return getOutputStream(new Entry(e, Entry.NEW));
+            } else {
+                if (!hasCreate && !hasCreateNew)
+                    throw new NoSuchFileException(getString(path));
+                checkParents(path);
+                return getOutputStream(new Entry(path, Entry.NEW));
+            }
+        }
+    }
+
+    // Returns an input stream for reading the contents of the specified
+    // file entry.
+    InputStream newInputStream(byte[] path) throws IOException {
+        synchronized (lock) {
+            Entry e = getEntry0(path);
+            if (e == null)
+                throw new NoSuchFileException(getString(path));
+            if (e.isDir())
+                throw new FileSystemException(getString(path), "is a directory", null);
+            return getInputStream(e);
+        }
+    }
+
+    private void checkOptions(Set<? extends OpenOption> options) {
+        // check for options of null type and option is an intance of StandardOpenOption
+        for (OpenOption option : options) {
+            if (option == null)
+                throw new NullPointerException();
+            if (!(option instanceof StandardOpenOption))
+                throw new IllegalArgumentException();
+        }
+    }
+
+    // Returns a Writable/ReadByteChannel for now. Might consdier to use
+    // newFileChannel() instead, which dump the entry data into a regular
+    // file on the default file system and create a FileChannel on top of
+    // it.
+    SeekableByteChannel newByteChannel(byte[] path,
+                                       Set<? extends OpenOption> options,
+                                       FileAttribute<?>... attrs)
+        throws IOException
+    {
+        checkOptions(options);
+        if (options.contains(StandardOpenOption.WRITE) ||
+            options.contains(StandardOpenOption.APPEND)) {
+            checkWritable();
+            final WritableByteChannel wbc = Channels.newChannel(newOutputStream(path,
+                                                options.toArray(new OpenOption[0])));
+            long leftover = 0;;
+            if (options.contains(StandardOpenOption.APPEND)) {
+                Entry e = getEntry0(path);
+                if (e != null && e.size >= 0)
+                    leftover = e.size;
+            }
+            final long offset = leftover;
+            return new SeekableByteChannel() {
+                long written = offset;
+                public boolean isOpen() {
+                    return wbc.isOpen();
+                }
+                public long position() throws IOException {
+                    return written;
+                }
+                public SeekableByteChannel position(long pos) throws IOException {
+                    throw new UnsupportedOperationException();
+                }
+                public int read(ByteBuffer dst) throws IOException {
+                    throw new UnsupportedOperationException();
+                }
+                public SeekableByteChannel truncate(long size) throws IOException {
+                    throw new UnsupportedOperationException();
+                }
+                public int write(ByteBuffer src) throws IOException {
+                    int n = wbc.write(src);
+                    written += n;
+                    return n;
+                }
+                public long size() throws IOException {
+                    return written;
+                }
+                public void close() throws IOException {
+                    wbc.close();
+                }
+            };
+        } else {
+            Entry e = getEntry0(path);
+            if (e == null || e.isDir())
+                throw new NoSuchFileException(getString(path));
+            final ReadableByteChannel rbc =
+                Channels.newChannel(getInputStream(e));
+            final long size = e.size;
+            return new SeekableByteChannel() {
+                long read = 0;
+                public boolean isOpen() {
+                    return rbc.isOpen();
+                }
+                public long position() throws IOException {
+                    return read;
+                }
+                public SeekableByteChannel position(long pos) throws IOException {
+                    throw new UnsupportedOperationException();
+                }
+                public int read(ByteBuffer dst) throws IOException {
+                    return rbc.read(dst);
+                }
+                public SeekableByteChannel truncate(long size) throws IOException {
+                    throw new NonWritableChannelException();
+                }
+                public int write (ByteBuffer src) throws IOException {
+                    throw new NonWritableChannelException();
+                }
+                public long size() throws IOException {
+                    return size;
+                }
+                public void close() throws IOException {
+                    rbc.close();
+                }
+            };
+        }
+    }
+
+    // Returns a FileChannel of the specified entry.
+    //
+    // This implementation creates a temporary file on the default file system,
+    // copy the entry data into it if the entry exists, and then create a
+    // FileChannel on top of it.
+    FileChannel newFileChannel(byte[] path,
+                               Set<? extends OpenOption> options,
+                               FileAttribute<?>... attrs)
+        throws IOException
+    {
+        checkOptions(options);
+        final  boolean forWrite = (options.contains(StandardOpenOption.WRITE) ||
+                                   options.contains(StandardOpenOption.APPEND));
+        Entry e = getEntry0(path);
+        if (forWrite) {
+            checkWritable();
+            if (e == null) {
+                if (!options.contains(StandardOpenOption.CREATE_NEW))
+                    throw new NoSuchFileException(getString(path));
+            } else {
+                if (options.contains(StandardOpenOption.CREATE_NEW))
+                    throw new FileAlreadyExistsException(getString(path));
+                if (e.isDir())
+                    throw new FileAlreadyExistsException("directory <"
+                        + getString(path) + "> exists");
+            }
+            options.remove(StandardOpenOption.CREATE_NEW); // for tmpfile
+        } else if (e == null || e.isDir()) {
+            throw new NoSuchFileException(getString(path));
+        }
+
+        final boolean isFCH = (e != null && e.type == Entry.FILECH);
+        final Path tmpfile = isFCH ? e.file : getTempPathForEntry(path);
+        final FileChannel fch = tmpfile.getFileSystem()
+                                       .provider()
+                                       .newFileChannel(tmpfile, options, attrs);
+        final Entry u = isFCH ? e : new Entry(path, tmpfile, Entry.FILECH);
+        if (forWrite) {
+            u.flag = FLAG_DATADESCR;
+            u.method = METHOD_DEFLATED;
+        }
+        // is there a better way to hook into the FileChannel's close method?
+        return new FileChannel() {
+            public int write(ByteBuffer src) throws IOException {
+                return fch.write(src);
+            }
+            public long write(ByteBuffer[] srcs, int offset, int length)
+                throws IOException
+            {
+                return fch.write(srcs, offset, length);
+            }
+            public long position() throws IOException {
+                return fch.position();
+            }
+            public FileChannel position(long newPosition)
+                throws IOException
+            {
+                fch.position(newPosition);
+                return this;
+            }
+            public long size() throws IOException {
+                return fch.size();
+            }
+            public FileChannel truncate(long size)
+                throws IOException
+            {
+                fch.truncate(size);
+                return this;
+            }
+            public void force(boolean metaData)
+                throws IOException
+            {
+                fch.force(metaData);
+            }
+            public long transferTo(long position, long count,
+                                   WritableByteChannel target)
+                throws IOException
+            {
+                return fch.transferTo(position, count, target);
+            }
+            public long transferFrom(ReadableByteChannel src,
+                                     long position, long count)
+                throws IOException
+            {
+                return fch.transferFrom(src, position, count);
+            }
+            public int read(ByteBuffer dst) throws IOException {
+                return fch.read(dst);
+            }
+            public int read(ByteBuffer dst, long position)
+                throws IOException
+            {
+                return fch.read(dst, position);
+            }
+            public long read(ByteBuffer[] dsts, int offset, int length)
+                throws IOException
+            {
+                return fch.read(dsts, offset, length);
+            }
+            public int write(ByteBuffer src, long position)
+                throws IOException
+            {
+               return fch.write(src, position);
+            }
+            public MappedByteBuffer map(MapMode mode,
+                                        long position, long size)
+                throws IOException
+            {
+                throw new UnsupportedOperationException();
+            }
+            public FileLock lock(long position, long size, boolean shared)
+                throws IOException
+            {
+                return fch.lock(position, size, shared);
+            }
+            public FileLock tryLock(long position, long size, boolean shared)
+                throws IOException
+            {
+                return fch.tryLock(position, size, shared);
+            }
+            protected void implCloseChannel() throws IOException {
+                fch.close();
+                if (forWrite) {
+                    u.mtime = javaToDosTime(System.currentTimeMillis());
+                    u.size = Attributes.readBasicFileAttributes(u.file).size();
+                    update(u);
+                } else {
+                    if (!isFCH)    // if this is a new fch for reading
+                        removeTempPathForEntry(tmpfile);
+                }
+            }
+        };
+    }
+
+    // the outstanding input streams that need to be closed
+    private Set<InputStream> streams =
+        Collections.synchronizedSet(new HashSet<InputStream>());
+
+    // the ex-channel and ex-path that need to close when their outstanding
+    // input streams are all closed by the obtainers.
+    private Set<ExChannelCloser> exChClosers = new HashSet<>();
+
+    private Set<Path> tmppaths = new HashSet<>();
+    private Path getTempPathForEntry(byte[] path) throws IOException {
+        Path tmpPath = createTempFileInSameDirectoryAs(zfpath);
+        tmppaths.add(tmpPath);
+
+        if (path != null) {
+            Entry e = getEntry0(path);
+            if (e != null) {
+                InputStream is = newInputStream(path);
+                OutputStream os = tmpPath.newOutputStream(WRITE);
+                try {
+                    copyStream(is, os);
+                } finally {
+                    is.close();
+                    os.close();
+                }
+            }
+        }
+        return tmpPath;
+    }
+
+    private void removeTempPathForEntry(Path path) throws IOException {
+        path.delete();
+        tmppaths.remove(path);
+    }
+
+    // check if all parents really exit. ZIP spec does not require
+    // the existence of any "parent directory".
+    private void checkParents(byte[] path) throws IOException {
+        while ((path = getParent(path)) != null) {
+            if (!inodes.containsKey(new EntryName(path)))
+                throw new NoSuchFileException(getString(path));
+        }
+    }
+
+    private static byte[] getParent(byte[] path) {
+        int off = path.length - 1;
+        if (off > 0 && path[off] == '/')  // isDirectory
+            off--;
+        while (off > 0 && path[off] != '/') { off--; }
+        if (off == 0)
+            return null;                  // top entry
+        return Arrays.copyOf(path, off + 1);
+    }
+
+    // If "starter" is the parent directory of "path"
+    private static boolean isParentOf(byte[] p, byte[] c) {
+        final int plen = p.length;
+        if (plen == 0)          // root dir
+            return true;
+        if (plen  >= c.length)
+            return false;
+        int n = 0;
+        while (n < plen) {
+            if (p[n] != c[n])
+                return false;
+            n++;
+        }
+        if (p[n - 1] != '/' && (c[n] != '/' || n == c.length - 1))
+            return false;
+        return true;
+    }
+
+    ///////////////////////////////////////////////////////////////////
+    private void initZipFile() throws IOException {
+        ch = zfpath.newByteChannel(READ);
+        initCEN();
+    }
+
+    private volatile boolean isOpen = true;
+    private SeekableByteChannel ch; // channel to the zipfile
+    ByteBuffer cen;        // CEN & ENDHDR
+    private END  end;
+    private long locpos;   // position of first LOC header (usually 0)
+
+    // name -> pos (in cen), package private for ZipInfo
+    LinkedHashMap<EntryName, IndexNode> inodes;
+
+    byte[] getBytes(String name) {
+        return zc.getBytes(name);
+    }
+    String getString(byte[] name) {
+        return zc.toString(name);
+    }
+
+    protected void finalize() throws IOException {
+        close();
+    }
+
+    private long getDataPos(Entry e) throws IOException {
+        if (e.locoff == -1) {
+            Entry e2 = getEntry0(e.name);
+            if (e2 == null)
+                throw new ZipException("invalid loc for entry <" + e.name + ">");
+            e.locoff = e2.locoff;
+        }
+        byte[] buf = new byte[LOCHDR];
+        if (readFullyAt(buf, 0, buf.length, e.locoff) != buf.length)
+            throw new ZipException("invalid loc for entry <" + e.name + ">");
+        return locpos + e.locoff + LOCHDR + LOCNAM(buf) + LOCEXT(buf);
+    }
+
+    // Reads len bytes of data from the specified offset into buf.
+    // Returns the total number of bytes read.
+    // Each/every byte read from here (except the cen, which is mapped).
+    private long readFullyAt(byte[] buf, int off, long len, long pos)
+        throws IOException
+    {
+        ByteBuffer bb = ByteBuffer.wrap(buf);
+        bb.position(off);
+        bb.limit((int)(off + len));
+        return readFullyAt(bb, pos);
+    }
+
+    private long readFullyAt(ByteBuffer bb, long pos)
+        throws IOException
+    {
+        synchronized(ch) {
+            return ch.position(pos).read(bb);
+        }
+    }
+
+    // Searches for end of central directory (END) header. The contents of
+    // the END header will be read and placed in endbuf. Returns the file
+    // position of the END header, otherwise returns -1 if the END header
+    // was not found or an error occurred.
+    private END findEND() throws IOException
+    {
+        byte[] buf = new byte[READBLOCKSZ];
+        long ziplen = ch.size();
+        long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0;
+        long minPos = minHDR - (buf.length - ENDHDR);
+
+        for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR))
+        {
+            int off = 0;
+            if (pos < 0) {
+                // Pretend there are some NUL bytes before start of file
+                off = (int)-pos;
+                Arrays.fill(buf, 0, off, (byte)0);
+            }
+            int len = buf.length - off;
+            if (readFullyAt(buf, off, len, pos + off) != len)
+                zerror("zip END header not found");
+
+            // Now scan the block backwards for END header signature
+            for (int i = buf.length - ENDHDR; i >= 0; i--) {
+                if (buf[i+0] == (byte)'P'    &&
+                    buf[i+1] == (byte)'K'    &&
+                    buf[i+2] == (byte)'\005' &&
+                    buf[i+3] == (byte)'\006' &&
+                    (pos + i + ENDHDR + ENDCOM(buf, i) == ziplen)) {
+                    // Found END header
+                    buf = Arrays.copyOfRange(buf, i, i + ENDHDR);
+                    END end = new END();
+                    end.endsub = ENDSUB(buf);
+                    end.centot = ENDTOT(buf);
+                    end.cenlen = ENDSIZ(buf);
+                    end.cenoff = ENDOFF(buf);
+                    end.comlen = ENDCOM(buf);
+                    end.endpos = pos + i;
+                    if (end.cenlen == ZIP64_MINVAL ||
+                        end.cenoff == ZIP64_MINVAL ||
+                        end.centot == ZIP64_MINVAL32)
+                    {
+                        // need to find the zip64 end;
+                        byte[] loc64 = new byte[ZIP64_LOCHDR];
+                        if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR)
+                            != loc64.length) {
+                            return end;
+                        }
+                        long end64pos = ZIP64_LOCOFF(loc64);
+                        byte[] end64buf = new byte[ZIP64_ENDHDR];
+                        if (readFullyAt(end64buf, 0, end64buf.length, end64pos)
+                            != end64buf.length) {
+                            return end;
+                        }
+                        // end64 found, re-calcualte everything.
+                        end.cenlen = ZIP64_ENDSIZ(end64buf);
+                        end.cenoff = ZIP64_ENDOFF(end64buf);
+                        end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g
+                        end.endpos = end64pos;
+                    }
+                    return end;
+                }
+            }
+        }
+        zerror("zip END header not found");
+        return null; //make compiler happy
+    }
+
+    // Reads zip file central directory. Returns the file position of first
+    // CEN header, otherwise returns -1 if an error occured. If zip->msg != NULL
+    // then the error was a zip format error and zip->msg has the error text.
+    // Always pass in -1 for knownTotal; it's used for a recursive call.
+    private long initCEN() throws IOException {
+        end = findEND();
+        if (end.endpos == 0) {
+            inodes = new LinkedHashMap<EntryName, IndexNode>(10);
+            locpos = 0;
+            return 0;         // only END header present
+        }
+        if (end.cenlen > end.endpos)
+            zerror("invalid END header (bad central directory size)");
+        long cenpos = end.endpos - end.cenlen;     // position of CEN table
+
+        // Get position of first local file (LOC) header, taking into
+        // account that there may be a stub prefixed to the zip file.
+        locpos = cenpos - end.cenoff;
+        if (locpos < 0)
+            zerror("invalid END header (bad central directory offset)");
+
+        // read in the CEN and END
+        cen = ByteBuffer.allocate((int)(end.cenlen + ENDHDR));
+        if (readFullyAt(cen, cenpos) != end.cenlen + ENDHDR) {
+            zerror("read CEN tables failed");
+        }
+        cen.order(ByteOrder.LITTLE_ENDIAN).flip();
+
+        // Iterate through the entries in the central directory
+        inodes = new LinkedHashMap<EntryName, IndexNode>(end.centot + 1);
+        int pos = 0;
+        int limit = cen.remaining() - ENDHDR;
+        int i = 0;
+        byte[] bBuf = new byte[1024];
+        while (pos < limit) {
+            if (CENSIG(cen, pos) != CENSIG)
+                zerror("invalid CEN header (bad signature)");
+            int method = CENHOW(cen, pos);
+            int nlen   = CENNAM(cen, pos);
+            int elen   = CENEXT(cen, pos);
+            int clen   = CENCOM(cen, pos);
+            if ((CENFLG(cen, pos) & 1) != 0)
+                zerror("invalid CEN header (encrypted entry)");
+            if (method != METHOD_STORED && method != METHOD_DEFLATED)
+                zerror("invalid CEN header (bad compression method: " + method + ")");
+            if (pos + CENHDR + nlen > limit)
+                zerror("invalid CEN header (bad header size)");
+            if (bBuf.length < nlen)
+                 bBuf = new byte[nlen];
+            cen.position(pos + CENHDR);
+            byte[] name = new byte[nlen];
+            cen.get(name);
+            inodes.put(new EntryName(name), new IndexNode(name, pos));
+            // skip ext and comment
+            cen.position(pos += (CENHDR + nlen + elen + clen));
+            i++;
+        }
+        if (cen.remaining() != ENDHDR) {
+            zerror("invalid CEN header (bad header size)");
+        }
+        dirs = null;  // clear the dir map
+        return cenpos;
+    }
+
+    private void ensureOpen() throws IOException {
+        if (!isOpen)
+            throw new ClosedFileSystemException();
+    }
+
+    // Creates a new empty temporary file in the same directory as the
+    // specified file.  A variant of File.createTempFile.
+    private static Path createTempFileInSameDirectoryAs(Path path)
+        throws IOException
+    {
+        Path parent = path.toAbsolutePath().getParent();
+        String dir = (parent == null)? "." : parent.toString();
+        return File.createTempFile("zipfstmp", null, new File(dir)).toPath();
+    }
+
+    ////////////////////update & sync //////////////////////////////////////
+
+    private boolean hasUpdate = false;
+    private void updateDelete(Entry e) {
+        EntryName en = new EntryName(e.name);
+        inodes.remove(en);
+        hasUpdate = true;
+    }
+
+    private void update(Entry e) {
+        EntryName en = new EntryName(e.name);
+        inodes.put(en, e);
+        hasUpdate = true;
+    }
+
+    // copy over the whole LOC entry (header if necessary, data and ext) from
+    // old zip to the new one.
+    private long copyLOCEntry(Entry e, boolean updateHeader,
+                              OutputStream os,
+                              long written, byte[] buf)
+        throws IOException
+    {
+        long locoff = e.locoff;  // where to read
+        e.locoff = written;      // update the e.locoff with new value
+
+        // calculate the size need to write out
+        long size = 0;
+        //  if there is A ext
+        if ((e.flag & FLAG_DATADESCR) != 0) {
+            if (e.size >= ZIP64_MINVAL || e.csize >= ZIP64_MINVAL)
+                size = 24;
+            else
+                size = 16;
+        }
+        if (updateHeader) {       // if we need update the loc header
+            locoff += LOCHDR + e.nlen + e.elen;  // skip header
+            size += e.csize;
+            written = e.writeLOC(os) + size;
+        } else {
+            size += LOCHDR + e.nlen + e.elen + e.csize;
+            written = size;
+        }
+        int n;
+        while (size > 0 &&
+            (n = (int)readFullyAt(buf, 0, buf.length, locoff)) != -1)
+        {
+            if (size < n)
+                n = (int)size;
+            os.write(buf, 0, n);
+            size -= n;
+            locoff += n;
+        }
+        return written;
+    }
+
+    // sync the zip file system, if there is any udpate
+    private void sync() throws IOException {
+        assert Thread.holdsLock(this);
+
+        // check ex-closer
+        if (!exChClosers.isEmpty()) {
+            for (ExChannelCloser ecc : exChClosers) {
+                if (ecc.streams.isEmpty()) {
+                    ecc.ch.close();
+                    ecc.path.delete();
+                    exChClosers.remove(ecc);
+                }
+            }
+        }
+        if (!hasUpdate)
+            return;
+
+        Path tmpFile = createTempFileInSameDirectoryAs(zfpath);
+        OutputStream os = tmpFile.newOutputStream(WRITE);
+        ArrayList<Entry> elist = new ArrayList<>(inodes.size());
+        long written = 0;
+        byte[] buf = new byte[8192];
+        Entry e = null;
+
+        // write loc
+        for (IndexNode inode : inodes.values()) {
+            if (inode instanceof Entry) {    // an updated inode
+                e = (Entry)inode;
+                try {
+                    if (e.type == Entry.COPY) {
+                        // entry copy: the only thing changed is the "name"
+                        // and "nlen" in LOC header, so we udpate/rewrite the
+                        // LOC in new file and simply copy the rest (data and
+                        // ext) without enflating/deflating from the old zip
+                        // file LOC entry.
+                        written += copyLOCEntry(e, true, os, written, buf);
+                    } else {                          // NEW or FILECH
+                        e.locoff = written;
+                        written += e.writeLOC(os);    // write loc header
+                        if (e.bytes != null) {        // in-memory, deflated
+                            os.write(e.bytes);        // already
+                            written += e.bytes.length;
+                        } else if (e.file != null) {  // tmp file
+                            InputStream is = e.file.newInputStream();
+                            int n;
+                            if (e.type == Entry.NEW) {  // deflated already
+                                while ((n = is.read(buf)) != -1) {
+                                    os.write(buf, 0, n);
+                                    written += n;
+                                }
+                            } else if (e.type == Entry.FILECH) {
+                                // the data are not deflated, use ZEOS
+                                OutputStream os2 = new EntryOutputStream(e, os);
+                                while ((n = is.read(buf)) != -1) {
+                                    os2.write(buf, 0, n);
+                                }
+                                os2.close();
+                                written += e.csize;
+                                if ((e.flag & FLAG_DATADESCR) != 0)
+                                    written += e.writeEXT(os);
+                            }
+                            is.close();
+                            e.file.delete();
+                            tmppaths.remove(e.file);
+                        } else {
+                            // dir, 0-length data
+                        }
+                    }
+                    elist.add(e);
+                } catch (IOException x) {
+                    x.printStackTrace();    // skip any in-accurate entry
+                }
+            } else {    // unchanged inode
+                e = Entry.readCEN(cen, inode.pos);
+                try {
+                    written += copyLOCEntry(e, false, os, written, buf);
+                    elist.add(e);
+                } catch (IOException x) {
+                    x.printStackTrace();    // skip any wrong entry
+                }
+            }
+        }
+
+        // now write back the cen and end table
+        end.cenoff = written;
+        for (Entry entry : elist) {
+            written += entry.writeCEN(os);
+        }
+        end.centot = elist.size();
+        end.cenlen = written - end.cenoff;
+        end.write(os, written);
+        os.close();
+
+        if (!streams.isEmpty()) {
+            // There are outstanding input streams open on existing "ch",
+            // so, don't close the "cha" and delete the "file for now, let
+            // the "ex-channel-closer" to handle them
+            ExChannelCloser ecc = new ExChannelCloser(
+                                      createTempFileInSameDirectoryAs(zfpath),
+                                      ch,
+                                      streams);
+            zfpath.moveTo(ecc.path, REPLACE_EXISTING);
+            exChClosers.add(ecc);
+            streams = Collections.synchronizedSet(new HashSet<InputStream>());
+        } else {
+            ch.close();
+            zfpath.delete();
+        }
+        tmpFile.moveTo(zfpath, REPLACE_EXISTING);
+        hasUpdate = false;    // clear
+
+        if (isOpen) {
+            ch = zfpath.newByteChannel(READ); // re-fresh "ch" and "cen"
+            initCEN();
+        }
+        //System.out.println("->sync() done!");
+    }
+
+    private Entry getEntry0(byte[] path) throws IOException {
+        assert Thread.holdsLock(this);
+
+        if (path == null)
+            throw new NullPointerException("path");
+        if (path.length == 0)
+            return null;
+        EntryName en = new EntryName(path);
+        IndexNode inode = null;
+        synchronized (lock) {
+            ensureOpen();
+            if ((inode = inodes.get(en)) == null) {
+                if (path[path.length -1] == '/')  // already has a slash
+                    return null;
+                path = Arrays.copyOf(path, path.length + 1);
+                path[path.length - 1] = '/';
+                en.name(path);
+                if ((inode = inodes.get(en)) == null)
+                    return null;
+            }
+            if (inode instanceof Entry)
+                return (Entry)inode;
+            return Entry.readCEN(cen, inode.pos);
+        }
+    }
+
+    // Test if the "name" a parent directory of any entry (dir empty)
+    boolean isAncestor(byte[] name) {
+        for (Map.Entry<EntryName, IndexNode> entry : inodes.entrySet()) {
+            byte[] ename = entry.getKey().name;
+            if (isParentOf(name, ename))
+                return true;
+        }
+        return false;
+    }
+
+    public void deleteFile(byte[] path, boolean failIfNotExists)
+        throws IOException
+    {
+        checkWritable();
+        synchronized(lock) {
+            Entry e = getEntry0(path);
+            if (e == null) {
+                if (path != null && path.length == 0)
+                    throw new ZipException("root directory </> can't not be delete");
+                if (failIfNotExists)
+                    throw new NoSuchFileException(getString(path));
+            } else {
+                if (e.isDir() && isAncestor(path))
+                    throw new DirectoryNotEmptyException(getString(path));
+                updateDelete(e);
+            }
+        }
+    }
+
+    private static void copyStream(InputStream is, OutputStream os)
+        throws IOException
+    {
+        byte[] copyBuf = new byte[8192];
+        int n;
+        while ((n = is.read(copyBuf)) != -1) {
+            os.write(copyBuf, 0, n);
+        }
+    }
+
+    // Returns an out stream for either
+    // (1) writing the contents of a new entry, if the entry exits, or
+    // (2) updating/replacing the contents of the specified existing entry.
+    private OutputStream getOutputStream(Entry e) throws IOException {
+
+        ensureOpen();
+        if (e.mtime == -1)
+            e.mtime = javaToDosTime(System.currentTimeMillis());
+        if (e.method == -1)
+            e.method = METHOD_DEFLATED;  // TBD:  use default method
+        // store size, compressed size, and crc-32 in LOC header
+        e.flag = 0;
+        if (zc.isUTF8())
+            e.flag |= FLAG_EFS;
+        OutputStream os;
+        if (useTempFile) {
+            e.file = getTempPathForEntry(null);
+            os = e.file.newOutputStream(WRITE);
+        } else {
+            os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192);
+        }
+        return new EntryOutputStream(e, os);
+    }
+
+    private InputStream getInputStream(Entry e)
+        throws IOException
+    {
+        InputStream eis = null;
+
+        if (e.type == Entry.NEW) {
+            if (e.bytes != null)
+                eis = new ByteArrayInputStream(e.bytes);
+            else if (e.file != null)
+                eis = e.file.newInputStream();
+            else
+                throw new ZipException("update entry data is missing");
+        } else if (e.type == Entry.FILECH) {
+            // FILECH result is un-compressed.
+            eis = e.file.newInputStream();
+            // TBD: wrap to hook close()
+            // streams.add(eis);
+            return eis;
+        } else {  // untouced  CEN or COPY
+            eis = new EntryInputStream(e, ch);
+        }
+        if (e.method == METHOD_DEFLATED) {
+            // MORE: Compute good size for inflater stream:
+            long bufSize = e.size + 2; // Inflater likes a bit of slack
+            if (bufSize > 65536)
+                bufSize = 8192;
+            final long size = e.size;;
+            eis = new InflaterInputStream(eis, getInflater(), (int)bufSize) {
+
+                private boolean isClosed = false;
+                public void close() throws IOException {
+                    if (!isClosed) {
+                        releaseInflater(inf);
+                        this.in.close();
+                        isClosed = true;
+                    }
+                }
+                // Override fill() method to provide an extra "dummy" byte
+                // at the end of the input stream. This is required when
+                // using the "nowrap" Inflater option. (it appears the new
+                // zlib in 7 does not need it, but keep it for now)
+                protected void fill() throws IOException {
+                    if (eof) {
+                        throw new EOFException(
+                            "Unexpected end of ZLIB input stream");
+                    }
+                    len = this.in.read(buf, 0, buf.length);
+                    if (len == -1) {
+                        buf[0] = 0;
+                        len = 1;
+                        eof = true;
+                    }
+                    inf.setInput(buf, 0, len);
+                }
+                private boolean eof;
+
+                public int available() throws IOException {
+                    if (isClosed)
+                        return 0;
+                    long avail = size - inf.getBytesWritten();
+                    return avail > (long) Integer.MAX_VALUE ?
+                        Integer.MAX_VALUE : (int) avail;
+                }
+            };
+        } else if (e.method != METHOD_STORED) {
+            throw new ZipException("invalid compression method");
+        }
+        streams.add(eis);
+        return eis;
+    }
+
+    // Inner class implementing the input stream used to read
+    // a (possibly compressed) zip file entry.
+    private class EntryInputStream extends InputStream {
+        private SeekableByteChannel zfch; // local ref to zipfs's "ch". zipfs.ch might
+                                          // point to a new channel after sync()
+        private   long pos;               // current position within entry data
+        protected long rem;               // number of remaining bytes within entry
+        protected long size;              // uncompressed size of this entry
+
+        EntryInputStream(Entry e, SeekableByteChannel zfch)
+            throws IOException
+        {
+            this.zfch = zfch;
+            rem = e.csize;
+            size = e.size;
+            pos = getDataPos(e);
+        }
+        public int read(byte b[], int off, int len) throws IOException {
+            ensureOpen();
+            if (rem == 0) {
+                return -1;
+            }
+            if (len <= 0) {
+                return 0;
+            }
+            if (len > rem) {
+                len = (int) rem;
+            }
+            // readFullyAt()
+            long n = 0;
+            ByteBuffer bb = ByteBuffer.wrap(b);
+            bb.position(off);
+            bb.limit(off + len);
+            synchronized(zfch) {
+                n = zfch.position(pos).read(bb);
+            }
+            if (n > 0) {
+                pos += n;
+                rem -= n;
+            }
+            if (rem == 0) {
+                close();
+            }
+            return (int)n;
+        }
+        public int read() throws IOException {
+            byte[] b = new byte[1];
+            if (read(b, 0, 1) == 1) {
+                return b[0] & 0xff;
+            } else {
+                return -1;
+            }
+        }
+        public long skip(long n) throws IOException {
+            ensureOpen();
+            if (n > rem)
+                n = rem;
+            pos += n;
+            rem -= n;
+            if (rem == 0) {
+                close();
+            }
+            return n;
+        }
+        public int available() {
+            return rem > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) rem;
+        }
+
+        public long size() {
+            return size;
+        }
+        public void close() {
+            rem = 0;
+            streams.remove(this);
+        }
+    }
+
+    class EntryOutputStream extends DeflaterOutputStream
+    {
+        private CRC32 crc;
+        private Entry e;
+        private long written;
+
+        EntryOutputStream(Entry e, OutputStream os)
+            throws IOException
+        {
+            super(os, getDeflater());
+            if (e == null)
+                throw new NullPointerException("Zip entry is null");
+            this.e = e;
+            crc = new CRC32();
+        }
+
+        @Override
+        public void write(byte b[], int off, int len) throws IOException {
+            if (e.type != Entry.FILECH)    // only from sync
+                ensureOpen();
+            if (off < 0 || len < 0 || off > b.length - len) {
+                throw new IndexOutOfBoundsException();
+            } else if (len == 0) {
+                return;
+            }
+            switch (e.method) {
+            case METHOD_DEFLATED:
+                super.write(b, off, len);
+                break;
+            case METHOD_STORED:
+                written += len;
+                out.write(b, off, len);
+                break;
+            default:
+                throw new ZipException("invalid compression method");
+            }
+            crc.update(b, off, len);
+        }
+
+        @Override
+        public void close() throws IOException {
+            // TBD ensureOpen();
+            switch (e.method) {
+            case METHOD_DEFLATED:
+                finish();
+                e.size  = def.getBytesRead();
+                e.csize = def.getBytesWritten();
+                e.crc = crc.getValue();
+                break;
+            case METHOD_STORED:
+                // we already know that both e.size and e.csize are the same
+                e.size = e.csize = written;
+                e.crc = crc.getValue();
+                break;
+            default:
+                throw new ZipException("invalid compression method");
+            }
+            //crc.reset();
+            if (out instanceof ByteArrayOutputStream)
+                e.bytes = ((ByteArrayOutputStream)out).toByteArray();
+
+            if (e.type == Entry.FILECH) {
+                releaseDeflater(def);
+                return;
+            }
+            super.close();
+            releaseDeflater(def);
+            update(e);
+        }
+    }
+
+    private static void zerror(String msg) {
+        throw new ZipError(msg);
+    }
+
+    // Maxmum number of de/inflater we cache
+    private final int MAX_FLATER = 20;
+    // List of available Inflater objects for decompression
+    private List<Inflater> inflaters = new ArrayList<>();
+
+    // Gets an inflater from the list of available inflaters or allocates
+    // a new one.
+    private Inflater getInflater() {
+        synchronized (inflaters) {
+            int size = inflaters.size();
+            if (size > 0) {
+                Inflater inf = (Inflater)inflaters.remove(size - 1);
+                return inf;
+            } else {
+                return new Inflater(true);
+            }
+        }
+    }
+
+    // Releases the specified inflater to the list of available inflaters.
+    private void releaseInflater(Inflater inf) {
+        synchronized (inflaters) {
+            if (inflaters.size() < MAX_FLATER) {
+                inf.reset();
+                inflaters.add(inf);
+            } else {
+                inf.end();
+            }
+        }
+    }
+
+    // List of available Deflater objects for compression
+    private List<Deflater> deflaters = new ArrayList<>();
+
+    // Gets an deflater from the list of available deflaters or allocates
+    // a new one.
+    private Deflater getDeflater() {
+        synchronized (deflaters) {
+            int size = deflaters.size();
+            if (size > 0) {
+                Deflater def = (Deflater)deflaters.remove(size - 1);
+                return def;
+            } else {
+                return new Deflater(Deflater.DEFAULT_COMPRESSION, true);
+            }
+        }
+    }
+
+    // Releases the specified inflater to the list of available inflaters.
+    private void releaseDeflater(Deflater def) {
+        synchronized (deflaters) {
+            if (inflaters.size() < MAX_FLATER) {
+               def.reset();
+               deflaters.add(def);
+            } else {
+               def.end();
+            }
+        }
+    }
+
+    // End of central directory record
+    static class END {
+        int  disknum;
+        int  sdisknum;
+        int  endsub;     // endsub
+        int  centot;     // 4 bytes
+        long cenlen;     // 4 bytes
+        long cenoff;     // 4 bytes
+        int  comlen;     // comment length
+        byte[] comment;
+
+        /* members of Zip64 end of central directory locator */
+        int diskNum;
+        long endpos;
+        int disktot;
+
+        void write(OutputStream os, long offset) throws IOException {
+            boolean hasZip64 = false;
+            long xlen = cenlen;
+            long xoff = cenoff;
+            if (xlen >= ZIP64_MINVAL) {
+                xlen = ZIP64_MINVAL;
+                hasZip64 = true;
+            }
+            if (xoff >= ZIP64_MINVAL) {
+                xoff = ZIP64_MINVAL;
+                hasZip64 = true;
+            }
+            int count = centot;
+            if (count >= ZIP64_MINVAL32) {
+                count = ZIP64_MINVAL32;
+                hasZip64 = true;
+            }
+            if (hasZip64) {
+                long off64 = offset;
+                //zip64 end of central directory record
+                writeInt(os, ZIP64_ENDSIG);       // zip64 END record signature
+                writeLong(os, ZIP64_ENDHDR - 12); // size of zip64 end
+                writeShort(os, 45);               // version made by
+                writeShort(os, 45);               // version needed to extract
+                writeInt(os, 0);                  // number of this disk
+                writeInt(os, 0);                  // central directory start disk
+                writeLong(os, centot);            // number of directory entires on disk
+                writeLong(os, centot);            // number of directory entires
+                writeLong(os, cenlen);            // length of central directory
+                writeLong(os, cenoff);            // offset of central directory
+
+                //zip64 end of central directory locator
+                writeInt(os, ZIP64_LOCSIG);       // zip64 END locator signature
+                writeInt(os, 0);                  // zip64 END start disk
+                writeLong(os, off64);             // offset of zip64 END
+                writeInt(os, 1);                  // total number of disks (?)
+            }
+            writeInt(os, ENDSIG);                 // END record signature
+            writeShort(os, 0);                    // number of this disk
+            writeShort(os, 0);                    // central directory start disk
+            writeShort(os, count);                // number of directory entries on disk
+            writeShort(os, count);                // total number of directory entries
+            writeInt(os, xlen);                   // length of central directory
+            writeInt(os, xoff);                   // offset of central directory
+            if (comment != null) {            // zip file comment
+                writeShort(os, comment.length);
+                writeBytes(os, comment);
+            } else {
+                writeShort(os, 0);
+            }
+        }
+    }
+
+    // wrapper for the byte[] name
+    static class EntryName {
+        byte[] name;
+        int hashcode;    // node is hashable/hashed by its name
+
+        public EntryName (byte[] name) {
+            name(name);
+        }
+
+        void name(byte[] name) {
+            this.name = name;
+            this.hashcode = Arrays.hashCode(name);
+        }
+
+        public boolean equals(Object other) {
+            if (!(other instanceof EntryName))
+                return false;
+            return Arrays.equals(name, ((EntryName)other).name);
+        }
+
+        public int hashCode() {
+            return hashcode;
+        }
+    }
+
+    // can simply use Integer instead, if we don't use it to
+    // build a internal node tree.
+    static class IndexNode {
+        byte[] name;
+        int pos = -1;     // postion in cen table, -1 menas the
+                          // entry does not exists in zip file
+        IndexNode(byte[] name, int pos) {
+            this.name = name;
+            this.pos = pos;
+        }
+
+        IndexNode() {}
+
+        IndexNode sibling;
+        IndexNode child;  // 1st child
+    }
+
+    static class Entry extends IndexNode {
+
+        static final int CEN    = 1;    // entry read from cen
+        static final int NEW    = 2;    // updated contents in bytes or file
+        static final int FILECH = 3;    // fch update in "file"
+        static final int COPY   = 4;    // copy of a CEN entry
+
+        byte[] bytes;      // updated content bytes
+        Path   file;       // use tmp file to store bytes;
+        int    type = CEN; // default is the entry read from cen
+
+        // entry attributes
+        int    version;
+        int    flag;
+        int    method = -1;    // compression method
+        long   mtime  = -1;    // last modification time (in DOS time)
+        long   atime  = -1;    // last access time
+        long   ctime  = -1;    // create time
+        long   crc    = -1;    // crc-32 of entry data
+        long   csize  = -1;    // compressed size of entry data
+        long   size   = -1;    // uncompressed size of entry data
+        int    nlen;
+        int    elen;
+        byte[] extra;
+
+        // loc
+        long   startPos;
+        long   endPos;         // exclusive
+
+        // cen
+        int    versionMade;
+        int    disk;
+        int    attrs;
+        long   attrsEx;
+        long   locoff;
+
+        int    clen;
+        byte[] comment;
+
+        // ZIP64 flag
+        boolean hasZip64;
+
+        Entry() {}
+
+        Entry(byte[] name) {
+            this.name = name;
+            //this.nlen = name.length;
+            this.mtime  = javaToDosTime(System.currentTimeMillis());
+            this.crc       = 0;
+            this.size      = 0;
+            this.csize     = 0;
+            this.method    = METHOD_DEFLATED;
+        }
+
+        Entry(byte[] name, int type) {
+            this(name);
+            this.type = type;
+        }
+
+        Entry (byte[] name, Path file, int type) {
+            this(name, type);
+            this.file = file;
+            this.method = METHOD_STORED;
+        }
+
+        Entry(Entry e) {
+            this.version   = e.version;
+            this.name      = e.name;  // copyOf?
+            this.nlen      = e.nlen;
+            this.ctime     = e.ctime;
+            this.atime     = e.atime;
+            this.mtime     = e.mtime;
+            this.crc       = e.crc;
+            this.size      = e.size;
+            this.csize     = e.csize;
+            this.method    = e.method;
+            this.extra     = (e.extra == null)?
+                             null:Arrays.copyOf(e.extra, e.extra.length);
+            this.elen      = e.elen;
+            this.versionMade = e.versionMade;
+            this.disk      = e.disk;
+            this.attrs     = e.attrs;
+            this.attrsEx   = e.attrsEx;
+            this.locoff    = e.locoff;
+            this.clen      = e.clen;
+            this.comment   = (e.comment == null)?
+                             null:Arrays.copyOf(e.comment, e.comment.length);
+            this.startPos = e.startPos;
+            this.endPos   = e.endPos;
+            this.hasZip64 = e.hasZip64;;
+        }
+
+        Entry (Entry e, int type) {
+            this(e);
+            this.type = type;
+        }
+
+        boolean isDir() {
+            return name != null &&
+                   (name.length == 0 ||
+                    name[name.length - 1] == '/');
+        }
+
+        int version() throws ZipException {
+            if (method == METHOD_DEFLATED)
+                return 20;
+            else if (method == METHOD_STORED)
+                return 10;
+            throw new ZipException("unsupported compression method");
+        }
+
+        ///////////////////// CEN //////////////////////
+        static Entry readCEN(ByteBuffer cen, int pos) throws IOException
+        {
+            return new Entry().cen(cen, pos);
+        }
+
+        private Entry cen(ByteBuffer cen, int pos) throws IOException
+        {
+            if (CENSIG(cen, pos) != CENSIG)
+                zerror("invalid CEN header (bad signature)");
+            versionMade = CENVEM(cen, pos);
+            version     = CENVER(cen, pos);
+            flag        = CENFLG(cen, pos);
+            method      = CENHOW(cen, pos);
+            mtime       = CENTIM(cen, pos);
+            crc         = CENCRC(cen, pos);
+            csize       = CENSIZ(cen, pos);
+            size        = CENLEN(cen, pos);
+            nlen        = CENNAM(cen, pos);
+            elen        = CENEXT(cen, pos);
+            clen        = CENCOM(cen, pos);
+            disk        = CENDSK(cen, pos);
+            attrs       = CENATT(cen, pos);
+            attrsEx     = CENATX(cen, pos);
+            locoff      = CENOFF(cen, pos);
+
+            cen.position(pos + CENHDR);
+            name = new byte[nlen];
+            cen.get(name);
+
+            if (elen > 0) {
+                extra = new byte[elen];
+                cen.get(extra);
+                if (csize == ZIP64_MINVAL || size == ZIP64_MINVAL ||
+                    locoff == ZIP64_MINVAL) {
+                    int off = 0;
+                    while (off + 4 < elen) {
+                        // extra spec: HeaderID+DataSize+Data
+                        int sz = SH(extra, off + 2);
+                        if (SH(extra, off) == EXTID_ZIP64) {
+                            off += 4;
+                            if (size == ZIP64_MINVAL) {
+                                // if invalid zip64 extra fields, just skip
+                                if (sz < 8 || (off + 8) > elen)
+                                    break;
+                                size = LL(extra, off);
+                                sz -= 8;
+                                off += 8;
+                            }
+                            if (csize == ZIP64_MINVAL) {
+                                if (sz < 8 || (off + 8) > elen)
+                                    break;
+                                csize = LL(extra, off);
+                                sz -= 8;
+                                off += 8;
+                            }
+                            if (locoff == ZIP64_MINVAL) {
+                                if (sz < 8 || (off + 8) > elen)
+                                    break;
+                                locoff = LL(extra, off);
+                                sz -= 8;
+                                off += 8;
+                            }
+                            break;
+                        }
+                        off += (sz + 4);
+                    }
+                }
+            }
+            if (clen > 0) {
+                comment = new byte[clen];
+                cen.get(comment);
+            }
+            return this;
+        }
+
+        int writeCEN(OutputStream os) throws IOException
+        {
+            int written  = CENHDR;
+            int version0 = version();
+
+            long csize0  = csize;
+            long size0   = size;
+            long locoff0 = locoff;
+            int e64len   = 0;
+
+            // confirm size/length
+            nlen = (name != null) ? name.length : 0;
+            elen = (extra != null) ? extra.length : 0;
+            clen = (comment != null) ? comment.length : 0;
+
+            boolean hasZip64 = false;
+            if (csize >= ZIP64_MINVAL) {
+                csize0 = ZIP64_MINVAL;
+                e64len += 8;                 // csize(8)
+                hasZip64 = true;
+            }
+            if (size >= ZIP64_MINVAL) {
+                size0 = ZIP64_MINVAL;        // size(8)
+                e64len += 8;
+                hasZip64 = true;
+            }
+            if (locoff >= ZIP64_MINVAL) {
+                locoff0 = ZIP64_MINVAL;
+                e64len += 8;                 // offset(8)
+                hasZip64 = true;
+            }
+            writeInt(os, CENSIG);            // CEN header signature
+            if (hasZip64) {
+                writeShort(os, 45);          // ver 4.5 for zip64
+                writeShort(os, 45);
+            } else {
+                writeShort(os, version0);    // version made by
+                writeShort(os, version0);    // version needed to extract
+            }
+            writeShort(os, flag);            // general purpose bit flag
+            writeShort(os, method);          // compression method
+            writeInt(os, mtime);             // last modification time
+            writeInt(os, crc);               // crc-32
+            writeInt(os, csize0);            // compressed size
+            writeInt(os, size0);             // uncompressed size
+            writeShort(os, name.length);
+
+            if (hasZip64) {
+                // + headid(2) + datasize(2)
+                writeShort(os, e64len + 4 + elen);
+            } else {
+                writeShort(os, elen);
+            }
+            if (comment != null) {
+                writeShort(os, Math.min(clen, 0xffff));
+            } else {
+                writeShort(os, 0);
+            }
+            writeShort(os, 0);              // starting disk number
+            writeShort(os, 0);              // internal file attributes (unused)
+            writeInt(os, 0);                // external file attributes (unused)
+            writeInt(os, locoff0);          // relative offset of local header
+            writeBytes(os, name);
+            if (hasZip64) {
+                writeShort(os, EXTID_ZIP64);// Zip64 extra
+                writeShort(os, e64len);
+                if (size0 == ZIP64_MINVAL)
+                    writeLong(os, size);
+                if (csize0 == ZIP64_MINVAL)
+                    writeLong(os, csize);
+                if (locoff0 == ZIP64_MINVAL)
+                    writeLong(os, locoff);
+            }
+            if (extra != null) {
+                writeBytes(os, extra);
+            }
+            if (comment != null) {
+                //TBD: 0, Math.min(commentBytes.length, 0xffff));
+                writeBytes(os, comment);
+            }
+            return CENHDR + nlen + elen + clen + (hasZip64?(e64len + 4):0);
+        }
+
+        ///////////////////// LOC //////////////////////
+        static Entry readLOC(ZipFileSystem zf, long pos)
+            throws IOException
+        {
+            return readLOC(zf, pos, new byte[1024]);
+        }
+
+        static Entry readLOC(ZipFileSystem zf, long pos, byte[] buf)
+            throws IOException
+        {
+            return new Entry().loc(zf, pos, buf);
+        }
+
+        Entry loc(ZipFileSystem zf, long pos, byte[] buf)
+            throws IOException
+        {
+            assert (buf.length >= LOCHDR);
+            if (zf.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR) {
+                throw new ZipException("loc: reading failed");
+            }
+            if (LOCSIG(buf) != LOCSIG) {
+                throw new ZipException("loc: wrong sig ->"
+                                       + Long.toString(LOCSIG(buf), 16));
+            }
+            startPos = pos;
+            version  = LOCVER(buf);
+            flag     = LOCFLG(buf);
+            method   = LOCHOW(buf);
+            mtime    = LOCTIM(buf);
+            crc      = LOCCRC(buf);
+            csize    = LOCSIZ(buf);
+            size     = LOCLEN(buf);
+            nlen     = LOCNAM(buf);
+            elen     = LOCEXT(buf);
+
+            name = new byte[nlen];
+            if (zf.readFullyAt(name, 0, nlen, pos + LOCHDR) != nlen) {
+                throw new ZipException("loc: name reading failed");
+            }
+            if (elen > 0) {
+                extra = new byte[elen];
+                if (zf.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen)
+                    != elen) {
+                    throw new ZipException("loc: ext reading failed");
+                }
+            }
+            pos += (LOCHDR + nlen + elen);
+            if ((flag & FLAG_DATADESCR) != 0) {
+                // Data Descriptor
+                Entry e = zf.getEntry0(name);  // get the size/csize from cen
+                if (e == null)
+                    throw new ZipException("loc: name not found in cen");
+                size = e.size;
+                csize = e.csize;
+                pos += (method == METHOD_STORED ? size : csize);
+                if (size >= ZIP64_MINVAL || csize >= ZIP64_MINVAL)
+                    pos += 24;
+                else
+                    pos += 16;
+            } else {
+                boolean hasZip64 = false;
+                if (extra != null &&
+                    (size == ZIP64_MINVAL || csize == ZIP64_MINVAL)) {
+                    // zip64 ext: must include both size and csize
+                    int off = 0;
+                    while (off + 20 < elen) {    // HeaderID+DataSize+Data
+                        int sz = SH(extra, off + 2);
+                        if (SH(extra, off) == EXTID_ZIP64 && sz == 16) {
+                            size = LL(extra, off + 4);
+                            csize = LL(extra, off + 12);
+                            hasZip64 = true;
+                            break;
+                        }
+                        off += (sz + 4);
+                    }
+                }
+                pos += (method == METHOD_STORED ? size : csize);
+            }
+            endPos = pos;
+            return this;
+        }
+
+        int writeLOC(OutputStream os)
+            throws IOException
+        {
+            writeInt(os, LOCSIG);               // LOC header signature
+
+            int version = version();
+            if ((flag & FLAG_DATADESCR) != 0) {
+                writeShort(os, version());      // version needed to extract
+                writeShort(os, flag);           // general purpose bit flag
+                writeShort(os, method);         // compression method
+                writeInt(os, mtime);            // last modification time
+
+                // store size, uncompressed size, and crc-32 in data descriptor
+                // immediately following compressed entry data
+                writeInt(os, 0);
+                writeInt(os, 0);
+                writeInt(os, 0);
+            } else {
+                if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
+                    hasZip64 = true;
+                    writeShort(os, 45);         // ver 4.5 for zip64
+                } else {
+                    writeShort(os, version());  // version needed to extract
+                }
+                writeShort(os, flag);           // general purpose bit flag
+                writeShort(os, method);         // compression method
+                writeInt(os, mtime);            // last modification time
+                writeInt(os, crc);              // crc-32
+                if (hasZip64) {
+                    writeInt(os, ZIP64_MINVAL);
+                    writeInt(os, ZIP64_MINVAL);
+                    //TBD:  e.elen += 20;       //headid(2) + size(2) + size(8) + csize(8)
+                } else {
+                    writeInt(os, csize);        // compressed size
+                    writeInt(os, size);         // uncompressed size
+                }
+            }
+            writeShort(os, name.length);
+            writeShort(os, elen + (hasZip64 ? 20 : 0));
+            writeBytes(os, name);
+            if (hasZip64) {
+                // TBD: should we update extra directory?
+                writeShort(os, EXTID_ZIP64);
+                writeShort(os, 16);
+                writeLong(os, size);
+                writeLong(os, csize);
+            }
+            if (extra != null) {
+                writeBytes(os, extra);
+            }
+            return LOCHDR + name.length + elen + (hasZip64 ? 20 : 0);
+        }
+
+        // Data Descriptior
+        int writeEXT(OutputStream os)
+            throws IOException
+        {
+            writeInt(os, EXTSIG);           // EXT header signature
+            writeInt(os, crc);              // crc-32
+            if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) {
+                writeLong(os, csize);
+                writeLong(os, size);
+                return 24;
+            } else {
+                writeInt(os, csize);        // compressed size
+                writeInt(os, size);         // uncompressed size
+                return 16;
+            }
+        }
+
+        // read NTFS, UNIX and ZIP64 data from cen.extra
+        void readExtra() {
+            if (extra == null)
+                return;
+            int elen = extra.length;
+            int off = 0;
+            while (off + 4 < elen) {
+                // extra spec: HeaderID+DataSize+Data
+                int sz = SH(extra, off + 2);
+                int tag = SH(extra, off);
+                off += 4;
+                int pos = off;
+                if (pos + sz > elen)         // invalid data
+                    break;
+                switch (tag) {
+                case EXTID_ZIP64 :
+                    if (size == ZIP64_MINVAL) {
+                        if (pos + 8 > elen)  // invalid zip64 extra
+                            break;           // fields, just skip
+                        size = LL(extra, pos);
+                        pos += 8;
+                    }
+                    if (csize == ZIP64_MINVAL) {
+                        if (pos + 8 > elen)
+                            break;
+                        csize = LL(extra, pos);
+                        pos += 8;
+                    }
+                    if (locoff == ZIP64_MINVAL) {
+                        if (pos + 8 > elen)
+                            break;
+                        locoff = LL(extra, pos);
+                        pos += 8;
+                    }
+                    break;
+                case EXTID_NTFS:
+                    pos += 4;    // reserved 4 bytes
+                    if (SH(extra, pos) !=  0x0001)
+                        break;
+                    if (SH(extra, pos + 2) != 24)
+                        break;
+                    mtime = LL(extra, pos + 4);
+                    atime = LL(extra, pos + 12);
+                    ctime = LL(extra, pos + 20);
+                    break;
+                case EXTID_UNIX:
+                    atime = LG(extra, pos);
+                    mtime = LG(extra, pos + 4);
+                    break;
+                default:    // unknow
+                }
+                off += sz;
+            }
+        }
+    }
+
+    private static class ExChannelCloser  {
+        Path path;
+        SeekableByteChannel ch;
+        Set<InputStream> streams;
+        ExChannelCloser(Path path,
+                        SeekableByteChannel ch,
+                        Set<InputStream> streams)
+        {
+            this.path = path;
+            this.ch = ch;
+            this.streams = streams;
+        }
+    }
+
+    // ZIP directory has two issues:
+    // (1) ZIP spec does not require the ZIP file to include
+    //     directory entry
+    // (2) all entries are not stored/organized in a "tree"
+    //     structure.
+    // A possible solution is to build the node tree ourself as
+    // implemented below.
+    private HashMap<EntryName, IndexNode> dirs;
+    private IndexNode root;
+    private IndexNode addToDir(EntryName child) {
+        IndexNode cinode = dirs.get(child);
+        if (cinode != null)
+            return cinode;
+
+        byte[] cname = child.name;
+        byte[] pname = getParent(cname);
+        IndexNode pinode;
+
+        if (pname != null)
+            pinode = addToDir(new EntryName(pname));
+        else
+            pinode = root;
+        cinode = inodes.get(child);
+        if (cname[cname.length -1] != '/') {  // not a dir
+            cinode.sibling = pinode.child;
+            pinode.child = cinode;
+            return null;
+        }
+        cinode = dirs.get(child);
+        if (cinode == null)  // pseudo directry entry
+            cinode = new IndexNode(cname, -1);
+        cinode.sibling = pinode.child;
+        pinode.child = cinode;
+
+        dirs.put(child, cinode);
+        return cinode;
+    }
+
+    private HashMap<EntryName, IndexNode> getDirs()
+        throws IOException
+    {
+        if (hasUpdate)
+            sync();
+        if (dirs != null)
+            return dirs;
+        dirs = new HashMap<EntryName, IndexNode>();
+        byte[] empty = new byte[0];
+        root = new IndexNode(empty, -1);
+        dirs.put(new EntryName(empty), root);
+
+        EntryName[] names = inodes.keySet().toArray(new EntryName[0]);
+        int i = names.length;
+        while (--i >= 0) {
+            addToDir(names[i]);
+        }
+        // for (int i EntryName en : inodes.keySet()) {
+        //     addToDir(en);
+        // }
+        return dirs;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystemProvider.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.file.FileRef;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystemAlreadyExistsException;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.ProviderMismatchException;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.spi.FileSystemProvider;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/*
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli, Jaya Hangal
+ */
+
+public class ZipFileSystemProvider extends FileSystemProvider {
+    private final Map<Path, ZipFileSystem> filesystems = new HashMap<>();
+
+    public ZipFileSystemProvider() {}
+
+    @Override
+    public String getScheme() {
+        return "zip";
+    }
+
+    protected Path uriToPath(URI uri) {
+        String scheme = uri.getScheme();
+        if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) {
+            throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'");
+        }
+        try {
+            return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null))
+                        .toAbsolutePath();
+        } catch (URISyntaxException e) {
+            throw new AssertionError(e); //never thrown
+        }
+    }
+
+    @Override
+    public FileSystem newFileSystem(URI uri, Map<String, ?> env)
+        throws IOException
+    {
+        return newFileSystem(uriToPath(uri), env);
+    }
+
+    @Override
+    public FileSystem newFileSystem(FileRef file, Map<String, ?> env)
+        throws IOException
+    {
+        if (!(file instanceof Path))
+            throw new UnsupportedOperationException();
+        Path path = (Path)file;
+        if (!path.toUri().getScheme().equalsIgnoreCase("file")) {
+            throw new UnsupportedOperationException();
+        }
+        return newFileSystem(path, env);
+    }
+
+    private FileSystem newFileSystem(Path path, Map<String, ?> env)
+        throws IOException
+    {
+        synchronized(filesystems) {
+            if (filesystems.containsKey(path))
+                throw new FileSystemAlreadyExistsException();
+            ZipFileSystem zipfs = new ZipFileSystem(this, path, env);
+            filesystems.put(path, zipfs);
+            return zipfs;
+        }
+    }
+
+    @Override
+    public Path getPath(URI uri) {
+        FileSystem fs = getFileSystem(uri);
+        String fragment = uri.getFragment();
+        if (fragment == null) {
+            throw new IllegalArgumentException("URI: "
+                + uri
+                + " does not contain path fragment ex. zip:///c:/foo.zip#/BAR");
+        }
+        return fs.getPath(fragment);
+    }
+
+    @Override
+    public FileChannel newFileChannel(Path path,
+            Set<? extends OpenOption> options,
+            FileAttribute<?>... attrs)
+            throws IOException
+    {
+        if (path == null)
+            throw new NullPointerException("path is null");
+        if (path instanceof ZipPath)
+            return ((ZipPath)path).newFileChannel(options, attrs);
+        throw new ProviderMismatchException();
+    }
+
+    @Override
+    public FileSystem getFileSystem(URI uri) {
+        synchronized (filesystems) {
+            ZipFileSystem zipfs = filesystems.get(uriToPath(uri));
+            if (zipfs == null)
+                throw new FileSystemNotFoundException();
+            return zipfs;
+        }
+    }
+
+    void removeFileSystem(Path zfpath) {
+        synchronized (filesystems) {
+            filesystems.remove(zfpath);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipInfo.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.io.PrintStream;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import com.sun.nio.zipfs.ZipFileSystem.Entry;
+import static com.sun.nio.zipfs.ZipConstants.*;
+import static com.sun.nio.zipfs.ZipUtils.*;
+
+/**
+ * Print the loc and cen tables of the ZIP file
+ *
+ * @author  Xueming Shen
+ */
+
+public class ZipInfo {
+
+    public static void main(String[] args) throws Throwable {
+        if (args.length < 2) {
+            print("Usage: java ZipInfo [cen|loc] zfname");
+        } else {
+            Map<String, ?> env = Collections.emptyMap();
+            ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider()
+                                    .newFileSystem(Paths.get(args[1]), env));
+
+            long pos = 0;
+
+            if ("loc".equals(args[0])) {
+                print("[Local File Header]%n");
+                byte[] buf = new byte[1024];
+                for (int i = 0; i < zfs.getEntryNames().length; i++) {
+                    Entry loc = Entry.readLOC(zfs, pos, buf);
+                    print("--------loc[%x]--------%n", pos);
+                    printLOC(loc);
+                    pos = loc.endPos;
+                }
+            } if ("cen".equals(args[0])) {
+                int i = 0;
+                Iterator<ZipFileSystem.IndexNode> itr = zfs.inodes.values().iterator();
+                print("[Central Directory Header]%n");
+                while (itr.hasNext()) {
+                    Entry cen = Entry.readCEN(zfs.cen, itr.next().pos);
+                    print("--------cen[%d]--------%n", i);
+                    printCEN(cen);
+                    i++;
+                }
+            }
+            zfs.close();
+        }
+    }
+
+    static void print(String fmt, Object... objs) {
+        System.out.printf(fmt, objs);
+    }
+
+    static void printLOC(Entry loc) {
+        print("  [%x, %x]%n", loc.startPos, loc.endPos);
+        print("  Signature   :     %8x%n", LOCSIG);
+        print("  Version     :         %4x    [%d.%d]%n",
+                  loc.version, loc. version/10, loc. version%10);
+        print("  Flag        :         %4x%n", loc.flag);
+        print("  Method      :         %4x%n", loc. method);
+        print("  LastMTime   :     %8x    [%tc]%n",
+                  loc.mtime, dosToJavaTime(loc.mtime));
+        print("  CRC         :     %8x%n", loc.crc);
+        print("  CSize       :     %8x%n", loc.csize);
+        print("  Size        :     %8x%n", loc.size);
+        print("  NameLength  :         %4x    [%s]%n",
+                  loc.nlen, new String(loc.name));
+        print("  ExtraLength :         %4x%n", loc.elen);
+        if (loc.hasZip64)
+            print(" *ZIP64*%n");
+    }
+
+    static void printCEN(Entry cen) {
+        print("  Signature   :     %08x%n", CENSIG);
+        print("  VerMadeby   :         %4x    [%d.%d]%n",
+                  cen.versionMade, cen.versionMade/10, cen.versionMade%10);
+        print("  VerExtract  :         %4x    [%d.%d]%n",
+                  cen.version, cen.version/10, cen.version%10);
+        print("  Flag        :         %4x%n", cen.flag);
+        print("  Method      :         %4x%n", cen.method);
+        print("  LastMTime   :     %8x    [%tc]%n",
+                  cen.mtime, dosToJavaTime(cen.mtime));
+        print("  CRC         :     %8x%n", cen.crc);
+        print("  CSize       :     %8x%n", cen.csize);
+        print("  Size        :     %8x%n", cen.size);
+        print("  NameLen     :         %4x    [%s]%n",
+                  cen.nlen, new String(cen.name));
+        print("  ExtraLen    :         %4x%n", cen.elen);
+        print("  CommentLen  :         %4x%n", cen.clen);
+        print("  DiskStart   :         %4x%n", cen.disk);
+        print("  Attrs       :         %4x%n", cen.attrs);
+        print("  AttrsEx     :     %8x%n", cen.attrsEx);
+        print("  LocOff      :     %8x%n", cen.locoff);
+        if (cen.hasZip64)
+            print(" *ZIP64*%n");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipPath.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,964 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.io.File;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.*;
+import java.nio.file.DirectoryStream.Filter;
+import java.nio.file.spi.FileSystemProvider;
+import java.nio.file.attribute.BasicFileAttributeView;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.FileTime;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/**
+ *
+ * @author  Xueming Shen, Rajendra Gutupalli,Jaya Hangal
+ */
+
+public class ZipPath extends Path {
+
+    private final ZipFileSystem zfs;
+    private final byte[] path;
+    private volatile int[] offsets;
+    private int hashcode = 0;  // cached hashcode (created lazily)
+
+    ZipPath(ZipFileSystem zfs, byte[] path) {
+        this(zfs, path, false);
+    }
+
+    ZipPath(ZipFileSystem zfs, byte[] path, boolean normalized)
+    {
+        this.zfs = zfs;
+        if (normalized)
+            this.path = path;
+        else
+            this.path = normalize(path);
+    }
+
+    @Override
+    public ZipPath getRoot() {
+        if (this.isAbsolute())
+            return new ZipPath(zfs, new byte[]{path[0]});
+        else
+            return null;
+    }
+
+    @Override
+    public Path getName() {
+        initOffsets();
+        int count = offsets.length;
+        if (count == 0)
+            return null;  // no elements so no name
+        if (count == 1 && path[0] != '/')
+            return this;
+        int lastOffset = offsets[count-1];
+        int len = path.length - lastOffset;
+        byte[] result = new byte[len];
+        System.arraycopy(path, lastOffset, result, 0, len);
+        return new ZipPath(zfs, result);
+    }
+
+    @Override
+    public ZipPath getParent() {
+        initOffsets();
+        int count = offsets.length;
+        if (count == 0)    // no elements so no parent
+            return null;
+        int len = offsets[count-1] - 1;
+        if (len <= 0)      // parent is root only (may be null)
+            return getRoot();
+        byte[] result = new byte[len];
+        System.arraycopy(path, 0, result, 0, len);
+        return new ZipPath(zfs, result);
+    }
+
+    @Override
+    public int getNameCount() {
+        initOffsets();
+        return offsets.length;
+    }
+
+    @Override
+    public ZipPath getName(int index) {
+        initOffsets();
+        if (index < 0 || index >= offsets.length)
+            throw new IllegalArgumentException();
+        int begin = offsets[index];
+        int len;
+        if (index == (offsets.length-1))
+            len = path.length - begin;
+        else
+            len = offsets[index+1] - begin - 1;
+        // construct result
+        byte[] result = new byte[len];
+        System.arraycopy(path, begin, result, 0, len);
+        return new ZipPath(zfs, result);
+    }
+
+    @Override
+    public ZipPath subpath(int beginIndex, int endIndex) {
+        initOffsets();
+        if (beginIndex < 0 ||
+            beginIndex >=  offsets.length ||
+            endIndex > offsets.length ||
+            beginIndex >= endIndex)
+            throw new IllegalArgumentException();
+
+        // starting offset and length
+        int begin = offsets[beginIndex];
+        int len;
+        if (endIndex == offsets.length)
+            len = path.length - begin;
+        else
+            len = offsets[endIndex] - begin - 1;
+        // construct result
+        byte[] result = new byte[len];
+        System.arraycopy(path, begin, result, 0, len);
+        return new ZipPath(zfs, result);
+    }
+
+    @Override
+    public ZipPath toRealPath(boolean resolveLinks) throws IOException {
+        ZipPath realPath = new ZipPath(zfs, getResolvedPath());
+        realPath.checkAccess();
+        return realPath;
+    }
+
+    @Override
+    public boolean isHidden() {
+        return false;
+    }
+
+    @Override
+    public ZipPath toAbsolutePath() {
+        if (isAbsolute()) {
+            return this;
+        } else {
+            //add / bofore the existing path
+            byte[] defaultdir = zfs.getDefaultDir().path;
+            int defaultlen = defaultdir.length;
+            boolean endsWith = (defaultdir[defaultlen - 1] == '/');
+            byte[] t = null;
+            if (endsWith)
+                t = new byte[defaultlen + path.length];
+            else
+                t = new byte[defaultlen + 1 + path.length];
+            System.arraycopy(defaultdir, 0, t, 0, defaultlen);
+            if (!endsWith)
+                t[defaultlen++] = '/';
+            System.arraycopy(path, 0, t, defaultlen, path.length);
+            return new ZipPath(zfs, t, true);  // normalized
+        }
+    }
+
+    @Override
+    public URI toUri() {
+        String zfPath = zfs.toString();
+        if (File.separatorChar == '\\')  // replace all separators by '/'
+            zfPath = "/" + zfPath.replace("\\", "/");
+        try {
+            return new URI("zip", "",
+                           zfPath,
+                           zfs.getString(toAbsolutePath().path));
+        } catch (Exception ex) {
+            throw new AssertionError(ex);
+        }
+    }
+
+    private boolean equalsNameAt(ZipPath other, int index) {
+        int mbegin = offsets[index];
+        int mlen = 0;
+        if (index == (offsets.length-1))
+            mlen = path.length - mbegin;
+        else
+            mlen = offsets[index + 1] - mbegin - 1;
+        int obegin = other.offsets[index];
+        int olen = 0;
+        if (index == (other.offsets.length - 1))
+            olen = other.path.length - obegin;
+        else
+            olen = other.offsets[index + 1] - obegin - 1;
+        if (mlen != olen)
+            return false;
+        int n = 0;
+        while(n < mlen) {
+            if (path[mbegin + n] != other.path[obegin + n])
+                return false;
+            n++;
+        }
+        return true;
+    }
+
+    @Override
+    public Path relativize(Path other) {
+        final ZipPath o = checkPath(other);
+        if (o.equals(this))
+            return null;
+        if (/* this.getFileSystem() != o.getFileSystem() || */
+            this.isAbsolute() != o.isAbsolute()) {
+            throw new IllegalArgumentException();
+        }
+        int mc = this.getNameCount();
+        int oc = o.getNameCount();
+        int n = Math.min(mc, oc);
+        int i = 0;
+        while (i < n) {
+            if (!equalsNameAt(o, i))
+                break;
+            i++;
+        }
+        int dotdots = mc - i;
+        int len = dotdots * 3 - 1;
+        if (i < oc)
+            len += (o.path.length - o.offsets[i] + 1);
+        byte[] result = new byte[len];
+
+        int pos = 0;
+        while (dotdots > 0) {
+            result[pos++] = (byte)'.';
+            result[pos++] = (byte)'.';
+            if (pos < len)       // no tailing slash at the end
+                result[pos++] = (byte)'/';
+            dotdots--;
+        }
+        if (i < oc)
+            System.arraycopy(o.path, o.offsets[i],
+                             result, pos,
+                             o.path.length - o.offsets[i]);
+        return new ZipPath(getFileSystem(), result);
+    }
+
+    @Override
+    public ZipFileSystem getFileSystem() {
+        return zfs;
+    }
+
+    @Override
+    public boolean isAbsolute() {
+        return (this.path[0] == '/');
+    }
+
+    @Override
+    public ZipPath resolve(Path other) {
+        if (other == null)
+            return this;
+        final ZipPath o = checkPath(other);
+        if (o.isAbsolute())
+            return o;
+        byte[] resolved = null;
+        if (this.path[path.length - 1] == '/') {
+            resolved = new byte[path.length + o.path.length];
+            System.arraycopy(path, 0, resolved, 0, path.length);
+            System.arraycopy(o.path, 0, resolved, path.length, o.path.length);
+        } else {
+            resolved = new byte[path.length + 1 + o.path.length];
+            System.arraycopy(path, 0, resolved, 0, path.length);
+            resolved[path.length] = '/';
+            System.arraycopy(o.path, 0, resolved, path.length + 1, o.path.length);
+        }
+        return new ZipPath(zfs, resolved);
+    }
+
+    @Override
+    public ZipPath resolve(String other) {
+        return resolve(getFileSystem().getPath(other));
+    }
+
+    @Override
+    public boolean startsWith(Path other) {
+        final ZipPath o = checkPath(other);
+        if (o.isAbsolute() != this.isAbsolute())
+            return false;
+        final int oCount = o.getNameCount();
+        if (getNameCount() < oCount)
+            return false;
+        for (int i = 0; i < oCount; i++) {
+            if (!o.getName(i).equals(getName(i)))
+                return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean endsWith(Path other) {
+        final ZipPath o = checkPath(other);
+        if (o.isAbsolute())
+            return this.isAbsolute() ? this.equals(o) : false;
+        int i = o.getNameCount();
+        int j = this.getNameCount();
+        if (j < i)
+            return false;
+        for (--i, --j; i >= 0; i--, j--) {
+            if (!o.getName(i).equals(this.getName(j)))
+                return false;
+        }
+        return true;
+    }
+
+    @Override
+    public Path normalize() {
+        byte[] resolved = getResolved();
+        if (resolved == path)    // no change
+            return this;
+        if (resolved.length == 0)
+            return null;
+        return new ZipPath(zfs, resolved, true);
+    }
+
+    private ZipPath checkPath(Path path) {
+        if (path == null)
+            throw new NullPointerException();
+        if (!(path instanceof ZipPath))
+            throw new ProviderMismatchException();
+        return (ZipPath) path;
+    }
+
+    // create offset list if not already created
+    private void initOffsets() {
+        if (offsets == null) {
+            int count, index;
+            // count names
+            count = 0;
+            index = 0;
+            while (index < path.length) {
+                byte c = path[index++];
+                if (c != '/') {
+                    count++;
+                    while (index < path.length && path[index] != '/')
+                        index++;
+                }
+            }
+            // populate offsets
+            int[] result = new int[count];
+            count = 0;
+            index = 0;
+            while (index < path.length) {
+                byte c = path[index];
+                if (c == '/') {
+                    index++;
+                } else {
+                    result[count++] = index++;
+                    while (index < path.length && path[index] != '/')
+                        index++;
+                }
+            }
+            synchronized (this) {
+                if (offsets == null)
+                    offsets = result;
+            }
+        }
+    }
+
+    // resolved path for locating zip entry inside the zip file,
+    // the result path does not contain ./ and .. components
+    private volatile byte[] resolved = null;
+    byte[] getResolvedPath() {
+        byte[] r = resolved;
+        if (r == null) {
+            if (isAbsolute())
+                r = getResolved();
+            else
+                r = toAbsolutePath().getResolvedPath();
+            if (r[0] == '/')
+                r = Arrays.copyOfRange(r, 1, r.length);
+            resolved = r;
+        }
+        return resolved;
+    }
+
+    // removes redundant slashs, replace "\" to zip separator "/"
+    // and check for invalid characters
+    private byte[] normalize(byte[] path) {
+        if (path.length == 0)
+            return path;
+        byte prevC = 0;
+        for (int i = 0; i < path.length; i++) {
+            byte c = path[i];
+            if (c == '\\')
+                return normalize(path, i);
+            if (c == (byte)'/' && prevC == '/')
+                return normalize(path, i - 1);
+            if (c == '\u0000')
+                throw new InvalidPathException(zfs.getString(path),
+                                               "Path: nul character not allowed");
+            prevC = c;
+        }
+        return path;
+    }
+
+    private byte[] normalize(byte[] path, int off) {
+        byte[] to = new byte[path.length];
+        int n = 0;
+        while (n < off) {
+            to[n] = path[n];
+            n++;
+        }
+        int m = n;
+        byte prevC = 0;
+        while (n < path.length) {
+            byte c = path[n++];
+            if (c == (byte)'\\')
+                c = (byte)'/';
+            if (c == (byte)'/' && prevC == (byte)'/')
+                continue;
+            if (c == '\u0000')
+                throw new InvalidPathException(zfs.getString(path),
+                                               "Path: nul character not allowed");
+            to[m++] = c;
+            prevC = c;
+        }
+        if (m > 1 && to[m - 1] == '/')
+            m--;
+        return (m == to.length)? to : Arrays.copyOf(to, m);
+    }
+
+    // Remove DotSlash(./) and resolve DotDot (..) components
+    private byte[] getResolved() {
+        if (path.length == 0)
+            return path;
+        for (int i = 0; i < path.length; i++) {
+            byte c = path[i];
+            if (c == (byte)'.')
+                return resolve0();
+        }
+        return path;
+    }
+
+    // TBD: performance, avoid initOffsets
+    private byte[] resolve0() {
+        byte[] to = new byte[path.length];
+        int nc = getNameCount();
+        int[] lastM = new int[nc];
+        int lastMOff = -1;
+        int m = 0;
+        for (int i = 0; i < nc; i++) {
+            int n = offsets[i];
+            int len = (i == offsets.length - 1)?
+                      (path.length - n):(offsets[i + 1] - n - 1);
+            if (len == 1 && path[n] == (byte)'.')
+                continue;
+            if (len == 2 && path[n] == '.' && path[n + 1] == '.') {
+                if (lastMOff >= 0) {
+                    m = lastM[lastMOff--];  // retreat
+                    continue;
+                }
+                if (path[0] == '/') {  // "/../xyz" skip
+                    if (m == 0)
+                        to[m++] = '/';
+                } else {               // "../xyz" -> "../xyz"
+                    if (m != 0 && to[m-1] != '/')
+                        to[m++] = '/';
+                    while (len-- > 0)
+                        to[m++] = path[n++];
+                }
+                continue;
+            }
+            if (m == 0 && path[0] == '/' ||   // absolute path
+                m != 0 && to[m-1] != '/') {   // not the first name
+                to[m++] = '/';
+            }
+            lastM[++lastMOff] = m;
+            while (len-- > 0)
+                to[m++] = path[n++];
+        }
+        if (m > 1 && to[m - 1] == '/')
+            m--;
+        return (m == to.length)? to : Arrays.copyOf(to, m);
+    }
+
+    @Override
+    public String toString() {
+        return zfs.getString(path);
+    }
+
+    @Override
+    public int hashCode() {
+        int h = hashcode;
+        if (h == 0)
+            hashcode = h = Arrays.hashCode(path);
+        return h;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return obj != null &&
+               obj instanceof ZipPath &&
+               this.zfs == ((ZipPath)obj).zfs &&
+               compareTo((Path) obj) == 0;
+    }
+
+    @Override
+    public int compareTo(Path other) {
+        final ZipPath o = checkPath(other);
+        int len1 = this.path.length;
+        int len2 = o.path.length;
+
+        int n = Math.min(len1, len2);
+        byte v1[] = this.path;
+        byte v2[] = o.path;
+
+        int k = 0;
+        while (k < n) {
+            int c1 = v1[k] & 0xff;
+            int c2 = v2[k] & 0xff;
+            if (c1 != c2)
+                return c1 - c2;
+            k++;
+        }
+        return len1 - len2;
+    }
+
+    @Override
+    public Path createSymbolicLink(
+            Path target, FileAttribute<?>... attrs) throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public Path createLink(
+            Path existing) throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public Path readSymbolicLink() throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public Path createDirectory(FileAttribute<?>... attrs)
+        throws IOException
+    {
+        zfs.createDirectory(getResolvedPath(), attrs);
+        return this;
+    }
+
+    public final Path createFile(FileAttribute<?>... attrs)
+        throws IOException
+    {
+        OutputStream os = newOutputStream(CREATE_NEW, WRITE);
+        try {
+            os.close();
+        } catch (IOException x) {}
+        return this;
+    }
+
+    @Override
+    public InputStream newInputStream(OpenOption... options)
+            throws IOException {
+        if (options.length > 0) {
+            for (OpenOption opt : options) {
+                if (opt != READ)
+                    throw new UnsupportedOperationException("'" + opt + "' not allowed");
+            }
+        }
+        return zfs.newInputStream(getResolvedPath());
+    }
+
+    private static final DirectoryStream.Filter<Path> acceptAllFilter =
+        new DirectoryStream.Filter<Path>() {
+            @Override public boolean accept(Path entry) { return true; }
+        };
+
+    @Override
+    public final DirectoryStream<Path> newDirectoryStream() throws IOException {
+        return newDirectoryStream(acceptAllFilter);
+    }
+
+    @Override
+    public DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter)
+        throws IOException
+    {
+        return new ZipDirectoryStream(this, filter);
+    }
+
+    @Override
+    public final DirectoryStream<Path> newDirectoryStream(String glob)
+        throws IOException
+    {
+        // avoid creating a matcher if all entries are required.
+        if (glob.equals("*"))
+            return newDirectoryStream();
+
+        // create a matcher and return a filter that uses it.
+        final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob);
+        DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
+            @Override
+            public boolean accept(Path entry)  {
+                return matcher.matches(entry.getName());
+            }
+        };
+        return newDirectoryStream(filter);
+    }
+
+    @Override
+    public final void delete() throws IOException {
+        zfs.deleteFile(getResolvedPath(), true);
+    }
+
+    @Override
+    public final void deleteIfExists() throws IOException {
+        zfs.deleteFile(getResolvedPath(), false);
+    }
+
+    ZipFileAttributes getAttributes() throws IOException
+    {
+        ZipFileAttributes zfas = zfs.getFileAttributes(getResolvedPath());
+        if (zfas == null)
+            throw new NoSuchFileException(toString());
+        return zfas;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <V extends FileAttributeView> V getFileAttributeView(Class<V> type,
+                                                                LinkOption... options)
+    {
+        return (V)ZipFileAttributeView.get(this, type);
+    }
+
+    @Override
+    public void setAttribute(String attribute,
+                             Object value,
+                             LinkOption... options)
+        throws IOException
+    {
+        String type = null;
+        String attr = null;
+        int colonPos = attribute.indexOf(':');
+        if (colonPos == -1) {
+            type = "basic";
+            attr = attribute;
+        } else {
+            type = attribute.substring(0, colonPos++);
+            attr = attribute.substring(colonPos);
+        }
+        ZipFileAttributeView view = ZipFileAttributeView.get(this, type);
+        if (view == null)
+            throw new UnsupportedOperationException("view <" + view + "> is not supported");
+        view.setAttribute(attr, value);
+    }
+
+    void setTimes(FileTime mtime, FileTime atime, FileTime ctime)
+        throws IOException
+    {
+        zfs.setTimes(getResolvedPath(), mtime, atime, ctime);
+    }
+
+    private Object getAttributesImpl(String attribute, boolean domap)
+        throws IOException
+    {
+        String view = null;
+        String attr = null;
+        int colonPos = attribute.indexOf(':');
+        if (colonPos == -1) {
+            view = "basic";
+            attr = attribute;
+        } else {
+            view = attribute.substring(0, colonPos++);
+            attr = attribute.substring(colonPos);
+        }
+        ZipFileAttributeView zfv = ZipFileAttributeView.get(this, view);
+        if (zfv == null) {
+            throw new UnsupportedOperationException("view not supported");
+        }
+        return zfv.getAttribute(attr, domap);
+    }
+
+    @Override
+    public Object getAttribute(String attribute, LinkOption... options)
+        throws IOException
+    {
+        return getAttributesImpl(attribute, false);
+    }
+
+    @Override
+    public Map<String,?> readAttributes(String attribute, LinkOption... options)
+        throws IOException
+    {
+        return (Map<String, ?>)getAttributesImpl(attribute, true);
+    }
+
+    @Override
+    public FileStore getFileStore() throws IOException {
+        // each ZipFileSystem only has one root (as requested for now)
+        if (exists())
+            return zfs.getFileStore(this);
+        throw new NoSuchFileException(zfs.getString(path));
+    }
+
+    @Override
+    public boolean isSameFile(Path other) throws IOException {
+        if (other == null ||
+            this.getFileSystem() != other.getFileSystem())
+            return false;
+        this.checkAccess();
+        other.checkAccess();
+        return Arrays.equals(this.getResolvedPath(),
+                             ((ZipPath)other).getResolvedPath());
+    }
+
+    public WatchKey register(
+            WatchService watcher,
+            WatchEvent.Kind<?>[] events,
+            WatchEvent.Modifier... modifiers) {
+        if (watcher == null || events == null || modifiers == null) {
+            throw new NullPointerException();
+        }
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) {
+        return register(watcher, events, new WatchEvent.Modifier[0]);
+    }
+
+    @Override
+    public Iterator<Path> iterator() {
+        return new Iterator<Path>() {
+            private int i = 0;
+
+            @Override
+            public boolean hasNext() {
+                return (i < getNameCount());
+            }
+
+            @Override
+            public Path next() {
+                if (i < getNameCount()) {
+                    Path result = getName(i);
+                    i++;
+                    return result;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            }
+
+            @Override
+            public void remove() {
+                throw new ReadOnlyFileSystemException();
+            }
+        };
+    }
+
+    @Override
+    public SeekableByteChannel newByteChannel(Set<? extends OpenOption> options,
+                                              FileAttribute<?>... attrs)
+        throws IOException
+    {
+        return zfs.newByteChannel(getResolvedPath(), options, attrs);
+    }
+
+
+    FileChannel newFileChannel(Set<? extends OpenOption> options,
+                               FileAttribute<?>... attrs)
+        throws IOException
+    {
+        return zfs.newFileChannel(getResolvedPath(), options, attrs);
+    }
+
+    @Override
+    public SeekableByteChannel newByteChannel(OpenOption... options)
+            throws IOException {
+        Set<OpenOption> set = new HashSet<OpenOption>(options.length);
+        Collections.addAll(set, options);
+        return newByteChannel(set);
+    }
+
+    @Override
+    public void checkAccess(AccessMode... modes) throws IOException {
+        boolean w = false;
+        boolean x = false;
+        for (AccessMode mode : modes) {
+            switch (mode) {
+                case READ:
+                    break;
+                case WRITE:
+                    w = true;
+                    break;
+                case EXECUTE:
+                    x = true;
+                    break;
+                default:
+                    throw new UnsupportedOperationException();
+            }
+        }
+        ZipFileAttributes attrs = zfs.getFileAttributes(getResolvedPath());
+        if (attrs == null && (path.length != 1 || path[0] != '/'))
+            throw new NoSuchFileException(toString());
+        if (w) {
+            if (zfs.isReadOnly())
+                throw new AccessDeniedException(toString());
+        }
+        if (x)
+            throw new AccessDeniedException(toString());
+
+    }
+
+    @Override
+    public boolean exists() {
+        if (path.length == 1 && path[0] == '/')
+            return true;
+        try {
+            return zfs.exists(getResolvedPath());
+        } catch (IOException x) {}
+        return false;
+    }
+
+    @Override
+    public boolean notExists() {
+        return !exists();
+    }
+
+
+    @Override
+    public OutputStream newOutputStream(OpenOption... options)
+        throws IOException
+    {
+        if (options.length == 0)
+            return zfs.newOutputStream(getResolvedPath(),
+                                       CREATE_NEW, WRITE);
+        return zfs.newOutputStream(getResolvedPath(), options);
+    }
+
+    @Override
+    public Path moveTo(Path target, CopyOption... options)
+        throws IOException
+    {
+        if (this.zfs.provider() == target.getFileSystem().provider() &&
+            this.zfs.getZipFile().isSameFile(((ZipPath)target).zfs.getZipFile()))
+        {
+            zfs.copyFile(true,
+                         getResolvedPath(),
+                         ((ZipPath)target).getResolvedPath(),
+                         options);
+        } else {
+            copyToTarget(target, options);
+            delete();
+        }
+        return target;
+    }
+
+    @Override
+    public Path copyTo(Path target, CopyOption... options)
+        throws IOException
+    {
+        if (this.zfs.provider() == target.getFileSystem().provider() &&
+            this.zfs.getZipFile().isSameFile(((ZipPath)target).zfs.getZipFile()))
+        {
+            zfs.copyFile(false,
+                         getResolvedPath(),
+                         ((ZipPath)target).getResolvedPath(),
+                         options);
+        } else {
+            copyToTarget(target, options);
+        }
+        return target;
+    }
+
+    private void copyToTarget(Path target, CopyOption... options)
+        throws IOException
+    {
+        boolean replaceExisting = false;
+        boolean copyAttrs = false;
+        for (CopyOption opt : options) {
+            if (opt == REPLACE_EXISTING)
+                replaceExisting = true;
+            else if (opt == COPY_ATTRIBUTES)
+                copyAttrs = false;
+        }
+        // attributes of source file
+        ZipFileAttributes zfas = getAttributes();
+        // check if target exists
+        boolean exists;
+        if (replaceExisting) {
+            try {
+                target.deleteIfExists();
+                exists = false;
+            } catch (DirectoryNotEmptyException x) {
+                exists = true;
+            }
+        } else {
+            exists = target.exists();
+        }
+        if (exists)
+            throw new FileAlreadyExistsException(target.toString());
+
+        if (zfas.isDirectory()) {
+            // create directory or file
+            target.createDirectory();
+        } else {
+            InputStream is = zfs.newInputStream(getResolvedPath());
+            try {
+                OutputStream os = target.newOutputStream();
+                try {
+                    byte[] buf = new byte[8192];
+                    int n = 0;
+                    while ((n = is.read(buf)) != -1) {
+                        os.write(buf, 0, n);
+                    }
+                } finally {
+                    os.close();
+                }
+            } finally {
+                is.close();
+            }
+        }
+        if (copyAttrs) {
+            BasicFileAttributeView view =
+                target.getFileAttributeView(BasicFileAttributeView.class);
+            try {
+                view.setTimes(zfas.lastModifiedTime(), null, null);
+            } catch (IOException x) {
+                // rollback?
+                try {
+                    target.delete();
+                } catch (IOException ignore) { }
+                throw x;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipUtils.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.sun.nio.zipfs;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ *
+ * @author Xueming Shen
+ */
+
+class ZipUtils {
+
+    /*
+     * Writes a 16-bit short to the output stream in little-endian byte order.
+     */
+    public static void writeShort(OutputStream os, int v) throws IOException {
+        os.write((v >>> 0) & 0xff);
+        os.write((v >>> 8) & 0xff);
+    }
+
+    /*
+     * Writes a 32-bit int to the output stream in little-endian byte order.
+     */
+    public static void writeInt(OutputStream os, long v) throws IOException {
+        os.write((int)((v >>>  0) & 0xff));
+        os.write((int)((v >>>  8) & 0xff));
+        os.write((int)((v >>> 16) & 0xff));
+        os.write((int)((v >>> 24) & 0xff));
+    }
+
+    /*
+     * Writes a 64-bit int to the output stream in little-endian byte order.
+     */
+    public static void writeLong(OutputStream os, long v) throws IOException {
+        os.write((int)((v >>>  0) & 0xff));
+        os.write((int)((v >>>  8) & 0xff));
+        os.write((int)((v >>> 16) & 0xff));
+        os.write((int)((v >>> 24) & 0xff));
+        os.write((int)((v >>> 32) & 0xff));
+        os.write((int)((v >>> 40) & 0xff));
+        os.write((int)((v >>> 48) & 0xff));
+        os.write((int)((v >>> 56) & 0xff));
+    }
+
+    /*
+     * Writes an array of bytes to the output stream.
+     */
+    public static void writeBytes(OutputStream os, byte[] b)
+        throws IOException
+    {
+        os.write(b, 0, b.length);
+    }
+
+    /*
+     * Writes an array of bytes to the output stream.
+     */
+    public static void writeBytes(OutputStream os, byte[] b, int off, int len)
+        throws IOException
+    {
+        os.write(b, off, len);
+    }
+
+    /*
+     * Append a slash at the end, if it does not have one yet
+     */
+    public static byte[] toDirectoryPath(byte[] dir) {
+        if (dir.length != 0 && dir[dir.length - 1] != '/') {
+            dir = Arrays.copyOf(dir, dir.length + 1);
+            dir[dir.length - 1] = '/';
+        }
+        return dir;
+    }
+
+    /*
+     * Converts DOS time to Java time (number of milliseconds since epoch).
+     */
+    public static long dosToJavaTime(long dtime) {
+        Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
+                          (int)(((dtime >> 21) & 0x0f) - 1),
+                          (int)((dtime >> 16) & 0x1f),
+                          (int)((dtime >> 11) & 0x1f),
+                          (int)((dtime >> 5) & 0x3f),
+                          (int)((dtime << 1) & 0x3e));
+        return d.getTime();
+    }
+
+    /*
+     * Converts Java time to DOS time.
+     */
+    public static long javaToDosTime(long time) {
+        Date d = new Date(time);
+        int year = d.getYear() + 1900;
+        if (year < 1980) {
+            return (1 << 21) | (1 << 16);
+        }
+        return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
+               d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
+               d.getSeconds() >> 1;
+    }
+
+    private static final String regexMetaChars = ".^$+{[]|()";
+    private static final String globMetaChars = "\\*?[{";
+    private static boolean isRegexMeta(char c) {
+        return regexMetaChars.indexOf(c) != -1;
+    }
+    private static boolean isGlobMeta(char c) {
+        return globMetaChars.indexOf(c) != -1;
+    }
+    private static char EOL = 0;  //TBD
+    private static char next(String glob, int i) {
+        if (i < glob.length()) {
+            return glob.charAt(i);
+        }
+        return EOL;
+    }
+
+    /*
+     * Creates a regex pattern from the given glob expression.
+     *
+     * @throws  PatternSyntaxException
+     */
+    public static String toRegexPattern(String globPattern) {
+        boolean inGroup = false;
+        StringBuilder regex = new StringBuilder("^");
+
+        int i = 0;
+        while (i < globPattern.length()) {
+            char c = globPattern.charAt(i++);
+            switch (c) {
+                case '\\':
+                    // escape special characters
+                    if (i == globPattern.length()) {
+                        throw new PatternSyntaxException("No character to escape",
+                                globPattern, i - 1);
+                    }
+                    char next = globPattern.charAt(i++);
+                    if (isGlobMeta(next) || isRegexMeta(next)) {
+                        regex.append('\\');
+                    }
+                    regex.append(next);
+                    break;
+                case '/':
+                    regex.append(c);
+                    break;
+                case '[':
+                    // don't match name separator in class
+                    regex.append("[[^/]&&[");
+                    if (next(globPattern, i) == '^') {
+                        // escape the regex negation char if it appears
+                        regex.append("\\^");
+                        i++;
+                    } else {
+                        // negation
+                        if (next(globPattern, i) == '!') {
+                            regex.append('^');
+                            i++;
+                        }
+                        // hyphen allowed at start
+                        if (next(globPattern, i) == '-') {
+                            regex.append('-');
+                            i++;
+                        }
+                    }
+                    boolean hasRangeStart = false;
+                    char last = 0;
+                    while (i < globPattern.length()) {
+                        c = globPattern.charAt(i++);
+                        if (c == ']') {
+                            break;
+                        }
+                        if (c == '/') {
+                            throw new PatternSyntaxException("Explicit 'name separator' in class",
+                                    globPattern, i - 1);
+                        }
+                        // TBD: how to specify ']' in a class?
+                        if (c == '\\' || c == '[' ||
+                                c == '&' && next(globPattern, i) == '&') {
+                            // escape '\', '[' or "&&" for regex class
+                            regex.append('\\');
+                        }
+                        regex.append(c);
+
+                        if (c == '-') {
+                            if (!hasRangeStart) {
+                                throw new PatternSyntaxException("Invalid range",
+                                        globPattern, i - 1);
+                            }
+                            if ((c = next(globPattern, i++)) == EOL || c == ']') {
+                                break;
+                            }
+                            if (c < last) {
+                                throw new PatternSyntaxException("Invalid range",
+                                        globPattern, i - 3);
+                            }
+                            regex.append(c);
+                            hasRangeStart = false;
+                        } else {
+                            hasRangeStart = true;
+                            last = c;
+                        }
+                    }
+                    if (c != ']') {
+                        throw new PatternSyntaxException("Missing ']", globPattern, i - 1);
+                    }
+                    regex.append("]]");
+                    break;
+                case '{':
+                    if (inGroup) {
+                        throw new PatternSyntaxException("Cannot nest groups",
+                                globPattern, i - 1);
+                    }
+                    regex.append("(?:(?:");
+                    inGroup = true;
+                    break;
+                case '}':
+                    if (inGroup) {
+                        regex.append("))");
+                        inGroup = false;
+                    } else {
+                        regex.append('}');
+                    }
+                    break;
+                case ',':
+                    if (inGroup) {
+                        regex.append(")|(?:");
+                    } else {
+                        regex.append(',');
+                    }
+                    break;
+                case '*':
+                    if (next(globPattern, i) == '*') {
+                        // crosses directory boundaries
+                        regex.append(".*");
+                        i++;
+                    } else {
+                        // within directory boundary
+                        regex.append("[^/]*");
+                    }
+                    break;
+                case '?':
+                   regex.append("[^/]");
+                   break;
+                default:
+                    if (isRegexMeta(c)) {
+                        regex.append('\\');
+                    }
+                    regex.append(c);
+            }
+        }
+        if (inGroup) {
+            throw new PatternSyntaxException("Missing '}", globPattern, i - 1);
+        }
+        return regex.append('$').toString();
+    }
+}
--- a/jdk/src/share/native/java/lang/System.c	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/native/java/lang/System.c	Wed Jul 05 17:24:13 2017 +0200
@@ -97,14 +97,20 @@
     } else ((void) 0)
 
 #ifndef VENDOR /* Third party may overwrite this. */
-#define VENDOR "Sun Microsystems Inc."
-#define VENDOR_URL "http://java.sun.com/"
+#define VENDOR "Oracle Corporation"
+#define VENDOR_URL "http://java.oracle.com/"
 #define VENDOR_URL_BUG "http://java.sun.com/cgi-bin/bugreport.cgi"
 #endif
 
 #define JAVA_MAX_SUPPORTED_VERSION 51
 #define JAVA_MAX_SUPPORTED_MINOR_VERSION 0
 
+#ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */
+  #error "ERROR: No override of JAVA_SPECIFICATION_VENDOR is allowed"
+#else
+  #define JAVA_SPECIFICATION_VENDOR "Oracle Corporation"
+#endif
+
 static int fmtdefault; // boolean value
 jobject fillI18nProps(JNIEnv *env, jobject props, char *baseKey,
                       char *platformDispVal, char *platformFmtVal,
@@ -185,7 +191,8 @@
             JDK_MAJOR_VERSION "." JDK_MINOR_VERSION);
     PUTPROP(props, "java.specification.name",
             "Java Platform API Specification");
-    PUTPROP(props, "java.specification.vendor", "Sun Microsystems Inc.");
+    PUTPROP(props, "java.specification.vendor",
+            JAVA_SPECIFICATION_VENDOR);
 
     PUTPROP(props, "java.version", RELEASE);
     PUTPROP(props, "java.vendor", VENDOR);
@@ -239,7 +246,7 @@
     /* Printing properties */
     /* Note: java.awt.printerjob is an implementation private property which
      * just happens to have a java.* name because it is referenced in
-     * a java.awt class. It is the mechanism by which the Sun implementation
+     * a java.awt class. It is the mechanism by which the implementation
      * finds the appropriate class in the JRE for the platform.
      * It is explicitly not designed to be overridden by clients as
      * a way of replacing the implementation class, and in any case
@@ -267,7 +274,7 @@
     /* Java2D properties */
     /* Note: java.awt.graphicsenv is an implementation private property which
      * just happens to have a java.* name because it is referenced in
-     * a java.awt class. It is the mechanism by which the Sun implementation
+     * a java.awt class. It is the mechanism by which the implementation
      * finds the appropriate class in the JRE for the platform.
      * It is explicitly not designed to be overridden by clients as
      * a way of replacing the implementation class, and in any case
--- a/jdk/src/share/sample/nio/file/Chmod.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/sample/nio/file/Chmod.java	Wed Jul 05 17:24:13 2017 +0200
@@ -285,18 +285,12 @@
         }
 
         @Override
-        public FileVisitResult preVisitDirectory(FileRef dir) {
+        public FileVisitResult preVisitDirectory(FileRef dir, BasicFileAttributes attrs) {
             chmod(dir, changer);
             return CONTINUE;
         }
 
         @Override
-        public FileVisitResult preVisitDirectoryFailed(FileRef dir, IOException exc) {
-            System.err.println("WARNING: " + exc);
-            return CONTINUE;
-        }
-
-        @Override
         public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) {
             chmod(file, changer);
             return CONTINUE;
--- a/jdk/src/share/sample/nio/file/Copy.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/sample/nio/file/Copy.java	Wed Jul 05 17:24:13 2017 +0200
@@ -85,7 +85,7 @@
         }
 
         @Override
-        public FileVisitResult preVisitDirectory(Path dir) {
+        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
             // before visiting entries in a directory we copy the directory
             // (okay if directory already exists).
             CopyOption[] options = (preserve) ?
@@ -104,19 +104,9 @@
         }
 
         @Override
-        public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
-            System.err.format("Unable to copy: %s: %s%n", dir, exc);
-            return CONTINUE;
-        }
-
-        @Override
         public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
-            if (attrs.isDirectory()) {
-                System.err.println("cycle detected: " + file);
-            } else {
-                copyFile(file, target.resolve(source.relativize(file)),
-                         prompt, preserve);
-            }
+            copyFile(file, target.resolve(source.relativize(file)),
+                     prompt, preserve);
             return CONTINUE;
         }
 
@@ -137,7 +127,11 @@
 
         @Override
         public FileVisitResult visitFileFailed(Path file, IOException exc) {
-            System.err.format("Unable to copy: %s: %s%n", file, exc);
+            if (exc instanceof FileSystemLoopException) {
+                System.err.println("cycle detected: " + file);
+            } else {
+                System.err.format("Unable to copy: %s: %s%n", file, exc);
+            }
             return CONTINUE;
         }
     }
--- a/jdk/src/share/sample/nio/file/WatchDir.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/share/sample/nio/file/WatchDir.java	Wed Jul 05 17:24:13 2017 +0200
@@ -78,12 +78,10 @@
         // register directory and sub-directories
         Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
             @Override
-            public FileVisitResult preVisitDirectory(Path dir) {
-                try {
-                    register(dir);
-                } catch (IOException x) {
-                    throw new IOError(x);
-                }
+            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+                throws IOException
+            {
+                register(dir);
                 return FileVisitResult.CONTINUE;
             }
         });
--- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux	Wed Jul 05 17:24:13 2017 +0200
@@ -176,7 +176,13 @@
             }});
     }
 
-    synchronized void processExited(int exitcode) {
+    void processExited(int exitcode) {
+        synchronized (this) {
+            this.exitcode = exitcode;
+            hasExited = true;
+            notifyAll();
+        }
+
         if (stdout instanceof ProcessPipeInputStream)
             ((ProcessPipeInputStream) stdout).processExited();
 
@@ -185,10 +191,6 @@
 
         if (stdin instanceof ProcessPipeOutputStream)
             ((ProcessPipeOutputStream) stdin).processExited();
-
-        this.exitcode = exitcode;
-        hasExited = true;
-        notifyAll();
     }
 
     public OutputStream getOutputStream() {
--- a/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java	Wed Jul 05 17:24:13 2017 +0200
@@ -64,7 +64,10 @@
             accessor.setFile(fd, null);
             accessor.setFiles(fd, null, null);
         } else {
-            accessor.setDirectory(fd, directory);
+            // Fix 6987233: add the trailing slash if it's absent
+            accessor.setDirectory(fd, directory +
+                    (directory.endsWith(File.separator) ?
+                     "" : File.separator));
             accessor.setFile(fd, filenames[0]);
             accessor.setFiles(fd, directory, filenames);
         }
--- a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java	Wed Jul 05 17:24:13 2017 +0200
@@ -705,12 +705,8 @@
             throw new IllegalStateException("Attempt to resize uncreated window");
         }
         insLog.fine("Setting bounds on " + this + " to (" + x + ", " + y + "), " + width + "x" + height);
-        if (width <= 0) {
-            width = 1;
-        }
-        if (height <= 0) {
-            height = 1;
-        }
+        width = Math.max(MIN_SIZE, width);
+        height = Math.max(MIN_SIZE, height);
         XToolkit.awtLock();
         try {
              XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getWindow(), x,y,width,height);
--- a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java	Wed Jul 05 17:24:13 2017 +0200
@@ -763,12 +763,8 @@
     }
 
     private void checkShellRectSize(Rectangle shellRect) {
-        if (shellRect.width < 0) {
-            shellRect.width = 1;
-        }
-        if (shellRect.height < 0) {
-            shellRect.height = 1;
-        }
+        shellRect.width = Math.max(MIN_SIZE, shellRect.width);
+        shellRect.height = Math.max(MIN_SIZE, shellRect.height);
     }
 
     private void checkShellRectPos(Rectangle shellRect) {
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java	Wed Jul 05 17:24:13 2017 +0200
@@ -28,9 +28,12 @@
 import sun.awt.EmbeddedFrame;
 import java.awt.*;
 import java.awt.AWTKeyStroke;
+import java.util.logging.Logger;
 
 public class XEmbeddedFrame extends EmbeddedFrame {
 
+    private static final Logger log = Logger.getLogger(XEmbeddedFrame.class.getName());
+
     long handle;
     public XEmbeddedFrame() {
     }
@@ -70,6 +73,21 @@
         this(handle, supportsXEmbed, false);
     }
 
+    /*
+     * The method shouldn't be called in case of active XEmbed.
+     */
+    public boolean traverseIn(boolean direction) {
+        XEmbeddedFramePeer peer = (XEmbeddedFramePeer)getPeer();
+        if (peer != null) {
+            if (peer.supportsXEmbed() && peer.isXEmbedActive()) {
+                log.fine("The method shouldn't be called when XEmbed is active!");
+            } else {
+                return super.traverseIn(direction);
+            }
+        }
+        return false;
+    }
+
     protected boolean traverseOut(boolean direction) {
         XEmbeddedFramePeer xefp = (XEmbeddedFramePeer) getPeer();
         if (direction == FORWARD) {
@@ -81,6 +99,20 @@
         return true;
     }
 
+    /*
+     * The method shouldn't be called in case of active XEmbed.
+     */
+    public void synthesizeWindowActivation(boolean doActivate) {
+        XEmbeddedFramePeer peer = (XEmbeddedFramePeer)getPeer();
+        if (peer != null) {
+            if (peer.supportsXEmbed() && peer.isXEmbedActive()) {
+                log.fine("The method shouldn't be called when XEmbed is active!");
+            } else {
+                peer.synthesizeFocusInOut(doActivate);
+            }
+        }
+    }
+
     public void registerAccelerator(AWTKeyStroke stroke) {
         XEmbeddedFramePeer xefp = (XEmbeddedFramePeer) getPeer();
         if (xefp != null) {
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java	Wed Jul 05 17:24:13 2017 +0200
@@ -35,6 +35,8 @@
 import sun.awt.EmbeddedFrame;
 import sun.awt.SunToolkit;
 
+import static sun.awt.X11.XConstants.*;
+
 public class XEmbeddedFramePeer extends XFramePeer {
 
     private static final PlatformLogger xembedLog = PlatformLogger.getLogger("sun.awt.X11.xembed.XEmbeddedFramePeer");
@@ -305,4 +307,20 @@
         EmbeddedFrame frame = (EmbeddedFrame)target;
         frame.notifyModalBlocked(blocker, blocked);
     }
+
+    public void synthesizeFocusInOut(boolean doFocus) {
+        XFocusChangeEvent xev = new XFocusChangeEvent();
+
+        XToolkit.awtLock();
+        try {
+            xev.set_type(doFocus ? FocusIn : FocusOut);
+            xev.set_window(getFocusProxy().getWindow());
+            xev.set_mode(NotifyNormal);
+            XlibWrapper.XSendEvent(XToolkit.getDisplay(), getFocusProxy().getWindow(), false,
+                                   NoEventMask, xev.pData);
+        } finally {
+            XToolkit.awtUnlock();
+            xev.dispose();
+        }
+    }
 }
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1482,8 +1482,19 @@
         try {
             if (numberOfButtons == 0) {
                 numberOfButtons = getNumberOfButtonsImpl();
+                numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons;
+                //4th and 5th buttons are for wheel and shouldn't be reported as buttons.
+                //If we have more than 3 physical buttons and a wheel, we report N-2 buttons.
+                //If we have 3 physical buttons and a wheel, we report 3 buttons.
+                //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively.
+                if (numberOfButtons >=5) {
+                    numberOfButtons -= 2;
+                } else if (numberOfButtons == 4 || numberOfButtons ==5){
+                    numberOfButtons = 3;
+                }
             }
-            return (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons;
+            //Assume don't have to re-query the number again and again.
+            return numberOfButtons;
         } finally {
             awtUnlock();
         }
--- a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java	Wed Jul 05 17:24:13 2017 +0200
@@ -156,9 +156,4 @@
             return supportsFileAttributeView(UserDefinedFileAttributeView.class);
         return super.supportsFileAttributeView(name);
     }
-
-    @Override
-    boolean isLoopback() {
-        return false;
-    }
 }
--- a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java	Wed Jul 05 17:24:13 2017 +0200
@@ -108,9 +108,4 @@
             return supportsFileAttributeView(UserDefinedFileAttributeView.class);
         return super.supportsFileAttributeView(name);
     }
-
-    @Override
-    boolean isLoopback() {
-        return type().equals("lofs");
-    }
 }
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java	Wed Jul 05 17:24:13 2017 +0200
@@ -76,12 +76,6 @@
      */
     abstract UnixMountEntry findMountEntry() throws IOException;
 
-    /**
-     * Returns true if this file store represents a loopback file system that
-     * will have the same device ID as underlying file system.
-     */
-    abstract boolean isLoopback();
-
     UnixPath file() {
         return file;
     }
@@ -169,22 +163,13 @@
         if (!(ob instanceof UnixFileStore))
             return false;
         UnixFileStore other = (UnixFileStore)ob;
-        if (dev != other.dev)
-            return false;
-        // deviceIDs are equal but they may not be equal if one or both of
-        // them is a loopback file system
-        boolean thisIsLoopback = isLoopback();
-        if (thisIsLoopback != other.isLoopback())
-            return false;  // one, but not both, are lofs
-        if (!thisIsLoopback)
-            return true;    // neither is lofs
-        // both are lofs so compare mount points
-        return Arrays.equals(this.entry.dir(), other.entry.dir());
+        return (this.dev == other.dev) &&
+               Arrays.equals(this.entry.dir(), other.entry.dir());
     }
 
     @Override
     public int hashCode() {
-        return (int)(dev ^ (dev >>> 32));
+        return (int)(dev ^ (dev >>> 32)) ^ Arrays.hashCode(entry.dir());
     }
 
     @Override
--- a/jdk/src/solaris/native/java/io/io_util_md.c	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/native/java/io/io_util_md.c	Wed Jul 05 17:24:13 2017 +0200
@@ -83,8 +83,6 @@
             close(devnull);
         }
     } else if (JVM_Close(fd) == -1) {
-            SET_FD(this, fd, fid); // restore fd
-            printf("JVM_Close returned -1\n");
-            JNU_ThrowIOExceptionWithLastError(env, "close failed");
+        JNU_ThrowIOExceptionWithLastError(env, "close failed");
     }
 }
--- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Wed Jul 05 17:24:13 2017 +0200
@@ -124,7 +124,7 @@
 static int initialized = 0;
 
 /*
- * Find an internet address for a given hostname.  Not this this
+ * Find an internet address for a given hostname.  Note that this
  * code only works for addresses of type INET. The translation
  * of %d.%d.%d.%d to an address (int) occurs in java now, so the
  * String "host" shouldn't *ever* be a %d.%d.%d.%d string
@@ -200,7 +200,7 @@
          */
         if (isspace((unsigned char)hostname[0])) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
-                            (char *)hostname);
+                            hostname);
             JNU_ReleaseStringPlatformChars(env, host, hostname);
             return NULL;
         }
@@ -210,8 +210,7 @@
 
         if (error) {
             /* report error */
-            JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
-                            (char *)hostname);
+            ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
             JNU_ReleaseStringPlatformChars(env, host, hostname);
             return NULL;
         } else {
@@ -407,7 +406,7 @@
             addr |= ((caddr[1] <<16) & 0xff0000);
             addr |= ((caddr[2] <<8) & 0xff00);
             addr |= (caddr[3] & 0xff);
-            memset((char *) &him4, 0, sizeof(him4));
+            memset((void *) &him4, 0, sizeof(him4));
             him4.sin_addr.s_addr = (uint32_t) htonl(addr);
             him4.sin_family = AF_INET;
             sa = (struct sockaddr *) &him4;
@@ -417,7 +416,7 @@
              * For IPv6 address construct a sockaddr_in6 structure.
              */
             (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
-            memset((char *) &him6, 0, sizeof(him6));
+            memset((void *) &him6, 0, sizeof(him6));
             memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
             him6.sin6_family = AF_INET6;
             sa = (struct sockaddr *) &him6 ;
@@ -579,8 +578,8 @@
                                                          ifArray, ttl);
     }
 
-    memset((char *) caddr, 0, 16);
-    memset((char *) &him6, 0, sizeof(him6));
+    memset((void *) caddr, 0, 16);
+    memset((void *) &him6, 0, sizeof(him6));
     (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
     memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
     him6.sin6_family = AF_INET6;
@@ -600,8 +599,8 @@
      * for it.
      */
     if (!(IS_NULL(ifArray))) {
-      memset((char *) caddr, 0, 16);
-      memset((char *) &inf6, 0, sizeof(inf6));
+      memset((void *) caddr, 0, 16);
+      memset((void *) &inf6, 0, sizeof(inf6));
       (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
       memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
       inf6.sin6_family = AF_INET6;
--- a/jdk/src/solaris/native/java/net/net_util_md.c	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/native/java/net/net_util_md.c	Wed Jul 05 17:24:13 2017 +0200
@@ -61,6 +61,7 @@
 
 getaddrinfo_f getaddrinfo_ptr = NULL;
 freeaddrinfo_f freeaddrinfo_ptr = NULL;
+gai_strerror_f gai_strerror_ptr = NULL;
 getnameinfo_f getnameinfo_ptr = NULL;
 
 /*
@@ -342,11 +343,14 @@
     freeaddrinfo_ptr = (freeaddrinfo_f)
         JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
 
+    gai_strerror_ptr = (gai_strerror_f)
+        JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
+
     getnameinfo_ptr = (getnameinfo_f)
         JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
 
     if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
-        /* Wee need all 3 of them */
+        /* We need all 3 of them */
         getaddrinfo_ptr = NULL;
     }
 
@@ -355,6 +359,35 @@
 #endif /* AF_INET6 */
 }
 
+void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
+                                           const char* hostname,
+                                           int gai_error)
+{
+    int size;
+    char *buf;
+    const char *format = "%s: %s";
+    const char *error_string =
+        (gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error);
+    if (error_string == NULL)
+        error_string = "unknown error";
+
+    size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
+    buf = (char *) malloc(size);
+    if (buf) {
+        jstring s;
+        sprintf(buf, format, hostname, error_string);
+        s = JNU_NewStringPlatform(env, buf);
+        if (s != NULL) {
+            jobject x = JNU_NewObjectByName(env,
+                                            "java/net/UnknownHostException",
+                                            "(Ljava/lang/String;)V", s);
+            if (x != NULL)
+                (*env)->Throw(env, x);
+        }
+        free(buf);
+    }
+}
+
 void
 NET_AllocSockaddr(struct sockaddr **him, int *len) {
 #ifdef AF_INET6
@@ -1173,19 +1206,26 @@
     }
 
     /*
-     * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris need to
-     * ensure that value is <= max_buf as otherwise we get
-     * an invalid argument.
+     * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
+     * the value when it exceeds the system limit.
      */
 #ifdef __solaris__
     if (level == SOL_SOCKET) {
         if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
             int sotype, arglen;
             int *bufsize, maxbuf;
+            int ret;
+
+            /* Attempt with the original size */
+            ret = setsockopt(fd, level, opt, arg, len);
+            if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
+                return ret;
+
+            /* Exceeded system limit so clamp and retry */
 
             if (!init_max_buf) {
-                tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf", 64*1024);
-                udp_max_buf = getParam("/dev/udp", "udp_max_buf", 64*1024);
+                tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf", 1024*1024);
+                udp_max_buf = getParam("/dev/udp", "udp_max_buf", 2048*1024);
                 init_max_buf = 1;
             }
 
--- a/jdk/src/solaris/native/java/net/net_util_md.h	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/native/java/net/net_util_md.h	Wed Jul 05 17:24:13 2017 +0200
@@ -84,11 +84,13 @@
 
 /* needed from libsocket on Solaris 8 */
 
-typedef int (*getaddrinfo_f)(const char *nodename, const char  *servname,
-     const struct addrinfo *hints, struct addrinfo **res);
+typedef int (*getaddrinfo_f)(const char *nodename, const char *servname,
+    const struct addrinfo *hints, struct addrinfo **res);
 
 typedef void (*freeaddrinfo_f)(struct addrinfo *);
 
+typedef const char * (*gai_strerror_f)(int ecode);
+
 typedef int (*getnameinfo_f)(const struct sockaddr *, size_t,
     char *, size_t, char *, size_t, int);
 
@@ -96,6 +98,10 @@
 extern freeaddrinfo_f freeaddrinfo_ptr;
 extern getnameinfo_f getnameinfo_ptr;
 
+void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
+                                           const char* hostname,
+                                           int gai_error);
+
 /* do we have address translation support */
 
 extern jboolean NET_addrtransAvailable();
--- a/jdk/src/solaris/native/sun/awt/awt_InputMethod.c	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_InputMethod.c	Wed Jul 05 17:24:13 2017 +0200
@@ -1473,6 +1473,10 @@
 static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) {
     /* mark that XIM server was destroyed */
     X11im = NULL;
+    JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+    /* free the old pX11IMData and set it to null. this also avoids crashing
+     * the jvm if the XIM server reappears */
+    X11InputMethodData *pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
 }
 
 /*
--- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java	Wed Jul 05 17:24:13 2017 +0200
@@ -556,24 +556,26 @@
 
         Component target = (Component)getTarget();
         Window window = SunToolkit.getContainingWindow(target);
-        if (window != null && !window.isOpaque()) {
-            // Non-opaque windows do not support heavyweight children.
-            // Redirect all painting to the Window's Graphics instead.
-            // The caller is responsible for calling the
-            // WindowPeer.updateWindow() after painting has finished.
-            int x = 0, y = 0;
-            for (Component c = target; c != window; c = c.getParent()) {
-                x += c.getX();
-                y += c.getY();
-            }
-
+        if (window != null) {
             Graphics g =
                 ((WWindowPeer)window.getPeer()).getTranslucentGraphics();
+            // getTranslucentGraphics() returns non-null value for non-opaque windows only
+            if (g != null) {
+                // Non-opaque windows do not support heavyweight children.
+                // Redirect all painting to the Window's Graphics instead.
+                // The caller is responsible for calling the
+                // WindowPeer.updateWindow() after painting has finished.
+                int x = 0, y = 0;
+                for (Component c = target; c != window; c = c.getParent()) {
+                    x += c.getX();
+                    y += c.getY();
+                }
 
-            g.translate(x, y);
-            g.clipRect(0, 0, target.getWidth(), target.getHeight());
+                g.translate(x, y);
+                g.clipRect(0, 0, target.getWidth(), target.getHeight());
 
-            return g;
+                return g;
+            }
         }
 
         SurfaceData surfaceData = this.surfaceData;
--- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java	Wed Jul 05 17:24:13 2017 +0200
@@ -191,9 +191,20 @@
     public void activateEmbeddingTopLevel() {
     }
 
-    public void synthesizeWindowActivation(boolean doActivate) {
-        ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate);
+    public void synthesizeWindowActivation(final boolean doActivate) {
+        if (!doActivate || EventQueue.isDispatchThread()) {
+            ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate);
+        } else {
+            // To avoid focus concurrence b/w IE and EmbeddedFrame
+            // activation is postponed by means of posting it to EDT.
+            EventQueue.invokeLater(new Runnable() {
+                    public void run() {
+                        ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true);
+                    }
+                });
+        }
     }
+
     public void registerAccelerator(AWTKeyStroke stroke) {}
     public void unregisterAccelerator(AWTKeyStroke stroke) {}
 
--- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java	Wed Jul 05 17:24:13 2017 +0200
@@ -595,16 +595,6 @@
     }
 
     @Override
-    public Graphics getGraphics() {
-        synchronized (getStateLock()) {
-            if (!isOpaque) {
-                return getTranslucentGraphics();
-            }
-        }
-        return super.getGraphics();
-    }
-
-    @Override
     public void setBackground(Color c) {
         super.setBackground(c);
         synchronized (getStateLock()) {
--- a/jdk/src/windows/lib/tzmappings	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/lib/tzmappings	Wed Jul 05 17:24:13 2017 +0200
@@ -1,5 +1,4 @@
 #
-# 
 # This file describes mapping information between Windows and Java
 # time zones.
 # Format: Each line should include a colon separated fields of Windows
@@ -11,7 +10,7 @@
 #                            NOTE
 # This table format is not a public interface of any Java
 # platforms. No applications should depend on this file in any form.
-# 
+#
 # This table has been generated by a program and should not be edited
 # manually.
 #
@@ -84,8 +83,8 @@
 Ekaterinburg Standard Time:10,11::Asia/Yekaterinburg:
 West Asia:10,11:UZ:Asia/Tashkent:
 West Asia Standard Time:10,11:UZ:Asia/Tashkent:
-Central Asia:12,13::Asia/Dhaka:
-Central Asia Standard Time:12,13::Asia/Dhaka:
+Central Asia:12,13::Asia/Almaty:
+Central Asia Standard Time:12,13::Asia/Almaty:
 N. Central Asia Standard Time:12,13::Asia/Novosibirsk:
 Bangkok:14,15::Asia/Bangkok:
 Bangkok Standard Time:14,15::Asia/Bangkok:
@@ -167,22 +166,27 @@
 Greenwich Standard Time:88,89::GMT:
 Argentina Standard Time:900,900::America/Buenos_Aires:
 Azerbaijan Standard Time:901,901:AZ:Asia/Baku:
-Central Brazilian Standard Time:902,902:BR:America/Manaus:
-Central Standard Time (Mexico):903,903::America/Mexico_City:
-Georgian Standard Time:904,904:GE:Asia/Tbilisi:
-Jordan Standard Time:905,905:JO:Asia/Amman:
-Mauritius Standard Time:906,906:MU:Indian/Mauritius:
-Middle East Standard Time:907,907:LB:Asia/Beirut:
-Montevideo Standard Time:908,908:UY:America/Montevideo:
-Morocco Standard Time:909,909:MA:Africa/Casablanca:
-Mountain Standard Time (Mexico):910,910:MX:America/Chihuahua:
-Namibia Standard Time:911,911:NA:Africa/Windhoek:
-Pacific Standard Time (Mexico):912,912:MX:America/Tijuana:
-Pakistan Standard Time:913,913::Asia/Karachi:
-UTC:914,914::UTC:
-Venezuela Standard Time:915,915::America/Caracas:
-Kamchatka Standard Time:916,916:RU:Asia/Kamchatka:
-Paraguay Standard Time:917,917:PY:America/Asuncion:
-Western Brazilian Standard Time:918,918:BR:America/Rio_Branco:
-Ulaanbaatar Standard Time:919,919::Asia/Ulaanbaatar:
-Armenian Standard Time:920,920:AM:Asia/Yerevan:
+Bangladesh Standard Time:902,902::Asia/Dhaka:
+Central Brazilian Standard Time:903,903:BR:America/Manaus:
+Central Standard Time (Mexico):904,904::America/Mexico_City:
+Georgian Standard Time:905,905:GE:Asia/Tbilisi:
+Jordan Standard Time:906,906:JO:Asia/Amman:
+Kamchatka Standard Time:907,907:RU:Asia/Kamchatka:
+Mauritius Standard Time:908,908:MU:Indian/Mauritius:
+Middle East Standard Time:909,909:LB:Asia/Beirut:
+Montevideo Standard Time:910,910:UY:America/Montevideo:
+Morocco Standard Time:911,911:MA:Africa/Casablanca:
+Mountain Standard Time (Mexico):912,912:MX:America/Chihuahua:
+Namibia Standard Time:913,913:NA:Africa/Windhoek:
+Pacific Standard Time (Mexico):914,914:MX:America/Tijuana:
+Pakistan Standard Time:915,915::Asia/Karachi:
+Paraguay Standard Time:916,916:PY:America/Asuncion:
+Syria Standard Time:917,917:SY:Asia/Damascus:
+UTC:918,918::UTC:
+UTC+12:919,919::GMT+1200:
+UTC-02:920,920::GMT-0200:
+UTC-11:921,921::GMT-1100:
+Ulaanbaatar Standard Time:922,922::Asia/Ulaanbaatar:
+Venezuela Standard Time:923,923::America/Caracas:
+Western Brazilian Standard Time:924,924:BR:America/Rio_Branco:
+Armenian Standard Time:925,925:AM:Asia/Yerevan:
--- a/jdk/src/windows/native/java/io/io_util_md.c	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/native/java/io/io_util_md.c	Wed Jul 05 17:24:13 2017 +0200
@@ -531,7 +531,6 @@
     SET_FD(this, -1, fid);
 
     if (CloseHandle(h) == 0) { /* Returns zero on failure */
-        SET_FD(this, fd, fid); // restore fd
         JNU_ThrowIOExceptionWithLastError(env, "close failed");
     }
     return 0;
--- a/jdk/src/windows/native/sun/net/spi/DefaultProxySelector.c	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/native/sun/net/spi/DefaultProxySelector.c	Wed Jul 05 17:24:13 2017 +0200
@@ -250,6 +250,10 @@
           return proxy;
         }
       }
+    } else {
+      /* ProxyEnable == 0 or Query failed      */
+      /* close the handle to the registry key  */
+      RegCloseKey(hKey);
     }
   }
 
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp	Wed Jul 05 17:24:13 2017 +0200
@@ -2329,6 +2329,19 @@
     MSG msg;
     InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
 
+    AwtWindow *toplevel = GetContainer();
+    if (toplevel && !toplevel->IsSimpleWindow()) {
+        /*
+         * The frame should be focused by click in case it is
+         * the active window but not the focused window. See 6886678.
+         */
+        if (toplevel->GetHWnd() == ::GetActiveWindow() &&
+            toplevel->GetHWnd() != AwtComponent::GetFocusedWindow())
+        {
+            toplevel->AwtSetActiveWindow();
+        }
+    }
+
     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y,
                    GetJavaModifiers(), clickCount, JNI_FALSE,
                    GetButton(button), &msg);
--- a/jdk/src/windows/native/sun/windows/awt_Desktop.cpp	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Desktop.cpp	Wed Jul 05 17:24:13 2017 +0200
@@ -59,15 +59,17 @@
                     FORMAT_MESSAGE_FROM_SYSTEM  |
                     FORMAT_MESSAGE_IGNORE_INSERTS,
                     NULL,
-                    GetLastError(),
+                    (int)retval,
                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                     (LPTSTR)&buffer,
                     0,
                     NULL );
 
-        jstring errmsg = JNU_NewStringPlatform(env, buffer, len);
-        LocalFree(buffer);
-        return errmsg;
+        if (buffer) {
+            jstring errmsg = JNU_NewStringPlatform(env, buffer);
+            LocalFree(buffer);
+            return errmsg;
+        }
     }
 
     return NULL;
--- a/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp	Wed Jul 05 17:24:13 2017 +0200
@@ -505,7 +505,8 @@
     SetIntegerProperty(TEXT("win.drag.width"), cxdrag);
     SetIntegerProperty(TEXT("win.drag.height"), cydrag);
     SetIntegerProperty(TEXT("DnD.gestureMotionThreshold"), max(cxdrag, cydrag)/2);
-    SetIntegerProperty(TEXT("awt.mouse.numButtons"), GetSystemMetrics(SM_CMOUSEBUTTONS));
+    SetIntegerProperty(TEXT("awt.mouse.numButtons"), AwtToolkit::GetNumberOfButtons());
+
     SetIntegerProperty(TEXT("awt.multiClickInterval"), GetDoubleClickTime());
 
     // BEGIN cross-platform properties
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp	Wed Jul 05 17:24:13 2017 +0200
@@ -133,6 +133,8 @@
 
 static LPCTSTR szAwtToolkitClassName = TEXT("SunAwtToolkit");
 
+static const int MOUSE_BUTTONS_WINDOWS_SUPPORTED = 5; //three standard buttons + XBUTTON1 + XBUTTON2.
+
 UINT AwtToolkit::GetMouseKeyState()
 {
     static BOOL mbSwapped = ::GetSystemMetrics(SM_SWAPBUTTON);
@@ -2310,5 +2312,9 @@
 
 JNIEXPORT jint JNICALL Java_sun_awt_windows_WToolkit_getNumberOfButtonsImpl
 (JNIEnv *, jobject self) {
-    return GetSystemMetrics(SM_CMOUSEBUTTONS);
+    return AwtToolkit::GetNumberOfButtons();
 }
+
+UINT AwtToolkit::GetNumberOfButtons() {
+    return MOUSE_BUTTONS_WINDOWS_SUPPORTED;
+}
--- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h	Wed Jul 05 17:24:13 2017 +0200
@@ -185,6 +185,7 @@
     BOOL IsDynamicLayoutActive();
     BOOL areExtraMouseButtonsEnabled();
     void setExtraMouseButtonsEnabled(BOOL enable);
+    static UINT GetNumberOfButtons();
 
     INLINE BOOL localPump() { return m_localPump; }
     INLINE BOOL VerifyComponents() { return FALSE; } // TODO: Use new DebugHelper class to set this flag
--- a/jdk/test/ProblemList.txt	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 17:24:13 2017 +0200
@@ -165,6 +165,12 @@
 #  very small tests and could greatly benefit from a samevm test run.
 #  So a large batch of beans tests are currently run with othervm mode.
 
+# Filed 6986807
+java/beans/Introspector/TestTypeResolver.java   		generic-all
+
+# Filed 6986813
+java/beans/Introspector/memory/Test4508780.java			generic-all
+
 # Linux, some kind of problems with X11 display
 java/beans/PropertyChangeSupport/Test4682386.java		generic-all
 java/beans/PropertyChangeSupport/TestSynchronization.java	generic-all
@@ -493,6 +499,9 @@
 
 # jdk_security
 
+# Filed 6986868
+sun/security/tools/jarsigner/crl.sh				generic-all
+
 # Filed 6951285, not sure how often this fails, last was Linux 64bit Fedora 9
 sun/security/krb5/auto/MaxRetries.java				generic-all
 
@@ -689,10 +698,22 @@
 
 # jdk_tools
 
+# Filed 6952105
+com/sun/jdi/SuspendThreadTest.java				generic-all
+
+# Filed 6986875
+sun/tools/jps/jps-Vvml.sh					generic-all
+
+# Filed 6979016
+sun/tools/jconsole/ResourceCheckTest.sh				generic-all
+
 ############################################################################
 
 # jdk_util
 
+# Filed 6933803
+java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java	generic-all
+
 # Fails with assertion error on windows
 #   11 separate stacktraces created... file reuse problem?
 java/util/zip/ZipFile/ReadLongZipFileName.java			generic-all
--- a/jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java	Wed Jul 05 17:24:13 2017 +0200
@@ -31,8 +31,6 @@
 import javax.security.auth.callback.*;
 import java.util.*;
 
-import com.sun.security.ntlm.NTLMException;
-
 public class NTLMTest {
 
     private static final String MECH = "NTLM";
@@ -95,19 +93,13 @@
             checkVersion("LM/NTLM", "LMv2");
             throw new Exception("Should not succeed");
         } catch (SaslException se) {
-            NTLMException ne = (NTLMException)se.getCause();
-            if (ne.errorCode() != NTLMException.AUTH_FAILED) {
-                throw new Exception("Failed false");
-            }
+            // OK
         }
         try {
             checkVersion("LMv2/NTLMv2", "LM");
             throw new Exception("Should not succeed");
         } catch (SaslException se) {
-            NTLMException ne = (NTLMException)se.getCause();
-            if (ne.errorCode() != NTLMException.AUTH_FAILED) {
-                throw new Exception("Failed false");
-            }
+            // OK
         }
 
     }
--- a/jdk/test/com/sun/servicetag/JavaServiceTagTest.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/JavaServiceTagTest.java	Wed Jul 05 17:24:13 2017 +0200
@@ -124,8 +124,9 @@
             throw new RuntimeException("Unexpected platform_arch: " +
                 st.getPlatformArch());
         }
+        String vendor = System.getProperty("java.vendor");
         if (!st.getProductVendor().
-                equals("Sun Microsystems")) {
+                equals(vendor)) {
             throw new RuntimeException("Unexpected product_vendor: " +
                 st.getProductVendor());
         }
--- a/jdk/test/com/sun/servicetag/JavaServiceTagTest1.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/JavaServiceTagTest1.java	Wed Jul 05 17:24:13 2017 +0200
@@ -196,8 +196,10 @@
             throw new RuntimeException("Unexpected platform_arch: " +
                 st.getPlatformArch());
         }
+
+        String vendor = System.getProperty("java.vendor");
         if (!st.getProductVendor().
-                equals("Sun Microsystems")) {
+                equals(vendor)) {
             throw new RuntimeException("Unexpected product_vendor: " +
                 st.getProductVendor());
         }
--- a/jdk/test/com/sun/servicetag/Util.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/Util.java	Wed Jul 05 17:24:13 2017 +0200
@@ -162,6 +162,8 @@
         for (ServiceTag st : svcTags) {
             ServiceTag st1 = stMap.get(st.getInstanceURN());
             if (!matches(st, st1)) {
+                System.err.println(st);
+                System.err.println(st1);
                 throw new RuntimeException("ServiceTag in the registry " +
                     "does not match the one in the map");
             }
--- a/jdk/test/com/sun/servicetag/environ.properties	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/environ.properties	Wed Jul 05 17:24:13 2017 +0200
@@ -4,6 +4,6 @@
 osVersion=5.10
 osArchitecture=sparc
 systemModel=Sun-Fire-V440
-systemManufacturer=Sun Microsystems
-cpuManufacturer=Sun Microsystems
+systemManufacturer=Oracle Corporation
+cpuManufacturer=Oracle Corporation
 serialNumber=BEL078932
--- a/jdk/test/com/sun/servicetag/missing-environ-field.xml	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/missing-environ-field.xml	Wed Jul 05 17:24:13 2017 +0200
@@ -19,7 +19,7 @@
 <product_parent_urn>urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3</product_parent_urn>
 <product_parent>Java Platform Standard Edition 6 (Java SE 6)</product_parent>
 <product_defined_inst_id>id=1.6.0-internal-b00 sparc,dir=/myjdk/solaris-sparc</product_defined_inst_id>
-<product_vendor>Sun Microsystems</product_vendor>
+<product_vendor>Oracle Corporation</product_vendor>
 <platform_arch>sparc</platform_arch>
 <timestamp>2007-11-12 06:15:11 GMT</timestamp>
 <container>global</container>
@@ -34,7 +34,7 @@
 <product_parent_urn>urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3</product_parent_urn>
 <product_parent>Java Platform Standard Edition 6 (Java SE 6)</product_parent>
 <product_defined_inst_id>id=1.6.0_05-b01 sparc,dir=/myjdk/solaris-i586</product_defined_inst_id>
-<product_vendor>Sun Microsystems</product_vendor>
+<product_vendor>Oracle Corporation</product_vendor>
 <platform_arch>i386</platform_arch>
 <timestamp>2007-11-12 06:15:11 GMT</timestamp>
 <container>global</container>
--- a/jdk/test/com/sun/servicetag/newer-registry-version.xml	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/newer-registry-version.xml	Wed Jul 05 17:24:13 2017 +0200
@@ -20,7 +20,7 @@
 <product_parent_urn>urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3</product_parent_urn>
 <product_parent>Java Platform Standard Edition 6 (Java SE 6)</product_parent>
 <product_defined_inst_id>id=1.6.0-internal-b00 sparc,dir=/myjdk/solaris-sparc</product_defined_inst_id>
-<product_vendor>Sun Microsystems</product_vendor>
+<product_vendor>Oracle Corporation</product_vendor>
 <platform_arch>sparc</platform_arch>
 <timestamp>2007-11-13 00:49:01 GMT</timestamp>
 <container>global</container>
--- a/jdk/test/com/sun/servicetag/registration.xml	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/registration.xml	Wed Jul 05 17:24:13 2017 +0200
@@ -7,8 +7,8 @@
 <osVersion>5.10</osVersion>
 <osArchitecture>sparc</osArchitecture>
 <systemModel>Sun-Fire-V440</systemModel>
-<systemManufacturer>Sun Microsystems</systemManufacturer>
-<cpuManufacturer>Sun Microsystems</cpuManufacturer>
+<systemManufacturer>Oracle Corporation</systemManufacturer>
+<cpuManufacturer>Oracle Corporation</cpuManufacturer>
 <serialNumber>BEL078932</serialNumber>
 </environment>
 <registry urn="urn:st:9543ffaa-a4f1-4f77-b2d1-f561922d4e4a" version="1.0">
@@ -20,7 +20,7 @@
 <product_parent_urn>urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3</product_parent_urn>
 <product_parent>Java Platform Standard Edition 6 (Java SE 6)</product_parent>
 <product_defined_inst_id>id=1.6.0-internal-b00 sparc,dir=/myjdk/solaris-sparc</product_defined_inst_id>
-<product_vendor>Sun Microsystems</product_vendor>
+<product_vendor>Oracle Corporation</product_vendor>
 <platform_arch>sparc</platform_arch>
 <timestamp>2007-11-13 00:49:01 GMT</timestamp>
 <container>global</container>
@@ -35,7 +35,7 @@
 <product_parent_urn>urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3</product_parent_urn>
 <product_parent>Java Platform Standard Edition 6 (Java SE 6)</product_parent>
 <product_defined_inst_id>id=1.6.0_05-b01 i386,dir=/myjdk/solaris-i586</product_defined_inst_id>
-<product_vendor>Sun Microsystems</product_vendor>
+<product_vendor>Oracle Corporation</product_vendor>
 <platform_arch>i386</platform_arch>
 <timestamp>2007-11-13 00:49:01 GMT</timestamp>
 <container>global</container>
@@ -50,7 +50,7 @@
 <product_parent_urn>urn:uuid:596ffcfa-63d5-11d7-9886-ac816a682f92</product_parent_urn>
 <product_parent>Solaris Operating System</product_parent>
 <product_defined_inst_id/>
-<product_vendor>Sun Microsystems</product_vendor>
+<product_vendor>Oracle Corporation</product_vendor>
 <platform_arch>sparc</platform_arch>
 <timestamp>2007-11-13 00:49:01 GMT</timestamp>
 <container>global</container>
--- a/jdk/test/com/sun/servicetag/servicetag1.properties	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag1.properties	Wed Jul 05 17:24:13 2017 +0200
@@ -5,7 +5,7 @@
 product_parent_urn=urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3
 product_parent=Java Platform Standard Edition 6 (Java SE 6)
 product_defined_inst_id=id=1.6.0-internal-b00 sparc,dir=/myjdk/solaris-sparc
-product_vendor=Sun Microsystems
+product_vendor=Oracle Corporation
 platform_arch=sparc
 timestamp=2007-11-12 05:19:40 GMT
 container=global
--- a/jdk/test/com/sun/servicetag/servicetag2.properties	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag2.properties	Wed Jul 05 17:24:13 2017 +0200
@@ -5,7 +5,7 @@
 product_parent_urn=urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3
 product_parent=Java Platform Standard Edition 6 (Java SE 6)
 product_defined_inst_id=id=1.6.0_05-b01 i386,dir=/myjdk/solaris-i586
-product_vendor=Sun Microsystems
+product_vendor=Oracle Corporation
 platform_arch=i386
 timestamp=2007-11-12 06:12:21 GMT
 container=global
--- a/jdk/test/com/sun/servicetag/servicetag3.properties	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag3.properties	Wed Jul 05 17:24:13 2017 +0200
@@ -5,7 +5,7 @@
 product_parent_urn=urn:uuid:596ffcfa-63d5-11d7-9886-ac816a682f92
 product_parent=Solaris Operating System
 product_defined_inst_id=
-product_vendor=Sun Microsystems
+product_vendor=Oracle Corporation
 platform_arch=sparc
 timestamp=2007-06-20 22:07:11 GMT
 container=global
--- a/jdk/test/com/sun/servicetag/servicetag4.properties	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag4.properties	Wed Jul 05 17:24:13 2017 +0200
@@ -5,7 +5,7 @@
 product_parent_urn=urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3
 product_parent=Java Platform Standard Edition 6 (Java SE 6)
 product_defined_inst_id=id=1.6.0_05-b01 amd64,dir=/myjdk/linux-amd64
-product_vendor=Sun Microsystems
+product_vendor=Oracle Corporation
 platform_arch=x64
 timestamp=2007-12-12 05:19:40 GMT
 container=global
--- a/jdk/test/com/sun/servicetag/servicetag5.properties	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag5.properties	Wed Jul 05 17:24:13 2017 +0200
@@ -5,7 +5,7 @@
 product_parent_urn=urn:uuid:fdc90b21-018d-4cab-b866-612c7c119ed3
 product_parent=Java Platform Standard Edition 6 (Java SE 6)
 product_defined_inst_id=id=1.6.0_06-b06 i386,dir=/w/mchung/bundles/jdk1.6.0_05/jre
-product_vendor=Sun Microsystems
+product_vendor=Oracle Corporation
 platform_arch=x86
 timestamp=2007-11-29 17:59:42 GMT
 container=global
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/demo/zipfs/Basic.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2009, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.*;
+import java.net.URI;
+import java.io.IOException;
+
+/**
+ * Basic test for zip provider
+ */
+
+public class Basic {
+    public static void main(String[] args) throws Exception {
+        Path zipfile = Paths.get(args[0]);
+
+        // Test: zip should should be returned in provider list
+        boolean found = false;
+
+        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+            if (provider.getScheme().equalsIgnoreCase("zip")) {
+                found = true;
+                break;
+            }
+        }
+        if (!found)
+            throw new RuntimeException("'zip' provider not installed");
+
+        // Test: FileSystems#newFileSystem(FileRef)
+        Map<String,?> env = new HashMap<String,Object>();
+        FileSystems.newFileSystem(zipfile, env, null).close();
+
+        // Test: FileSystems#newFileSystem(URI)
+        URI uri = URI.create("zip" + zipfile.toUri().toString().substring(4));
+        FileSystem fs = FileSystems.newFileSystem(uri, env, null);
+
+        // Test: exercise toUri method
+        String expected = uri.toString() + "#/foo";
+        String actual = fs.getPath("/foo").toUri().toString();
+        if (!actual.equals(expected)) {
+            throw new RuntimeException("toUri returned '" + actual +
+                "', expected '" + expected + "'");
+        }
+
+        // Test: exercise directory iterator and retrieval of basic attributes
+        Files.walkFileTree(fs.getPath("/"), new FileTreePrinter());
+
+        // Test: DirectoryStream
+        found = false;
+        DirectoryStream<Path> stream = fs.getPath("/").newDirectoryStream();
+        try {
+            for (Path entry: stream) {
+                found = entry.toString().equals("/META-INF/");
+                if (found) break;
+            }
+        } finally {
+            stream.close();
+        }
+
+        if (!found)
+            throw new RuntimeException("Expected file not found");
+
+        // Test: copy file from zip file to current (scratch) directory
+        Path source = fs.getPath("/META-INF/services/java.nio.file.spi.FileSystemProvider");
+        if (source.exists()) {
+            Path target = Paths.get(source.getName().toString());
+            source.copyTo(target, StandardCopyOption.REPLACE_EXISTING);
+            try {
+                long s1 = Attributes.readBasicFileAttributes(source).size();
+                long s2 = Attributes.readBasicFileAttributes(target).size();
+                if (s2 != s1)
+                    throw new RuntimeException("target size != source size");
+            } finally {
+                target.delete();
+            }
+        }
+
+        // Test: FileStore
+        FileStore store = fs.getPath("/").getFileStore();
+        if (!store.supportsFileAttributeView("basic"))
+            throw new RuntimeException("BasicFileAttributeView should be supported");
+
+        // Test: ClosedFileSystemException
+        fs.close();
+        if (fs.isOpen())
+            throw new RuntimeException("FileSystem should be closed");
+        try {
+            fs.getPath("/missing").checkAccess(AccessMode.READ);
+        } catch (ClosedFileSystemException x) { }
+    }
+
+    // FileVisitor that pretty prints a file tree
+    static class FileTreePrinter extends SimpleFileVisitor<Path> {
+        private int indent = 0;
+
+        private void indent() {
+            StringBuilder sb = new StringBuilder(indent);
+            for (int i=0; i<indent; i++) sb.append(" ");
+            System.out.print(sb);
+        }
+
+        @Override
+        public FileVisitResult preVisitDirectory(Path dir,
+                                                 BasicFileAttributes attrs)
+        {
+            if (dir.getName() != null) {
+                indent();
+                System.out.println(dir.getName() + "/");
+                indent++;
+            }
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult visitFile(Path file,
+                                         BasicFileAttributes attrs)
+        {
+            indent();
+            System.out.print(file.getName());
+            if (attrs.isRegularFile())
+                System.out.format(" (%d)", attrs.size());
+            System.out.println();
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult postVisitDirectory(Path dir, IOException exc)
+            throws IOException
+        {
+            if (exc != null)
+                super.postVisitDirectory(dir, exc);
+            if (dir.getName() != null)
+                indent--;
+            return FileVisitResult.CONTINUE;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/demo/zipfs/PathOps.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2009, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.nio.file.*;
+import java.net.*;
+import java.util.*;
+import java.io.IOException;
+
+/**
+ * Tests path operations for zip provider.
+ */
+
+public class PathOps {
+
+    static final java.io.PrintStream out = System.out;
+    static FileSystem fs;
+
+    private String input;
+    private Path path;
+    private Exception exc;
+
+    private PathOps(String s) {
+        out.println();
+        input = s;
+        try {
+            path = fs.getPath(s);
+            out.format("%s -> %s", s, path);
+        } catch (Exception x) {
+            exc = x;
+            out.format("%s -> %s", s, x);
+        }
+        out.println();
+    }
+
+    Path path() {
+        return path;
+    }
+
+    void fail() {
+        throw new RuntimeException("PathOps failed");
+    }
+
+    void checkPath() {
+        if (path == null) {
+            throw new InternalError("path is null");
+        }
+    }
+
+    void check(Object result, String expected) {
+        out.format("\tExpected: %s\n", expected);
+        out.format("\tActual: %s\n",  result);
+        if (result == null) {
+            if (expected == null) return;
+        } else {
+            // compare string representations
+            if (expected != null && result.toString().equals(expected.toString()))
+                return;
+        }
+        fail();
+    }
+
+    void check(Object result, boolean expected) {
+        check(result, Boolean.toString(expected));
+    }
+
+    PathOps root(String expected) {
+        out.println("check root");
+        checkPath();
+        check(path.getRoot(), expected);
+        return this;
+    }
+
+    PathOps parent(String expected) {
+        out.println("check parent");
+        checkPath();
+        check(path.getParent(), expected);
+        return this;
+    }
+
+    PathOps name(String expected) {
+        out.println("check name");
+        checkPath();
+        check(path.getName(), expected);
+        return this;
+    }
+
+    PathOps element(int index, String expected) {
+        out.format("check element %d\n", index);
+        checkPath();
+        check(path.getName(index), expected);
+        return this;
+    }
+
+    PathOps subpath(int startIndex, int endIndex, String expected) {
+        out.format("test subpath(%d,%d)\n", startIndex, endIndex);
+        checkPath();
+        check(path.subpath(startIndex, endIndex), expected);
+        return this;
+    }
+
+    PathOps starts(String prefix) {
+        out.format("test startsWith with %s\n", prefix);
+        checkPath();
+        Path s = fs.getPath(prefix);
+        check(path.startsWith(s), true);
+        return this;
+    }
+
+    PathOps notStarts(String prefix) {
+        out.format("test not startsWith with %s\n", prefix);
+        checkPath();
+        Path s = fs.getPath(prefix);
+        check(path.startsWith(s), false);
+        return this;
+    }
+
+    PathOps ends(String suffix) {
+        out.format("test endsWith %s\n", suffix);
+        checkPath();
+        Path s = fs.getPath(suffix);
+        check(path.endsWith(s), true);
+        return this;
+    }
+
+    PathOps notEnds(String suffix) {
+        out.format("test not endsWith %s\n", suffix);
+        checkPath();
+        Path s = fs.getPath(suffix);
+        check(path.endsWith(s), false);
+        return this;
+    }
+
+    PathOps absolute() {
+        out.println("check path is absolute");
+        checkPath();
+        check(path.isAbsolute(), true);
+        return this;
+    }
+
+    PathOps notAbsolute() {
+        out.println("check path is not absolute");
+        checkPath();
+        check(path.isAbsolute(), false);
+        return this;
+    }
+
+    PathOps resolve(String other, String expected) {
+        out.format("test resolve %s\n", other);
+        checkPath();
+        check(path.resolve(other), expected);
+        return this;
+    }
+
+    PathOps relativize(String other, String expected) {
+        out.format("test relativize %s\n", other);
+        checkPath();
+        Path that = fs.getPath(other);
+        check(path.relativize(that), expected);
+        return this;
+    }
+
+    PathOps normalize(String expected) {
+        out.println("check normalized path");
+        checkPath();
+        check(path.normalize(), expected);
+        return this;
+    }
+
+    PathOps string(String expected) {
+        out.println("check string representation");
+        checkPath();
+        check(path, expected);
+        return this;
+    }
+
+    PathOps invalid() {
+        if (!(exc instanceof InvalidPathException)) {
+            out.println("InvalidPathException not thrown as expected");
+            fail();
+        }
+        return this;
+    }
+
+    static PathOps test(String s) {
+        return new PathOps(s);
+    }
+
+    // -- PathOpss --
+
+    static void header(String s) {
+        out.println();
+        out.println();
+        out.println("-- " + s + " --");
+    }
+
+    static void doPathOpTests() {
+        header("Path operations");
+
+        // all components
+        test("/a/b/c")
+            .root("/")
+            .parent("/a/b")
+            .name("c");
+
+        // root component only
+        test("/")
+            .root("/")
+            .parent(null)
+            .name(null);
+
+        // no root component
+        test("a/b")
+            .root(null)
+            .parent("a")
+            .name("b");
+
+        // name component only
+        test("foo")
+            .root(null)
+            .parent(null)
+            .name("foo");
+
+        // startsWith
+        test("/")
+            .starts("/")
+            .notStarts("/foo");
+        test("/foo")
+            .starts("/")
+            .starts("/foo")
+            .notStarts("/f");
+        test("/foo/bar")
+            .starts("/")
+            .starts("/foo")
+            .starts("/foo/bar")
+            .notStarts("/f")
+            .notStarts("foo")
+            .notStarts("foo/bar");
+        test("foo")
+            .starts("foo")
+            .notStarts("f");
+        test("foo/bar")
+            .starts("foo")
+            .starts("foo/bar")
+            .notStarts("f")
+            .notStarts("/foo")
+            .notStarts("/foo/bar");
+
+        // endsWith
+        test("/")
+            .ends("/")
+            .notEnds("foo")
+            .notEnds("/foo");
+        test("/foo")
+            .ends("foo")
+            .ends("/foo")
+            .notEnds("/");
+        test("/foo/bar")
+            .ends("bar")
+            .ends("foo/bar")
+            .ends("/foo/bar")
+            .notEnds("/bar");
+        test("foo")
+            .ends("foo");
+        test("foo/bar")
+            .ends("bar")
+            .ends("foo/bar");
+
+        // elements
+        test("a/b/c")
+            .element(0,"a")
+            .element(1,"b")
+            .element(2,"c");
+
+        // isAbsolute
+        test("/")
+            .absolute();
+        test("/tmp")
+            .absolute();
+        test("tmp")
+            .notAbsolute();
+
+        // resolve
+        test("/tmp")
+            .resolve("foo", "/tmp/foo")
+            .resolve("/foo", "/foo");
+        test("tmp")
+            .resolve("foo", "tmp/foo")
+            .resolve("/foo", "/foo");
+
+        // relativize
+        test("/a/b/c")
+            .relativize("/a/b/c", null)
+            .relativize("/a/b/c/d/e", "d/e")
+            .relativize("/a/x", "../../x");
+
+        // normalize
+        test("/")
+            .normalize("/");
+        test("foo")
+            .normalize("foo");
+        test("/foo")
+            .normalize("/foo");
+        test(".")
+            .normalize(null);
+        test("..")
+            .normalize("..");
+        test("/..")
+            .normalize("/");
+        test("/../..")
+            .normalize("/");
+        test("foo/.")
+            .normalize("foo");
+        test("./foo")
+            .normalize("foo");
+        test("foo/..")
+            .normalize(null);
+        test("../foo")
+            .normalize("../foo");
+        test("../../foo")
+            .normalize("../../foo");
+        test("foo/bar/..")
+            .normalize("foo");
+        test("foo/bar/gus/../..")
+            .normalize("foo");
+        test("/foo/bar/gus/../..")
+            .normalize("/foo");
+
+        // invalid
+        test("foo\u0000bar")
+            .invalid();
+        test("\u0000foo")
+            .invalid();
+        test("bar\u0000")
+            .invalid();
+        test("//foo\u0000bar")
+            .invalid();
+        test("//\u0000foo")
+            .invalid();
+        test("//bar\u0000")
+            .invalid();
+
+        // normalization
+        test("//foo//bar")
+            .string("/foo/bar")
+            .root("/")
+            .parent("/foo")
+            .name("bar");
+    }
+
+    static void npes() {
+        header("NullPointerException");
+
+        Path path = fs.getPath("foo");
+
+        try {
+            path.resolve((String)null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.relativize(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.compareTo(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.startsWith(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+        try {
+            path.endsWith(null);
+            throw new RuntimeException("NullPointerException not thrown");
+        } catch (NullPointerException npe) {
+        }
+
+    }
+
+    public static void main(String[] args) throws Throwable {
+
+        Path zipfile = Paths.get(args[0]);
+        Map<String,?> env = new HashMap<String,Object>();
+        fs = FileSystems.newFileSystem(zipfile, env, null);
+        npes();
+        doPathOpTests();
+        fs.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/demo/zipfs/ZipFSTester.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,633 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.net.*;
+import java.util.*;
+
+import static java.nio.file.StandardOpenOption.*;
+import static java.nio.file.StandardCopyOption.*;
+
+/*
+ * Tests various zipfs operations.
+ */
+
+public class ZipFSTester {
+
+    public static void main(String[] args) throws Throwable {
+        FileSystem fs = null;
+        try {
+            fs = newZipFileSystem(Paths.get(args[0]), new HashMap<String, Object>());
+            test(fs);
+            test2(fs);   // more tests
+        } finally {
+            if (fs != null)
+                fs.close();
+        }
+    }
+
+    static void test(FileSystem fs)
+        throws Exception
+    {
+        Random rdm = new Random();
+
+        // clone a fs and test on it
+        Path tmpfsPath = getTempPath();
+        Map<String, Object> env = new HashMap<String, Object>();
+        env.put("createNew", true);
+        FileSystem fs0 = newZipFileSystem(tmpfsPath, env);
+        z2zcopy(fs, fs0, "/", 0);
+        fs0.close();                // sync to file
+
+        fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>());
+
+        try {
+            // prepare a src
+            Path src = getTempPath();
+            String tmpName = src.toString();
+            OutputStream os = src.newOutputStream();
+            byte[] bits = new byte[12345];
+            rdm.nextBytes(bits);
+            os.write(bits);
+            os.close();
+
+            // copyin
+            Path dst = getPathWithParents(fs, tmpName);
+            src.copyTo(dst);
+            checkEqual(src, dst);
+
+            // copy
+            Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) +
+                                           "/efg" + rdm.nextInt(100) + "/foo.class");
+            dst.copyTo(dst2);
+            //dst.moveTo(dst2);
+            checkEqual(src, dst2);
+
+            // delete
+            dst.delete();
+            if (dst.exists())
+                throw new RuntimeException("Failed!");
+
+            // moveout
+            Path dst3 = Paths.get(tmpName + "_Tmp");
+            dst2.moveTo(dst3);
+            checkEqual(src, dst3);
+
+            // delete
+            if (dst2.exists())
+                throw new RuntimeException("Failed!");
+            dst3.delete();
+            if (dst3.exists())
+                throw new RuntimeException("Failed!");
+
+            // newInputStream on dir
+            Path parent = dst2.getParent();
+            try {
+                parent.newInputStream();
+                throw new RuntimeException("Failed");
+            } catch (FileSystemException e) {
+                e.printStackTrace();    // expected fse
+            }
+
+            // rmdirs
+            try {
+                rmdirs(parent);
+            } catch (IOException x) {
+                x.printStackTrace();
+            }
+
+            // newFileChannel() copy in, out and verify via fch
+            fchCopy(src, dst);    // in
+            checkEqual(src, dst);
+            Path tmp = Paths.get(tmpName + "_Tmp");
+            fchCopy(dst, tmp);   //  out
+            checkEqual(src, tmp);
+            tmp.delete();
+
+            // test channels
+            channel(fs, dst);
+            dst.delete();
+            src.delete();
+        } finally {
+            if (fs != null)
+                fs.close();
+            if (tmpfsPath.exists())
+                tmpfsPath.delete();
+        }
+    }
+
+    static void test2(FileSystem fs) throws Exception {
+
+        Path fs1Path = getTempPath();
+        Path fs2Path = getTempPath();
+        Path fs3Path = getTempPath();
+
+        if (fs1Path.exists())
+            fs1Path.delete();
+        if (fs2Path.exists())
+            fs2Path.delete();
+        if (fs3Path.exists())
+            fs3Path.delete();
+
+        // create a new filesystem, copy everything from fs
+        Map<String, Object> env = new HashMap<String, Object>();
+        env.put("createNew", true);
+        FileSystem fs0 = newZipFileSystem(fs1Path, env);
+
+        final FileSystem fs2 = newZipFileSystem(fs2Path, env);
+        final FileSystem fs3 = newZipFileSystem(fs3Path, env);
+
+        System.out.println("copy src: fs -> fs0...");
+        z2zcopy(fs, fs0, "/", 0);   // copy fs -> fs1
+        fs0.close();                // dump to file
+
+        System.out.println("open fs0 as fs1");
+        env = new HashMap<String, Object>();
+        final FileSystem fs1 = newZipFileSystem(fs1Path, env);
+
+        System.out.println("listing...");
+        final ArrayList<String> files = new ArrayList<>();
+        final ArrayList<String> dirs = new ArrayList<>();
+        list(fs1.getPath("/"), files, dirs);
+
+        Thread t0 = new Thread(new Runnable() {
+            public void run() {
+                List<String> list = new ArrayList<>(dirs);
+                Collections.shuffle(list);
+                for (String path : list) {
+                    try {
+                        z2zcopy(fs1, fs2, path, 0);
+                    } catch (Exception x) {
+                        x.printStackTrace();
+                    }
+                }
+            }
+
+        });
+
+        Thread t1 = new Thread(new Runnable() {
+            public void run() {
+                List<String> list = new ArrayList<>(dirs);
+                Collections.shuffle(list);
+                for (String path : list) {
+                    try {
+                        z2zcopy(fs1, fs2, path, 1);
+                    } catch (Exception x) {
+                        x.printStackTrace();
+                    }
+                }
+            }
+
+        });
+
+        Thread t2 = new Thread(new Runnable() {
+            public void run() {
+                List<String> list = new ArrayList<>(dirs);
+                Collections.shuffle(list);
+                for (String path : list) {
+                    try {
+                        z2zcopy(fs1, fs2, path, 2);
+                    } catch (Exception x) {
+                        x.printStackTrace();
+                    }
+                }
+            }
+
+        });
+
+        Thread t3 = new Thread(new Runnable() {
+            public void run() {
+                List<String> list = new ArrayList<>(files);
+                Collections.shuffle(list);
+                while (!list.isEmpty()) {
+                    Iterator<String> itr = list.iterator();
+                    while (itr.hasNext()) {
+                        String path = itr.next();
+                        try {
+                            if (fs2.getPath(path).exists()) {
+                                z2zmove(fs2, fs3, path);
+                                itr.remove();
+                            }
+                        } catch (FileAlreadyExistsException x){
+                            itr.remove();
+                        } catch (Exception x) {
+                            x.printStackTrace();
+                        }
+                    }
+                }
+            }
+
+        });
+
+        System.out.println("copying/removing...");
+        t0.start(); t1.start(); t2.start(); t3.start();
+        t0.join(); t1.join(); t2.join(); t3.join();
+
+        System.out.println("closing: fs1, fs2");
+        fs1.close();
+        fs2.close();
+
+        int failed = 0;
+        System.out.println("checkEqual: fs vs fs3");
+        for (String path : files) {
+            try {
+                checkEqual(fs.getPath(path), fs3.getPath(path));
+            } catch (IOException x) {
+                //x.printStackTrace();
+                failed++;
+            }
+        }
+        System.out.println("closing: fs3");
+        fs3.close();
+
+        System.out.println("opening: fs3 as fs4");
+        FileSystem fs4 = newZipFileSystem(fs3Path, env);
+
+
+        ArrayList<String> files2 = new ArrayList<>();
+        ArrayList<String> dirs2 = new ArrayList<>();
+        list(fs4.getPath("/"), files2, dirs2);
+
+        System.out.println("checkEqual: fs vs fs4");
+        for (String path : files2) {
+            checkEqual(fs.getPath(path), fs4.getPath(path));
+        }
+        System.out.println("walking: fs4");
+        walk(fs4.getPath("/"));
+        System.out.println("closing: fs4");
+        fs4.close();
+
+        System.out.printf("failed=%d%n", failed);
+
+        fs1Path.delete();
+        fs2Path.delete();
+        fs3Path.delete();
+    }
+
+    private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
+        throws IOException
+    {
+        return FileSystems.newFileSystem(
+                   URI.create("zip" +
+                               path.toUri().toString().substring(4)),
+                   env,
+                   null);
+    }
+
+    private static Path getTempPath() throws IOException
+    {
+        File tmp = File.createTempFile("testzipfs_", "zip");
+        tmp.delete();    // we need a clean path, no file
+        return tmp.toPath();
+    }
+
+    private static void list(Path path, List<String> files, List<String> dirs )
+        throws IOException
+    {
+        if (Attributes.readBasicFileAttributes(path).isDirectory()) {
+            DirectoryStream<Path> ds = path.newDirectoryStream();
+            for (Path child : ds)
+                list(child, files, dirs);
+            ds.close();
+            dirs.add(path.toString());
+        } else {
+            files.add(path.toString());
+        }
+    }
+
+    private static void z2zcopy(FileSystem src, FileSystem dst, String path,
+                                int method)
+        throws IOException
+    {
+        Path srcPath = src.getPath(path);
+        Path dstPath = dst.getPath(path);
+
+        if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) {
+            if (!dstPath.exists()) {
+                try {
+                    mkdirs(dstPath);
+                } catch (FileAlreadyExistsException x) {}
+            }
+            DirectoryStream<Path> ds = srcPath.newDirectoryStream();
+            for (Path child : ds) {
+                z2zcopy(src, dst,
+                        path + (path.endsWith("/")?"":"/") + child.getName(),
+                        method);
+            }
+            ds.close();
+        } else {
+            try {
+                if (dstPath.exists())
+                    return;
+                switch (method) {
+                case 0:
+                    srcPath.copyTo(dstPath);
+                    break;
+                case 1:
+                    chCopy(srcPath, dstPath);
+                    break;
+                case 2:
+                    //fchCopy(srcPath, dstPath);
+                    streamCopy(srcPath, dstPath);
+                    break;
+                }
+            } catch (FileAlreadyExistsException x) {}
+        }
+    }
+
+    private static void z2zmove(FileSystem src, FileSystem dst, String path)
+        throws IOException
+    {
+        Path srcPath = src.getPath(path);
+        Path dstPath = dst.getPath(path);
+
+        if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) {
+            if (!dstPath.exists())
+                mkdirs(dstPath);
+            DirectoryStream<Path> ds = srcPath.newDirectoryStream();
+            for (Path child : ds) {
+                z2zmove(src, dst,
+                        path + (path.endsWith("/")?"":"/") + child.getName());
+            }
+            ds.close();
+        } else {
+            //System.out.println("moving..." + path);
+            Path parent = dstPath.getParent();
+            if (parent != null && parent.notExists())
+                mkdirs(parent);
+            srcPath.moveTo(dstPath);
+        }
+    }
+
+    private static void walk(Path path) throws IOException
+    {
+        Files.walkFileTree(
+            path,
+            new SimpleFileVisitor<Path>() {
+                private int indent = 0;
+                private void indent() {
+                    int n = 0;
+                    while (n++ < indent)
+                        System.out.printf(" ");
+                }
+
+                @Override
+                public FileVisitResult visitFile(Path file,
+                                                 BasicFileAttributes attrs)
+                {
+                    indent();
+                    System.out.printf("%s%n", file.getName().toString());
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult preVisitDirectory(Path dir,
+                                                         BasicFileAttributes attrs)
+                {
+                    indent();
+                    System.out.printf("[%s]%n", dir.toString());
+                    indent += 2;
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult postVisitDirectory(Path dir,
+                                                          IOException ioe)
+                    throws IOException
+                {
+                    indent -= 2;
+                    return FileVisitResult.CONTINUE;
+                }
+        });
+    }
+
+    private static void mkdirs(Path path) throws IOException {
+        path = path.toAbsolutePath();
+        Path parent = path.getParent();
+        if (parent != null) {
+            if (parent.notExists())
+                mkdirs(parent);
+        }
+        path.createDirectory();
+    }
+
+    private static void rmdirs(Path path) throws IOException {
+        while (path != null && path.getNameCount() != 0) {
+            path.delete();
+            path = path.getParent();
+        }
+    }
+
+    // check the content of two paths are equal
+    private static void checkEqual(Path src, Path dst) throws IOException
+    {
+        //System.out.printf("checking <%s> vs <%s>...%n",
+        //                  src.toString(), dst.toString());
+
+        //streams
+        InputStream isSrc = src.newInputStream();
+        InputStream isDst = dst.newInputStream();
+        byte[] bufSrc = new byte[8192];
+        byte[] bufDst = new byte[8192];
+
+        try {
+            int nSrc = 0;
+            while ((nSrc = isSrc.read(bufSrc)) != -1) {
+                int nDst = 0;
+                while (nDst < nSrc) {
+                    int n = isDst.read(bufDst, nDst, nSrc - nDst);
+                    if (n == -1) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nDst += n;
+                }
+                while (--nSrc >= 0) {
+                    if (bufSrc[nSrc] != bufDst[nSrc]) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nSrc--;
+                }
+            }
+        } finally {
+            isSrc.close();
+            isDst.close();
+        }
+
+        // channels
+        SeekableByteChannel chSrc = src.newByteChannel();
+        SeekableByteChannel chDst = dst.newByteChannel();
+        if (chSrc.size() != chDst.size()) {
+            System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
+                              chSrc.toString(), chSrc.size(),
+                              chDst.toString(), chDst.size());
+            throw new RuntimeException("CHECK FAILED!");
+        }
+        ByteBuffer bbSrc = ByteBuffer.allocate(8192);
+        ByteBuffer bbDst = ByteBuffer.allocate(8192);
+
+        try {
+            int nSrc = 0;
+            while ((nSrc = chSrc.read(bbSrc)) != -1) {
+                int nDst = chDst.read(bbDst);
+                if (nSrc != nDst) {
+                    System.out.printf("checking <%s> vs <%s>...%n",
+                                      src.toString(), dst.toString());
+                    throw new RuntimeException("CHECK FAILED!");
+                }
+                while (--nSrc >= 0) {
+                    if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
+                        System.out.printf("checking <%s> vs <%s>...%n",
+                                          src.toString(), dst.toString());
+                        throw new RuntimeException("CHECK FAILED!");
+                    }
+                    nSrc--;
+                }
+                bbSrc.flip();
+                bbDst.flip();
+            }
+        } catch (IOException x) {
+            x.printStackTrace();
+        } finally {
+            chSrc.close();
+            chDst.close();
+        }
+    }
+
+    private static void fchCopy(Path src, Path dst) throws IOException
+    {
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        Set<OpenOption> openwrite = new HashSet<>();
+        openwrite.add(CREATE_NEW);
+        openwrite.add(WRITE);
+
+        FileChannel srcFc = src.getFileSystem()
+                               .provider()
+                               .newFileChannel(src, read);
+        FileChannel dstFc = dst.getFileSystem()
+                               .provider()
+                               .newFileChannel(dst, openwrite);
+
+        try {
+            ByteBuffer bb = ByteBuffer.allocate(8192);
+            while (srcFc.read(bb) >= 0) {
+                bb.flip();
+                dstFc.write(bb);
+                bb.clear();
+            }
+        } finally {
+            srcFc.close();
+            dstFc.close();
+        }
+    }
+
+    private static void chCopy(Path src, Path dst) throws IOException
+    {
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        Set<OpenOption> openwrite = new HashSet<>();
+        openwrite.add(CREATE_NEW);
+        openwrite.add(WRITE);
+
+        SeekableByteChannel srcCh = src.newByteChannel(read);
+        SeekableByteChannel dstCh = dst.newByteChannel(openwrite);
+
+        try {
+            ByteBuffer bb = ByteBuffer.allocate(8192);
+            while (srcCh.read(bb) >= 0) {
+                bb.flip();
+                dstCh.write(bb);
+                bb.clear();
+            }
+        } finally {
+            srcCh.close();
+            dstCh.close();
+        }
+    }
+
+    private static void streamCopy(Path src, Path dst) throws IOException
+    {
+        InputStream isSrc = src.newInputStream();
+        OutputStream osDst = dst.newOutputStream();
+        byte[] buf = new byte[8192];
+        try {
+            int n = 0;
+            while ((n = isSrc.read(buf)) != -1) {
+                osDst.write(buf, 0, n);
+            }
+        } finally {
+            isSrc.close();
+            osDst.close();
+        }
+    }
+
+    static void channel(FileSystem fs, Path path)
+        throws Exception
+    {
+        System.out.println("test ByteChannel...");
+        SeekableByteChannel sbc = path.newByteChannel();
+        Set<OpenOption> read = new HashSet<>();
+        read.add(READ);
+        System.out.printf("   sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size());
+        ByteBuffer bb = ByteBuffer.allocate((int)sbc.size());
+        int n = sbc.read(bb);
+        System.out.printf("   sbc[1]: read=%d, pos=%d, size=%d%n",
+                          n, sbc.position(), sbc.size());
+        ByteBuffer bb2 = ByteBuffer.allocate((int)sbc.size());
+        int N = 120;
+        sbc.close();
+
+        // sbc.position(pos) is not supported in current version
+        // try the FileChannel
+        sbc = fs.provider().newFileChannel(path, read);
+        sbc.position(N);
+        System.out.printf("   sbc[2]: pos=%d, size=%d%n",
+                          sbc.position(), sbc.size());
+        bb2.limit(100);
+        n = sbc.read(bb2);
+        System.out.printf("   sbc[3]: read=%d, pos=%d, size=%d%n",
+                          n, sbc.position(), sbc.size());
+        System.out.printf("   sbc[4]: bb[%d]=%d, bb1[0]=%d%n",
+                          N, bb.get(N) & 0xff, bb2.get(0) & 0xff);
+        sbc.close();
+    }
+
+    // create parents if does not exist
+    static Path getPathWithParents(FileSystem fs, String name)
+        throws Exception
+    {
+        Path path = fs.getPath(name);
+        Path parent = path.getParent();
+        if (parent != null && parent.notExists())
+            mkdirs(parent);
+        return path;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/demo/zipfs/basic.sh	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,73 @@
+#
+# Copyright (c) 2009, 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.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please 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 6990846
+# @summary Test ZipFileSystem demo
+# @build Basic PathOps ZipFSTester
+# @run shell basic.sh
+
+if [ -z "${TESTJAVA}" ]; then
+    echo "Test must be run with jtreg"
+    exit 0
+fi
+
+ZIPFS="${TESTJAVA}/demo/nio/zipfs/zipfs.jar"
+if [ ! -r "${ZIPFS}" ]; then
+    echo "${ZIPFS} not found"
+    exit 0
+fi
+
+OS=`uname -s`
+case "$OS" in
+    Windows_* )
+        CLASSPATH="${TESTCLASSES};${ZIPFS}"
+        ;;
+    * )
+        CLASSPATH="${TESTCLASSES}:${ZIPFS}"
+        ;;
+esac
+export CLASSPATH
+
+failures=0
+
+go() {
+    echo ""
+    ${TESTJAVA}/bin/java $1 $2 $3 2>&1
+    if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+}
+
+# Run the tests
+
+go Basic "${ZIPFS}"
+go PathOps "${ZIPFS}"
+go ZipFSTester "${ZIPFS}"
+
+#
+# Results
+#
+
+if [ $failures -gt 0 ];
+then echo "$failures tests failed";
+else echo "All tests passed";
+fi
+exit $failures
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 1995, 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.
+ */
+
+/*
+  @test      FocusOwnerFrameOnClick.java %W% %E%
+  @bug       6886678
+  @summary   Tests that clicking an owner frame switches focus from its owned window.
+  @author    Anton Tarasov: area=awt.focus
+  @library   ../../regtesthelpers
+  @build     Util
+  @run       main FocusOwnerFrameOnClick
+*/
+
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.Applet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.lang.reflect.InvocationTargetException;
+import test.java.awt.regtesthelpers.Util;
+
+public class FocusOwnerFrameOnClick extends Applet {
+    Robot robot;
+    Frame frame = new Frame("Frame");
+    Window window = new Window(frame);
+    Button fButton = new Button("fButton");
+    Button wButton = new Button("wButton");
+
+    AtomicBoolean focused = new AtomicBoolean(false);
+
+    public static void main(String[] args) {
+        FocusOwnerFrameOnClick app = new FocusOwnerFrameOnClick();
+        app.init();
+        app.start();
+    }
+
+    public void init() {
+        robot = Util.createRobot();
+
+        frame.setLayout(new FlowLayout());
+        frame.setSize(200, 200);
+        frame.add(fButton);
+
+        window.setLocation(300, 0);
+        window.add(wButton);
+        window.pack();
+    }
+
+    public void start() {
+        frame.setVisible(true);
+        Util.waitForIdle(robot);
+
+        window.setVisible(true);
+        Util.waitForIdle(robot);
+
+        if (!wButton.hasFocus()) {
+            if (!Util.trackFocusGained(wButton, new Runnable() {
+                    public void run() {
+                        Util.clickOnComp(wButton, robot);
+                    }
+                }, 2000, false))
+            {
+                throw new TestErrorException("wButton didn't gain focus on showing");
+            }
+        }
+
+        Runnable clickAction = new Runnable() {
+                public void run() {
+                    Point loc = fButton.getLocationOnScreen();
+                    Dimension dim = fButton.getSize();
+
+                    robot.mouseMove(loc.x, loc.y + dim.height + 20);
+                    robot.delay(50);
+                    robot.mousePress(InputEvent.BUTTON1_MASK);
+                    robot.delay(50);
+                    robot.mouseRelease(InputEvent.BUTTON1_MASK);
+                }
+            };
+
+        if (!Util.trackWindowGainedFocus(frame, clickAction, 2000, true)) {
+            throw new TestFailedException("The frame wasn't focused on click");
+        }
+
+        System.out.println("Test passed.");
+    }
+}
+
+/**
+ * Thrown when the behavior being verified is found wrong.
+ */
+class TestFailedException extends RuntimeException {
+    TestFailedException(String msg) {
+        super("Test failed: " + msg);
+    }
+}
+
+/**
+ * Thrown when an error not related to the behavior being verified is encountered.
+ */
+class TestErrorException extends RuntimeException {
+    TestErrorException(String msg) {
+        super("Unexpected error: " + msg);
+    }
+}
--- a/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Extra.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Extra.java	Wed Jul 05 17:24:13 2017 +0200
@@ -21,16 +21,15 @@
     static final int SHIFT = 1;
     static final int CTRL = 2;
     static final int ALT = 3;
-    static CheckingModifierAdapter adapterTest1;
-    static CheckingModifierAdapter adapterTest2;
-    static CheckingModifierAdapter adapterTest3;
-    static CheckingModifierAdapter adapterTest4;
+    static CheckingModifierAdapterExtra adapterTest1;
+    static CheckingModifierAdapterExtra adapterTest2;
+    static CheckingModifierAdapterExtra adapterTest3;
+    static CheckingModifierAdapterExtra adapterTest4;
 
     static boolean debug = true; //dump all errors (debug) or throw first(under jtreg) exception
     static boolean autorun = false; //use robot or manual run
     static int testModifier = NONE;
 
-    static int [] mouseButtons;
     static int [] mouseButtonDownMasks;
 
     //an arrays representing a modifiersEx of extra mouse buttons while using ALT/CTRL/SHIFT or none of them
@@ -39,7 +38,6 @@
     static int [] modifiersExStandardCTRL;
     static int [] modifiersExStandardALT;
 
-    //    final static int [] mouseButtons = new int [] {MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON3_MASK};
     // BUTTON1, 2, 3 press-release.
     final static int  modifiersStandard = 0; //InputEvent.BUTTON_DOWN_MASK;
 
@@ -56,7 +54,7 @@
 
         if (modifiersEx != curStandardExModifiers[index]){
 //            System.out.println(">>>>>>>>>>>>>>> Pressed. modifiersEx "+modifiersEx +" : "+!= curStandardExModifiers");
-            MessageLogger.reportError("Test failed :  Pressed. modifiersEx != curStandardExModifiers");
+            MessageLogger.reportError("Test failed :  Pressed. modifiersEx != curStandardExModifiers. Got: " + modifiersEx + " , Expected: " + curStandardExModifiers[index]);
         }
 
      //check event.paramString() output
@@ -168,7 +166,7 @@
         }
 
         if (modifiersEx != curStandardExModifiers[index]){
-            MessageLogger.reportError("Test failed :  Released. modifiersEx != curStandardExModifiers");
+            MessageLogger.reportError("Test failed :  Released. modifiersEx != curStandardExModifiers. Got: " + modifiersEx + " , Expected: " + curStandardExModifiers[index]);
         }
 
      //check event.paramString() output
@@ -191,7 +189,7 @@
         }
 
         if (modifiersEx != curStandardExModifiers[index]){
-            MessageLogger.reportError("Test failed :  Clicked. modifiersEx != curStandardExModifiers");
+            MessageLogger.reportError("Test failed :  Clicked. modifiersEx != curStandardExModifiers. Got: " + modifiersEx + " , Expected: " + curStandardExModifiers[index]);
         }
 
      //check event.paramString() output
@@ -275,11 +273,11 @@
         this.addMouseListener(adapterTest1);
         robot.delay(1000);
         robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
-        for (int i = 3; i< mouseButtons.length; i++){
-            System.out.println("testNONE() => " +mouseButtons[i] );
-            robot.mousePress(mouseButtons[i]);
+        for (int i = 3; i< mouseButtonDownMasks.length; i++){
+            System.out.println("testNONE() => " +mouseButtonDownMasks[i] );
+            robot.mousePress(mouseButtonDownMasks[i]);
             robot.delay(100);
-            robot.mouseRelease(mouseButtons[i]);
+            robot.mouseRelease(mouseButtonDownMasks[i]);
         }
         robot.delay(1000);
         this.removeMouseListener(adapterTest1);
@@ -289,12 +287,12 @@
         this.addMouseListener(adapterTest2);
         robot.delay(1000);
         robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
-        for (int i = 3; i< mouseButtons.length; i++){
+        for (int i = 3; i< mouseButtonDownMasks.length; i++){
             robot.keyPress(KeyEvent.VK_SHIFT);
-            System.out.println("testSHIFT() => " +mouseButtons[i] );
-            robot.mousePress(mouseButtons[i]);
+            System.out.println("testSHIFT() => " +mouseButtonDownMasks[i] );
+            robot.mousePress(mouseButtonDownMasks[i]);
             robot.delay(100);
-            robot.mouseRelease(mouseButtons[i]);
+            robot.mouseRelease(mouseButtonDownMasks[i]);
             robot.keyRelease(KeyEvent.VK_SHIFT);
         }
         robot.delay(1000);
@@ -305,12 +303,12 @@
         this.addMouseListener(adapterTest3);
         robot.delay(1000);
         robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
-        for (int i = 3; i< mouseButtons.length; i++){
+        for (int i = 3; i< mouseButtonDownMasks.length; i++){
             robot.keyPress(KeyEvent.VK_CONTROL);
-            System.out.println("testCTRL() => " +mouseButtons[i] );
-            robot.mousePress(mouseButtons[i]);
+            System.out.println("testCTRL() => " +mouseButtonDownMasks[i] );
+            robot.mousePress(mouseButtonDownMasks[i]);
             robot.delay(100);
-            robot.mouseRelease(mouseButtons[i]);
+            robot.mouseRelease(mouseButtonDownMasks[i]);
             robot.keyRelease(KeyEvent.VK_CONTROL);
         }
         robot.delay(1000);
@@ -321,12 +319,12 @@
         this.addMouseListener(adapterTest4);
         robot.delay(1000);
         robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2);
-        for (int i = 3; i< mouseButtons.length; i++){
+        for (int i = 3; i< mouseButtonDownMasks.length; i++){
             robot.keyPress(KeyEvent.VK_ALT);
-            System.out.println("testALT() => " +mouseButtons[i] );
-            robot.mousePress(mouseButtons[i]);
+            System.out.println("testALT() => " +mouseButtonDownMasks[i] );
+            robot.mousePress(mouseButtonDownMasks[i]);
             robot.delay(100);
-            robot.mouseRelease(mouseButtons[i]);
+            robot.mouseRelease(mouseButtonDownMasks[i]);
             robot.keyRelease(KeyEvent.VK_ALT);
         }
         robot.delay(1000);
@@ -368,52 +366,52 @@
     }
 
     public static void initAdapters(){
-        adapterTest1 = new CheckingModifierAdapter(NONE);
-        adapterTest2 = new CheckingModifierAdapter(SHIFT);
-        adapterTest3 = new CheckingModifierAdapter(CTRL);
-        adapterTest4 = new CheckingModifierAdapter(ALT);
+        adapterTest1 = new CheckingModifierAdapterExtra(NONE);
+        adapterTest2 = new CheckingModifierAdapterExtra(SHIFT);
+        adapterTest3 = new CheckingModifierAdapterExtra(CTRL);
+        adapterTest4 = new CheckingModifierAdapterExtra(ALT);
     }
 
     public static void initVars(){
-        int [] tmp = new int [MouseInfo.getNumberOfButtons()];
-        for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){
-            tmp[i] = InputEvent.getMaskForButton(i+1);
-            //            System.out.println("TEST: "+tmp[i]);
+        //Init the array of the mouse button masks. It will be used for generating mouse events.
+        mouseButtonDownMasks = new int [MouseInfo.getNumberOfButtons()];
+        for (int i = 0; i < mouseButtonDownMasks.length; i++){
+            mouseButtonDownMasks[i] = InputEvent.getMaskForButton(i+1);
+            System.out.println("MouseArray [i] == "+mouseButtonDownMasks[i]);
         }
 
-        mouseButtons = Arrays.copyOf(tmp, tmp.length);
-
-        for (int i = 0; i < mouseButtons.length; i++){
-            System.out.println("MouseArray [i] == "+mouseButtons[i]);
-        }
-
-        mouseButtonDownMasks = Arrays.copyOf(tmp, tmp.length);
-
         // So we need to get the number of extra buttons on the mouse:  "MouseInfo.getNumberOfButtons() - 3"
         // and multyply on 3 because each button will generate three events : PRESS, RELEASE and CLICK.
-        tmp = new int [(MouseInfo.getNumberOfButtons()-3)*3];
+        int [] tmp = new int [(MouseInfo.getNumberOfButtons()-3)*3];
+
+        //Fill array of expected results for the case when mouse buttons are only used (no-modifier keys)
         Arrays.fill(tmp, 0);
-
         for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
             tmp[i] = mouseButtonDownMasks[j];
         }
         modifiersExStandard = Arrays.copyOf(tmp, tmp.length);
 
+        //Fill array of expected results for the case when mouse buttons are only used with SHIFT modifier key
         Arrays.fill(tmp, InputEvent.SHIFT_DOWN_MASK);
-        for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){
-            tmp[i] = tmp[j] | mouseButtonDownMasks[j];
+        for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
+            System.out.println("modifiersExStandardSHIFT FILLING : " + tmp[i] + " + " + mouseButtonDownMasks[j]);
+            tmp[i] = tmp[i] | mouseButtonDownMasks[j];
         }
         modifiersExStandardSHIFT = Arrays.copyOf(tmp, tmp.length);
 
+        //Fill array of expected results for the case when mouse buttons are only used with CTRL modifier key
         Arrays.fill(tmp, InputEvent.CTRL_DOWN_MASK);
-        for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){
-            tmp[i] = tmp[j] | mouseButtonDownMasks[j];
+        for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
+            System.out.println("modifiersExStandardCTRL FILLING : " + tmp[i] + " + " + mouseButtonDownMasks[j]);
+            tmp[i] = tmp[i] | mouseButtonDownMasks[j];
         }
         modifiersExStandardCTRL = Arrays.copyOf(tmp, tmp.length);
 
+        //Fill array of expected results for the case when mouse buttons are only used with ALT modifier key
         Arrays.fill(tmp, InputEvent.ALT_DOWN_MASK);
-        for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){
-            tmp[i] = tmp[j] | mouseButtonDownMasks[j];
+        for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){
+            System.out.println("modifiersExStandardALT FILLING : " + tmp[i] + " + " + mouseButtonDownMasks[j]);
+            tmp[i] = tmp[i] | mouseButtonDownMasks[j];
         }
         modifiersExStandardALT = Arrays.copyOf(tmp, tmp.length);
     }
@@ -436,9 +434,9 @@
 /* A class that invoke appropriate verification
  * routine with current modifier.
  */
-class CheckingModifierAdapter extends MouseAdapter{
+class CheckingModifierAdapterExtra extends MouseAdapter{
     int modifier;
-    public CheckingModifierAdapter(int modifier){
+    public CheckingModifierAdapterExtra(int modifier){
         this.modifier = modifier;
     }
 
--- a/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java	Wed Jul 05 17:24:13 2017 +0200
@@ -90,7 +90,7 @@
         int [] buttonMasks = new int[MouseInfo.getNumberOfButtons()]; // = InputEvent.getButtonDownMasks();
         for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){
             buttonMasks[i] = InputEvent.getMaskForButton(i+1);
-            System.out.println("TEST: "+buttonMasks[i]);
+            System.out.println("TEST: buttonMasks["+ i +"] = " + buttonMasks[i]);
         }
 
         for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/GetSamplesTest.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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     6735275
+ * @summary Test verifies that SampleModel.getSamples() throws an appropriate
+ *           exception if coordinates are not in bounds.
+ *
+ * @run     main GetSamplesTest
+ */
+
+import java.awt.image.BandedSampleModel;
+import java.awt.image.ComponentSampleModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.MultiPixelPackedSampleModel;
+import java.awt.image.PixelInterleavedSampleModel;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.util.Vector;
+
+public class GetSamplesTest {
+
+    public static int width = 100;
+    public static int height = 100;
+    public static int dataType = DataBuffer.TYPE_BYTE;
+    public static int numBands = 4;
+
+    public static void main(String[] args) {
+        Vector<Class<? extends SampleModel>> classes = new Vector<Class<? extends SampleModel>>();
+
+        classes.add(ComponentSampleModel.class);
+        classes.add(MultiPixelPackedSampleModel.class);
+        classes.add(SinglePixelPackedSampleModel.class);
+        classes.add(BandedSampleModel.class);
+        classes.add(PixelInterleavedSampleModel.class);
+
+        for (Class<? extends SampleModel> c : classes) {
+            doTest(c);
+        }
+    }
+    private static void doTest(Class<? extends SampleModel> c) {
+        System.out.println("Test for: " + c.getName());
+        SampleModel sm = createSampleModel(c);
+
+        DataBuffer db = sm.createDataBuffer();
+
+        int[] iArray = new int[ width * height + numBands];
+        float[] fArray = new float[ width * height + numBands];
+        double[] dArray = new double[ width * height + numBands];
+
+        boolean iOk = false;
+        boolean fOk = false;
+        boolean dOk = false;
+
+        try {
+            sm.getSamples(Integer.MAX_VALUE, 0, 1, 1, 0, iArray, db);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            System.out.println(e.getMessage());
+            iOk = true;
+        }
+
+        try {
+            sm.getSamples(Integer.MAX_VALUE, 0, 1, 1, 0, fArray, db);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            System.out.println(e.getMessage());
+            fOk = true;
+        }
+
+        try {
+            sm.getSamples(0, Integer.MAX_VALUE, 1, 1, 0, dArray, db);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            System.out.println(e.getMessage());
+            dOk = true;
+        }
+        if (!iOk || !fOk || !dOk) {
+            throw new RuntimeException("Test for " + c.getSimpleName() +
+                    " failed: iOk=" + iOk + "; fOk=" + fOk + "; dOk=" + dOk);
+        }
+    }
+
+    private static SampleModel createSampleModel(Class<? extends SampleModel> cls) {
+        SampleModel res = null;
+
+        if (cls == ComponentSampleModel.class) {
+            res = new ComponentSampleModel(dataType, width, height, 4, width * 4, new int[] { 0, 1, 2, 3 } );
+        } else if (cls == MultiPixelPackedSampleModel.class) {
+            res = new MultiPixelPackedSampleModel(dataType, width, height, 4);
+        } else if (cls == SinglePixelPackedSampleModel.class) {
+            res = new SinglePixelPackedSampleModel(dataType, width, height,
+                    new int[]{ 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff });
+        } else if (cls == BandedSampleModel.class) {
+            res = new BandedSampleModel(dataType, width, height, numBands);
+        } else if (cls == PixelInterleavedSampleModel.class) {
+            res = new PixelInterleavedSampleModel(dataType, width, height, 4, width * 4, new int[] { 0, 1, 2, 3 });
+        } else {
+            throw new RuntimeException("Unknown class " + cls);
+        }
+        return res;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/6976577/Test6976577.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 6976577
+ * @summary Tests public methods in non-public beans
+ * @author Sergey Malenkov
+ */
+
+import test.Accessor;
+
+import java.beans.EventSetDescriptor;
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+
+public class Test6976577 {
+
+    public static void main(String[] args) throws Exception {
+        Class<?> bt = Accessor.getBeanType();
+        Class<?> lt = Accessor.getListenerType();
+
+        // test PropertyDescriptor
+        PropertyDescriptor pd = new PropertyDescriptor("boolean", bt);
+        test(pd.getReadMethod());
+        test(pd.getWriteMethod());
+
+        // test IndexedPropertyDescriptor
+        IndexedPropertyDescriptor ipd = new IndexedPropertyDescriptor("indexed", bt);
+        test(ipd.getReadMethod());
+        test(ipd.getWriteMethod());
+        test(ipd.getIndexedReadMethod());
+        test(ipd.getIndexedWriteMethod());
+
+        // test EventSetDescriptor
+        EventSetDescriptor esd = new EventSetDescriptor(bt, "test", lt, "process");
+        test(esd.getAddListenerMethod());
+        test(esd.getRemoveListenerMethod());
+        test(esd.getGetListenerMethod());
+        test(esd.getListenerMethods());
+    }
+
+    private static void test(Method... methods) {
+        for (Method method : methods) {
+            if (method == null) {
+                throw new Error("public method is not found");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/6976577/test/Accessor.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,81 @@
+package test;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.EventListener;
+import java.util.TooManyListenersException;
+
+public class Accessor {
+
+    public static Class<?> getBeanType() {
+        return Bean.class;
+    }
+
+    public static Class<?> getListenerType() {
+        return TestListener.class;
+    }
+}
+
+interface TestEvent {
+}
+
+interface TestListener extends EventListener {
+    void process(TestEvent event);
+}
+
+class Bean {
+
+    private boolean b;
+    private int[] indexed;
+    private TestListener listener;
+    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+
+    public void addPropertyChangeListener(PropertyChangeListener listener) {
+        this.pcs.addPropertyChangeListener(listener);
+    }
+
+    public void addTestListener(TestListener listener) throws TooManyListenersException {
+        if (listener != null) {
+            if (this.listener != null) {
+                throw new TooManyListenersException();
+            }
+            this.listener = listener;
+        }
+    }
+
+    public void removeTestListener(TestListener listener) {
+        if (this.listener == listener) {
+            this.listener = null;
+        }
+    }
+
+    public TestListener[] getTestListeners() {
+        return (this.listener != null)
+                ? new TestListener[] { this.listener }
+                : new TestListener[0];
+    }
+
+    public boolean isBoolean() {
+        return this.b;
+    }
+
+    public void setBoolean(boolean b) {
+        this.b = b;
+    }
+
+    public int[] getIndexed() {
+        return this.indexed;
+    }
+
+    public void setIndexed(int[] values) {
+        this.indexed = values;
+    }
+
+    public int getIndexed(int index) {
+        return this.indexed[index];
+    }
+
+    public void setIndexed(int index, int value) {
+        this.indexed[index] = value;
+    }
+}
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1825,6 +1825,64 @@
         } catch (Throwable t) { unexpected(t); }
 
         //----------------------------------------------------------------
+        // Check that subprocesses which create subprocesses of their
+        // own do not cause parent to hang waiting for file
+        // descriptors to be closed.
+        //----------------------------------------------------------------
+        try {
+            if (Unix.is()
+                && new File("/bin/bash").exists()
+                && new File("/bin/sleep").exists()) {
+                final String[] cmd = { "/bin/bash", "-c", "(/bin/sleep 6666)" };
+                final ProcessBuilder pb = new ProcessBuilder(cmd);
+                final Process p = pb.start();
+                final InputStream stdout = p.getInputStream();
+                final InputStream stderr = p.getErrorStream();
+                final OutputStream stdin = p.getOutputStream();
+                final Thread reader = new Thread() {
+                    public void run() {
+                        try { stdout.read(); }
+                        catch (IOException e) {
+                            // e.printStackTrace();
+                            if (EnglishUnix.is() &&
+                                ! (e.getMessage().matches(".*Bad file descriptor.*")))
+                                unexpected(e);
+                        }
+                        catch (Throwable t) { unexpected(t); }}};
+                reader.setDaemon(true);
+                reader.start();
+                Thread.sleep(100);
+                p.destroy();
+                // Subprocess is now dead, but file descriptors remain open.
+                check(p.waitFor() != 0);
+                check(p.exitValue() != 0);
+                stdout.close();
+                stderr.close();
+                stdin.close();
+                //----------------------------------------------------------
+                // There remain unsolved issues with asynchronous close.
+                // Here's a highly non-portable experiment to demonstrate:
+                //----------------------------------------------------------
+                if (Boolean.getBoolean("wakeupJeff!")) {
+                    System.out.println("wakeupJeff!");
+                    // Initialize signal handler for INTERRUPT_SIGNAL.
+                    new FileInputStream("/bin/sleep").getChannel().close();
+                    // Send INTERRUPT_SIGNAL to every thread in this java.
+                    String[] wakeupJeff = {
+                        "/bin/bash", "-c",
+                        "/bin/ps --noheaders -Lfp $PPID | " +
+                        "/usr/bin/perl -nale 'print $F[3]' | " +
+                        // INTERRUPT_SIGNAL == 62 on my machine du jour.
+                        "/usr/bin/xargs kill -62"
+                    };
+                    new ProcessBuilder(wakeupJeff).start().waitFor();
+                    // If wakeupJeff worked, reader probably got EBADF.
+                    reader.join();
+                }
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
         // Attempt to start process with insufficient permissions fails.
         //----------------------------------------------------------------
         try {
--- a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java	Wed Jul 05 17:24:13 2017 +0200
@@ -29,7 +29,9 @@
 
 import java.nio.channels.*;
 import java.net.*;
+import static java.net.StandardSocketOption.*;
 import java.io.IOException;
+import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicReference;
@@ -39,6 +41,7 @@
     public static void main(String[] args) throws Exception {
         testBind();
         testAccept();
+        testSocketOptions();
     }
 
     static void testBind() throws Exception {
@@ -131,4 +134,39 @@
         }
 
     }
+
+    static void testSocketOptions() throws Exception {
+        System.out.println("-- socket options --");
+        AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel.open();
+        try {
+            // check supported options
+            Set<SocketOption<?>> options = ch.supportedOptions();
+            if (!options.contains(SO_REUSEADDR))
+                throw new RuntimeException("SO_REUSEADDR should be supported");
+            if (!options.contains(SO_RCVBUF))
+                throw new RuntimeException("SO_RCVBUF should be supported");
+
+            // allowed to change when not bound
+            ch.setOption(SO_RCVBUF, 256*1024);     // can't check
+            int before = ch.getOption(SO_RCVBUF);
+            int after = ch.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
+            if (after < before)
+                 throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
+            ch.setOption(SO_REUSEADDR, true);
+            checkOption(ch, SO_REUSEADDR, true);
+            ch.setOption(SO_REUSEADDR, false);
+            checkOption(ch, SO_REUSEADDR, false);
+        } finally {
+            ch.close();
+        }
+    }
+
+    static void checkOption(AsynchronousServerSocketChannel ch,
+                            SocketOption name, Object expectedValue)
+        throws IOException
+    {
+        Object value = ch.getOption(name);
+        if (!value.equals(expectedValue))
+            throw new RuntimeException("value not as expected");
+    }
 }
--- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Wed Jul 05 17:24:13 2017 +0200
@@ -121,8 +121,20 @@
         AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()
             .setOption(SO_RCVBUF, 128*1024)
             .setOption(SO_SNDBUF, 128*1024)
-            .setOption(SO_REUSEADDR, true)
-            .bind(new InetSocketAddress(0));
+            .setOption(SO_REUSEADDR, true);
+
+        // check SO_SNDBUF/SO_RCVBUF limits
+        int before, after;
+        before = ch.getOption(SO_SNDBUF);
+        after = ch.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
+        before = ch.getOption(SO_RCVBUF);
+        after = ch.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
+
+        ch.bind(new InetSocketAddress(0));
 
         // default values
         if ((Boolean)ch.getOption(SO_KEEPALIVE))
--- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java	Wed Jul 05 17:24:13 2017 +0200
@@ -68,8 +68,17 @@
         checkOption(dc, SO_BROADCAST, true);
         dc.setOption(SO_BROADCAST, false);
         checkOption(dc, SO_BROADCAST, false);
-        dc.setOption(SO_SNDBUF, 16*1024);       // can't check
-        dc.setOption(SO_RCVBUF, 16*1024);       // can't check
+        dc.setOption(SO_SNDBUF, 128*1024);       // can't check
+        dc.setOption(SO_RCVBUF, 128*1024);       // can't check
+        int before, after;
+        before = dc.getOption(SO_SNDBUF);
+        after = dc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
+        before = dc.getOption(SO_RCVBUF);
+        after = dc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
         dc.setOption(SO_REUSEADDR, true);
         checkOption(dc, SO_REUSEADDR, true);
         dc.setOption(SO_REUSEADDR, false);
--- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java	Wed Jul 05 17:24:13 2017 +0200
@@ -56,6 +56,10 @@
 
         // allowed to change when not bound
         ssc.setOption(SO_RCVBUF, 256*1024);     // can't check
+        int before = ssc.getOption(SO_RCVBUF);
+        int after = ssc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
         ssc.setOption(SO_REUSEADDR, true);
         checkOption(ssc, SO_REUSEADDR, true);
         ssc.setOption(SO_REUSEADDR, false);
--- a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java	Wed Jul 05 17:24:13 2017 +0200
@@ -70,6 +70,15 @@
         checkOption(sc, SO_KEEPALIVE, false);
         sc.setOption(SO_SNDBUF, 128*1024);      // can't check
         sc.setOption(SO_RCVBUF, 256*1024);      // can't check
+        int before, after;
+        before = sc.getOption(SO_SNDBUF);
+        after = sc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
+        before = sc.getOption(SO_RCVBUF);
+        after = sc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
+        if (after < before)
+            throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
         sc.setOption(SO_REUSEADDR, true);
         checkOption(sc, SO_REUSEADDR, true);
         sc.setOption(SO_REUSEADDR, false);
--- a/jdk/test/java/nio/file/FileStore/Basic.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/file/FileStore/Basic.java	Wed Jul 05 17:24:13 2017 +0200
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887 6873621
+ * @bug 4313887 6873621 6979526
  * @summary Unit test for java.nio.file.FileStore
  * @library ..
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/MaxDepth.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Unit test for Files.walkFileTree to test maxDepth parameter
+ */
+
+public class MaxDepth {
+    public static void main(String[] args) throws Exception {
+        final Path top = Paths.get(args[0]);
+
+        for (int i=0; i<5; i++) {
+            Set<FileVisitOption> opts = Collections.emptySet();
+            final int maxDepth = i;
+            Files.walkFileTree(top, opts, maxDepth, new SimpleFileVisitor<Path>() {
+                // compute depth based on relative path to top directory
+                private int depth(Path file) {
+                    Path rp = file.relativize(top);
+                    return (rp == null) ? 0 : rp.getNameCount();
+                }
+
+                @Override
+                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
+                    int d = depth(dir);
+                    if (d == maxDepth)
+                        throw new RuntimeException("Should not open directories at maxDepth");
+                    if (d > maxDepth)
+                        throw new RuntimeException("Too deep");
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+                    int d = depth(file);
+                    if (d > maxDepth)
+                        throw new RuntimeException("Too deep");
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+        }
+    }
+}
--- a/jdk/test/java/nio/file/Files/Misc.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/file/Files/Misc.java	Wed Jul 05 17:24:13 2017 +0200
@@ -30,6 +30,7 @@
 
 import java.nio.file.*;
 import java.nio.file.attribute.Attributes;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.io.IOException;
 import java.util.*;
 
@@ -117,25 +118,25 @@
 
         SimpleFileVisitor<Path> visitor = new SimpleFileVisitor<Path>() { };
         boolean ranTheGauntlet = false;
-        try { visitor.preVisitDirectory(null);
+        BasicFileAttributes attrs = Attributes.readBasicFileAttributes(Paths.get("."));
+
+        try { visitor.preVisitDirectory(null, attrs);
         } catch (NullPointerException x0) {
-        try { visitor.preVisitDirectoryFailed(null, new IOException());
+        try { visitor.preVisitDirectory(dir, null);
         } catch (NullPointerException x1) {
-        try { visitor.preVisitDirectoryFailed(dir, null);
+        try { visitor.visitFile(null, attrs);
         } catch (NullPointerException x2) {
-        try { visitor.visitFile(null, Attributes.readBasicFileAttributes(Paths.get(".")));
+        try {  visitor.visitFile(dir, null);
         } catch (NullPointerException x3) {
-        try {  visitor.visitFile(dir, null);
+        try { visitor.visitFileFailed(null, new IOException());
         } catch (NullPointerException x4) {
-        try { visitor.visitFileFailed(null, new IOException());
+        try { visitor.visitFileFailed(dir, null);
         } catch (NullPointerException x5) {
-        try { visitor.visitFileFailed(dir, null);
+        try { visitor.postVisitDirectory(null, new IOException());
         } catch (NullPointerException x6) {
-        try { visitor.postVisitDirectory(null, new IOException());
-        } catch (NullPointerException x7) {
             // if we get here then all visit* methods threw NPE as expected
             ranTheGauntlet = true;
-        }}}}}}}}
+        }}}}}}}
         if (!ranTheGauntlet)
             throw new RuntimeException("A visit method did not throw NPE");
     }
--- a/jdk/test/java/nio/file/Files/PrintFileTree.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/file/Files/PrintFileTree.java	Wed Jul 05 17:24:13 2017 +0200
@@ -56,29 +56,34 @@
 
         final boolean reportCycles = printCycles;
         Files.walkFileTree(dir, options, Integer.MAX_VALUE, new FileVisitor<FileRef>() {
-            public FileVisitResult preVisitDirectory(FileRef dir) {
+            @Override
+            public FileVisitResult preVisitDirectory(FileRef dir, BasicFileAttributes attrs) {
                 System.out.println(dir);
                 return FileVisitResult.CONTINUE;
             }
-            public FileVisitResult preVisitDirectoryFailed(FileRef dir, IOException exc) {
-                exc.printStackTrace();
-                return FileVisitResult.CONTINUE;
-            }
+            @Override
             public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) {
                 if (!attrs.isDirectory() || reportCycles)
                     System.out.println(file);
                 return FileVisitResult.CONTINUE;
             }
-            public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) {
-                if (exc != null) {
-                    exc.printStackTrace();
-                    return FileVisitResult.TERMINATE;
-                }
+            @Override
+            public FileVisitResult postVisitDirectory(FileRef dir, IOException exc)
+                throws IOException
+            {
+                if (exc != null)
+                    throw exc;
                 return FileVisitResult.CONTINUE;
             }
-            public FileVisitResult visitFileFailed(FileRef file, IOException exc) {
-                exc.printStackTrace();
-                return FileVisitResult.TERMINATE;
+            @Override
+            public FileVisitResult visitFileFailed(FileRef file, IOException exc)
+                throws IOException
+            {
+                if (reportCycles && (exc instanceof FileSystemLoopException)) {
+                    System.out.println(file);
+                    return FileVisitResult.CONTINUE;
+                }
+                throw exc;
             }
         });
     }
--- a/jdk/test/java/nio/file/Files/SkipSiblings.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/file/Files/SkipSiblings.java	Wed Jul 05 17:24:13 2017 +0200
@@ -54,32 +54,28 @@
     public static void main(String[] args) throws Exception {
         Path dir = Paths.get(args[0]);
 
-        Files.walkFileTree(dir, new FileVisitor<Path>() {
-            public FileVisitResult preVisitDirectory(Path dir) {
+        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
                 check(dir);
                 if (skip(dir))
                     return FileVisitResult.SKIP_SIBLINGS;
                 return FileVisitResult.CONTINUE;
             }
-            public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
-                throw new RuntimeException(exc);
-            }
-
+            @Override
             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                 check(file);
                 if (skip(file))
                     return FileVisitResult.SKIP_SIBLINGS;
                 return FileVisitResult.CONTINUE;
             }
+            @Override
             public FileVisitResult postVisitDirectory(Path dir, IOException x) {
                 if (x != null)
                     throw new RuntimeException(x);
                 check(dir);
                 return FileVisitResult.CONTINUE;
             }
-            public FileVisitResult visitFileFailed(Path file, IOException x) {
-                throw new RuntimeException(x);
-            }
         });
     }
 }
--- a/jdk/test/java/nio/file/Files/TerminateWalk.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/file/Files/TerminateWalk.java	Wed Jul 05 17:24:13 2017 +0200
@@ -49,22 +49,19 @@
     public static void main(String[] args) throws Exception {
         Path dir = Paths.get(args[0]);
 
-        Files.walkFileTree(dir, new FileVisitor<Path>() {
-            public FileVisitResult preVisitDirectory(Path dir) {
+        Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
                 return maybeTerminate();
             }
-            public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
-                return maybeTerminate();
-            }
+            @Override
             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                 return maybeTerminate();
             }
+            @Override
             public FileVisitResult postVisitDirectory(Path dir, IOException x) {
                 return maybeTerminate();
             }
-            public FileVisitResult visitFileFailed(Path file, IOException x) {
-                return maybeTerminate();
-            }
         });
     }
 }
--- a/jdk/test/java/nio/file/Files/WalkWithSecurity.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/file/Files/WalkWithSecurity.java	Wed Jul 05 17:24:13 2017 +0200
@@ -116,7 +116,7 @@
         }
 
         @Override
-        public FileVisitResult preVisitDirectory(Path dir) {
+        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
             System.out.println(dir);
             count++;
             return FileVisitResult.CONTINUE;
--- a/jdk/test/java/nio/file/Files/walk_file_tree.sh	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/file/Files/walk_file_tree.sh	Wed Jul 05 17:24:13 2017 +0200
@@ -22,9 +22,9 @@
 #
 
 # @test
-# @bug 4313887
+# @bug 4313887 6907737
 # @summary Unit test for walkFileTree method
-# @build CreateFileTree PrintFileTree SkipSiblings TerminateWalk
+# @build CreateFileTree PrintFileTree SkipSiblings TerminateWalk MaxDepth
 # @run shell walk_file_tree.sh
 
 # if TESTJAVA isn't set then we assume an interactive run.
@@ -84,6 +84,10 @@
 $JAVA TerminateWalk "$ROOT"
 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
 
+# test maxDepth
+$JAVA MaxDepth "$ROOT"
+if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+
 # clean-up
 rm -r "$ROOT"
 
--- a/jdk/test/java/nio/file/TestUtil.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/nio/file/TestUtil.java	Wed Jul 05 17:24:13 2017 +0200
@@ -44,15 +44,10 @@
         return createTemporaryDirectory(System.getProperty("java.io.tmpdir"));
     }
 
-    static void removeAll(Path dir) {
+    static void removeAll(Path dir) throws IOException {
         Files.walkFileTree(dir, new FileVisitor<Path>() {
             @Override
-            public FileVisitResult preVisitDirectory(Path dir) {
-                return FileVisitResult.CONTINUE;
-            }
-            @Override
-            public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
-                System.err.format("Error occured accessing directory %s\n", dir, exc);
+            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
                 return FileVisitResult.CONTINUE;
             }
             @Override
--- a/jdk/test/java/util/Collection/BiggernYours.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/Collection/BiggernYours.java	Wed Jul 05 17:24:13 2017 +0200
@@ -174,6 +174,11 @@
                 public int size() {return randomize(super.size());}});
 
         testCollections(
+            new ConcurrentLinkedDeque(),
+            new ConcurrentLinkedDeque() {
+                public int size() {return randomize(super.size());}});
+
+        testCollections(
             new ConcurrentLinkedQueue(),
             new ConcurrentLinkedQueue() {
                 public int size() {return randomize(super.size());}});
--- a/jdk/test/java/util/Collection/IteratorAtEnd.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/Collection/IteratorAtEnd.java	Wed Jul 05 17:24:13 2017 +0200
@@ -48,6 +48,7 @@
         testCollection(new PriorityQueue());
         testCollection(new LinkedBlockingQueue());
         testCollection(new ArrayBlockingQueue(100));
+        testCollection(new ConcurrentLinkedDeque());
         testCollection(new ConcurrentLinkedQueue());
         testCollection(new LinkedTransferQueue());
 
--- a/jdk/test/java/util/Collection/MOAT.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/Collection/MOAT.java	Wed Jul 05 17:24:13 2017 +0200
@@ -75,6 +75,7 @@
         testCollection(new ArrayBlockingQueue<Integer>(20));
         testCollection(new LinkedBlockingQueue<Integer>(20));
         testCollection(new LinkedBlockingDeque<Integer>(20));
+        testCollection(new ConcurrentLinkedDeque<Integer>());
         testCollection(new ConcurrentLinkedQueue<Integer>());
         testCollection(new LinkedTransferQueue<Integer>());
         testCollection(new ConcurrentSkipListSet<Integer>());
@@ -431,8 +432,9 @@
         q.poll();
         equal(q.size(), 4);
         checkFunctionalInvariants(q);
-        if ((q instanceof LinkedBlockingQueue) ||
-            (q instanceof LinkedBlockingDeque) ||
+        if ((q instanceof LinkedBlockingQueue)   ||
+            (q instanceof LinkedBlockingDeque)   ||
+            (q instanceof ConcurrentLinkedDeque) ||
             (q instanceof ConcurrentLinkedQueue)) {
             testQueueIteratorRemove(q);
         }
--- a/jdk/test/java/util/Collections/RacingCollections.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/Collections/RacingCollections.java	Wed Jul 05 17:24:13 2017 +0200
@@ -235,6 +235,7 @@
             new ArrayList<Queue<Integer>>(newConcurrentDeques());
         list.add(new LinkedBlockingQueue<Integer>(10));
         list.add(new LinkedTransferQueue<Integer>());
+        list.add(new ConcurrentLinkedQueue<Integer>());
         return list;
     }
 
@@ -248,6 +249,7 @@
     private static List<Deque<Integer>> newConcurrentDeques() {
         List<Deque<Integer>> list = new ArrayList<Deque<Integer>>();
         list.add(new LinkedBlockingDeque<Integer>(10));
+        list.add(new ConcurrentLinkedDeque<Integer>());
         return list;
     }
 
--- a/jdk/test/java/util/Deque/ChorusLine.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/Deque/ChorusLine.java	Wed Jul 05 17:24:13 2017 +0200
@@ -129,6 +129,7 @@
         deqs.add(new ArrayDeque<Integer>());
         deqs.add(new LinkedList<Integer>());
         deqs.add(new LinkedBlockingDeque<Integer>());
+        deqs.add(new ConcurrentLinkedDeque<Integer>());
 
         equal(deqs);
 
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java	Wed Jul 05 17:24:13 2017 +0200
@@ -55,6 +55,7 @@
 
     Collection<Queue<Integer>> concurrentQueues() {
         List<Queue<Integer>> queues = new ArrayList<Queue<Integer>>();
+        queues.add(new ConcurrentLinkedDeque<Integer>());
         queues.add(new ConcurrentLinkedQueue<Integer>());
         queues.add(new ArrayBlockingQueue<Integer>(items, false));
         //queues.add(new ArrayBlockingQueue<Integer>(count, true));
@@ -105,7 +106,7 @@
         final Queue<Integer> queue;
         final CyclicBarrier barrier;
         int items;
-        Stage (Queue<Integer> q, CyclicBarrier b, int items) {
+        Stage(Queue<Integer> q, CyclicBarrier b, int items) {
             queue = q;
             barrier = b;
             this.items = items;
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java	Wed Jul 05 17:24:13 2017 +0200
@@ -40,6 +40,7 @@
 
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -62,6 +63,7 @@
 
     Collection<Queue<Boolean>> queues() {
         List<Queue<Boolean>> queues = new ArrayList<Queue<Boolean>>();
+        queues.add(new ConcurrentLinkedDeque<Boolean>());
         queues.add(new ConcurrentLinkedQueue<Boolean>());
         queues.add(new ArrayBlockingQueue<Boolean>(count, false));
         queues.add(new ArrayBlockingQueue<Boolean>(count, true));
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java	Wed Jul 05 17:24:13 2017 +0200
@@ -48,6 +48,7 @@
         test(new LinkedBlockingQueue(20));
         test(new LinkedBlockingDeque());
         test(new LinkedBlockingDeque(20));
+        test(new ConcurrentLinkedDeque());
         test(new ConcurrentLinkedQueue());
         test(new LinkedTransferQueue());
         // Other concurrent queues (e.g. ArrayBlockingQueue) do not
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java	Wed Jul 05 17:24:13 2017 +0200
@@ -55,6 +55,7 @@
         testQueue(new LinkedBlockingDeque());
         testQueue(new ArrayBlockingQueue(10));
         testQueue(new PriorityBlockingQueue(10));
+        testQueue(new ConcurrentLinkedDeque());
         testQueue(new ConcurrentLinkedQueue());
         testQueue(new LinkedTransferQueue());
     }
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java	Wed Jul 05 17:24:13 2017 +0200
@@ -41,6 +41,7 @@
 
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingDeque;
@@ -62,6 +63,7 @@
 
     Collection<Queue<Boolean>> concurrentQueues() {
         List<Queue<Boolean>> queues = new ArrayList<Queue<Boolean>>();
+        queues.add(new ConcurrentLinkedDeque<Boolean>());
         queues.add(new ConcurrentLinkedQueue<Boolean>());
         queues.add(new ArrayBlockingQueue<Boolean>(count, false));
         queues.add(new ArrayBlockingQueue<Boolean>(count, true));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComboBox/6632953/bug6632953.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 6632953
+ * @summary MetalComboBoxUI.getBaseline(JComponent, int, int) throws IAE for valid width/height
+ * @author Alexander Potochkin
+ */
+
+import javax.swing.JComboBox;
+import javax.swing.plaf.metal.MetalComboBoxUI;
+
+public class bug6632953 {
+
+    public static void main(String... args) throws Exception {
+        MetalComboBoxUI ui = new MetalComboBoxUI();
+        ui.installUI(new JComboBox());
+        ui.getBaseline(new JComboBox(), 0, 0);
+        ui.getBaseline(new JComboBox(), 1, 1);
+        ui.getBaseline(new JComboBox(), 2, 2);
+        ui.getBaseline(new JComboBox(), 3, 3);
+        ui.getBaseline(new JComboBox(), 4, 4);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JScrollBar/6542335/bug6542335.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 6542335
+   @summary different behavior on knob of scroll bar between 1.4.2 and 5.0
+   @author  Alexander Potochkin
+   @run main bug6542335
+*/
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import javax.swing.plaf.basic.BasicScrollBarUI;
+import java.awt.*;
+import java.awt.event.InputEvent;
+
+public class bug6542335 {
+    private static JScrollBar sb;
+    private static MyScrollBarUI ui;
+
+    public static void main(String[] args) throws Exception {
+        Robot robot = new Robot();
+        robot.setAutoDelay(10);
+
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+            public void run() {
+                final JFrame frame = new JFrame("bug6542335");
+                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+                sb = new JScrollBar(0, 0, 1, 0, 1);
+
+                ui = new MyScrollBarUI();
+                sb.setUI(ui);
+
+                sb.setPreferredSize(new Dimension(200, 17));
+                DefaultBoundedRangeModel rangeModel = new DefaultBoundedRangeModel();
+                rangeModel.setMaximum(100);
+                rangeModel.setMinimum(0);
+                rangeModel.setExtent(50);
+                rangeModel.setValue(50);
+
+                sb.setModel(rangeModel);
+                frame.add(sb);
+
+                frame.setSize(200, 100);
+                frame.setVisible(true);
+            }
+        });
+
+        Rectangle thumbBounds = new Rectangle(ui.getThumbBounds());
+
+        toolkit.realSync();
+        Point l = sb.getLocationOnScreen();
+        robot.mouseMove(l.x + (int) (0.75 * sb.getWidth()), l.y + sb.getHeight()/2);
+        robot.mousePress(InputEvent.BUTTON1_MASK);
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        toolkit.realSync();
+
+        if (!thumbBounds.equals(ui.getThumbBounds())) {
+            throw new RuntimeException("Test failed");
+        }
+    }
+
+    static class MyScrollBarUI extends BasicScrollBarUI {
+        public Rectangle getThumbBounds() {
+            return super.getThumbBounds();
+        }
+    }
+}
--- a/jdk/test/javax/swing/JTable/Test6888156.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/javax/swing/JTable/Test6888156.java	Wed Jul 05 17:24:13 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -71,14 +71,14 @@
         table = new JTable(model);
     }
 
-    public void test(final LookAndFeel laf) throws Exception {
+    public void test(final String laf) throws Exception {
         SwingUtilities.invokeAndWait(new Runnable() {
             @Override public void run() {
                 try {
+                    System.out.println(laf);
                     UIManager.setLookAndFeel(laf);
-                } catch (UnsupportedLookAndFeelException e) {
-                    System.err.println(laf.getDescription() +
-                                       " is unsupported; continuing");
+                } catch (Exception e) {
+                    System.err.println(laf + " is unsupported; continuing");
                     return;
                 }
                 SwingUtilities.updateComponentTreeUI(table);
@@ -92,8 +92,10 @@
 
     public static void main(String[] args) throws Exception {
         Test6888156 t = new Test6888156();
-        t.test(new javax.swing.plaf.nimbus.NimbusLookAndFeel());
-        t.test(new com.sun.java.swing.plaf.gtk.GTKLookAndFeel());
+        t.test("javax.swing.plaf.nimbus.NimbusLookAndFeel");
+        t.test("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+        for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
+            t.test(laf.getClassName());
+        }
     }
 }
-
--- a/jdk/test/javax/swing/JTextArea/6940863/bug6940863.java	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/javax/swing/JTextArea/6940863/bug6940863.java	Wed Jul 05 17:24:13 2017 +0200
@@ -56,6 +56,7 @@
     public static void main(String[] args) throws Exception {
         if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) {
             System.out.println("The test is suitable only for Windows OS. Skipped");
+            return;
         }
 
         UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
--- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedCharEncoding.sh	Thu Oct 07 15:12:12 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-#
-# Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please 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 6502503
- # @run shell/timeout=140 ChunkedCharEncoding.sh
- # @summary Http URL connection don't work when default encoding is Cp037: HTTP Transfer-Encoding:chunked
-
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux )
-    PS=":"
-    FS="/"
-    ;;
-  CYGWIN* )
-    PS=";"
-    FS="/"
-    ;;
-  Windows* )
-    PS=";"
-    FS="\\"
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-# compile
-${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}TestAvailable.java
-
-# run with CP037 encoding specified. 
-${TESTJAVA}${FS}bin${FS}java -Dfile.encoding=Cp037 TestAvailable 2>&1 
-
-result=$?
-if [ "$result" -ne "0" ]; then
-    exit 1
-fi
-
-# no failures, exit.
-exit 0
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/www/http/HttpClient/StreamingRetry.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 6672144
+ * @summary HttpURLConnection.getInputStream sends POST request after failed chunked send
+ */
+
+import java.net.HttpURLConnection;
+import java.net.ServerSocket;
+import java.net.URL;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class StreamingRetry implements Runnable {
+    static final int ACCEPT_TIMEOUT = 20 * 1000; // 20 seconds
+    ServerSocket ss;
+
+    public static void main(String[] args) throws IOException {
+        (new StreamingRetry()).instanceMain();
+    }
+
+    void instanceMain() throws IOException {
+        test();
+        if (failed > 0) throw new RuntimeException("Some tests failed");
+    }
+
+    void test() throws IOException {
+        ss = new ServerSocket(0);
+        ss.setSoTimeout(ACCEPT_TIMEOUT);
+        int port = ss.getLocalPort();
+
+        (new Thread(this)).start();
+
+        try {
+            URL url = new URL("http://localhost:" + port + "/");
+            HttpURLConnection uc = (HttpURLConnection) url.openConnection();
+            uc.setDoOutput(true);
+            uc.setChunkedStreamingMode(4096);
+            OutputStream os = uc.getOutputStream();
+            os.write("Hello there".getBytes());
+
+            InputStream is = uc.getInputStream();
+            is.close();
+        } catch (IOException expected) {
+            //expected.printStackTrace();
+        } finally {
+            ss.close();
+        }
+    }
+
+    // Server
+    public void run() {
+        try {
+            (ss.accept()).close();
+            (ss.accept()).close();
+            ss.close();
+            fail("The server shouldn't accept a second connection");
+         } catch (IOException e) {
+            //OK, the clien will close the server socket if successfull
+        }
+    }
+
+    volatile int failed = 0;
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/www/protocol/http/6550798/TestCache.java	Wed Jul 05 17:24:13 2017 +0200
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.net.*;
+import java.io.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.PrintStream;
+import java.io.InputStream;
+import java.io.File;
+import java.net.CacheRequest;
+import java.net.CacheResponse;
+import java.net.ResponseCache;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarFile;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+public class TestCache extends java.net.ResponseCache {
+    private boolean inCacheHandler = false;
+    private boolean _downloading = false;
+
+    public static volatile boolean fail = false;
+
+    public static void reset() {
+        // Set system wide cache handler
+        System.out.println("install deploy cache handler");
+        ResponseCache.setDefault(new TestCache());
+    }
+
+    public synchronized CacheResponse get(final URI uri, String rqstMethod,
+            Map requestHeaders) throws IOException {
+        System.out.println("get: " + uri);
+        Thread.currentThread().dumpStack();
+        return null;
+    }
+
+    public synchronized CacheRequest put(URI uri, URLConnection conn)
+    throws IOException {
+        System.out.println("put: " + uri);
+        Thread.currentThread().dumpStack();
+        URL url = uri.toURL();
+        return new DeployCacheRequest(url, conn);
+
+    }
+}
+
+class DeployByteArrayOutputStream extends java.io.ByteArrayOutputStream {
+
+    private URL _url;
+    private URLConnection _conn;
+
+    DeployByteArrayOutputStream(URL url, URLConnection conn) {
+        _url = url;
+        _conn = conn;
+    }
+
+
+    public void close() throws IOException {
+
+        System.out.println("contentLength: " + _conn.getContentLength());
+        System.out.println("byte array size: " + size());
+        if ( _conn.getContentLength() == size()) {
+            System.out.println("correct content length");
+        } else {
+            System.out.println("wrong content length");
+            System.out.println("TEST FAILED");
+            TestCache.fail = true;
+        }
+        super.close();
+    }
+}
+
+class DeployCacheRequest extends java.net.CacheRequest {
+
+    private URL _url;
+    private URLConnection _conn;
+    private boolean _downloading = false;
+
+    DeployCacheRequest(URL url, URLConnection conn) {
+        System.out.println("DeployCacheRequest ctor for: " + url);
+        _url = url;
+        _conn = conn;
+    }
+
+    public void abort() {
+        System.out.println("abort called");
+    }
+
+    public OutputStream getBody() throws IOException {
+        System.out.println("getBody called");
+        return new DeployByteArrayOutputStream(_url, _conn);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/www/protocol/http/6550798/test.java	Wed Jul 05 17:24:13 2017 +0200
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 6550798
+ * @summary Using InputStream.skip with ResponseCache will cause partial data to be cached
+ * @run main/othervm test
+ */
+
+import java.net.*;
+import com.sun.net.httpserver.*;
+import java.io.*;
+
+public class test {
+
+    final static int LEN = 16 * 1024;
+
+    public static void main(String[] args)  throws Exception {
+
+        TestCache.reset();
+        HttpServer s = HttpServer.create (new InetSocketAddress(0), 10);
+        s.createContext ("/", new HttpHandler () {
+            public void handle (HttpExchange e) {
+                try {
+                    byte[] buf = new byte [LEN];
+                    OutputStream o = e.getResponseBody();
+                    e.sendResponseHeaders(200, LEN);
+                    o.write (buf);
+                    e.close();
+                } catch (IOException ex) {
+                    ex.printStackTrace();
+                    TestCache.fail = true;
+                }
+            }
+        });
+        s.start();
+
+        System.out.println("http request with cache hander");
+        URL u = new URL("http://127.0.0.1:"+s.getAddress().getPort()+"/f");
+        URLConnection conn = u.openConnection();
+
+        InputStream is = null;
+        try {
+            // this calls into TestCache.get
+            byte[] buf = new byte[8192];
+            is = new BufferedInputStream(conn.getInputStream());
+
+            is.skip(1000);
+
+            while (is.read(buf) != -1) {
+            }
+        } finally {
+            if (is != null) {
+                // this calls into TestCache.put
+                // TestCache.put will check if the resource
+                // should be cached
+                is.close();
+            }
+            s.stop(0);
+        }
+
+        if (TestCache.fail) {
+            System.out.println ("TEST FAILED");
+            throw new RuntimeException ();
+        } else {
+            System.out.println ("TEST OK");
+        }
+    }
+}
--- a/jdk/test/sun/security/tools/jarsigner/crl.sh	Thu Oct 07 15:12:12 2010 -0700
+++ b/jdk/test/sun/security/tools/jarsigner/crl.sh	Wed Jul 05 17:24:13 2017 +0200
@@ -63,7 +63,15 @@
 $KT -alias b -dname CN=b -keyalg rsa -genkey -validity 300
 $KT -alias b -gencrl -id 5:1 -id 6:2 -file crl3
 
-$TESTJAVA${FS}bin${FS}jrunscript -e 'println(new File("crl1").toURI())' > uri
+cat > ToURI.java <<EOF
+class ToURI {
+    public static void main(String[] args) throws Exception {
+        System.out.println(new java.io.File("crl1").toURI());
+    }
+}
+EOF
+$TESTJAVA${FS}bin${FS}javac ToURI.java
+$TESTJAVA${FS}bin${FS}java ToURI > uri
 $KT -alias c -dname CN=c -keyalg rsa -genkey -validity 300 \
     -ext crl=uri:`cat uri`
 
--- a/make/jprt.properties	Thu Oct 07 15:12:12 2010 -0700
+++ b/make/jprt.properties	Wed Jul 05 17:24:13 2017 +0200
@@ -25,49 +25,310 @@
 
 # Properties for jprt
 
-# Use whatever release that the submitted job requests
+# At submit time, the release supplied will be in jprt.submit.release
+#    and will be one of the official release names defined in jprt.
+#    jprt supports property value expansion using ${property.name} syntax.
+
+# This tells jprt what default release we want to build
 jprt.tools.default.release=${jprt.submit.release}
 
 # The different build flavors we want, we override here so we just get these 2
 jprt.build.flavors=product,fastdebug
 
-# Shortened list of vm tests
-jprt.test.targets=              \
-  *-product-*-jvm98,            \
-  *-product-*-scimark,          \
-  *-product-*-runThese,         \
-  *-product-*-GCBasher_default, \
-  *-product-*-GCOld_default,    \
-  *-product-*-jbb_default
+# Define the Windows we want (temporary)
+jprt.my.windows.i586.jdk7b107=windows_i586_5.0
+jprt.my.windows.i586.jdk7temp=windows_i586_5.0
+jprt.my.windows.i586.jdk7=windows_i586_5.1
+jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}}
+
+# Standard list of jprt build targets for this source tree
+jprt.build.targets= 						\
+    solaris_sparc_5.10-{product|fastdebug}, 			\
+    solaris_sparcv9_5.10-{product|fastdebug}, 			\
+    solaris_i586_5.10-{product|fastdebug}, 			\
+    solaris_x64_5.10-{product|fastdebug}, 			\
+    linux_i586_2.6-{product|fastdebug}, 			\
+    linux_x64_2.6-{product|fastdebug}, 				\
+    ${jprt.my.windows.i586}-{product|fastdebug}, 		\
+    windows_x64_5.2-{product|fastdebug}
+
+# User can select the test set with jprt submit "-testset name" option
+jprt.my.test.set=${jprt.test.set}
+
+# Default vm test targets (no fastdebug & limited c2 testing)
+jprt.vm.default.test.targets=              			\
+    								\
+    solaris_sparc_5.10-product-c1-jvm98, 			\
+    solaris_sparcv9_5.10-product-c2-jvm98, 			\
+    solaris_i586_5.10-product-c1-jvm98, 			\
+    solaris_x64_5.10-product-c2-jvm98, 				\
+    linux_i586_2.6-product-{c1|c2}-jvm98, 			\
+    linux_x64_2.6-product-c2-jvm98, 				\
+    ${jprt.my.windows.i586}-product-c1-jvm98, 			\
+    windows_x64_5.2-product-c2-jvm98, 				\
+    								\
+    solaris_sparc_5.10-product-c1-scimark, 			\
+    solaris_sparcv9_5.10-product-c2-scimark, 			\
+    solaris_i586_5.10-product-c1-scimark, 			\
+    solaris_x64_5.10-product-c2-scimark, 			\
+    linux_i586_2.6-product-{c1|c2}-scimark, 			\
+    linux_x64_2.6-product-c2-scimark, 				\
+    ${jprt.my.windows.i586}-product-c1-scimark, 		\
+    windows_x64_5.2-product-c2-scimark
 
-# Test targets in test/Makefile
-jprt.make.rule.test.targets=   \
-  *-product-*-langtools_jtreg, \
-  *-product-*-jdk_beans1,      \
-  *-product-*-jdk_beans2,      \
-  *-product-*-jdk_beans3,      \
-  *-product-*-jdk_io,          \
-  *-product-*-jdk_lang,        \
-  *-product-*-jdk_management1, \
-  *-product-*-jdk_management2, \
-  *-product-*-jdk_math,        \
-  *-product-*-jdk_misc,        \
-  *-product-*-jdk_net,         \
-  *-product-*-jdk_nio1,        \
-  *-product-*-jdk_nio2,        \
-  *-product-*-jdk_nio3,        \
-  *-product-*-jdk_security1,   \
-  *-product-*-jdk_security2,   \
-  *-product-*-jdk_security3,   \
-  *-product-*-jdk_text,        \
-  *-product-*-jdk_tools1,      \
-  *-product-*-jdk_tools2,      \
-  *-product-*-jdk_util
+# Default jdk test targets in test/Makefile (no fastdebug & limited c2 testing)
+jprt.make.rule.default.test.targets=				\
+    								\
+    solaris_sparc_5.10-product-c1-langtools_jtreg, 		\
+    solaris_sparcv9_5.10-product-c2-langtools_jtreg, 		\
+    solaris_i586_5.10-product-c1-langtools_jtreg, 		\
+    solaris_x64_5.10-product-c2-langtools_jtreg, 		\
+    linux_i586_2.6-product-{c1|c2}-langtools_jtreg, 		\
+    linux_x64_2.6-product-c2-langtools_jtreg, 			\
+    ${jprt.my.windows.i586}-product-c1-langtools_jtreg, 	\
+    windows_x64_5.2-product-c2-langtools_jtreg, 		\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_beans1, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_beans1, 		\
+    solaris_i586_5.10-product-c1-jdk_beans1, 			\
+    solaris_x64_5.10-product-c2-jdk_beans1, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_beans1, 			\
+    linux_x64_2.6-product-c2-jdk_beans1, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_beans1, 		\
+    windows_x64_5.2-product-c2-jdk_beans1, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_io, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_io, 			\
+    solaris_i586_5.10-product-c1-jdk_io, 			\
+    solaris_x64_5.10-product-c2-jdk_io, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_io, 			\
+    linux_x64_2.6-product-c2-jdk_io, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_io, 			\
+    windows_x64_5.2-product-c2-jdk_io, 				\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_lang, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_lang, 			\
+    solaris_i586_5.10-product-c1-jdk_lang, 			\
+    solaris_x64_5.10-product-c2-jdk_lang, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_lang, 			\
+    linux_x64_2.6-product-c2-jdk_lang, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_lang, 		\
+    windows_x64_5.2-product-c2-jdk_lang, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_math, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_math, 			\
+    solaris_i586_5.10-product-c1-jdk_math, 			\
+    solaris_x64_5.10-product-c2-jdk_math, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_math, 			\
+    linux_x64_2.6-product-c2-jdk_math, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_math, 		\
+    windows_x64_5.2-product-c2-jdk_math, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_misc, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_misc, 			\
+    solaris_i586_5.10-product-c1-jdk_misc, 			\
+    solaris_x64_5.10-product-c2-jdk_misc, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_misc, 			\
+    linux_x64_2.6-product-c2-jdk_misc, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_misc, 		\
+    windows_x64_5.2-product-c2-jdk_misc, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_net, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_net, 			\
+    solaris_i586_5.10-product-c1-jdk_net, 			\
+    solaris_x64_5.10-product-c2-jdk_net, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_net, 			\
+    linux_x64_2.6-product-c2-jdk_net, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_net, 		\
+    windows_x64_5.2-product-c2-jdk_net, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_nio1, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_nio1, 			\
+    solaris_i586_5.10-product-c1-jdk_nio1, 			\
+    solaris_x64_5.10-product-c2-jdk_nio1, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_nio1, 			\
+    linux_x64_2.6-product-c2-jdk_nio1, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_nio1, 		\
+    windows_x64_5.2-product-c2-jdk_nio1, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_nio2, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_nio2, 			\
+    solaris_i586_5.10-product-c1-jdk_nio2, 			\
+    solaris_x64_5.10-product-c2-jdk_nio2, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_nio2, 			\
+    linux_x64_2.6-product-c2-jdk_nio2, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_nio2, 		\
+    windows_x64_5.2-product-c2-jdk_nio2, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_nio3, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_nio3, 			\
+    solaris_i586_5.10-product-c1-jdk_nio3, 			\
+    solaris_x64_5.10-product-c2-jdk_nio3, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_nio3, 			\
+    linux_x64_2.6-product-c2-jdk_nio3, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_nio3, 		\
+    windows_x64_5.2-product-c2-jdk_nio3, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_security1, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_security1, 		\
+    solaris_i586_5.10-product-c1-jdk_security1, 		\
+    solaris_x64_5.10-product-c2-jdk_security1, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_security1, 		\
+    linux_x64_2.6-product-c2-jdk_security1, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_security1, 		\
+    windows_x64_5.2-product-c2-jdk_security1, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_text, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_text, 			\
+    solaris_i586_5.10-product-c1-jdk_text, 			\
+    solaris_x64_5.10-product-c2-jdk_text, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_text, 			\
+    linux_x64_2.6-product-c2-jdk_text, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_text, 		\
+    windows_x64_5.2-product-c2-jdk_text, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_tools1, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_tools1, 		\
+    solaris_i586_5.10-product-c1-jdk_tools1, 			\
+    solaris_x64_5.10-product-c2-jdk_tools1, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_tools1, 			\
+    linux_x64_2.6-product-c2-jdk_tools1, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_tools1, 		\
+    windows_x64_5.2-product-c2-jdk_tools1, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_util, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_util, 			\
+    solaris_i586_5.10-product-c1-jdk_util, 			\
+    solaris_x64_5.10-product-c2-jdk_util, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_util, 			\
+    linux_x64_2.6-product-c2-jdk_util, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_util, 		\
+    windows_x64_5.2-product-c2-jdk_util
 
-# Not Ready Yet:
-#   *-product-*-jdk_awt
-#   *-product-*-jdk_rmi
-#   *-product-*-jdk_swing
+# All vm test targets (but still no fastdebug & limited c2 testing)
+jprt.vm.all.test.targets=    					\
+    								\
+   ${jprt.vm.default.test.targets}, 				\
+    								\
+    solaris_sparc_5.10-product-c1-runThese, 			\
+    solaris_sparcv9_5.10-product-c2-runThese, 			\
+    solaris_i586_5.10-product-c1-runThese, 			\
+    solaris_x64_5.10-product-c2-runThese, 			\
+    linux_i586_2.6-product-{c1|c2}-runThese, 			\
+    linux_x64_2.6-product-c2-runThese, 				\
+    ${jprt.my.windows.i586}-product-c1-runThese, 		\
+    windows_x64_5.2-product-c2-runThese, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jbb_default, 			\
+    solaris_sparcv9_5.10-product-c2-jbb_default, 		\
+    solaris_i586_5.10-product-c1-jbb_default, 			\
+    solaris_x64_5.10-product-c2-jbb_default, 			\
+    linux_i586_2.6-product-{c1|c2}-jbb_default, 		\
+    linux_x64_2.6-product-c2-jbb_default, 			\
+    ${jprt.my.windows.i586}-product-c1-jbb_default, 		\
+    windows_x64_5.2-product-c2-jbb_default
+
+# All jdk test targets (but still no fastdebug & limited c2 testing)
+jprt.make.rule.all.test.targets=    				\
+    								\
+   ${jprt.make.rule.default.test.targets}, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_awt, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_awt, 			\
+    solaris_i586_5.10-product-c1-jdk_awt, 			\
+    solaris_x64_5.10-product-c2-jdk_awt, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_awt, 			\
+    linux_x64_2.6-product-c2-jdk_awt, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_awt, 		\
+    windows_x64_5.2-product-c2-jdk_awt, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_beans2, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_beans2, 		\
+    solaris_i586_5.10-product-c1-jdk_beans2, 			\
+    solaris_x64_5.10-product-c2-jdk_beans2, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_beans2, 			\
+    linux_x64_2.6-product-c2-jdk_beans2, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_beans2, 		\
+    windows_x64_5.2-product-c2-jdk_beans2, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_beans3, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_beans3, 		\
+    solaris_i586_5.10-product-c1-jdk_beans3, 			\
+    solaris_x64_5.10-product-c2-jdk_beans3, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_beans3, 			\
+    linux_x64_2.6-product-c2-jdk_beans3, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_beans3, 		\
+    windows_x64_5.2-product-c2-jdk_beans3, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_management1, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_management1, 		\
+    solaris_i586_5.10-product-c1-jdk_management1, 		\
+    solaris_x64_5.10-product-c2-jdk_management1, 		\
+    linux_i586_2.6-product-{c1|c2}-jdk_management1, 		\
+    linux_x64_2.6-product-c2-jdk_management1, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_management1, 	\
+    windows_x64_5.2-product-c2-jdk_management1, 		\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_management2, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_management2, 		\
+    solaris_i586_5.10-product-c1-jdk_management2, 		\
+    solaris_x64_5.10-product-c2-jdk_management2, 		\
+    linux_i586_2.6-product-{c1|c2}-jdk_management2, 		\
+    linux_x64_2.6-product-c2-jdk_management2, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_management2, 	\
+    windows_x64_5.2-product-c2-jdk_management2, 		\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_rmi, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_rmi, 			\
+    solaris_i586_5.10-product-c1-jdk_rmi, 			\
+    solaris_x64_5.10-product-c2-jdk_rmi, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_rmi, 			\
+    linux_x64_2.6-product-c2-jdk_rmi, 				\
+    ${jprt.my.windows.i586}-product-c1-jdk_rmi, 		\
+    windows_x64_5.2-product-c2-jdk_rmi, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_security2, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_security2, 		\
+    solaris_i586_5.10-product-c1-jdk_security2, 		\
+    solaris_x64_5.10-product-c2-jdk_security2, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_security2, 		\
+    linux_x64_2.6-product-c2-jdk_security2, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_security2, 		\
+    windows_x64_5.2-product-c2-jdk_security2, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_security3, 		\
+    solaris_sparcv9_5.10-product-c2-jdk_security3, 		\
+    solaris_i586_5.10-product-c1-jdk_security3, 		\
+    solaris_x64_5.10-product-c2-jdk_security3, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_security3, 		\
+    linux_x64_2.6-product-c2-jdk_security3, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_security3, 		\
+    windows_x64_5.2-product-c2-jdk_security3, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_swing, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_swing, 			\
+    solaris_i586_5.10-product-c1-jdk_swing, 			\
+    solaris_x64_5.10-product-c2-jdk_swing, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_swing, 			\
+    linux_x64_2.6-product-c2-jdk_swing, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_swing, 		\
+    windows_x64_5.2-product-c2-jdk_swing, 			\
+    								\
+    solaris_sparc_5.10-product-c1-jdk_tools2, 			\
+    solaris_sparcv9_5.10-product-c2-jdk_tools2, 		\
+    solaris_i586_5.10-product-c1-jdk_tools2, 			\
+    solaris_x64_5.10-product-c2-jdk_tools2, 			\
+    linux_i586_2.6-product-{c1|c2}-jdk_tools2, 			\
+    linux_x64_2.6-product-c2-jdk_tools2, 			\
+    ${jprt.my.windows.i586}-product-c1-jdk_tools2, 		\
+    windows_x64_5.2-product-c2-jdk_tools2
+
+# Select list to use (allow for testset to be empty too)
+jprt.make.rule..test.targets=${jprt.make.rule.default.test.targets} 
+jprt.make.rule.test.targets=${jprt.make.rule.${jprt.my.test.set}.test.targets} 
+jprt.vm..test.targets=${jprt.vm.default.test.targets} 
+jprt.vm.test.targets=${jprt.vm.${jprt.my.test.set}.test.targets} 
+jprt.test.targets=${jprt.vm.test.targets} 
 
 # Directories to be excluded from the source bundles
 jprt.bundle.exclude.src.dirs=build dist webrev