--- a/jdk/make/Makefile Thu Oct 07 15:12:19 2010 -0700
+++ b/jdk/make/Makefile Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/make/common/Cscope.gmk Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/make/common/Defs.gmk Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 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:19 2010 -0700
+++ b/jdk/make/common/shared/Defs-utils.gmk Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/make/common/shared/Defs.gmk Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/make/java/java/FILES_java.gmk Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/make/jprt.properties Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/make/mkdemo/Makefile Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/make/sun/cmm/lcms/Makefile Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/providers/RIXMLProvider.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/Installer.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/RegistrationData.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/Registry.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/com/sun/servicetag/SolarisSystemEnvironment.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/awt/Dialog.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/awt/event/ActionEvent.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/awt/image/SampleModel.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/beans/EventSetDescriptor.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/beans/Introspector.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/beans/MethodDescriptor.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/lang/System.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/net/InetAddress.java Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileVisitOption.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileVisitor.java Tue Oct 12 12:51:48 2010 -0700
@@ -40,33 +40,28 @@
* Path start = ...
* Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
* @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;
* }
* @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<Path>() {
* @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;
* }
* @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:19 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/Files.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/sql/DatabaseMetaData.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/sql/Statement.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/util/Locale.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/util/ResourceBundle.java Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Tue Oct 12 12:51:48 2010 -0700
@@ -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 "wait-free"
* 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:19 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/RecursiveAction.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/CachedRowSet.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/RowSetMetaDataImpl.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/RowSetProvider.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/WebRowSet.java Tue Oct 12 12:51:48 2010 -0700
@@ -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 @@
* <<font color=red>url</font>>jdbc:thin:oracle<<font color=red>/url</font>>
* <<font color=red>sync-provider</font>>
* <<font color=red>sync-provider-name</font>>.com.rowset.provider.RIOptimisticProvider<<font color=red>/sync-provider-name</font>>
- * <<font color=red>sync-provider-vendor</font>>Sun Microsystems<<font color=red>/sync-provider-vendor</font>>
+ * <<font color=red>sync-provider-vendor</font>>Oracle Corporation<<font color=red>/sync-provider-vendor</font>>
* <<font color=red>sync-provider-version</font>>1.0<<font color=red>/sync-provider-name</font>>
* <<font color=red>sync-provider-grade</font>>LOW<<font color=red>/sync-provider-grade</font>>
* <<font color=red>data-source-lock</font>>NONE<<font color=red>/data-source-lock</font>>
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/rowset.properties Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SQLOutputImpl.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialRef.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialStruct.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/spi/SyncFactory.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/spi/SyncProvider.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/spi/package.html Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/GroupLayout.java Tue Oct 12 12:51:48 2010 -0700
@@ -1464,8 +1464,8 @@
* <= {@code pref} <= {@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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JComponent.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JDesktopPane.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JLayer.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/JTable.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/ToolTipManager.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/LayerUI.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalComboBoxUI.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/sun/security/util/Resources.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/classes/sun/util/locale/BaseLocale.java Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/native/java/lang/System.c Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/sample/nio/file/Chmod.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/sample/nio/file/Copy.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/share/sample/nio/file/WatchDir.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java.linux Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/GtkFileDialogPeer.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/native/java/io/io_util_md.c Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/native/java/net/net_util_md.c Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/native/java/net/net_util_md.h Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/solaris/native/sun/awt/awt_InputMethod.c Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/lib/tzmappings Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/native/java/io/io_util_md.c Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/native/sun/net/spi/DefaultProxySelector.c Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Desktop.cpp Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/ProblemList.txt Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/JavaServiceTagTest.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/JavaServiceTagTest1.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/Util.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/environ.properties Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/missing-environ-field.xml Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/newer-registry-version.xml Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/registration.xml Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag1.properties Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag2.properties Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag3.properties Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag4.properties Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/com/sun/servicetag/servicetag5.properties Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Extra.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/file/FileStore/Basic.java Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/file/Files/Misc.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/file/Files/PrintFileTree.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/file/Files/SkipSiblings.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/file/Files/TerminateWalk.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/file/Files/WalkWithSecurity.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/file/Files/walk_file_tree.sh Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/nio/file/TestUtil.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/Collection/BiggernYours.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/Collection/IteratorAtEnd.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/Collection/MOAT.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/Collections/RacingCollections.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/Deque/ChorusLine.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/javax/swing/JTable/Test6888156.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/javax/swing/JTextArea/6940863/bug6940863.java Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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 Tue Oct 12 12:51:48 2010 -0700
@@ -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:19 2010 -0700
+++ b/jdk/test/sun/security/tools/jarsigner/crl.sh Tue Oct 12 12:51:48 2010 -0700
@@ -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`