changeset 1967:49eb9c3d7ce7

Merge
author vinnie
date Thu, 12 Nov 2009 23:04:42 +0000
parents 7475a2e71c40 (current diff) eb8b08775b82 (diff)
children 60646a58322b
files make/tools/fontchecker/Makefile make/tools/src/build/tools/fontchecker/FontCheckDummy.java make/tools/src/build/tools/fontchecker/FontChecker.java make/tools/src/build/tools/fontchecker/FontCheckerConstants.java make/tools/src/build/tools/fontchecker/FontFileFilter.java make/tools/src/build/tools/fontchecker/README.txt src/share/classes/java/nio/ByteBufferAs-X-Buffer.java src/share/classes/java/nio/Direct-X-Buffer-bin.java src/share/classes/java/nio/Direct-X-Buffer.java src/share/classes/java/nio/Heap-X-Buffer.java src/share/classes/java/nio/X-Buffer-bin.java src/share/classes/java/nio/X-Buffer.java src/share/classes/java/nio/charset/Charset-X-Coder.java src/share/classes/sun/misc/Version-template.java src/share/classes/sun/tools/jconsole/Version-template.java test/java/nio/Buffer/Basic-X.java test/java/nio/Buffer/CopyDirect-X-Memory.java
diffstat 199 files changed, 23072 insertions(+), 8043 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu Nov 12 23:00:23 2009 +0000
+++ b/.hgtags	Thu Nov 12 23:04:42 2009 +0000
@@ -49,3 +49,4 @@
 460639b036f327282832a4fe52b7aa45688afd50 jdk7-b72
 f708138c9aca4b389872838fe6773872fce3609e jdk7-b73
 eacb36e30327e7ae33baa068e82ddccbd91eaae2 jdk7-b74
+8885b22565077236a927e824ef450742e434a230 jdk7-b75
--- a/make/common/Defs-linux.gmk	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/common/Defs-linux.gmk	Thu Nov 12 23:04:42 2009 +0000
@@ -116,8 +116,16 @@
 LDFLAGS_COMMON_sparcv9  += -m64 -mcpu=v9
 CFLAGS_REQUIRED_sparc   += -m32 -mcpu=v9
 LDFLAGS_COMMON_sparc    += -m32 -mcpu=v9
-CFLAGS_REQUIRED         =  $(CFLAGS_REQUIRED_$(ARCH))
-LDFLAGS_COMMON          += $(LDFLAGS_COMMON_$(ARCH))
+ifeq ($(ZERO_BUILD), true)
+  CFLAGS_REQUIRED       =  $(ZERO_ARCHFLAG)
+  ifeq ($(ZERO_ENDIANNESS), little)
+    CFLAGS_REQUIRED     += -D_LITTLE_ENDIAN
+  endif
+  LDFLAGS_COMMON        += $(ZERO_ARCHFLAG)
+else
+  CFLAGS_REQUIRED       =  $(CFLAGS_REQUIRED_$(ARCH))
+  LDFLAGS_COMMON        += $(LDFLAGS_COMMON_$(ARCH))
+endif
 
 # If this is a --hash-style=gnu system, use --hash-style=both
 #   The gnu .hash section won't work on some Linux systems like SuSE 10.
@@ -217,7 +225,7 @@
 
 EXTRA_LIBS += -lc
 
-LDFLAGS_DEFS_OPTION  = -z defs
+LDFLAGS_DEFS_OPTION  = -Xlinker -z -Xlinker defs
 LDFLAGS_COMMON  += $(LDFLAGS_DEFS_OPTION)
 
 #
--- a/make/common/Defs.gmk	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/common/Defs.gmk	Thu Nov 12 23:04:42 2009 +0000
@@ -667,12 +667,7 @@
 LINTFLAGS       = $(LINTFLAGS_$(VARIANT)) $(LINTFLAGS_COMMON) \
 		  $(OTHER_LINTFLAGS)
 
-# this should be moved into Defs-<platform>.gmk.....
-ifeq ($(PLATFORM), windows)
-  VERSION_DEFINES = -DRELEASE="\"$(RELEASE)\""
-else
-  VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
-endif
+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/make/common/Program.gmk	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/common/Program.gmk	Thu Nov 12 23:04:42 2009 +0000
@@ -85,7 +85,7 @@
 	endif
     endif
     ifeq ($(PLATFORM), linux)
-	LDFLAGS += -z origin
+	LDFLAGS += -Wl,-z -Wl,origin
 	LDFLAGS += -Wl,--allow-shlib-undefined
 	LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/../lib/$(LIBARCH)/jli
 	LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/../jre/lib/$(LIBARCH)/jli
@@ -236,13 +236,13 @@
 endif # INCREMENTAL_BUILD
 
 ifdef JAVA_ARGS
-OTHER_CPPFLAGS += -DJAVA_ARGS=$(JAVA_ARGS)
-OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
+OTHER_CPPFLAGS += -DJAVA_ARGS='$(JAVA_ARGS)'
+OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
 endif
 
 ifeq ($(PLATFORM), windows)
 ifdef RELEASE
-OTHER_CPPFLAGS += -DVERSION="$(RELEASE)"
+OTHER_CPPFLAGS += -DVERSION='"$(RELEASE)"'
 endif
 endif
 
@@ -258,14 +258,8 @@
 OTHER_INCLUDES += -I$(LAUNCHER_SHARE_SRC)/bin -I$(LAUNCHER_PLATFORM_SRC)/bin
 OTHER_INCLUDES += -I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3
 
-# this may not be necessary...
-ifeq ($(PLATFORM), windows)
-OTHER_CPPFLAGS += -DPROGNAME="\"$(PROGRAM)\""
-VERSION_DEFINES += -DFULL_VERSION="\"$(FULL_VERSION)\""
-else
 OTHER_CPPFLAGS += -DPROGNAME='"$(PROGRAM)"'
 VERSION_DEFINES += -DFULL_VERSION='"$(FULL_VERSION)"'
-endif
 
 VERSION_DEFINES += -DJDK_MAJOR_VERSION='"$(JDK_MAJOR_VERSION)"' \
 		   -DJDK_MINOR_VERSION='"$(JDK_MINOR_VERSION)"'
@@ -279,8 +273,14 @@
 
 #
 # How to install jvm.cfg. 
-# 
-$(JVMCFG): $(LAUNCHER_PLATFORM_SRC)/bin/$(ARCH)/jvm.cfg 
+#
+ifeq ($(ZERO_BUILD), true)
+JVMCFG_ARCH = zero
+else
+JVMCFG_ARCH = $(ARCH)
+endif
+
+$(JVMCFG): $(LAUNCHER_PLATFORM_SRC)/bin/$(JVMCFG_ARCH)/jvm.cfg 
 	$(install-file)
 
 #
--- a/make/common/Release.gmk	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/common/Release.gmk	Thu Nov 12 23:04:42 2009 +0000
@@ -330,7 +330,7 @@
 #
 # Specific files and directories that will be filtered out from above areas.
 #
-SOURCE_FILTERs = $(SCM_DIRs) 'X-*' '*-X-*' '*-template.java' ',*'
+SOURCE_FILTERs = $(SCM_DIRs) ',*'
 SOURCE_FILES_filter = $(SOURCE_FILTERs:%=-name % -prune -o)
 
 #
--- a/make/common/Rules.gmk	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/common/Rules.gmk	Thu Nov 12 23:04:42 2009 +0000
@@ -63,7 +63,7 @@
 # If AUTO_FILES_PROPERTIES_DIRS used, automatically find properties files
 #
 ifdef AUTO_FILES_PROPERTIES_DIRS
-  AUTO_FILES_PROPERTIES_FILTERS1  = $(SCM_DIRs) 'X-*' '*-X-*' ',*'
+  AUTO_FILES_PROPERTIES_FILTERS1  = $(SCM_DIRs) ',*'
   AUTO_FILES_PROPERTIES_FILTERS1 += $(AUTO_PROPERTIES_PRUNE)
   FILES_properties_find_filters1 = $(AUTO_FILES_PROPERTIES_FILTERS1:%=-name % -prune -o)
   FILES_properties_auto1 := \
@@ -111,7 +111,7 @@
 
 ifdef AUTO_FILES_JAVA_DIRS
   # Filter out these files or directories
-  AUTO_FILES_JAVA_SOURCE_FILTERS1  = $(SCM_DIRs) 'X-*' '*-X-*' '*-template.java' ',*'
+  AUTO_FILES_JAVA_SOURCE_FILTERS1  = $(SCM_DIRs) ',*'
   AUTO_FILES_JAVA_SOURCE_FILTERS2  = 
   AUTO_FILES_JAVA_SOURCE_FILTERS1 += $(AUTO_JAVA_PRUNE)
   AUTO_FILES_JAVA_SOURCE_FILTERS2 += $(AUTO_JAVA_PRUNE)
--- a/make/java/instrument/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/java/instrument/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -109,7 +109,7 @@
     LDFLAGS += -R \$$ORIGIN/jli
   endif
   ifeq ($(PLATFORM), linux)
-    LDFLAGS += -z origin
+    LDFLAGS += -Wl,-z -Wl,origin
     LDFLAGS += -Wl,--allow-shlib-undefined
     LDFLAGS += -Wl,-rpath -Wl,\$$ORIGIN/jli
   endif
--- a/make/java/java/FILES_java.gmk	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/java/java/FILES_java.gmk	Thu Nov 12 23:04:42 2009 +0000
@@ -287,11 +287,18 @@
     java/util/concurrent/ExecutorService.java \
     java/util/concurrent/ExecutorCompletionService.java \
     java/util/concurrent/Executors.java \
+    java/util/concurrent/ForkJoinPool.java \
+    java/util/concurrent/ForkJoinTask.java \
+    java/util/concurrent/ForkJoinWorkerThread.java \
     java/util/concurrent/Future.java \
     java/util/concurrent/FutureTask.java \
     java/util/concurrent/LinkedBlockingDeque.java \
     java/util/concurrent/LinkedBlockingQueue.java \
+    java/util/concurrent/LinkedTransferQueue.java \
+    java/util/concurrent/Phaser.java \
     java/util/concurrent/PriorityBlockingQueue.java \
+    java/util/concurrent/RecursiveAction.java \
+    java/util/concurrent/RecursiveTask.java \
     java/util/concurrent/RejectedExecutionException.java \
     java/util/concurrent/RejectedExecutionHandler.java \
     java/util/concurrent/RunnableFuture.java \
@@ -302,9 +309,11 @@
     java/util/concurrent/Semaphore.java \
     java/util/concurrent/SynchronousQueue.java \
     java/util/concurrent/ThreadFactory.java \
+    java/util/concurrent/ThreadLocalRandom.java \
     java/util/concurrent/ThreadPoolExecutor.java \
     java/util/concurrent/TimeUnit.java \
     java/util/concurrent/TimeoutException.java \
+    java/util/concurrent/TransferQueue.java \
     java/util/concurrent/atomic/AtomicBoolean.java \
     java/util/concurrent/atomic/AtomicInteger.java \
     java/util/concurrent/atomic/AtomicIntegerArray.java \
--- a/make/java/jli/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/java/jli/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -48,11 +48,15 @@
 LAUNCHER_SHARE_SRC = $(SHARE_SRC)/bin
 LAUNCHER_PLATFORM_SRC = $(PLATFORM_SRC)/bin
 
+ifeq ($(ZERO_BUILD), true)
+ERGO_FAMILY=zero
+else
 ifeq ($(ARCH_FAMILY), amd64)
 ERGO_FAMILY=i586
 else
 ERGO_FAMILY=$(ARCH_FAMILY)
 endif
+endif
 
 
 #
--- a/make/java/main/java/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/java/main/java/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -57,7 +57,7 @@
 #
 include $(BUILDDIR)/common/Program.gmk
 OTHER_CPPFLAGS += -DEXPAND_CLASSPATH_WILDCARDS
-OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
+OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
 
 ifeq ($(PLATFORM), solaris)
 LDFLAGS += -R$(OPENWIN_LIB)
--- a/make/java/main/javaw/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/java/main/javaw/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -62,4 +62,5 @@
 #
 include $(BUILDDIR)/common/Program.gmk
 OTHER_CPPFLAGS += -DEXPAND_CLASSPATH_WILDCARDS
-OTHER_CPPFLAGS += -DLAUNCHER_NAME=\"$(LAUNCHER_NAME)\"
+OTHER_CPPFLAGS += -DLAUNCHER_NAME='"$(LAUNCHER_NAME)"'
+
--- a/make/java/nio/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/java/nio/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -335,6 +335,15 @@
 SCS_SRC=$(SNIO_SRC)/cs
 SFS_SRC=$(SNIO_SRC)/fs
 
+# Template files
+HEAP_X_BUF_TEMPLATE=$(BUF_SRC)/Heap-X-Buffer.java.template
+BYTE_X_BUF_TEMPLATE=$(BUF_SRC)/ByteBufferAs-X-Buffer.java.template
+X_BUF_TEMPLATE=$(BUF_SRC)/X-Buffer.java.template
+X_BUF_BIN_TEMPLATE=$(BUF_SRC)/X-Buffer-bin.java.template
+DIRECT_X_BUF_TEMPLATE=$(BUF_SRC)/Direct-X-Buffer.java.template
+DIRECT_X_BUF_BIN_TEMPLATE=$(BUF_SRC)/Direct-X-Buffer-bin.java.template
+CHARSET_X_CODER_TEMPLATE=$(CS_SRC)/Charset-X-Coder.java.template
+
 BUF_GEN=$(NIO_GEN)
 CH_GEN=$(NIO_GEN)/channels
 CS_GEN=$(NIO_GEN)/charset
@@ -357,39 +366,39 @@
 
 # Public abstract buffer classes
 #
-$(BUF_GEN)/ByteBuffer.java: $(BUF_SRC)/X-Buffer.java \
-			    $(BUF_SRC)/X-Buffer-bin.java \
+$(BUF_GEN)/ByteBuffer.java: $(X_BUF_TEMPLATE) \
+			    $(X_BUF_BIN_TEMPLATE) \
 			    $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=byte BIN=1 SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/CharBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/CharBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ShortBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ShortBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/IntBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/IntBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/LongBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/LongBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/FloatBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/FloatBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DoubleBuffer.java: $(BUF_SRC)/X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DoubleBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -397,72 +406,72 @@
 
 # Buffers whose contents are heap-allocated
 # 
-$(BUF_GEN)/HeapByteBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapByteBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=byte SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapByteBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapByteBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=byte RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapCharBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapCharBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapCharBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapCharBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapShortBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapShortBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapShortBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapShortBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapIntBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapIntBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapIntBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapIntBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapLongBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapLongBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapLongBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapLongBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapFloatBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapFloatBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapFloatBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapFloatBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapDoubleBuffer.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapDoubleBuffer.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/HeapDoubleBuffer%.java: $(BUF_SRC)/Heap-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/HeapDoubleBuffer%.java: $(HEAP_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -470,15 +479,15 @@
 
 # Direct byte buffer
 # 
-$(BUF_GEN)/DirectByteBuffer.java: $(BUF_SRC)/Direct-X-Buffer.java \
-				  $(BUF_SRC)/Direct-X-Buffer.java \
+$(BUF_GEN)/DirectByteBuffer.java: $(DIRECT_X_BUF_TEMPLATE) \
+				  $(DIRECT_X_BUF_TEMPLATE) \
 				  $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=byte BIN=1 SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectByteBuffer%.java: $(BUF_SRC)/Direct-X-Buffer.java \
-				   $(BUF_SRC)/Direct-X-Buffer.java \
+$(BUF_GEN)/DirectByteBuffer%.java: $(DIRECT_X_BUF_TEMPLATE) \
+				   $(DIRECT_X_BUF_TEMPLATE) \
 				   $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
@@ -487,62 +496,62 @@
 
 # Unswapped views of direct byte buffers
 #
-$(BUF_GEN)/DirectCharBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectCharBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectCharBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectCharBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectShortBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectShortBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectShortBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectShortBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectIntBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectIntBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectIntBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectIntBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectLongBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectLongBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectLongBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectLongBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectFloatBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectFloatBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectFloatBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectFloatBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectDoubleBufferU.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectDoubleBufferU.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectDoubleBuffer%U.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectDoubleBuffer%U.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* BO=U SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -550,62 +559,62 @@
 
 # Swapped views of direct byte buffers
 #
-$(BUF_GEN)/DirectCharBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectCharBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectCharBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectCharBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectShortBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectShortBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectShortBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectShortBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectIntBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectIntBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectIntBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectIntBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectLongBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectLongBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectLongBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectLongBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectFloatBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectFloatBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectFloatBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectFloatBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectDoubleBufferS.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectDoubleBufferS.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/DirectDoubleBuffer%S.java: $(BUF_SRC)/Direct-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/DirectDoubleBuffer%S.java: $(DIRECT_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* BO=S SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -613,62 +622,62 @@
 
 # Big-endian views of byte buffers
 #
-$(BUF_GEN)/ByteBufferAsCharBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsCharBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsCharBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsCharBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsShortBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsShortBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsShortBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsShortBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsIntBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsIntBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsIntBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsIntBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsLongBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsLongBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsLongBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsLongBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsFloatBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsFloatBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsFloatBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsFloatBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsDoubleBufferB.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsDoubleBufferB.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsDoubleBuffer%B.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsDoubleBuffer%B.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* BO=B SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -676,62 +685,62 @@
 
 # Little-endian views of byte buffers
 #
-$(BUF_GEN)/ByteBufferAsCharBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsCharBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsCharBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsCharBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=char RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsShortBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsShortBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsShortBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsShortBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=short RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsIntBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsIntBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsIntBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsIntBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=int RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsLongBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsLongBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsLongBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsLongBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=long RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsFloatBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsFloatBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsFloatBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsFloatBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=float RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsDoubleBufferL.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsDoubleBufferL.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
 	$(MV) $@.temp $@
-$(BUF_GEN)/ByteBufferAsDoubleBuffer%L.java: $(BUF_SRC)/ByteBufferAs-X-Buffer.java $(GEN_BUFFER_SH)
+$(BUF_GEN)/ByteBufferAsDoubleBuffer%L.java: $(BYTE_X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	TYPE=double RW=$* BO=L SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
@@ -745,13 +754,13 @@
 
 GEN_CODER_CMD = SPP="$(SPP_CMD)" SED="$(SED)" NAWK="$(NAWK)" SH="$(SH)" $(SH) $(GEN_CODER_SH)
 
-$(CS_GEN)/CharsetDecoder.java: $(CS_SRC)/Charset-X-Coder.java $(GEN_CODER_SH)
+$(CS_GEN)/CharsetDecoder.java: $(CHARSET_X_CODER_TEMPLATE) $(GEN_CODER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	$(GEN_CODER_CMD) decoder $< $@.temp
 	$(MV) $@.temp $@
 
-$(CS_GEN)/CharsetEncoder.java: $(CS_SRC)/Charset-X-Coder.java $(GEN_CODER_SH)
+$(CS_GEN)/CharsetEncoder.java: $(CHARSET_X_CODER_TEMPLATE) $(GEN_CODER_SH)
 	$(prep-target)
 	@$(RM) $@.temp
 	$(GEN_CODER_CMD) encoder $< $@.temp
--- a/make/java/nio/genBuffer.sh	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/java/nio/genBuffer.sh	Thu Nov 12 23:04:42 2009 +0000
@@ -154,7 +154,7 @@
   mv $DST $DST.tmp
   sed -e '/#BIN/,$d' <$DST.tmp >$DST
   rm -f $DST.tmp
-  binops=`dirname $SRC`/`basename $SRC .java`-bin.java
+  binops=`dirname $SRC`/`basename $SRC .java.template`-bin.java.template
   genBinOps char character 1 two one $binops >>$DST
   genBinOps short short 1 two one $binops >>$DST
   genBinOps int integer 2 four three $binops >>$DST
--- a/make/java/redist/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/java/redist/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -94,11 +94,13 @@
   endif
 endif # INCLUDE_SA
 
-# Hotspot client is only available on 32-bit builds
+# Hotspot client is only available on 32-bit non-Zero builds
+ifneq ($(ZERO_BUILD), true)
 ifeq ($(ARCH_DATA_MODEL), 32)
   IMPORT_LIST += $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVM_NAME) \
                  $(LIB_LOCATION)/$(CLIENT_LOCATION)/Xusage.txt
 endif
+endif
 
 ifeq ($(PLATFORM), windows)
 #  Windows     vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv  Windows
@@ -171,6 +173,7 @@
   IMPORT_LIST += $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDB_NAME)
 endif 
 
+ifneq ($(ZERO_BUILD), true)
 ifeq ($(ARCH_DATA_MODEL), 32)
 
 IMPORT_LIST += $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(LIBJSIG_NAME)
@@ -201,6 +204,8 @@
 
 endif # 32bit
 
+endif # ZERO_BUILD
+
 #  NOT Windows ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ NOT Windows
 
 endif # PLATFORM
--- a/make/java/version/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/java/version/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -33,7 +33,7 @@
 all build: $(GENSRCDIR)/sun/misc/Version.java
 
 $(GENSRCDIR)/sun/misc/Version.java: \
-		$(SHARE_SRC)/classes/sun/misc/Version-template.java
+		$(SHARE_SRC)/classes/sun/misc/Version.java.template
 	$(prep-target)
 	$(RM) $@.temp
 	$(SED) -e 's/@@launcher_name@@/$(LAUNCHER_NAME)/g' \
--- a/make/javax/sound/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/javax/sound/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -128,7 +128,7 @@
 
 # for dynamic inclusion of extra sound libs: these
 # JNI libs will be loaded from Platform.java
-CPPFLAGS += -DEXTRA_SOUND_JNI_LIBS="\"$(EXTRA_SOUND_JNI_LIBS)\""
+CPPFLAGS += -DEXTRA_SOUND_JNI_LIBS='"$(EXTRA_SOUND_JNI_LIBS)"'
 
 # integrate MIDI i/o in jsound lib
 ifeq ($(INCLUDE_MIDI),TRUE)
--- a/make/javax/sound/SoundDefs.gmk	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/javax/sound/SoundDefs.gmk	Thu Nov 12 23:04:42 2009 +0000
@@ -55,21 +55,25 @@
 
 endif # PLATFORM solaris
 
-ifeq ($(ARCH), i586)
-  CPPFLAGS += -DX_ARCH=X_I586
-endif # ARCH i586
-
-ifeq ($(ARCH), sparc)
-  CPPFLAGS += -DX_ARCH=X_SPARC
-endif # ARCH sparc
+ifeq ($(ZERO_BUILD), true)
+  CPPFLAGS += -DX_ARCH=X_ZERO
+else
+  ifeq ($(ARCH), i586)
+    CPPFLAGS += -DX_ARCH=X_I586
+  endif # ARCH i586
 
-ifeq ($(ARCH), sparcv9)
-  CPPFLAGS += -DX_ARCH=X_SPARCV9
-endif # ARCH sparcv9
+  ifeq ($(ARCH), sparc)
+    CPPFLAGS += -DX_ARCH=X_SPARC
+  endif # ARCH sparc
 
-ifeq ($(ARCH), amd64)
-  CPPFLAGS += -DX_ARCH=X_AMD64
-endif # ARCH amd64
+  ifeq ($(ARCH), sparcv9)
+    CPPFLAGS += -DX_ARCH=X_SPARCV9
+  endif # ARCH sparcv9
+
+  ifeq ($(ARCH), amd64)
+    CPPFLAGS += -DX_ARCH=X_AMD64
+  endif # ARCH amd64
+endif
 
 
 # files needed for MIDI i/o
--- a/make/jdk_generic_profile.sh	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/jdk_generic_profile.sh	Thu Nov 12 23:04:42 2009 +0000
@@ -339,3 +339,82 @@
 PATH="${path4sdk}"
 export PATH
 
+# Export variables required for Zero
+if [ "${ZERO_BUILD}" = true ] ; then
+  # ZERO_LIBARCH is the name of the architecture-specific
+  # subdirectory under $JAVA_HOME/jre/lib
+  arch=$(uname -m)
+  case "${arch}" in
+    x86_64)  ZERO_LIBARCH=amd64     ;;
+    i?86)    ZERO_LIBARCH=i386      ;;
+    sparc64) ZERO_LIBARCH=sparcv9   ;;
+    arm*)    ZERO_LIBARCH=arm       ;;
+    *)       ZERO_LIBARCH="$(arch)"
+  esac
+  export ZERO_LIBARCH
+
+  # ARCH_DATA_MODEL is the number of bits in a pointer
+  case "${ZERO_LIBARCH}" in
+    i386|ppc|s390|sparc|arm)
+      ARCH_DATA_MODEL=32
+      ;;
+    amd64|ppc64|s390x|sparcv9|ia64|alpha)
+      ARCH_DATA_MODEL=64
+      ;;
+    *)
+      echo "ERROR: Unable to determine ARCH_DATA_MODEL for ${ZERO_LIBARCH}"
+      exit 1
+  esac
+  export ARCH_DATA_MODEL
+
+  # ZERO_ENDIANNESS is the endianness of the processor
+  case "${ZERO_LIBARCH}" in
+    i386|amd64|ia64)
+      ZERO_ENDIANNESS=little
+      ;;
+    ppc*|s390*|sparc*|alpha)
+      ZERO_ENDIANNESS=big
+      ;;
+    *)
+      echo "ERROR: Unable to determine ZERO_ENDIANNESS for ${ZERO_LIBARCH}"
+      exit 1
+  esac
+  export ZERO_ENDIANNESS
+
+  # ZERO_ARCHDEF is used to enable architecture-specific code
+  case "${ZERO_LIBARCH}" in
+    i386)   ZERO_ARCHDEF=IA32  ;;
+    ppc*)   ZERO_ARCHDEF=PPC   ;;
+    s390*)  ZERO_ARCHDEF=S390  ;;
+    sparc*) ZERO_ARCHDEF=SPARC ;;
+    *)      ZERO_ARCHDEF=$(echo "${ZERO_LIBARCH}" | tr a-z A-Z)
+  esac
+  export ZERO_ARCHDEF
+
+  # ZERO_ARCHFLAG tells the compiler which mode to build for
+  case "${ZERO_LIBARCH}" in
+    s390)
+      ZERO_ARCHFLAG="-m31"
+      ;;
+    *)
+      ZERO_ARCHFLAG="-m${ARCH_DATA_MODEL}"
+  esac
+  export ZERO_ARCHFLAG
+
+  # LIBFFI_CFLAGS and LIBFFI_LIBS tell the compiler how to compile and
+  # link against libffi
+  pkgconfig=$(which pkg-config 2>/dev/null)
+  if [ -x "${pkgconfig}" ] ; then
+    if [ "${LIBFFI_CFLAGS}" = "" ] ; then
+      LIBFFI_CFLAGS=$("${pkgconfig}" --cflags libffi)
+    fi
+    if [ "${LIBFFI_LIBS}" = "" ] ; then
+      LIBFFI_LIBS=$("${pkgconfig}" --libs libffi)
+    fi
+  fi
+  if [ "${LIBFFI_LIBS}" = "" ] ; then
+      LIBFFI_LIBS="-lffi"
+  fi
+  export LIBFFI_CFLAGS
+  export LIBFFI_LIBS
+fi
--- a/make/jprt.properties	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/jprt.properties	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright 2006-2008 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2006-2009 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -34,8 +34,8 @@
 solaris_x64_5.10,\
 linux_i586_2.6,\
 linux_x64_2.6,\
-windows_i586,\
-windows_x64
+windows_i586_5.0,\
+windows_x64_5.2
 
 # The different build flavors we want
 jprt.build.flavors=product,fastdebug
@@ -51,21 +51,37 @@
 jprt.solaris_sparcv9.build.platform.match32=solaris_sparc_5.10
 jprt.solaris_x64.build.platform.match32=solaris_i586_5.10
 
-# Standard list of jprt test targets for this workspace
+# Standard test target for everybody
 jprt.test.targets=*-*-*-jvm98
-jprt.regression.test.targets=        \
-   *-product-*-java/lang,            \
-   *-product-*-java/security,        \
-   *-product-*-java/text,            \
-   *-product-*-java/util
 
-#jprt.regression.test.targets=   \
-#   *-product-*-java/awt,       \
-#   *-product-*-java/beans,     \
-#   *-product-*-java/io,        \
-#   *-product-*-java/net,       \
-#   *-product-*-java/nio,       \
-#   *-product-*-java/rmi,       \
+# 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
+
+# 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,       \
 
 # Directories needed to build
 jprt.bundle.exclude.src.dirs=build
--- a/make/launchers/Makefile.launcher	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/launchers/Makefile.launcher	Thu Nov 12 23:04:42 2009 +0000
@@ -137,15 +137,15 @@
   #   PROGRAM, JAVA_ARGS, and APP_CLASSPATH are used in src/share/bin/java.c
   #   SA is currently not available on windows (for any ARCH), or linux-ia64:
   ifneq ($(ARCH), ia64)
-    JDB_CLASSPATH = "{ \"/lib/tools.jar\", \"/lib/sa-jdi.jar\", \"/classes\" }"
-    OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(JDB_CLASSPATH)
+    JDB_CLASSPATH = { "/lib/tools.jar", "/lib/sa-jdi.jar", "/classes" }
+    OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(JDB_CLASSPATH)'
   endif
 endif
 
 # jconsole only
 ifeq ($(PROGRAM),jconsole)
-  JCONSOLE_CLASSPATH = "{ \"/lib/jconsole.jar\", \"/lib/tools.jar\", \"/classes\" }"
-  OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(JCONSOLE_CLASSPATH)
+  JCONSOLE_CLASSPATH = { "/lib/jconsole.jar", "/lib/tools.jar", "/classes" }
+  OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(JCONSOLE_CLASSPATH)'
   ifeq ($(PLATFORM), windows)
     OTHER_CPPFLAGS += -DJAVAW
     LDLIBS_COMMON  += user32.lib
@@ -163,8 +163,8 @@
 
 # SA tools need special app classpath
 ifeq ($(SA_TOOL),true)
-  SA_CLASSPATH = "{ \"/lib/tools.jar\", \"/lib/sa-jdi.jar\", \"/classes\"}"
-  OTHER_CPPFLAGS += -DAPP_CLASSPATH=$(SA_CLASSPATH)
+  SA_CLASSPATH = { "/lib/tools.jar", "/lib/sa-jdi.jar", "/classes" }
+  OTHER_CPPFLAGS += -DAPP_CLASSPATH='$(SA_CLASSPATH)'
 endif
 
 # Wildcards
@@ -173,11 +173,11 @@
 endif
 
 # Always tell native code what the main class is
-OTHER_CPPFLAGS += -DMAIN_CLASS=\"$(MAIN_CLASS)\"
+OTHER_CPPFLAGS += -DMAIN_CLASS='"$(MAIN_CLASS)"'
 
 # Construct initializer for initial arguments to java
 ALL_ARGS = -J-ms8m $(MAIN_JAVA_ARGS) $(MAIN_CLASS) $(MAIN_ARGS)
-JAVA_ARGS = "{ $(ALL_ARGS:%=\"%\",)  }"
+JAVA_ARGS = { $(ALL_ARGS:%="%",)  }
 
 # Always report launcher info
 build: launcher_info
--- a/make/netbeans/jconsole/build.properties	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/netbeans/jconsole/build.properties	Thu Nov 12 23:04:42 2009 +0000
@@ -33,7 +33,7 @@
     com/sun/tools/jconsole/ \
     sun/tools/jconsole/
 excludes=\
-    sun/tools/jconsole/Version-template.java
+    sun/tools/jconsole/Version.java.template
 jtreg.tests=\
     sun/tools/jconsole/
 javadoc.packagenames=\
--- a/make/netbeans/jconsole/build.xml	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/netbeans/jconsole/build.xml	Thu Nov 12 23:04:42 2009 +0000
@@ -35,7 +35,7 @@
 
     <target name="-pre-compile">
         <copy
-            file="${root}/src/share/classes/sun/tools/jconsole/Version-template.java"
+            file="${root}/src/share/classes/sun/tools/jconsole/Version.java.template"
             tofile="${gensrc.dir}/sun/tools/jconsole/Version.java"/>
         <replace
             file="${gensrc.dir}/sun/tools/jconsole/Version.java"
--- a/make/sun/awt/mapfile-vers	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/sun/awt/mapfile-vers	Thu Nov 12 23:04:42 2009 +0000
@@ -53,7 +53,6 @@
 		Java_sun_awt_image_GifImageDecoder_initIDs;
 		Java_sun_awt_image_GifImageDecoder_parseImage;
 		Java_sun_awt_image_ImageRepresentation_initIDs;
-		Java_sun_awt_image_ImageRepresentation_setBytePixels;
 		Java_sun_awt_image_ImageRepresentation_setDiffICM;
 		Java_sun_awt_image_ImageRepresentation_setICMpixels;
 		Java_sun_awt_image_ImagingLib_convolveBI;
--- a/make/sun/awt/mapfile-vers-linux	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/sun/awt/mapfile-vers-linux	Thu Nov 12 23:04:42 2009 +0000
@@ -55,7 +55,6 @@
 		Java_sun_awt_image_GifImageDecoder_parseImage;
 		Java_sun_awt_image_Image_initIDs;
 		Java_sun_awt_image_ImageRepresentation_initIDs;
-		Java_sun_awt_image_ImageRepresentation_setBytePixels;
 		Java_sun_awt_image_ImageRepresentation_setDiffICM;
 		Java_sun_awt_image_ImageRepresentation_setICMpixels;
 		Java_sun_awt_image_ImagingLib_convolveBI;
--- a/make/sun/jconsole/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/sun/jconsole/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -70,7 +70,7 @@
 build: $(FILES_png) $(FILES_gif) $(TEMPDIR)/manifest $(JARFILE)
 
 $(GENSRCDIR)/sun/tools/jconsole/Version.java: \
-                $(SHARE_SRC)/classes/sun/tools/jconsole/Version-template.java
+                $(SHARE_SRC)/classes/sun/tools/jconsole/Version.java.template
 	$(MKDIR) -p $(@D)
 	$(SED) -e 's/@@jconsole_version@@/$(FULL_VERSION)/g' $< > $@
 
--- a/make/sun/nio/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/sun/nio/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -44,14 +44,6 @@
 include FILES_java.gmk
 AUTO_FILES_JAVA_DIRS = sun/nio/cs/ext
 
-# Exclude a few sources on windows
-ifeq ($(PLATFORM), windows)
-  AUTO_JAVA_PRUNE = sun/nio/cs/ext/COMPOUND_TEXT.java         \
-                    sun/nio/cs/ext/COMPOUND_TEXT_Decoder.java \
-                    sun/nio/cs/ext/COMPOUND_TEXT_Encoder.java \
-                    sun/nio/cs/ext/CompoundTextSupport.java
-endif # PLATFORM
-
 # For Cygwin, command line arguments that are paths must be converted to
 # windows style paths. These paths cannot be used as targets, however, because 
 # the ":" in them  will interfere with GNU Make rules, generating "multiple
--- a/make/tools/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/make/tools/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -38,7 +38,6 @@
   compile_properties        \
   dir_diff                  \
   dtdbuilder                \
-  fontchecker               \
   freetypecheck             \
   generate_break_iterator   \
   GenerateCharacter         \
--- a/make/tools/fontchecker/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-#
-# Copyright 1998-2005 Sun Microsystems, Inc.  All Rights Reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Sun designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
-# CA 95054 USA or visit www.sun.com if you need additional information or
-# have any questions.
-#
-
-#
-# Makefile for building the fontchecker tool
-#
-
-BUILDDIR = ../..
-PACKAGE = build.tools.fontchecker
-PRODUCT = tools
-PROGRAM = fontchecker
-include $(BUILDDIR)/common/Defs.gmk
-
-BUILDTOOL_SOURCE_ROOT = $(BUILDDIR)/tools/src
-BUILDTOOL_MAIN        = $(PKGDIR)/FontChecker.java
-
-#
-# Build tool jar rules.
-#
-include $(BUILDDIR)/common/BuildToolJar.gmk
-
--- a/make/tools/src/build/tools/fontchecker/FontCheckDummy.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * Copyright 2002-2004 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package build.tools.fontchecker;
-
-import java.awt.*;
-import java.awt.image.*;
-import java.io.*;
-
-/**
- * FontCheckDummy (not unlike Crash Test Dummy).
- *
- * <PRE>
- * FontCheckDummy is the "child" process. Its task is to verify
- * integrity of system fonts. Since unexpected crashes are known
- * to occur when certain fonts are manipulated, the process is
- * "monitored" by the parent process, which might have to restart
- * the "child" if it crashes.
- * </PRE>
- *
- * @author Ilya Bagrak
- */
-public class FontCheckDummy implements FontCheckerConstants {
-
-    /**
-     * Input stream from parent process.
-     */
-    private BufferedReader is;
-
-    /**
-     * Output stream to parent process.
-     */
-    private BufferedOutputStream os;
-
-    /**
-     * Image on which font characters will be drawn.
-     */
-    private BufferedImage bi;
-
-    /**
-     * graphics object on which characters will be drawn.
-     */
-    private Graphics graphics;
-
-    /**
-     * This constructor wraps the process's standard output and input streams
-     * to enable easier communication with parent process. It also initializes
-     * the graphics object used for drawing font characters.
-     * <BR><BR>
-     * @see FontCheckerConstants
-     */
-    public FontCheckDummy() {
-        is = new BufferedReader(new InputStreamReader(System.in));
-        os = new BufferedOutputStream(System.out);
-        /* make suffficient space for 12 point font */
-        bi = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
-        graphics = bi.getGraphics();
-        try {
-            os.write(CHILD_STARTED_OK);
-            os.flush();
-        } catch (IOException e) {
-            System.exit(-1);
-        }
-    }
-
-    /**
-     * Initializes an instance of Font from given font path.
-     * <BR>
-     * This methods attempts to create an instance of font from
-     * a string that represents path to the font file.
-     * <BR><BR>
-     * @param fontPath string representing path to font file
-     * @param flag indicating whether or not checking of non-TrueType fonts
-     * is necessary
-     */
-    private void testFont(String fontPath, boolean checkNonTTF) {
-
-        FontFileFilter fff = new FontFileFilter(checkNonTTF);
-        File fontFile = new File(fontPath);
-        if (!fontFile.canRead()) {
-            try {
-                os.write(ERR_FONT_NOT_FOUND);
-                os.flush();
-            } catch (IOException e) {
-                System.exit(-1);
-            }
-        }
-        Font font = null;
-        try {
-            File file = new File(fontPath);
-            font = Font.createFont(fff.getFontType(fontPath), file);
-        } catch (FontFormatException e1) {
-        } catch (IOException e2) {
-        }
-        if (font == null) {
-             return;
-        }
-        font = font.deriveFont(Font.PLAIN, 12);
-        String name = font.getFontName();
-        String family = font.getFamily();
-
-        char[] testChars = { '0' };
-        if (font.canDisplay(testChars[0])) {
-            graphics.setFont(font);
-            graphics.drawChars(testChars, 0, 1, 20, 20);
-        }
-        try {
-            os.write(ERR_FONT_OK);
-            os.flush();
-        } catch (IOException e) {
-            System.exit(-1);
-        }
-    }
-
-    /**
-     * Begins synchronous communication betweeen parent and child processes.
-     * <BR>
-     * This method begins communication between parent and child processes.
-     * FontCheckDummy reads a line of text from input stream (@see #is).
-     */
-    public void run() {
-        String command = null;
-        while (true) {
-            try {
-                command = is.readLine();
-            } catch (IOException e) {
-                System.exit(-1);
-            }
-            if (command != null && command.length() >= 1) {
-                int cmd = Integer.parseInt(command.substring(0,1));
-                if (cmd == EXITCOMMAND) {
-                    return;
-                }
-                boolean checkNonTTF = ((cmd == 1) ? true : false);
-                String fontPath = command.substring(1);
-                testFont(fontPath, checkNonTTF);
-            } else {
-                return;
-            }
-        }
-    }
-
-    public static void main(String[] args) {
-        try {
-            /* Background app. */
-            System.setProperty("java.awt.headless", "true");
-            System.setProperty("sun.java2d.noddraw", "true");
-            new FontCheckDummy().run();
-        } catch (Throwable t) {
-        }
-        System.exit(0);
-    }
-}
--- a/make/tools/src/build/tools/fontchecker/FontChecker.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,452 +0,0 @@
-/*
- * Copyright 2002-2004 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package build.tools.fontchecker;
-
-import java.io.*;
-import java.util.*;
-import java.awt.event.*;
-import sun.font.FontManager;
-
-/**
- * FontChecker.
- *
- * <PRE>
- * This is a FontChecker program. This class is a "parent" process
- * which invokes a "child" process. The child process will test
- * series of fonts and may crash as it encounters invalid fonts.
- * The "parent" process must then interpret error codes passed to it
- * by the "child" process and restart the "child" process if necessary.
- *
- * usage: java FontChecker [-v] -o outputfile
- *
- *        -o is the name of the file to contains canonical path names of
- *           bad fonts that are identified. This file is not created if
- *           no bad fonts are found.
- *        -v verbose: prints progress messages.
- *
- * </PRE>
- *
- * @author Ilya Bagrak
- */
-public class FontChecker implements ActionListener, FontCheckerConstants {
-
-    /**
-     * Output stream to subprocess.
-     * Corresponds to the subprocess's System.in".
-     */
-    private PrintWriter procPipeOut;
-
-    /**
-     * Input stream from subprocess.
-     * Corresponds to the subprocess's System.out".
-     */
-    private BufferedInputStream procPipeIn;
-
-    /**
-     * Child process.
-     */
-    private Process childProc;
-
-    /**
-     * Name of output file to write file names of bad fonts
-     */
-    private String outputFile;
-
-    /**
-     * Reference to currently executing thread.
-     */
-    private Thread currThread;
-
-    /**
-     * Timeout timer for a single font check
-     */
-    private javax.swing.Timer timeOne;
-
-    /**
-     * Timeout timer for all font checks
-     */
-    private javax.swing.Timer timeAll;
-
-    /**
-     * max time (in milliseconds) allowed for checking a single font.
-     */
-    private static int timeoutOne = 10000;
-
-    /**
-     * max time (in milliseconds) allowed for checking all fonts.
-     */
-    private static int timeoutAll = 120000;
-
-    /**
-     * Boolean flag indicating whether FontChecker is required to
-     * check non-TrueType fonts.
-     */
-    private boolean checkNonTTF = false;
-
-    /**
-     * List of bad fonts found in the system.
-     */
-    private Vector badFonts = new Vector();
-
-    /**
-     * whether to print warnings messges etc to stdout/err
-     * default is false
-     */
-    private static boolean verbose = false;
-
-    /* Command to use to exec sub-process. */
-    private static String javaCmd = "java";
-
-    static void printlnMessage(String s) {
-        if (verbose) {
-            System.out.println(s);
-        }
-    }
-
-    /**
-     * Event handler for timer event.
-     * <BR>
-     * Stops the timer and interrupts the current thread which is
-     * still waiting on I/O from the child process.
-     * <BR><BR>
-     * @param evt timer event
-     */
-    public void actionPerformed(ActionEvent evt) {
-        if (evt.getSource() == timeOne) {
-            timeOne.stop();
-            printlnMessage("Child timed out: killing");
-            childProc.destroy();
-        } else {
-            doExit(); // went on too long (ie timeAll timed out).
-        }
-    }
-
-    /**
-     * Initializes a FontChecker.
-     * <BR>
-     * This method is usually called after an unrecoverable error has
-     * been detected and a child process has  either crashed or is in bad
-     * state. The method creates a new child process from
-     * scratch and initializes it's input/output streams.
-     */
-    public void initialize() {
-        try {
-            if (childProc != null) {
-                childProc.destroy();
-            }
-            String fileSeparator = System.getProperty("file.separator");
-            String javaHome = System.getProperty("java.home");
-            String classPath =  System.getProperty("java.class.path");
-            classPath = "\"" + classPath + "\"";
-            String opt = "-cp " + classPath + " -Dsun.java2d.fontpath=\"" +
-                javaHome + fileSeparator + "lib" + fileSeparator + "fonts\"";
-
-            /* command to exec the child process with the same JRE */
-            String cmd =
-                new String(javaHome + fileSeparator + "bin" +
-                           fileSeparator + javaCmd +
-                           " -XXsuppressExitMessage " + opt +
-                           " com.sun.java2d.fontchecker.FontCheckDummy");
-            printlnMessage("cmd="+cmd);
-            childProc = Runtime.getRuntime().exec(cmd);
-
-        } catch (IOException e) {
-            printlnMessage("can't execute child process");
-            System.exit(0);
-        } catch (SecurityException e) {
-            printlnMessage("Error: access denied");
-            System.exit(0);
-        }
-
-        /* initialize input/output streams to/from child process */
-        procPipeOut = new PrintWriter(childProc.getOutputStream());
-        procPipeIn = new BufferedInputStream(childProc.getInputStream());
-
-        try {
-            int code = procPipeIn.read();
-            if (code != CHILD_STARTED_OK) {
-                printlnMessage("bad child process start status="+code);
-                doExit();
-            }
-        } catch (IOException e) {
-            printlnMessage("can't read child process start status unknown");
-            doExit();
-        }
-    }
-
-    private void doExit() {
-        try {
-            if (procPipeOut != null) {
-                /* Tell the child to exit */
-                procPipeOut.write(EXITCOMMAND+System.getProperty("line.separator"));
-                procPipeOut.flush();
-                procPipeOut.close();
-            }
-        } catch (Throwable t) {
-        }
-        System.exit(0);
-    }
-
-    /**
-     * Tries to verify integrity of a font specified by a path.
-     * <BR>
-     * This method is used to test whether a font specified by the given
-     * path is valid and does not crash the system.
-     * <BR><BR>
-     * @param fontPath a string representation of font path
-     * to standard out during while this font is tried
-     * @return returns <code>true</code> if font is OK, and
-     * <code>false</code> otherwise.
-     */
-    public boolean tryFont(File fontFile) {
-        int bytesRead = 0;
-        String fontPath = fontFile.getAbsolutePath();
-
-        printlnMessage("Checking font "+fontPath);
-
-        /* store reference to the current thread, so that when the timer
-         * fires it can be interrupted
-         */
-        currThread = Thread.currentThread();
-        timeOne.restart();
-
-        /* write a string command out to child process
-         * The command is formed by appending whether to test non-TT fonts
-         * and font path to be tested
-         */
-        String command = Integer.toString(checkNonTTF ? 1 : 0) +
-                         fontPath +
-                         System.getProperty("line.separator");
-        procPipeOut.write(command);
-        procPipeOut.flush();
-
-        /* check if underlying stream has encountered an error after
-         * command has been issued
-         */
-        if (procPipeOut.checkError()){
-            printlnMessage("Error: font crashed");
-            initialize();
-            return false;
-        }
-
-        /* trying reading error code back from child process */
-        try {
-            bytesRead = procPipeIn.read();
-        } catch(InterruptedIOException e) {
-            /* A timeout timer fired before the operation completed */
-            printlnMessage("Error: timeout occured");
-            initialize();
-            return false;
-        } catch(IOException e) {
-            /* there was an error reading from the stream */
-            timeOne.stop();
-            printlnMessage("Error: font crashed");
-            initialize();
-            return false;
-        } catch (Throwable t) {
-            bytesRead = ERR_FONT_READ_EXCPT;
-        } finally {
-          timeOne.stop();
-        }
-
-        if (bytesRead == ERR_FONT_OK) {
-            printlnMessage("Font integrity verified");
-            return true;
-        } else if (bytesRead > 0) {
-
-            switch(bytesRead){
-            case ERR_FONT_NOT_FOUND:
-                printlnMessage("Error: font not found!");
-                break;
-            case ERR_FONT_BAD_FORMAT:
-                printlnMessage("Error: incorrect font format");
-                break;
-            case ERR_FONT_READ_EXCPT:
-                printlnMessage("Error: exception reading font");
-                break;
-            case ERR_FONT_DISPLAY:
-                printlnMessage("Error: can't display characters");
-                break;
-            case ERR_FONT_CRASH:
-                printlnMessage("Error: font crashed");
-                break;
-            default:
-                printlnMessage("Error: invalid error code:"+bytesRead);
-                break;
-
-            }
-        } else if (bytesRead == ERR_FONT_EOS) {
-            printlnMessage("Error: end of stream marker encountered");
-        } else {
-            printlnMessage("Error: invalid error code:"+bytesRead);
-        }
-
-        /* if we still haven't returned from this method, some error
-         * condition has occured and it is safer to re-initialize
-         */
-        initialize();
-        return false;
-    }
-
-    /**
-     * Checks the integrity of all system fonts.
-     * <BR>
-     * This method goes through every font in system's font path and verifies
-     * its integrity via the tryFont method.
-     * <BR><BR>
-     * @param restart <code>true</code> if checking of fonts should continue
-     * after the first  bad font is found, and <code>false</code> otherwise
-     * @return returns <code>true</code> if all fonts are valid,
-     * <code>false</code> otherwise
-     * @see #tryFont(String, boolean, boolean)
-     */
-    public boolean checkFonts(boolean restart) {
-
-        /* file filter to filter out none-truetype font files */
-        FontFileFilter fff = new FontFileFilter(checkNonTTF);
-        boolean checkOk = true;
-
-        /* get platform-independent font path. Note that this bypasses
-         * the normal GraphicsEnvironment initialisation. In conjunction with
-         * the headless setting above, so we want to add
-         * java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
-         * to trigger a more normal initialisation.
-         */
-        java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
-        String fontPath = FontManager.getFontPath(true);
-        StringTokenizer st =
-            new StringTokenizer(fontPath,
-                                System.getProperty("path.separator"));
-
-        /* some systems may have multiple font paths separated by
-         * platform-dependent characters, so fontPath string needs to be
-         * parsed
-         */
-        timeOne = new javax.swing.Timer(timeoutOne, this);
-        timeAll = new javax.swing.Timer(timeoutAll, this);
-        timeAll.restart();
-        while (st.hasMoreTokens()) {
-            File fontRoot = new File(st.nextToken());
-            File[] fontFiles = fontRoot.listFiles(fff);
-
-            for (int i = 0; i < fontFiles.length; i++) {
-                /* for each font file that is not a directory and passes
-                 * through the font filter run the test
-                 */
-                if (!fontFiles[i].isDirectory() &&
-                    !tryFont(fontFiles[i])) {
-
-                    checkOk = false;
-                    badFonts.add(fontFiles[i].getAbsolutePath());
-                    if (!restart) {
-                        break;
-                    }
-                }
-            }
-        }
-
-        /* Tell the child to exit */
-        procPipeOut.write(EXITCOMMAND+System.getProperty("line.separator"));
-        procPipeOut.flush();
-        procPipeOut.close();
-
-        return checkOk;
-    }
-
-    public static void main(String args[]){
-        try {
-            /* Background app. */
-            System.setProperty("java.awt.headless", "true");
-            System.setProperty("sun.java2d.noddraw", "true");
-
-            boolean restart = true;
-            boolean errorFlag = false;
-
-            FontChecker fc = new FontChecker();
-            int arg = 0;
-
-            while (arg < args.length && errorFlag == false) {
-                if (args[arg].equals("-v")) {
-                    verbose = true;
-                }
-                else if (args[arg].equals("-w") &&
-                         System.getProperty("os.name", "unknown").
-                         startsWith("Windows")) {
-                    javaCmd = "javaw";
-                }
-                else if (args[arg].equals("-o")) {
-                    /* set output file */
-                    if (++arg < args.length)
-                        fc.outputFile = args[arg];
-                    else {
-                        /* invalid argument format */
-                        printlnMessage("Error: invalid argument format");
-                        errorFlag = true;
-                    }
-                }
-                else {
-                    /* invalid command line argument */
-                    printlnMessage("Error: invalid argument value");
-                    errorFlag = true;
-                }
-                arg++;
-            }
-
-            if (errorFlag || fc.outputFile == null) {
-                System.exit(0);
-            }
-
-            File outfile = new File(fc.outputFile);
-            if (outfile.exists()) {
-                outfile.delete();
-            }
-
-            fc.initialize();
-
-            if (!fc.checkFonts(restart)) {
-                String[] badFonts = (String[])fc.badFonts.toArray(new String[0]);
-                if (badFonts.length > 0) {
-                    printlnMessage("Bad Fonts:");
-                    try {
-                        FileOutputStream fos =
-                            new FileOutputStream(fc.outputFile);
-                        PrintStream ps = new  PrintStream(fos);
-                        for (int i = 0; i < badFonts.length; i++) {
-                            ps.println(badFonts[i]);
-                            printlnMessage(badFonts[i]);
-                        }
-                        fos.close();
-                    } catch (IOException e) {
-                    }
-                }
-            } else {
-                printlnMessage("No bad fonts found.");
-        }
-        } catch (Throwable t) {
-        }
-        System.exit(0);
-    }
-}
--- a/make/tools/src/build/tools/fontchecker/FontCheckerConstants.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2002-2004 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package build.tools.fontchecker;
-
-public interface FontCheckerConstants {
-
-    /* code sent to indicate child process started OK */
-    public static final int CHILD_STARTED_OK   = 100;
-
-    /* error codes returned from child process */
-    public static final int ERR_FONT_OK         = 65;
-    public static final int ERR_FONT_NOT_FOUND  = 60;
-    public static final int ERR_FONT_BAD_FORMAT = 61;
-    public static final int ERR_FONT_READ_EXCPT = 62;
-    public static final int ERR_FONT_DISPLAY    = 64;
-    public static final int ERR_FONT_EOS        = -1;
-    /* nl char sent after child crashes */
-    public static final int ERR_FONT_CRASH      = 10;
-
-    /* 0 and 1 are reserved, and commands can only be a single digit integer */
-    public static final int EXITCOMMAND = 2;
-}
--- a/make/tools/src/build/tools/fontchecker/FontFileFilter.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright 2002-2003 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * <PRE>
- * This class filters TrueType font files from other file
- * found in the font path.
- *
- * </PRE>
- *
- * @author Ilya Bagrak
- */
-
-package build.tools.fontchecker;
-
-import java.awt.*;
-import java.io.*;
-
-public class FontFileFilter implements java.io.FileFilter, FontCheckerConstants {
-
-    /**
-     * Boolean flag indicating whether this filter filters out
-     * non-TrueType fonts.
-     */
-    private boolean checkNonTTF;
-
-    public FontFileFilter() {
-        this(false);
-    }
-
-    public FontFileFilter(boolean checkNonTTF) {
-        super();
-        this.checkNonTTF = checkNonTTF;
-    }
-
-    /**
-     * Checks whether a file is accepted by this filter.
-     * <BR>
-     * This method checks whehter a file is accepted by this filter.
-     * This filter is made to accept all the file whose extension is
-     * either .ttf or .TTF. These files are assumed to be TrueType fonts.
-     * <BR><BR>
-     * @return returns a boolean value indicating whether or not a file is
-     * accepted
-     */
-    public boolean accept(File pathname) {
-
-        String name = pathname.getName();
-        return (name.endsWith(".ttf") ||
-                name.endsWith(".TTF") ||
-                name.endsWith(".ttc") ||
-                name.endsWith(".TTC"))  ||
-            (name.endsWith(".pfb") ||
-             name.endsWith(".PFB") ||
-             name.endsWith(".pfa") ||
-             name.endsWith(".PFA") &&
-             checkNonTTF == true);
-    }
-
-    public static int getFontType(String filename) {
-        if (filename.endsWith(".ttf") ||
-            filename.endsWith(".TTF") ||
-            filename.endsWith(".ttc") ||
-            filename.endsWith(".TTC"))
-            return Font.TRUETYPE_FONT;
-        else if (filename.endsWith(".pfb") ||
-                 filename.endsWith(".PFB") ||
-                 filename.endsWith(".pfa") ||
-                 filename.endsWith(".PFA"))
-            return Font.TYPE1_FONT;
-        else
-            return 999;
-    }
-
-}
--- a/make/tools/src/build/tools/fontchecker/README.txt	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2002-2003 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-Instructions for running FontChecker 
-------------------------------------
-
-FontChecker is a program designed to identify fonts that may cause JRE
-crashes. Such fonts may be corrupted files, or badly constructed fonts.
-Some crashes may also be due to bugs in the JRE's font code.
-This test is designed to run quickly and silently as part of the JRE
-installation process. It will only benefit users who install the JRE
-via that mechanism. It cannot guarantee to identify all "bad fonts" because
-the tests are minimal. Nor can it prevent problems due to fonts installed
-subsequently to the JRE's installation. However it does ensure that the
-vast majority of problem fonts are identified. This is important
-"RAS" functionality. It is targeted at the consumer/plugin market where
-there is substantial likelihood of end-users having installed software
-packages which may be delivered with fonts that are not up to commercial
-standards.
-
-The test is designed to be "fail safe". If the program fails to run
-properly it has no impact on the installer or on JRE execution.
-Thus there is no need to monitor successful execution of the test.
-
-The test is not a new "tool" in the sense of "javah" etc.
-The test is not designed to be user executable or visible, and should
-be unpacked by the installer into a temporary location, and executed
-once the rest of the JRE is installed (ie as a postinstall step), and
-can then be deleted from the temporary location once installation is
-complete. Not deleting the jar file before execution is complete is
-probably the sole reason that the installer may want to wait for
-the program to complete.
-
-The FontChecker application can be run directly from the jar 
-file with this command: 
-	%java -jar fontchecker.jar -o <file>
-
-The output file is a required parameter in this version of the application.
-The JRE installer should use the above form, and use it to create an
-output file which must be named "badfonts.txt" and be placed into
-the JRE's lib\fonts directory eg:-
-
-        java -jar fontchecker.jar -o "C:\Program Files\jre\lib\fonts\badfonts.txt"
-
-Note the lower case "badfonts.txt", and the string quotes because of the spaces
-in the path name.
-The location given here is an example and needs to be calculated at install
-time as $JREHOME\lib\fonts\badfonts.txt
-The location and name are important, because the JRE at runtime will
-look for this exactly located name and file.
-This location is private to that JRE instance. It will not affect
-any other JRE installed on the system.
-
-If running from a different directory than that containing the jar file,
-use the form containing the full path to the jar file, eg :
-
-	java -jar C:\fc\fontchecker.jar -o "C:\Program Files\jre\lib\fonts\badfonts.txt"
-
-FontChecker application accepts following command line flags. 
-usage: java -jar fontchecker.jar -o outputfile
-	                -v 
-
-       -o is the name of the file to contains canonical path names of
-          bad fonts that are identified. This file is not created if
-          no bad fonts are found.
-
-       -v verbose mode: print progress/warning messages. Not recommended
-         for installer use.
-
-       -w if running on Windows, use "javaw" to exec the sub-process.
--- a/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java	Thu Nov 12 23:04:42 2009 +0000
@@ -62,6 +62,8 @@
 
 import java.io.*;
 import java.nio.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.StringTokenizer;
@@ -502,12 +504,18 @@
             iis.reset();
 
             try {
-                if (metadata.colorSpace == PROFILE_LINKED)
+                if (metadata.colorSpace == PROFILE_LINKED &&
+                    isLinkedProfileAllowed() &&
+                    !isUncOrDevicePath(profile))
+                {
+                    String path = new String(profile, "windows-1252");
+
                     colorSpace =
-                        new ICC_ColorSpace(ICC_Profile.getInstance(new String(profile)));
-                else
+                        new ICC_ColorSpace(ICC_Profile.getInstance(path));
+                } else {
                     colorSpace =
                         new ICC_ColorSpace(ICC_Profile.getInstance(profile));
+                }
             } catch (Exception e) {
                 colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
             }
@@ -1745,4 +1753,69 @@
         public void sequenceStarted(ImageReader src, int minIndex) {}
         public void readAborted(ImageReader src) {}
     }
+
+    private static Boolean isLinkedProfileDisabled = null;
+
+    private static boolean isLinkedProfileAllowed() {
+        if (isLinkedProfileDisabled == null) {
+            PrivilegedAction<Boolean> a = new PrivilegedAction<Boolean>() {
+                public Boolean run() {
+                    return Boolean.getBoolean("sun.imageio.plugins.bmp.disableLinkedProfiles");
+                }
+            };
+            isLinkedProfileDisabled = AccessController.doPrivileged(a);
+        }
+        return !isLinkedProfileDisabled;
+    }
+
+    private static Boolean isWindowsPlatform = null;
+
+    /**
+     * Verifies whether the byte array contans a unc path.
+     * Non-UNC path examples:
+     *  c:\path\to\file  - simple notation
+     *  \\?\c:\path\to\file - long notation
+     *
+     * UNC path examples:
+     *  \\server\share - a UNC path in simple notation
+     *  \\?\UNC\server\share - a UNC path in long notation
+     *  \\.\some\device - a path to device.
+     */
+    private static boolean isUncOrDevicePath(byte[] p) {
+        if (isWindowsPlatform == null) {
+            PrivilegedAction<Boolean> a = new PrivilegedAction<Boolean>() {
+                public Boolean run() {
+                    String osname = System.getProperty("os.name");
+                    return (osname != null &&
+                            osname.toLowerCase().startsWith("win"));
+                }
+            };
+            isWindowsPlatform = AccessController.doPrivileged(a);
+        }
+
+        if (!isWindowsPlatform) {
+            /* no need for the check on platforms except windows */
+            return false;
+        }
+
+        /* normalize prefix of the path */
+        if (p[0] == '/') p[0] = '\\';
+        if (p[1] == '/') p[1] = '\\';
+        if (p[3] == '/') p[3] = '\\';
+
+
+        if ((p[0] == '\\') && (p[1] == '\\')) {
+            if ((p[2] == '?') && (p[3] == '\\')) {
+                // long path: whether unc or local
+                return ((p[4] == 'U' || p[4] == 'u') &&
+                        (p[5] == 'N' || p[5] == 'n') &&
+                        (p[6] == 'C' || p[6] == 'c'));
+            } else {
+                // device path or short unc notation
+                return true;
+            }
+        } else {
+            return false;
+        }
+    }
 }
--- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package com.sun.java.swing.plaf.motif;
 
+import sun.awt.AppContext;
+
 import javax.swing.*;
 import javax.swing.border.*;
 import javax.swing.plaf.basic.*;
@@ -46,16 +48,23 @@
  */
 public class MotifButtonUI extends BasicButtonUI {
 
-    private final static MotifButtonUI motifButtonUI = new MotifButtonUI();
-
     protected Color selectColor;
 
     private boolean defaults_initialized = false;
 
+    private static final Object MOTIF_BUTTON_UI_KEY = new Object();
+
     // ********************************
     //          Create PLAF
     // ********************************
-    public static ComponentUI createUI(JComponent c){
+    public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        MotifButtonUI motifButtonUI =
+                (MotifButtonUI) appContext.get(MOTIF_BUTTON_UI_KEY);
+        if (motifButtonUI == null) {
+            motifButtonUI = new MotifButtonUI();
+            appContext.put(MOTIF_BUTTON_UI_KEY, motifButtonUI);
+        }
         return motifButtonUI;
     }
 
--- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package com.sun.java.swing.plaf.motif;
 
+import sun.awt.AppContext;
+
 import javax.swing.*;
 
 import javax.swing.plaf.*;
@@ -45,7 +47,7 @@
  */
 public class MotifCheckBoxUI extends MotifRadioButtonUI {
 
-    private static final MotifCheckBoxUI motifCheckBoxUI = new MotifCheckBoxUI();
+    private static final Object MOTIF_CHECK_BOX_UI_KEY = new Object();
 
     private final static String propertyPrefix = "CheckBox" + ".";
 
@@ -55,7 +57,14 @@
     // ********************************
     //         Create PLAF
     // ********************************
-    public static ComponentUI createUI(JComponent c){
+    public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        MotifCheckBoxUI motifCheckBoxUI =
+                (MotifCheckBoxUI) appContext.get(MOTIF_CHECK_BOX_UI_KEY);
+        if (motifCheckBoxUI == null) {
+            motifCheckBoxUI = new MotifCheckBoxUI();
+            appContext.put(MOTIF_CHECK_BOX_UI_KEY, motifCheckBoxUI);
+        }
         return motifCheckBoxUI;
     }
 
--- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package com.sun.java.swing.plaf.motif;
 
+import sun.awt.AppContext;
+
 import javax.swing.*;
 import javax.swing.plaf.basic.BasicLabelUI;
 import javax.swing.plaf.ComponentUI;
@@ -44,9 +46,16 @@
  */
 public class MotifLabelUI extends BasicLabelUI
 {
-    static MotifLabelUI sharedInstance = new MotifLabelUI();
+    private static final Object MOTIF_LABEL_UI_KEY = new Object();
 
     public static ComponentUI createUI(JComponent c) {
-        return sharedInstance;
+        AppContext appContext = AppContext.getAppContext();
+        MotifLabelUI motifLabelUI =
+                (MotifLabelUI) appContext.get(MOTIF_LABEL_UI_KEY);
+        if (motifLabelUI == null) {
+            motifLabelUI = new MotifLabelUI();
+            appContext.put(MOTIF_LABEL_UI_KEY, motifLabelUI);
+        }
+        return motifLabelUI;
     }
 }
--- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package com.sun.java.swing.plaf.motif;
 
+import sun.awt.AppContext;
+
 import javax.swing.*;
 import javax.swing.border.*;
 import javax.swing.plaf.basic.BasicRadioButtonUI;
@@ -47,7 +49,7 @@
  */
 public class MotifRadioButtonUI extends BasicRadioButtonUI {
 
-    private static final MotifRadioButtonUI motifRadioButtonUI = new MotifRadioButtonUI();
+    private static final Object MOTIF_RADIO_BUTTON_UI_KEY = new Object();
 
     protected Color focusColor;
 
@@ -57,6 +59,13 @@
     //         Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        MotifRadioButtonUI motifRadioButtonUI =
+                (MotifRadioButtonUI) appContext.get(MOTIF_RADIO_BUTTON_UI_KEY);
+        if (motifRadioButtonUI == null) {
+            motifRadioButtonUI = new MotifRadioButtonUI();
+            appContext.put(MOTIF_RADIO_BUTTON_UI_KEY, motifRadioButtonUI);
+        }
         return motifRadioButtonUI;
     }
 
--- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifToggleButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifToggleButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package com.sun.java.swing.plaf.motif;
 
+import sun.awt.AppContext;
+
 import java.awt.*;
 import java.awt.event.*;
 
@@ -48,7 +50,7 @@
  */
 public class MotifToggleButtonUI extends BasicToggleButtonUI
 {
-    private final static MotifToggleButtonUI motifToggleButtonUI = new MotifToggleButtonUI();
+    private static final Object MOTIF_TOGGLE_BUTTON_UI_KEY = new Object();
 
     protected Color selectColor;
 
@@ -58,6 +60,13 @@
     //         Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent b) {
+        AppContext appContext = AppContext.getAppContext();
+        MotifToggleButtonUI motifToggleButtonUI =
+                (MotifToggleButtonUI) appContext.get(MOTIF_TOGGLE_BUTTON_UI_KEY);
+        if (motifToggleButtonUI == null) {
+            motifToggleButtonUI = new MotifToggleButtonUI();
+            appContext.put(MOTIF_TOGGLE_BUTTON_UI_KEY, motifToggleButtonUI);
+        }
         return motifToggleButtonUI;
     }
 
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -35,6 +35,7 @@
 import static com.sun.java.swing.plaf.windows.TMSchema.*;
 import static com.sun.java.swing.plaf.windows.TMSchema.Part.*;
 import static com.sun.java.swing.plaf.windows.XPStyle.Skin;
+import sun.awt.AppContext;
 
 
 /**
@@ -52,8 +53,6 @@
  */
 public class WindowsButtonUI extends BasicButtonUI
 {
-    private final static WindowsButtonUI windowsButtonUI = new WindowsButtonUI();
-
     protected int dashedRectGapX;
     protected int dashedRectGapY;
     protected int dashedRectGapWidth;
@@ -63,11 +62,19 @@
 
     private boolean defaults_initialized = false;
 
+    private static final Object WINDOWS_BUTTON_UI_KEY = new Object();
 
     // ********************************
     //          Create PLAF
     // ********************************
-    public static ComponentUI createUI(JComponent c){
+    public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        WindowsButtonUI windowsButtonUI =
+                (WindowsButtonUI) appContext.get(WINDOWS_BUTTON_UI_KEY);
+        if (windowsButtonUI == null) {
+            windowsButtonUI = new WindowsButtonUI();
+            appContext.put(WINDOWS_BUTTON_UI_KEY, windowsButtonUI);
+        }
         return windowsButtonUI;
     }
 
@@ -151,7 +158,7 @@
      * allocating them in each paint call substantially reduced the time
      * it took paint to run.  Obviously, this method can't be re-entered.
      */
-    private static Rectangle viewRect = new Rectangle();
+    private Rectangle viewRect = new Rectangle();
 
     public void paint(Graphics g, JComponent c) {
         if (XPStyle.getXP() != null) {
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package com.sun.java.swing.plaf.windows;
 
+import sun.awt.AppContext;
+
 import javax.swing.plaf.basic.*;
 import javax.swing.*;
 import javax.swing.plaf.*;
@@ -49,7 +51,7 @@
     // of BasicCheckBoxUI because we want to pick up all the
     // painting changes made in MetalRadioButtonUI.
 
-    private static final WindowsCheckBoxUI windowsCheckBoxUI = new WindowsCheckBoxUI();
+    private static final Object WINDOWS_CHECK_BOX_UI_KEY = new Object();
 
     private final static String propertyPrefix = "CheckBox" + ".";
 
@@ -59,6 +61,13 @@
     //          Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        WindowsCheckBoxUI windowsCheckBoxUI =
+                (WindowsCheckBoxUI) appContext.get(WINDOWS_CHECK_BOX_UI_KEY);
+        if (windowsCheckBoxUI == null) {
+            windowsCheckBoxUI = new WindowsCheckBoxUI();
+            appContext.put(WINDOWS_CHECK_BOX_UI_KEY, windowsCheckBoxUI);
+        }
         return windowsCheckBoxUI;
     }
 
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,6 +26,8 @@
 package com.sun.java.swing.plaf.windows;
 
 import sun.swing.SwingUtilities2;
+import sun.awt.AppContext;
+
 import java.awt.Color;
 import java.awt.Graphics;
 
@@ -51,12 +53,19 @@
  */
 public class WindowsLabelUI extends BasicLabelUI {
 
-    private final static WindowsLabelUI windowsLabelUI = new WindowsLabelUI();
+    private static final Object WINDOWS_LABEL_UI_KEY = new Object();
 
     // ********************************
     //          Create PLAF
     // ********************************
-    public static ComponentUI createUI(JComponent c){
+    public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        WindowsLabelUI windowsLabelUI =
+                (WindowsLabelUI) appContext.get(WINDOWS_LABEL_UI_KEY);
+        if (windowsLabelUI == null) {
+            windowsLabelUI = new WindowsLabelUI();
+            appContext.put(WINDOWS_LABEL_UI_KEY, windowsLabelUI);
+        }
         return windowsLabelUI;
     }
 
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package com.sun.java.swing.plaf.windows;
 
+import sun.awt.AppContext;
+
 import javax.swing.plaf.basic.*;
 import javax.swing.*;
 import javax.swing.plaf.*;
@@ -44,7 +46,7 @@
  */
 public class WindowsRadioButtonUI extends BasicRadioButtonUI
 {
-    private static final WindowsRadioButtonUI windowsRadioButtonUI = new WindowsRadioButtonUI();
+    private static final Object WINDOWS_RADIO_BUTTON_UI_KEY = new Object();
 
     protected int dashedRectGapX;
     protected int dashedRectGapY;
@@ -59,6 +61,13 @@
     //          Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        WindowsRadioButtonUI windowsRadioButtonUI =
+                (WindowsRadioButtonUI) appContext.get(WINDOWS_RADIO_BUTTON_UI_KEY);
+        if (windowsRadioButtonUI == null) {
+            windowsRadioButtonUI = new WindowsRadioButtonUI();
+            appContext.put(WINDOWS_RADIO_BUTTON_UI_KEY, windowsRadioButtonUI);
+        }
         return windowsRadioButtonUI;
     }
 
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package com.sun.java.swing.plaf.windows;
 
+import sun.awt.AppContext;
+
 import javax.swing.plaf.basic.*;
 import javax.swing.border.*;
 import javax.swing.plaf.*;
@@ -49,18 +51,25 @@
  */
 public class WindowsToggleButtonUI extends BasicToggleButtonUI
 {
-    protected static int dashedRectGapX;
-    protected static int dashedRectGapY;
-    protected static int dashedRectGapWidth;
-    protected static int dashedRectGapHeight;
+    protected int dashedRectGapX;
+    protected int dashedRectGapY;
+    protected int dashedRectGapWidth;
+    protected int dashedRectGapHeight;
 
     protected Color focusColor;
 
-    private final static WindowsToggleButtonUI windowsToggleButtonUI = new WindowsToggleButtonUI();
+    private static final Object WINDOWS_TOGGLE_BUTTON_UI_KEY = new Object();
 
     private boolean defaults_initialized = false;
 
     public static ComponentUI createUI(JComponent b) {
+        AppContext appContext = AppContext.getAppContext();
+        WindowsToggleButtonUI windowsToggleButtonUI =
+                (WindowsToggleButtonUI) appContext.get(WINDOWS_TOGGLE_BUTTON_UI_KEY);
+        if (windowsToggleButtonUI == null) {
+            windowsToggleButtonUI = new WindowsToggleButtonUI();
+            appContext.put(WINDOWS_TOGGLE_BUTTON_UI_KEY, windowsToggleButtonUI);
+        }
         return windowsToggleButtonUI;
     }
 
--- a/src/share/classes/com/sun/jndi/ldap/Connection.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/com/sun/jndi/ldap/Connection.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1999-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,12 +32,8 @@
 import java.io.OutputStream;
 import java.io.InputStream;
 import java.net.Socket;
-import java.util.Vector;
-import java.util.Hashtable;
 
 import javax.naming.CommunicationException;
-import javax.naming.AuthenticationException;
-import javax.naming.AuthenticationNotSupportedException;
 import javax.naming.ServiceUnavailableException;
 import javax.naming.NamingException;
 import javax.naming.InterruptedNamingException;
@@ -47,6 +43,8 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import sun.misc.IOUtils;
 //import javax.net.SocketFactory;
 
 /**
@@ -799,7 +797,6 @@
         byte inbuf[];   // Buffer for reading incoming bytes
         int inMsgId;    // Message id of incoming response
         int bytesread;  // Number of bytes in inbuf
-        int bytesleft;  // Number of bytes that need to read for completing resp
         int br;         // Temp; number of bytes read from stream
         int offset;     // Offset of where to store bytes in inbuf
         int seqlen;     // Length of ASN sequence
@@ -811,7 +808,7 @@
         try {
             while (true) {
                 try {
-                    inbuf = new byte[2048];
+                    inbuf = new byte[10];
 
                     offset = 0;
                     seqlen = 0;
@@ -871,19 +868,10 @@
                     }
 
                     // read in seqlen bytes
-                    bytesleft = seqlen;
-                    if ((offset + bytesleft) > inbuf.length) {
-                        byte nbuf[] = new byte[offset + bytesleft];
-                        System.arraycopy(inbuf, 0, nbuf, 0, offset);
-                        inbuf = nbuf;
-                    }
-                    while (bytesleft > 0) {
-                        bytesread = in.read(inbuf, offset, bytesleft);
-                        if (bytesread < 0)
-                            break; // EOF
-                        offset += bytesread;
-                        bytesleft -= bytesread;
-                    }
+                    byte[] left = IOUtils.readFully(in, seqlen, false);
+                    inbuf = Arrays.copyOf(inbuf, offset + left.length);
+                    System.arraycopy(left, 0, inbuf, offset, left.length);
+                    offset += left.length;
 /*
 if (dump > 0) {
 System.err.println("seqlen: " + seqlen);
--- a/src/share/classes/java/awt/KeyboardFocusManager.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/awt/KeyboardFocusManager.java	Thu Nov 12 23:04:42 2009 +0000
@@ -53,7 +53,8 @@
 import java.util.StringTokenizer;
 import java.util.WeakHashMap;
 
-import sun.util.logging.PlatformLogger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import sun.awt.AppContext;
 import sun.awt.HeadlessToolkit;
@@ -110,7 +111,7 @@
 {
 
     // Shared focus engine logger
-    private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");
+    private static final Logger focusLog = Logger.getLogger("java.awt.focus.KeyboardFocusManager");
 
     static {
         /* ensure that the necessary native libraries are loaded */
@@ -153,7 +154,7 @@
      */
     private static native void initIDs();
 
-    private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.KeyboardFocusManager");
+    private static final Logger log = Logger.getLogger("java.awt.KeyboardFocusManager");
 
     /**
      * The identifier for the Forward focus traversal keys.
@@ -503,8 +504,8 @@
             if (this == getCurrentKeyboardFocusManager()) {
                 return focusOwner;
             } else {
-                if (focusLog.isLoggable(PlatformLogger.FINER)) {
-                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
+                if (focusLog.isLoggable(Level.FINER)) {
+                    focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                 }
                 throw new SecurityException(notPrivileged);
             }
@@ -608,9 +609,9 @@
     }
 
     void setNativeFocusOwner(Component comp) {
-        if (focusLog.isLoggable(PlatformLogger.FINEST)) {
-            focusLog.finest("Calling peer {0} setCurrentFocusOwner for {1}",
-                            peer, comp);
+        if (focusLog.isLoggable(Level.FINEST)) {
+            focusLog.log(Level.FINEST, "Calling peer {0} setCurrentFocusOwner for {1}",
+                         new Object[] {String.valueOf(peer), String.valueOf(comp)});
         }
         peer.setCurrentFocusOwner(comp);
     }
@@ -672,8 +673,8 @@
             if (this == getCurrentKeyboardFocusManager()) {
                 return permanentFocusOwner;
             } else {
-                if (focusLog.isLoggable(PlatformLogger.FINER)) {
-                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
+                if (focusLog.isLoggable(Level.FINER)) {
+                    focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                 }
                 throw new SecurityException(notPrivileged);
             }
@@ -780,8 +781,8 @@
             if (this == getCurrentKeyboardFocusManager()) {
                return focusedWindow;
             } else {
-                if (focusLog.isLoggable(PlatformLogger.FINER)) {
-                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
+                if (focusLog.isLoggable(Level.FINER)) {
+                    focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                 }
                 throw new SecurityException(notPrivileged);
             }
@@ -884,8 +885,8 @@
             if (this == getCurrentKeyboardFocusManager()) {
                return activeWindow;
             } else {
-                if (focusLog.isLoggable(PlatformLogger.FINER)) {
-                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
+                if (focusLog.isLoggable(Level.FINER)) {
+                    focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                 }
                 throw new SecurityException(notPrivileged);
             }
@@ -918,8 +919,8 @@
         Window oldActiveWindow;
         synchronized (KeyboardFocusManager.class) {
             oldActiveWindow = getActiveWindow();
-            if (focusLog.isLoggable(PlatformLogger.FINER)) {
-                focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
+            if (focusLog.isLoggable(Level.FINER)) {
+                focusLog.log(Level.FINER, "Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
             }
 
             try {
@@ -1214,8 +1215,8 @@
             if (this == getCurrentKeyboardFocusManager()) {
                 return currentFocusCycleRoot;
             } else {
-                if (focusLog.isLoggable(PlatformLogger.FINER)) {
-                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
+                if (focusLog.isLoggable(Level.FINER)) {
+                    focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                 }
                 throw new SecurityException(notPrivileged);
             }
@@ -2148,9 +2149,9 @@
 
         HeavyweightFocusRequest(Component heavyweight, Component descendant,
                                 boolean temporary, CausedFocusEvent.Cause cause) {
-            if (log.isLoggable(PlatformLogger.FINE)) {
+            if (log.isLoggable(Level.FINE)) {
                 if (heavyweight == null) {
-                    log.fine("Assertion (heavyweight != null) failed");
+                    log.log(Level.FINE, "Assertion (heavyweight != null) failed");
                 }
             }
 
@@ -2160,12 +2161,12 @@
         }
         boolean addLightweightRequest(Component descendant,
                                       boolean temporary, CausedFocusEvent.Cause cause) {
-            if (log.isLoggable(PlatformLogger.FINE)) {
+            if (log.isLoggable(Level.FINE)) {
                 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
-                    log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
+                    log.log(Level.FINE, "Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
                 }
                 if (descendant == null) {
-                    log.fine("Assertion (descendant != null) failed");
+                    log.log(Level.FINE, "Assertion (descendant != null) failed");
                 }
             }
 
@@ -2338,12 +2339,12 @@
         (Component heavyweight, Component descendant, boolean temporary,
          boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
     {
-        if (log.isLoggable(PlatformLogger.FINE)) {
+        if (log.isLoggable(Level.FINE)) {
             if (heavyweight == null) {
-                log.fine("Assertion (heavyweight != null) failed");
+                log.log(Level.FINE, "Assertion (heavyweight != null) failed");
             }
             if (time == 0) {
-                log.fine("Assertion (time != 0) failed");
+                log.log(Level.FINE, "Assertion (time != 0) failed");
             }
         }
 
@@ -2360,31 +2361,31 @@
         Component currentFocusOwner = thisManager.getGlobalFocusOwner();
         Component nativeFocusOwner = thisManager.getNativeFocusOwner();
         Window nativeFocusedWindow = thisManager.getNativeFocusedWindow();
-        if (focusLog.isLoggable(PlatformLogger.FINER)) {
-            focusLog.finer("SNFH for {0} in {1}",
-                           descendant, heavyweight);
+        if (focusLog.isLoggable(Level.FINER)) {
+            focusLog.log(Level.FINER, "SNFH for {0} in {1}",
+                         new Object[] {String.valueOf(descendant), String.valueOf(heavyweight)});
         }
-        if (focusLog.isLoggable(PlatformLogger.FINEST)) {
-            focusLog.finest("0. Current focus owner {0}",
-                            currentFocusOwner);
-            focusLog.finest("0. Native focus owner {0}",
-                            nativeFocusOwner);
-            focusLog.finest("0. Native focused window {0}",
-                            nativeFocusedWindow);
+        if (focusLog.isLoggable(Level.FINEST)) {
+            focusLog.log(Level.FINEST, "0. Current focus owner {0}",
+                         String.valueOf(currentFocusOwner));
+            focusLog.log(Level.FINEST, "0. Native focus owner {0}",
+                         String.valueOf(nativeFocusOwner));
+            focusLog.log(Level.FINEST, "0. Native focused window {0}",
+                         String.valueOf(nativeFocusedWindow));
         }
         synchronized (heavyweightRequests) {
             HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
-            if (focusLog.isLoggable(PlatformLogger.FINEST)) {
-                focusLog.finest("Request {0}", hwFocusRequest);
+            if (focusLog.isLoggable(Level.FINEST)) {
+                focusLog.log(Level.FINEST, "Request {0}", String.valueOf(hwFocusRequest));
             }
             if (hwFocusRequest == null &&
                 heavyweight == nativeFocusOwner)
             {
                 if (descendant == currentFocusOwner) {
                     // Redundant request.
-                    if (focusLog.isLoggable(PlatformLogger.FINEST))
-                        focusLog.finest("1. SNFH_FAILURE for {0}",
-                                        descendant);
+                    if (focusLog.isLoggable(Level.FINEST))
+                        focusLog.log(Level.FINEST, "1. SNFH_FAILURE for {0}",
+                                     String.valueOf(descendant));
                     return SNFH_FAILURE;
                 }
 
@@ -2416,8 +2417,8 @@
                 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
                 SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
 
-                if (focusLog.isLoggable(PlatformLogger.FINEST))
-                    focusLog.finest("2. SNFH_HANDLED for {0}", descendant);
+                if (focusLog.isLoggable(Level.FINEST))
+                    focusLog.log(Level.FINEST, "2. SNFH_HANDLED for {0}", String.valueOf(descendant));
                 return SNFH_SUCCESS_HANDLED;
             } else if (hwFocusRequest != null &&
                        hwFocusRequest.heavyweight == heavyweight) {
@@ -2430,7 +2431,7 @@
                     manager.enqueueKeyEvents(time, descendant);
                 }
 
-                if (focusLog.isLoggable(PlatformLogger.FINEST))
+                if (focusLog.isLoggable(Level.FINEST))
                     focusLog.finest("3. SNFH_HANDLED for lightweight" +
                                     descendant + " in " + heavyweight);
                 return SNFH_SUCCESS_HANDLED;
@@ -2453,7 +2454,7 @@
                                              (hwFocusRequest != null)
                                              ? hwFocusRequest.heavyweight
                                              : nativeFocusedWindow)) {
-                        if (focusLog.isLoggable(PlatformLogger.FINEST))
+                        if (focusLog.isLoggable(Level.FINEST))
                             focusLog.finest("4. SNFH_FAILURE for " + descendant);
                         return SNFH_FAILURE;
                     }
@@ -2463,7 +2464,7 @@
                 heavyweightRequests.add
                     (new HeavyweightFocusRequest(heavyweight, descendant,
                                                  temporary, cause));
-                if (focusLog.isLoggable(PlatformLogger.FINEST))
+                if (focusLog.isLoggable(Level.FINEST))
                     focusLog.finest("5. SNFH_PROCEED for " + descendant);
                 return SNFH_SUCCESS_PROCEED;
             }
@@ -2854,13 +2855,14 @@
         }
 
         KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
-        if (focusLog.isLoggable(PlatformLogger.FINER)) {
+        if (focusLog.isLoggable(Level.FINER)) {
             if (event instanceof FocusEvent || event instanceof WindowEvent) {
-                focusLog.finer(">>> {0}", event);
+                focusLog.log(Level.FINER, ">>> {0}", new Object[] {String.valueOf(event)});
             }
-            if (focusLog.isLoggable(PlatformLogger.FINER) && event instanceof KeyEvent) {
-                focusLog.finer("    focus owner is {0}", manager.getGlobalFocusOwner());
-                focusLog.finer(">>> {0}", event);
+            if (focusLog.isLoggable(Level.FINER) && event instanceof KeyEvent) {
+                focusLog.log(Level.FINER, "    focus owner is {0}",
+                                          new Object[] {String.valueOf(manager.getGlobalFocusOwner())});
+                focusLog.log(Level.FINER, ">>> {0}", new Object[] {String.valueOf(event)});
             }
         }
 
@@ -2944,9 +2946,9 @@
         }
     }
     static void removeLastFocusRequest(Component heavyweight) {
-        if (log.isLoggable(PlatformLogger.FINE)) {
+        if (log.isLoggable(Level.FINE)) {
             if (heavyweight == null) {
-                log.fine("Assertion (heavyweight != null) failed");
+                log.log(Level.FINE, "Assertion (heavyweight != null) failed");
             }
         }
 
--- a/src/share/classes/java/awt/color/ICC_Profile.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/awt/color/ICC_Profile.java	Thu Nov 12 23:04:42 2009 +0000
@@ -865,7 +865,9 @@
         case ColorSpace.CS_PYCC:
             synchronized(ICC_Profile.class) {
                 if (PYCCprofile == null) {
-                    if (getProfileFile("PYCC.pf") != null) {
+                    if (!sun.jkernel.DownloadManager.isJREComplete() ||
+                        standardProfileExists("PYCC.pf"))
+                    {
                         ProfileDeferralInfo pInfo =
                             new ProfileDeferralInfo("PYCC.pf",
                                                     ColorSpace.TYPE_3CLR, 3,
@@ -963,15 +965,15 @@
      * and it does not permit read access to the given file.
      */
     public static ICC_Profile getInstance(String fileName) throws IOException {
-    ICC_Profile thisProfile;
-    FileInputStream fis;
+        ICC_Profile thisProfile;
+        FileInputStream fis = null;
+
 
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) {
-            security.checkRead(fileName);
+        File f = getProfileFile(fileName);
+        if (f != null) {
+            fis = new FileInputStream(f);
         }
-
-        if ((fis = openProfile(fileName)) == null) {
+        if (fis == null) {
             throw new IOException("Cannot open file " + fileName);
         }
 
@@ -1083,11 +1085,22 @@
     void activateDeferredProfile() throws ProfileDataException {
         byte profileData[];
         FileInputStream fis;
-        String fileName = deferralInfo.filename;
+        final String fileName = deferralInfo.filename;
 
         profileActivator = null;
         deferralInfo = null;
-        if ((fis = openProfile(fileName)) == null) {
+        PrivilegedAction<FileInputStream> pa = new PrivilegedAction<FileInputStream>() {
+            public FileInputStream run() {
+                File f = getStandardProfileFile(fileName);
+                if (f != null) {
+                    try {
+                        return new FileInputStream(f);
+                    } catch (FileNotFoundException e) {}
+                }
+                return null;
+            }
+        };
+        if ((fis = AccessController.doPrivileged(pa)) == null) {
             throw new ProfileDataException("Cannot open file " + fileName);
         }
         try {
@@ -1786,59 +1799,36 @@
      * available, such as a profile for sRGB.  Built-in profiles use .pf as
      * the file name extension for profiles, e.g. sRGB.pf.
      */
-    private static FileInputStream openProfile(final String fileName) {
-        return (FileInputStream)java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction() {
-            public Object run() {
-                File f = privilegedGetProfileFile(fileName);
-                if (f != null) {
-                    try {
-                        return new FileInputStream(f);
-                    } catch (FileNotFoundException e) {
-                    }
-                }
-                return null;
-            }
-        });
-    }
-
-    private static File getProfileFile(final String fileName) {
-        return (File)java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction() {
-            public Object run() {
-                return privilegedGetProfileFile(fileName);
-            }
-        });
-    }
-
-    /*
-     * this version is called from doPrivileged in openProfile
-     * or getProfileFile, so the whole method is privileged!
-     */
-
-    private static File privilegedGetProfileFile(String fileName) {
+    private static File getProfileFile(String fileName) {
         String path, dir, fullPath;
 
         File f = new File(fileName); /* try absolute file name */
-
+        if (f.isAbsolute()) {
+            /* Rest of code has little sense for an absolute pathname,
+               so return here. */
+            return f.isFile() ? f : null;
+        }
         if ((!f.isFile()) &&
                 ((path = System.getProperty("java.iccprofile.path")) != null)){
                                     /* try relative to java.iccprofile.path */
                 StringTokenizer st =
                     new StringTokenizer(path, File.pathSeparator);
-                while (st.hasMoreTokens() && (!f.isFile())) {
+                while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) {
                     dir = st.nextToken();
                         fullPath = dir + File.separatorChar + fileName;
                     f = new File(fullPath);
+                    if (!isChildOf(f, dir)) {
+                        f = null;
+                    }
                 }
             }
 
-        if ((!f.isFile()) &&
+        if (((f == null) || (!f.isFile())) &&
                 ((path = System.getProperty("java.class.path")) != null)) {
                                     /* try relative to java.class.path */
                 StringTokenizer st =
                     new StringTokenizer(path, File.pathSeparator);
-                while (st.hasMoreTokens() && (!f.isFile())) {
+                while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) {
                     dir = st.nextToken();
                         fullPath = dir + File.separatorChar + fileName;
                     f = new File(fullPath);
@@ -1858,13 +1848,69 @@
                     }
                 }
             }
-
-        if (f.isFile()) {
+        if ((f == null) || (!f.isFile())) {
+            /* try the directory of built-in profiles */
+            f = getStandardProfileFile(fileName);
+        }
+        if (f != null && f.isFile()) {
             return f;
         }
         return null;
     }
 
+    /**
+     * Returns a file object corresponding to a built-in profile
+     * specified by fileName.
+     * If there is no built-in profile with such name, then the method
+     * returns null.
+     */
+    private static File getStandardProfileFile(String fileName) {
+        String dir = System.getProperty("java.home") +
+            File.separatorChar + "lib" + File.separatorChar + "cmm";
+        String fullPath = dir + File.separatorChar + fileName;
+        File f = new File(fullPath);
+        if (!f.isFile()) {
+            //make sure file was installed in the kernel mode
+            try {
+                //kernel uses platform independent paths =>
+                //   should not use platform separator char
+                sun.jkernel.DownloadManager.downloadFile("lib/cmm/"+fileName);
+            } catch (IOException ioe) {}
+        }
+        return (f.isFile() && isChildOf(f, dir)) ? f : null;
+    }
+
+    /**
+     * Checks whether given file resides inside give directory.
+     */
+    private static boolean isChildOf(File f, String dirName) {
+        try {
+            File dir = new File(dirName);
+            String canonicalDirName = dir.getCanonicalPath();
+            if (!canonicalDirName.endsWith(File.separator)) {
+                canonicalDirName += File.separator;
+            }
+            String canonicalFileName = f.getCanonicalPath();
+            return canonicalFileName.startsWith(canonicalDirName);
+        } catch (IOException e) {
+            /* we do not expect the IOException here, because invocation
+             * of this function is always preceeded by isFile() call.
+             */
+            return false;
+        }
+    }
+
+    /**
+     * Checks whether built-in profile specified by fileName exists.
+     */
+    private static boolean standardProfileExists(final String fileName) {
+        return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+                public Boolean run() {
+                    return getStandardProfileFile(fileName) != null;
+                }
+            });
+    }
+
 
     /*
      * Serialization support.
--- a/src/share/classes/java/beans/MetaData.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/beans/MetaData.java	Thu Nov 12 23:04:42 2009 +0000
@@ -42,12 +42,11 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
-import java.sql.Timestamp;
-
 import java.util.*;
 
 import javax.swing.Box;
@@ -290,13 +289,44 @@
  * @author Sergey A. Malenkov
  */
 final class java_sql_Timestamp_PersistenceDelegate extends java_util_Date_PersistenceDelegate {
-    protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
-        Timestamp oldTime = (Timestamp)oldInstance;
-        Timestamp newTime = (Timestamp)newInstance;
+    private static final Method getNanosMethod = getNanosMethod();
+
+    private static Method getNanosMethod() {
+        try {
+            Class<?> c = Class.forName("java.sql.Timestamp", true, null);
+            return c.getMethod("getNanos");
+        } catch (ClassNotFoundException e) {
+            return null;
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError(e);
+        }
+    }
 
-        int nanos = oldTime.getNanos();
-        if (nanos != newTime.getNanos()) {
-            out.writeStatement(new Statement(oldTime, "setNanos", new Object[] {nanos}));
+    /**
+     * Invoke Timstamp getNanos.
+     */
+    private static int getNanos(Object obj) {
+        if (getNanosMethod == null)
+            throw new AssertionError("Should not get here");
+        try {
+            return (Integer)getNanosMethod.invoke(obj);
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof RuntimeException)
+                throw (RuntimeException)cause;
+            if (cause instanceof Error)
+                throw (Error)cause;
+            throw new AssertionError(e);
+        } catch (IllegalAccessException iae) {
+            throw new AssertionError(iae);
+        }
+    }
+
+    protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
+        // assumes oldInstance and newInstance are Timestamps
+        int nanos = getNanos(oldInstance);
+        if (nanos != getNanos(newInstance)) {
+            out.writeStatement(new Statement(oldInstance, "setNanos", new Object[] {nanos}));
         }
     }
 }
--- a/src/share/classes/java/lang/ClassLoader.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/lang/ClassLoader.java	Thu Nov 12 23:04:42 2009 +0000
@@ -186,11 +186,6 @@
         parallelLoaders.add(ClassLoader.class);
     }
 
-    // If initialization succeed this is set to true and security checks will
-    // succeed.  Otherwise the object is not initialized and the object is
-    // useless.
-    private final boolean initialized;
-
     // The parent class loader for delegation
     // Note: VM hardcoded the offset of this field, thus all new fields
     // must be added *after* it.
@@ -232,6 +227,31 @@
     private final HashMap<String, Package> packages =
         new HashMap<String, Package>();
 
+    private static Void checkCreateClassLoader() {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkCreateClassLoader();
+        }
+        return null;
+    }
+
+    private ClassLoader(Void unused, ClassLoader parent) {
+        this.parent = parent;
+        if (parallelLoaders.contains(this.getClass())) {
+            parallelLockMap = new ConcurrentHashMap<String, Object>();
+            package2certs = new ConcurrentHashMap<String, Certificate[]>();
+            domains =
+                Collections.synchronizedSet(new HashSet<ProtectionDomain>());
+            assertionLock = new Object();
+        } else {
+            // no finer-grained lock; lock on the classloader instance
+            parallelLockMap = null;
+            package2certs = new Hashtable<String, Certificate[]>();
+            domains = new HashSet<ProtectionDomain>();
+            assertionLock = this;
+        }
+    }
+
     /**
      * Creates a new class loader using the specified parent class loader for
      * delegation.
@@ -252,25 +272,7 @@
      * @since  1.2
      */
     protected ClassLoader(ClassLoader parent) {
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) {
-            security.checkCreateClassLoader();
-        }
-        this.parent = parent;
-        if (parallelLoaders.contains(this.getClass())) {
-            parallelLockMap = new ConcurrentHashMap<String, Object>();
-            package2certs = new ConcurrentHashMap<String, Certificate[]>();
-            domains =
-                Collections.synchronizedSet(new HashSet<ProtectionDomain>());
-            assertionLock = new Object();
-        } else {
-            // no finer-grained lock; lock on the classloader instance
-            parallelLockMap = null;
-            package2certs = new Hashtable<String, Certificate[]>();
-            domains = new HashSet<ProtectionDomain>();
-            assertionLock = this;
-        }
-        initialized = true;
+        this(checkCreateClassLoader(), parent);
     }
 
     /**
@@ -289,25 +291,7 @@
      *          of a new class loader.
      */
     protected ClassLoader() {
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) {
-            security.checkCreateClassLoader();
-        }
-        this.parent = getSystemClassLoader();
-        if (parallelLoaders.contains(this.getClass())) {
-            parallelLockMap = new ConcurrentHashMap<String, Object>();
-            package2certs = new ConcurrentHashMap<String, Certificate[]>();
-            domains =
-                Collections.synchronizedSet(new HashSet<ProtectionDomain>());
-            assertionLock = new Object();
-        } else {
-            // no finer-grained lock; lock on the classloader instance
-            parallelLockMap = null;
-            package2certs = new Hashtable<String, Certificate[]>();
-            domains = new HashSet<ProtectionDomain>();
-            assertionLock = this;
-        }
-        initialized = true;
+        this(checkCreateClassLoader(), getSystemClassLoader());
     }
 
     // -- Class --
@@ -754,7 +738,6 @@
                                          ProtectionDomain protectionDomain)
         throws ClassFormatError
     {
-        check();
         protectionDomain = preDefineClass(name, protectionDomain);
 
         Class c = null;
@@ -838,8 +821,6 @@
                                          ProtectionDomain protectionDomain)
         throws ClassFormatError
     {
-        check();
-
         int len = b.remaining();
 
         // Use byte[] if not a direct ByteBufer:
@@ -984,7 +965,6 @@
      * @see  #defineClass(String, byte[], int, int)
      */
     protected final void resolveClass(Class<?> c) {
-        check();
         resolveClass0(c);
     }
 
@@ -1015,7 +995,6 @@
     protected final Class<?> findSystemClass(String name)
         throws ClassNotFoundException
     {
-        check();
         ClassLoader system = getSystemClassLoader();
         if (system == null) {
             if (!checkName(name))
@@ -1035,7 +1014,6 @@
      */
     private Class findBootstrapClassOrNull(String name)
     {
-        check();
         if (!checkName(name)) return null;
 
         return findBootstrapClass(name);
@@ -1044,13 +1022,6 @@
     // return null if not found
     private native Class findBootstrapClass(String name);
 
-    // Check to make sure the class loader has been initialized.
-    private void check() {
-        if (!initialized) {
-            throw new SecurityException("ClassLoader object not initialized");
-        }
-    }
-
     /**
      * Returns the class with the given <a href="#name">binary name</a> if this
      * loader has been recorded by the Java virtual machine as an initiating
@@ -1066,7 +1037,6 @@
      * @since  1.1
      */
     protected final Class<?> findLoadedClass(String name) {
-        check();
         if (!checkName(name))
             return null;
         return findLoadedClass0(name);
@@ -1087,7 +1057,6 @@
      * @since  1.1
      */
     protected final void setSigners(Class<?> c, Object[] signers) {
-        check();
         c.setSigners(signers);
     }
 
@@ -2205,3 +2174,4 @@
         return sys;
     }
 }
+
--- a/src/share/classes/java/math/BigInteger.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/math/BigInteger.java	Thu Nov 12 23:04:42 2009 +0000
@@ -288,11 +288,11 @@
      */
     public BigInteger(String val, int radix) {
         int cursor = 0, numDigits;
-        int len = val.length();
+        final int len = val.length();
 
         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
             throw new NumberFormatException("Radix out of range");
-        if (val.length() == 0)
+        if (len == 0)
             throw new NumberFormatException("Zero length BigInteger");
 
         // Check for at most one leading sign
@@ -303,7 +303,7 @@
             // No leading sign character or at most one leading sign character
             if (index1 == 0 || index2 == 0) {
                 cursor = 1;
-                if (val.length() == 1)
+                if (len == 1)
                     throw new NumberFormatException("Zero length BigInteger");
             }
             if (index1 == 0)
@@ -342,7 +342,7 @@
         // Process remaining digit groups
         int superRadix = intRadix[radix];
         int groupVal = 0;
-        while (cursor < val.length()) {
+        while (cursor < len) {
             group = val.substring(cursor, cursor += digitsPerInt[radix]);
             groupVal = Integer.parseInt(group, radix);
             if (groupVal < 0)
--- a/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio;
-
-
-class ByteBufferAs$Type$Buffer$RW$$BO$                  // package-private
-    extends {#if[ro]?ByteBufferAs}$Type$Buffer{#if[ro]?$BO$}
-{
-
-#if[rw]
-
-    protected final ByteBuffer bb;
-    protected final int offset;
-
-#end[rw]
-
-    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb) {   // package-private
-#if[rw]
-        super(-1, 0,
-              bb.remaining() >> $LG_BYTES_PER_VALUE$,
-              bb.remaining() >> $LG_BYTES_PER_VALUE$);
-        this.bb = bb;
-        // enforce limit == capacity
-        int cap = this.capacity();
-        this.limit(cap);
-        int pos = this.position();
-        assert (pos <= cap);
-        offset = pos;
-#else[rw]
-        super(bb);
-#end[rw]
-    }
-
-    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb,
-                                     int mark, int pos, int lim, int cap,
-                                     int off)
-    {
-#if[rw]
-        super(mark, pos, lim, cap);
-        this.bb = bb;
-        offset = off;
-#else[rw]
-        super(bb, mark, pos, lim, cap, off);
-#end[rw]
-    }
-
-    public $Type$Buffer slice() {
-        int pos = this.position();
-        int lim = this.limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-        int off = (pos << $LG_BYTES_PER_VALUE$) + offset;
-        assert (off >= 0);
-        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb, -1, 0, rem, rem, off);
-    }
-
-    public $Type$Buffer duplicate() {
-        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb,
-                                                    this.markValue(),
-                                                    this.position(),
-                                                    this.limit(),
-                                                    this.capacity(),
-                                                    offset);
-    }
-
-    public $Type$Buffer asReadOnlyBuffer() {
-#if[rw]
-        return new ByteBufferAs$Type$BufferR$BO$(bb,
-                                                 this.markValue(),
-                                                 this.position(),
-                                                 this.limit(),
-                                                 this.capacity(),
-                                                 offset);
-#else[rw]
-        return duplicate();
-#end[rw]
-    }
-
-#if[rw]
-
-    protected int ix(int i) {
-        return (i << $LG_BYTES_PER_VALUE$) + offset;
-    }
-
-    public $type$ get() {
-        return Bits.get$Type$$BO$(bb, ix(nextGetIndex()));
-    }
-
-    public $type$ get(int i) {
-        return Bits.get$Type$$BO$(bb, ix(checkIndex(i)));
-    }
-
-#end[rw]
-
-    public $Type$Buffer put($type$ x) {
-#if[rw]
-        Bits.put$Type$$BO$(bb, ix(nextPutIndex()), x);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put(int i, $type$ x) {
-#if[rw]
-        Bits.put$Type$$BO$(bb, ix(checkIndex(i)), x);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer compact() {
-#if[rw]
-        int pos = position();
-        int lim = limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-
-        ByteBuffer db = bb.duplicate();
-        db.limit(ix(lim));
-        db.position(ix(0));
-        ByteBuffer sb = db.slice();
-        sb.position(pos << $LG_BYTES_PER_VALUE$);
-        sb.compact();
-        position(rem);
-        limit(capacity());
-        discardMark();
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public boolean isDirect() {
-        return bb.isDirect();
-    }
-
-    public boolean isReadOnly() {
-        return {#if[rw]?false:true};
-    }
-
-#if[char]
-
-    public String toString(int start, int end) {
-        if ((end > limit()) || (start > end))
-            throw new IndexOutOfBoundsException();
-        try {
-            int len = end - start;
-            char[] ca = new char[len];
-            CharBuffer cb = CharBuffer.wrap(ca);
-            CharBuffer db = this.duplicate();
-            db.position(start);
-            db.limit(end);
-            cb.put(db);
-            return new String(ca);
-        } catch (StringIndexOutOfBoundsException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-
-    // --- Methods to support CharSequence ---
-
-    public CharBuffer subSequence(int start, int end) {
-        int pos = position();
-        int lim = limit();
-        assert (pos <= lim);
-        pos = (pos <= lim ? pos : lim);
-        int len = lim - pos;
-
-        if ((start < 0) || (end > len) || (start > end))
-            throw new IndexOutOfBoundsException();
-        return new ByteBufferAsCharBuffer$RW$$BO$(bb,
-                                                  -1,
-                                                  pos + start,
-                                                  pos + end,
-                                                  capacity(),
-                                                  offset);
-    }
-
-#end[char]
-
-
-    public ByteOrder order() {
-#if[boB]
-        return ByteOrder.BIG_ENDIAN;
-#end[boB]
-#if[boL]
-        return ByteOrder.LITTLE_ENDIAN;
-#end[boL]
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+
+class ByteBufferAs$Type$Buffer$RW$$BO$                  // package-private
+    extends {#if[ro]?ByteBufferAs}$Type$Buffer{#if[ro]?$BO$}
+{
+
+#if[rw]
+
+    protected final ByteBuffer bb;
+    protected final int offset;
+
+#end[rw]
+
+    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb) {   // package-private
+#if[rw]
+        super(-1, 0,
+              bb.remaining() >> $LG_BYTES_PER_VALUE$,
+              bb.remaining() >> $LG_BYTES_PER_VALUE$);
+        this.bb = bb;
+        // enforce limit == capacity
+        int cap = this.capacity();
+        this.limit(cap);
+        int pos = this.position();
+        assert (pos <= cap);
+        offset = pos;
+#else[rw]
+        super(bb);
+#end[rw]
+    }
+
+    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb,
+                                     int mark, int pos, int lim, int cap,
+                                     int off)
+    {
+#if[rw]
+        super(mark, pos, lim, cap);
+        this.bb = bb;
+        offset = off;
+#else[rw]
+        super(bb, mark, pos, lim, cap, off);
+#end[rw]
+    }
+
+    public $Type$Buffer slice() {
+        int pos = this.position();
+        int lim = this.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        int off = (pos << $LG_BYTES_PER_VALUE$) + offset;
+        assert (off >= 0);
+        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb, -1, 0, rem, rem, off);
+    }
+
+    public $Type$Buffer duplicate() {
+        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb,
+                                                    this.markValue(),
+                                                    this.position(),
+                                                    this.limit(),
+                                                    this.capacity(),
+                                                    offset);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new ByteBufferAs$Type$BufferR$BO$(bb,
+                                                 this.markValue(),
+                                                 this.position(),
+                                                 this.limit(),
+                                                 this.capacity(),
+                                                 offset);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    protected int ix(int i) {
+        return (i << $LG_BYTES_PER_VALUE$) + offset;
+    }
+
+    public $type$ get() {
+        return Bits.get$Type$$BO$(bb, ix(nextGetIndex()));
+    }
+
+    public $type$ get(int i) {
+        return Bits.get$Type$$BO$(bb, ix(checkIndex(i)));
+    }
+
+#end[rw]
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        Bits.put$Type$$BO$(bb, ix(nextPutIndex()), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        Bits.put$Type$$BO$(bb, ix(checkIndex(i)), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        ByteBuffer db = bb.duplicate();
+        db.limit(ix(lim));
+        db.position(ix(0));
+        ByteBuffer sb = db.slice();
+        sb.position(pos << $LG_BYTES_PER_VALUE$);
+        sb.compact();
+        position(rem);
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public boolean isDirect() {
+        return bb.isDirect();
+    }
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+#if[char]
+
+    public String toString(int start, int end) {
+        if ((end > limit()) || (start > end))
+            throw new IndexOutOfBoundsException();
+        try {
+            int len = end - start;
+            char[] ca = new char[len];
+            CharBuffer cb = CharBuffer.wrap(ca);
+            CharBuffer db = this.duplicate();
+            db.position(start);
+            db.limit(end);
+            cb.put(db);
+            return new String(ca);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        pos = (pos <= lim ? pos : lim);
+        int len = lim - pos;
+
+        if ((start < 0) || (end > len) || (start > end))
+            throw new IndexOutOfBoundsException();
+        return new ByteBufferAsCharBuffer$RW$$BO$(bb,
+                                                  -1,
+                                                  pos + start,
+                                                  pos + end,
+                                                  capacity(),
+                                                  offset);
+    }
+
+#end[char]
+
+
+    public ByteOrder order() {
+#if[boB]
+        return ByteOrder.BIG_ENDIAN;
+#end[boB]
+#if[boL]
+        return ByteOrder.LITTLE_ENDIAN;
+#end[boL]
+    }
+
+}
--- a/src/share/classes/java/nio/Direct-X-Buffer-bin.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#warn This file is preprocessed before being compiled
-
-class XXX {
-
-#begin
-
-#if[rw]
-
-    private $type$ get$Type$(long a) {
-        if (unaligned) {
-            $memtype$ x = unsafe.get$Memtype$(a);
-            return $fromBits$(nativeByteOrder ? x : Bits.swap(x));
-        }
-        return Bits.get$Type$(a, bigEndian);
-    }
-
-    public $type$ get$Type$() {
-        return get$Type$(ix(nextGetIndex($BYTES_PER_VALUE$)));
-    }
-
-    public $type$ get$Type$(int i) {
-        return get$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)));
-    }
-
-#end[rw]
-
-    private ByteBuffer put$Type$(long a, $type$ x) {
-#if[rw]
-        if (unaligned) {
-            $memtype$ y = $toBits$(x);
-            unsafe.put$Memtype$(a, (nativeByteOrder ? y : Bits.swap(y)));
-        } else {
-            Bits.put$Type$(a, x, bigEndian);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public ByteBuffer put$Type$($type$ x) {
-#if[rw]
-        put$Type$(ix(nextPutIndex($BYTES_PER_VALUE$)), x);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public ByteBuffer put$Type$(int i, $type$ x) {
-#if[rw]
-        put$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)), x);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer as$Type$Buffer() {
-        int off = this.position();
-        int lim = this.limit();
-        assert (off <= lim);
-        int rem = (off <= lim ? lim - off : 0);
-
-        int size = rem >> $LG_BYTES_PER_VALUE$;
-        if (!unaligned && ((address + off) % $BYTES_PER_VALUE$ != 0)) {
-            return (bigEndian
-                    ? ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$B(this,
-                                                                       -1,
-                                                                       0,
-                                                                       size,
-                                                                       size,
-                                                                       off))
-                    : ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$L(this,
-                                                                       -1,
-                                                                       0,
-                                                                       size,
-                                                                       size,
-                                                                       off)));
-        } else {
-            return (nativeByteOrder
-                    ? ($Type$Buffer)(new Direct$Type$Buffer$RW$U(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off))
-                    : ($Type$Buffer)(new Direct$Type$Buffer$RW$S(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off)));
-        }
-    }
-
-#end
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/nio/Direct-X-Buffer-bin.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+class XXX {
+
+#begin
+
+#if[rw]
+
+    private $type$ get$Type$(long a) {
+        if (unaligned) {
+            $memtype$ x = unsafe.get$Memtype$(a);
+            return $fromBits$(nativeByteOrder ? x : Bits.swap(x));
+        }
+        return Bits.get$Type$(a, bigEndian);
+    }
+
+    public $type$ get$Type$() {
+        return get$Type$(ix(nextGetIndex($BYTES_PER_VALUE$)));
+    }
+
+    public $type$ get$Type$(int i) {
+        return get$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)));
+    }
+
+#end[rw]
+
+    private ByteBuffer put$Type$(long a, $type$ x) {
+#if[rw]
+        if (unaligned) {
+            $memtype$ y = $toBits$(x);
+            unsafe.put$Memtype$(a, (nativeByteOrder ? y : Bits.swap(y)));
+        } else {
+            Bits.put$Type$(a, x, bigEndian);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public ByteBuffer put$Type$($type$ x) {
+#if[rw]
+        put$Type$(ix(nextPutIndex($BYTES_PER_VALUE$)), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public ByteBuffer put$Type$(int i, $type$ x) {
+#if[rw]
+        put$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer as$Type$Buffer() {
+        int off = this.position();
+        int lim = this.limit();
+        assert (off <= lim);
+        int rem = (off <= lim ? lim - off : 0);
+
+        int size = rem >> $LG_BYTES_PER_VALUE$;
+        if (!unaligned && ((address + off) % $BYTES_PER_VALUE$ != 0)) {
+            return (bigEndian
+                    ? ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$B(this,
+                                                                       -1,
+                                                                       0,
+                                                                       size,
+                                                                       size,
+                                                                       off))
+                    : ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$L(this,
+                                                                       -1,
+                                                                       0,
+                                                                       size,
+                                                                       size,
+                                                                       off)));
+        } else {
+            return (nativeByteOrder
+                    ? ($Type$Buffer)(new Direct$Type$Buffer$RW$U(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off))
+                    : ($Type$Buffer)(new Direct$Type$Buffer$RW$S(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off)));
+        }
+    }
+
+#end
+
+}
--- a/src/share/classes/java/nio/Direct-X-Buffer.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,464 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio;
-
-import sun.misc.Cleaner;
-import sun.misc.Unsafe;
-import sun.nio.ch.DirectBuffer;
-
-
-class Direct$Type$Buffer$RW$$BO$
-#if[rw]
-    extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
-#else[rw]
-    extends Direct$Type$Buffer$BO$
-#end[rw]
-    implements DirectBuffer
-{
-
-#if[rw]
-
-    // Cached unsafe-access object
-    protected static final Unsafe unsafe = Bits.unsafe();
-
-    // Cached array base offset
-    private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class);
-
-    // Cached unaligned-access capability
-    protected static final boolean unaligned = Bits.unaligned();
-
-    // Base address, used in all indexing calculations
-    // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
-    //    protected long address;
-
-    // If this buffer is a view of another buffer then we keep a reference to
-    // that buffer so that its memory isn't freed before we're done with it
-    protected Object viewedBuffer = null;
-
-    public Object viewedBuffer() {
-        return viewedBuffer;
-    }
-
-#if[byte]
-
-    private static class Deallocator
-        implements Runnable
-    {
-
-        private static Unsafe unsafe = Unsafe.getUnsafe();
-
-        private long address;
-        private long size;
-        private int capacity;
-
-        private Deallocator(long address, long size, int capacity) {
-            assert (address != 0);
-            this.address = address;
-            this.size = size;
-            this.capacity = capacity;
-        }
-
-        public void run() {
-            if (address == 0) {
-                // Paranoia
-                return;
-            }
-            unsafe.freeMemory(address);
-            address = 0;
-            Bits.unreserveMemory(size, capacity);
-        }
-
-    }
-
-    private final Cleaner cleaner;
-
-    public Cleaner cleaner() { return cleaner; }
-
-#else[byte]
-
-    public Cleaner cleaner() { return null; }
-
-#end[byte]
-
-#end[rw]
-
-#if[byte]
-
-    // Primary constructor
-    //
-    Direct$Type$Buffer$RW$(int cap) {                   // package-private
-#if[rw]
-        super(-1, 0, cap, cap, false);
-        int ps = Bits.pageSize();
-        int size = cap + ps;
-        Bits.reserveMemory(size, cap);
-
-        long base = 0;
-        try {
-            base = unsafe.allocateMemory(size);
-        } catch (OutOfMemoryError x) {
-            Bits.unreserveMemory(size, cap);
-            throw x;
-        }
-        unsafe.setMemory(base, size, (byte) 0);
-        if (base % ps != 0) {
-            // Round up to page boundary
-            address = base + ps - (base & (ps - 1));
-        } else {
-            address = base;
-        }
-        cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
-#else[rw]
-        super(cap);
-#end[rw]
-    }
-
-#if[rw]
-
-    // Invoked only by JNI: NewDirectByteBuffer(void*, long)
-    //
-    private Direct$Type$Buffer(long addr, int cap) {
-        super(-1, 0, cap, cap, false);
-        address = addr;
-        cleaner = null;
-    }
-
-#end[rw]
-
-    // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
-    //
-    protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
-#if[rw]
-        super(-1, 0, cap, cap, true);
-        address = addr;
-        viewedBuffer = null;
-        cleaner = Cleaner.create(this, unmapper);
-#else[rw]
-        super(cap, addr, unmapper);
-#end[rw]
-    }
-
-#end[byte]
-
-    // For duplicates and slices
-    //
-    Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
-                               int mark, int pos, int lim, int cap,
-                               int off)
-    {
-#if[rw]
-        super(mark, pos, lim, cap);
-        address = db.address() + off;
-        viewedBuffer = db;
-#if[byte]
-        cleaner = null;
-#end[byte]
-#else[rw]
-        super(db, mark, pos, lim, cap, off);
-#end[rw]
-    }
-
-    public $Type$Buffer slice() {
-        int pos = this.position();
-        int lim = this.limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-        int off = (pos << $LG_BYTES_PER_VALUE$);
-        assert (off >= 0);
-        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
-    }
-
-    public $Type$Buffer duplicate() {
-        return new Direct$Type$Buffer$RW$$BO$(this,
-                                              this.markValue(),
-                                              this.position(),
-                                              this.limit(),
-                                              this.capacity(),
-                                              0);
-    }
-
-    public $Type$Buffer asReadOnlyBuffer() {
-#if[rw]
-        return new Direct$Type$BufferR$BO$(this,
-                                           this.markValue(),
-                                           this.position(),
-                                           this.limit(),
-                                           this.capacity(),
-                                           0);
-#else[rw]
-        return duplicate();
-#end[rw]
-    }
-
-#if[rw]
-
-    public long address() {
-        return address;
-    }
-
-    private long ix(int i) {
-        return address + (i << $LG_BYTES_PER_VALUE$);
-    }
-
-    public $type$ get() {
-        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
-    }
-
-    public $type$ get(int i) {
-        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
-    }
-
-    public $Type$Buffer get($type$[] dst, int offset, int length) {
-#if[rw]
-        if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
-            checkBounds(offset, length, dst.length);
-            int pos = position();
-            int lim = limit();
-            assert (pos <= lim);
-            int rem = (pos <= lim ? lim - pos : 0);
-            if (length > rem)
-                throw new BufferUnderflowException();
-
-#if[!byte]
-            if (order() != ByteOrder.nativeOrder())
-                Bits.copyTo$Memtype$Array(ix(pos), dst,
-                                          offset << $LG_BYTES_PER_VALUE$,
-                                          length << $LG_BYTES_PER_VALUE$);
-            else
-#end[!byte]
-                Bits.copyToArray(ix(pos), dst, arrayBaseOffset,
-                                 offset << $LG_BYTES_PER_VALUE$,
-                                 length << $LG_BYTES_PER_VALUE$);
-            position(pos + length);
-        } else {
-            super.get(dst, offset, length);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-#end[rw]
-
-    public $Type$Buffer put($type$ x) {
-#if[rw]
-        unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put(int i, $type$ x) {
-#if[rw]
-        unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put($Type$Buffer src) {
-#if[rw]
-        if (src instanceof Direct$Type$Buffer$BO$) {
-            if (src == this)
-                throw new IllegalArgumentException();
-            Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
-
-            int spos = sb.position();
-            int slim = sb.limit();
-            assert (spos <= slim);
-            int srem = (spos <= slim ? slim - spos : 0);
-
-            int pos = position();
-            int lim = limit();
-            assert (pos <= lim);
-            int rem = (pos <= lim ? lim - pos : 0);
-
-            if (srem > rem)
-                throw new BufferOverflowException();
-            unsafe.copyMemory(sb.ix(spos), ix(pos), srem << $LG_BYTES_PER_VALUE$);
-            sb.position(spos + srem);
-            position(pos + srem);
-        } else if (src.hb != null) {
-
-            int spos = src.position();
-            int slim = src.limit();
-            assert (spos <= slim);
-            int srem = (spos <= slim ? slim - spos : 0);
-
-            put(src.hb, src.offset + spos, srem);
-            src.position(spos + srem);
-
-        } else {
-            super.put(src);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put($type$[] src, int offset, int length) {
-#if[rw]
-        if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
-            checkBounds(offset, length, src.length);
-            int pos = position();
-            int lim = limit();
-            assert (pos <= lim);
-            int rem = (pos <= lim ? lim - pos : 0);
-            if (length > rem)
-                throw new BufferOverflowException();
-
-#if[!byte]
-            if (order() != ByteOrder.nativeOrder())
-                Bits.copyFrom$Memtype$Array(src, offset << $LG_BYTES_PER_VALUE$,
-                                            ix(pos), length << $LG_BYTES_PER_VALUE$);
-            else
-#end[!byte]
-                Bits.copyFromArray(src, arrayBaseOffset, offset << $LG_BYTES_PER_VALUE$,
-                                   ix(pos), length << $LG_BYTES_PER_VALUE$);
-            position(pos + length);
-        } else {
-            super.put(src, offset, length);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer compact() {
-#if[rw]
-        int pos = position();
-        int lim = limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-
-        unsafe.copyMemory(ix(pos), ix(0), rem << $LG_BYTES_PER_VALUE$);
-        position(rem);
-        limit(capacity());
-        discardMark();
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public boolean isDirect() {
-        return true;
-    }
-
-    public boolean isReadOnly() {
-        return {#if[rw]?false:true};
-    }
-
-
-#if[char]
-
-    public String toString(int start, int end) {
-        if ((end > limit()) || (start > end))
-            throw new IndexOutOfBoundsException();
-        try {
-            int len = end - start;
-            char[] ca = new char[len];
-            CharBuffer cb = CharBuffer.wrap(ca);
-            CharBuffer db = this.duplicate();
-            db.position(start);
-            db.limit(end);
-            cb.put(db);
-            return new String(ca);
-        } catch (StringIndexOutOfBoundsException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-
-    // --- Methods to support CharSequence ---
-
-    public CharBuffer subSequence(int start, int end) {
-        int pos = position();
-        int lim = limit();
-        assert (pos <= lim);
-        pos = (pos <= lim ? pos : lim);
-        int len = lim - pos;
-
-        if ((start < 0) || (end > len) || (start > end))
-            throw new IndexOutOfBoundsException();
-        return new DirectCharBuffer$RW$$BO$(this,
-                                            -1,
-                                            pos + start,
-                                            pos + end,
-                                            capacity(),
-                                            offset);
-    }
-
-#end[char]
-
-
-
-#if[!byte]
-
-    public ByteOrder order() {
-#if[boS]
-        return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
-                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
-#end[boS]
-#if[boU]
-        return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
-                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
-#end[boU]
-    }
-
-#end[!byte]
-
-
-
-#if[byte]
-
-    byte _get(int i) {                          // package-private
-        return unsafe.getByte(address + i);
-    }
-
-    void _put(int i, byte b) {                  // package-private
-#if[rw]
-        unsafe.putByte(address + i, b);
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    // #BIN
-    //
-    // Binary-data access methods  for short, char, int, long, float,
-    // and double will be inserted here
-
-#end[byte]
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/nio/Direct-X-Buffer.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+import sun.misc.Cleaner;
+import sun.misc.Unsafe;
+import sun.nio.ch.DirectBuffer;
+
+
+class Direct$Type$Buffer$RW$$BO$
+#if[rw]
+    extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
+#else[rw]
+    extends Direct$Type$Buffer$BO$
+#end[rw]
+    implements DirectBuffer
+{
+
+#if[rw]
+
+    // Cached unsafe-access object
+    protected static final Unsafe unsafe = Bits.unsafe();
+
+    // Cached array base offset
+    private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class);
+
+    // Cached unaligned-access capability
+    protected static final boolean unaligned = Bits.unaligned();
+
+    // Base address, used in all indexing calculations
+    // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
+    //    protected long address;
+
+    // If this buffer is a view of another buffer then we keep a reference to
+    // that buffer so that its memory isn't freed before we're done with it
+    protected Object viewedBuffer = null;
+
+    public Object viewedBuffer() {
+        return viewedBuffer;
+    }
+
+#if[byte]
+
+    private static class Deallocator
+        implements Runnable
+    {
+
+        private static Unsafe unsafe = Unsafe.getUnsafe();
+
+        private long address;
+        private long size;
+        private int capacity;
+
+        private Deallocator(long address, long size, int capacity) {
+            assert (address != 0);
+            this.address = address;
+            this.size = size;
+            this.capacity = capacity;
+        }
+
+        public void run() {
+            if (address == 0) {
+                // Paranoia
+                return;
+            }
+            unsafe.freeMemory(address);
+            address = 0;
+            Bits.unreserveMemory(size, capacity);
+        }
+
+    }
+
+    private final Cleaner cleaner;
+
+    public Cleaner cleaner() { return cleaner; }
+
+#else[byte]
+
+    public Cleaner cleaner() { return null; }
+
+#end[byte]
+
+#end[rw]
+
+#if[byte]
+
+    // Primary constructor
+    //
+    Direct$Type$Buffer$RW$(int cap) {                   // package-private
+#if[rw]
+        super(-1, 0, cap, cap, false);
+        int ps = Bits.pageSize();
+        int size = cap + ps;
+        Bits.reserveMemory(size, cap);
+
+        long base = 0;
+        try {
+            base = unsafe.allocateMemory(size);
+        } catch (OutOfMemoryError x) {
+            Bits.unreserveMemory(size, cap);
+            throw x;
+        }
+        unsafe.setMemory(base, size, (byte) 0);
+        if (base % ps != 0) {
+            // Round up to page boundary
+            address = base + ps - (base & (ps - 1));
+        } else {
+            address = base;
+        }
+        cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
+#else[rw]
+        super(cap);
+#end[rw]
+    }
+
+#if[rw]
+
+    // Invoked only by JNI: NewDirectByteBuffer(void*, long)
+    //
+    private Direct$Type$Buffer(long addr, int cap) {
+        super(-1, 0, cap, cap, false);
+        address = addr;
+        cleaner = null;
+    }
+
+#end[rw]
+
+    // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
+    //
+    protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
+#if[rw]
+        super(-1, 0, cap, cap, true);
+        address = addr;
+        viewedBuffer = null;
+        cleaner = Cleaner.create(this, unmapper);
+#else[rw]
+        super(cap, addr, unmapper);
+#end[rw]
+    }
+
+#end[byte]
+
+    // For duplicates and slices
+    //
+    Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
+                               int mark, int pos, int lim, int cap,
+                               int off)
+    {
+#if[rw]
+        super(mark, pos, lim, cap);
+        address = db.address() + off;
+        viewedBuffer = db;
+#if[byte]
+        cleaner = null;
+#end[byte]
+#else[rw]
+        super(db, mark, pos, lim, cap, off);
+#end[rw]
+    }
+
+    public $Type$Buffer slice() {
+        int pos = this.position();
+        int lim = this.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        int off = (pos << $LG_BYTES_PER_VALUE$);
+        assert (off >= 0);
+        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
+    }
+
+    public $Type$Buffer duplicate() {
+        return new Direct$Type$Buffer$RW$$BO$(this,
+                                              this.markValue(),
+                                              this.position(),
+                                              this.limit(),
+                                              this.capacity(),
+                                              0);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new Direct$Type$BufferR$BO$(this,
+                                           this.markValue(),
+                                           this.position(),
+                                           this.limit(),
+                                           this.capacity(),
+                                           0);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    public long address() {
+        return address;
+    }
+
+    private long ix(int i) {
+        return address + (i << $LG_BYTES_PER_VALUE$);
+    }
+
+    public $type$ get() {
+        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
+    }
+
+    public $type$ get(int i) {
+        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
+    }
+
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+#if[rw]
+        if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
+            checkBounds(offset, length, dst.length);
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+            if (length > rem)
+                throw new BufferUnderflowException();
+
+#if[!byte]
+            if (order() != ByteOrder.nativeOrder())
+                Bits.copyTo$Memtype$Array(ix(pos), dst,
+                                          offset << $LG_BYTES_PER_VALUE$,
+                                          length << $LG_BYTES_PER_VALUE$);
+            else
+#end[!byte]
+                Bits.copyToArray(ix(pos), dst, arrayBaseOffset,
+                                 offset << $LG_BYTES_PER_VALUE$,
+                                 length << $LG_BYTES_PER_VALUE$);
+            position(pos + length);
+        } else {
+            super.get(dst, offset, length);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+#end[rw]
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($Type$Buffer src) {
+#if[rw]
+        if (src instanceof Direct$Type$Buffer$BO$) {
+            if (src == this)
+                throw new IllegalArgumentException();
+            Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
+
+            int spos = sb.position();
+            int slim = sb.limit();
+            assert (spos <= slim);
+            int srem = (spos <= slim ? slim - spos : 0);
+
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+
+            if (srem > rem)
+                throw new BufferOverflowException();
+            unsafe.copyMemory(sb.ix(spos), ix(pos), srem << $LG_BYTES_PER_VALUE$);
+            sb.position(spos + srem);
+            position(pos + srem);
+        } else if (src.hb != null) {
+
+            int spos = src.position();
+            int slim = src.limit();
+            assert (spos <= slim);
+            int srem = (spos <= slim ? slim - spos : 0);
+
+            put(src.hb, src.offset + spos, srem);
+            src.position(spos + srem);
+
+        } else {
+            super.put(src);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+#if[rw]
+        if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
+            checkBounds(offset, length, src.length);
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+            if (length > rem)
+                throw new BufferOverflowException();
+
+#if[!byte]
+            if (order() != ByteOrder.nativeOrder())
+                Bits.copyFrom$Memtype$Array(src, offset << $LG_BYTES_PER_VALUE$,
+                                            ix(pos), length << $LG_BYTES_PER_VALUE$);
+            else
+#end[!byte]
+                Bits.copyFromArray(src, arrayBaseOffset, offset << $LG_BYTES_PER_VALUE$,
+                                   ix(pos), length << $LG_BYTES_PER_VALUE$);
+            position(pos + length);
+        } else {
+            super.put(src, offset, length);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        unsafe.copyMemory(ix(pos), ix(0), rem << $LG_BYTES_PER_VALUE$);
+        position(rem);
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public boolean isDirect() {
+        return true;
+    }
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+
+#if[char]
+
+    public String toString(int start, int end) {
+        if ((end > limit()) || (start > end))
+            throw new IndexOutOfBoundsException();
+        try {
+            int len = end - start;
+            char[] ca = new char[len];
+            CharBuffer cb = CharBuffer.wrap(ca);
+            CharBuffer db = this.duplicate();
+            db.position(start);
+            db.limit(end);
+            cb.put(db);
+            return new String(ca);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        pos = (pos <= lim ? pos : lim);
+        int len = lim - pos;
+
+        if ((start < 0) || (end > len) || (start > end))
+            throw new IndexOutOfBoundsException();
+        return new DirectCharBuffer$RW$$BO$(this,
+                                            -1,
+                                            pos + start,
+                                            pos + end,
+                                            capacity(),
+                                            offset);
+    }
+
+#end[char]
+
+
+
+#if[!byte]
+
+    public ByteOrder order() {
+#if[boS]
+        return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+#end[boS]
+#if[boU]
+        return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
+                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+#end[boU]
+    }
+
+#end[!byte]
+
+
+
+#if[byte]
+
+    byte _get(int i) {                          // package-private
+        return unsafe.getByte(address + i);
+    }
+
+    void _put(int i, byte b) {                  // package-private
+#if[rw]
+        unsafe.putByte(address + i, b);
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    // #BIN
+    //
+    // Binary-data access methods  for short, char, int, long, float,
+    // and double will be inserted here
+
+#end[byte]
+
+}
--- a/src/share/classes/java/nio/Heap-X-Buffer.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,595 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio;
-
-
-/**
-#if[rw]
- * A read/write Heap$Type$Buffer.
-#else[rw]
- * A read-only Heap$Type$Buffer.  This class extends the corresponding
- * read/write class, overriding the mutation methods to throw a {@link
- * ReadOnlyBufferException} and overriding the view-buffer methods to return an
- * instance of this class rather than of the superclass.
-#end[rw]
- */
-
-class Heap$Type$Buffer$RW$
-    extends {#if[ro]?Heap}$Type$Buffer
-{
-
-    // For speed these fields are actually declared in X-Buffer;
-    // these declarations are here as documentation
-    /*
-#if[rw]
-    protected final $type$[] hb;
-    protected final int offset;
-#end[rw]
-    */
-
-    Heap$Type$Buffer$RW$(int cap, int lim) {            // package-private
-#if[rw]
-        super(-1, 0, lim, cap, new $type$[cap], 0);
-        /*
-        hb = new $type$[cap];
-        offset = 0;
-        */
-#else[rw]
-        super(cap, lim);
-        this.isReadOnly = true;
-#end[rw]
-    }
-
-    Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
-#if[rw]
-        super(-1, off, off + len, buf.length, buf, 0);
-        /*
-        hb = buf;
-        offset = 0;
-        */
-#else[rw]
-        super(buf, off, len);
-        this.isReadOnly = true;
-#end[rw]
-    }
-
-    protected Heap$Type$Buffer$RW$($type$[] buf,
-                                   int mark, int pos, int lim, int cap,
-                                   int off)
-    {
-#if[rw]
-        super(mark, pos, lim, cap, buf, off);
-        /*
-        hb = buf;
-        offset = off;
-        */
-#else[rw]
-        super(buf, mark, pos, lim, cap, off);
-        this.isReadOnly = true;
-#end[rw]
-    }
-
-    public $Type$Buffer slice() {
-        return new Heap$Type$Buffer$RW$(hb,
-                                        -1,
-                                        0,
-                                        this.remaining(),
-                                        this.remaining(),
-                                        this.position() + offset);
-    }
-
-    public $Type$Buffer duplicate() {
-        return new Heap$Type$Buffer$RW$(hb,
-                                        this.markValue(),
-                                        this.position(),
-                                        this.limit(),
-                                        this.capacity(),
-                                        offset);
-    }
-
-    public $Type$Buffer asReadOnlyBuffer() {
-#if[rw]
-        return new Heap$Type$BufferR(hb,
-                                     this.markValue(),
-                                     this.position(),
-                                     this.limit(),
-                                     this.capacity(),
-                                     offset);
-#else[rw]
-        return duplicate();
-#end[rw]
-    }
-
-#if[rw]
-
-    protected int ix(int i) {
-        return i + offset;
-    }
-
-    public $type$ get() {
-        return hb[ix(nextGetIndex())];
-    }
-
-    public $type$ get(int i) {
-        return hb[ix(checkIndex(i))];
-    }
-
-    public $Type$Buffer get($type$[] dst, int offset, int length) {
-        checkBounds(offset, length, dst.length);
-        if (length > remaining())
-            throw new BufferUnderflowException();
-        System.arraycopy(hb, ix(position()), dst, offset, length);
-        position(position() + length);
-        return this;
-    }
-
-    public boolean isDirect() {
-        return false;
-    }
-
-#end[rw]
-
-    public boolean isReadOnly() {
-        return {#if[rw]?false:true};
-    }
-
-    public $Type$Buffer put($type$ x) {
-#if[rw]
-        hb[ix(nextPutIndex())] = x;
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put(int i, $type$ x) {
-#if[rw]
-        hb[ix(checkIndex(i))] = x;
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put($type$[] src, int offset, int length) {
-#if[rw]
-        checkBounds(offset, length, src.length);
-        if (length > remaining())
-            throw new BufferOverflowException();
-        System.arraycopy(src, offset, hb, ix(position()), length);
-        position(position() + length);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer put($Type$Buffer src) {
-#if[rw]
-        if (src instanceof Heap$Type$Buffer) {
-            if (src == this)
-                throw new IllegalArgumentException();
-            Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
-            int n = sb.remaining();
-            if (n > remaining())
-                throw new BufferOverflowException();
-            System.arraycopy(sb.hb, sb.ix(sb.position()),
-                             hb, ix(position()), n);
-            sb.position(sb.position() + n);
-            position(position() + n);
-        } else if (src.isDirect()) {
-            int n = src.remaining();
-            if (n > remaining())
-                throw new BufferOverflowException();
-            src.get(hb, ix(position()), n);
-            position(position() + n);
-        } else {
-            super.put(src);
-        }
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer compact() {
-#if[rw]
-        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
-        position(remaining());
-        limit(capacity());
-        discardMark();
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-
-
-#if[byte]
-
-    byte _get(int i) {                          // package-private
-        return hb[i];
-    }
-
-    void _put(int i, byte b) {                  // package-private
-#if[rw]
-        hb[i] = b;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    // char
-
-#if[rw]
-
-    public char getChar() {
-        return Bits.getChar(this, ix(nextGetIndex(2)), bigEndian);
-    }
-
-    public char getChar(int i) {
-        return Bits.getChar(this, ix(checkIndex(i, 2)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putChar(char x) {
-#if[rw]
-        Bits.putChar(this, ix(nextPutIndex(2)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putChar(int i, char x) {
-#if[rw]
-        Bits.putChar(this, ix(checkIndex(i, 2)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public CharBuffer asCharBuffer() {
-        int size = this.remaining() >> 1;
-        int off = offset + position();
-        return (bigEndian
-                ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
-                                                               -1,
-                                                               0,
-                                                               size,
-                                                               size,
-                                                               off))
-                : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
-                                                               -1,
-                                                               0,
-                                                               size,
-                                                               size,
-                                                               off)));
-    }
-
-
-    // short
-
-#if[rw]
-
-    public short getShort() {
-        return Bits.getShort(this, ix(nextGetIndex(2)), bigEndian);
-    }
-
-    public short getShort(int i) {
-        return Bits.getShort(this, ix(checkIndex(i, 2)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putShort(short x) {
-#if[rw]
-        Bits.putShort(this, ix(nextPutIndex(2)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putShort(int i, short x) {
-#if[rw]
-        Bits.putShort(this, ix(checkIndex(i, 2)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public ShortBuffer asShortBuffer() {
-        int size = this.remaining() >> 1;
-        int off = offset + position();
-        return (bigEndian
-                ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off))
-                : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off)));
-    }
-
-
-    // int
-
-#if[rw]
-
-    public int getInt() {
-        return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
-    }
-
-    public int getInt(int i) {
-        return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putInt(int x) {
-#if[rw]
-        Bits.putInt(this, ix(nextPutIndex(4)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putInt(int i, int x) {
-#if[rw]
-        Bits.putInt(this, ix(checkIndex(i, 4)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public IntBuffer asIntBuffer() {
-        int size = this.remaining() >> 2;
-        int off = offset + position();
-        return (bigEndian
-                ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
-                                                             -1,
-                                                             0,
-                                                             size,
-                                                             size,
-                                                             off))
-                : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
-                                                             -1,
-                                                             0,
-                                                             size,
-                                                             size,
-                                                             off)));
-    }
-
-
-    // long
-
-#if[rw]
-
-    public long getLong() {
-        return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian);
-    }
-
-    public long getLong(int i) {
-        return Bits.getLong(this, ix(checkIndex(i, 8)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putLong(long x) {
-#if[rw]
-        Bits.putLong(this, ix(nextPutIndex(8)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putLong(int i, long x) {
-#if[rw]
-        Bits.putLong(this, ix(checkIndex(i, 8)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public LongBuffer asLongBuffer() {
-        int size = this.remaining() >> 3;
-        int off = offset + position();
-        return (bigEndian
-                ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
-                                                               -1,
-                                                               0,
-                                                               size,
-                                                               size,
-                                                               off))
-                : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
-                                                               -1,
-                                                               0,
-                                                               size,
-                                                               size,
-                                                               off)));
-    }
-
-
-    // float
-
-#if[rw]
-
-    public float getFloat() {
-        return Bits.getFloat(this, ix(nextGetIndex(4)), bigEndian);
-    }
-
-    public float getFloat(int i) {
-        return Bits.getFloat(this, ix(checkIndex(i, 4)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putFloat(float x) {
-#if[rw]
-        Bits.putFloat(this, ix(nextPutIndex(4)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putFloat(int i, float x) {
-#if[rw]
-        Bits.putFloat(this, ix(checkIndex(i, 4)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public FloatBuffer asFloatBuffer() {
-        int size = this.remaining() >> 2;
-        int off = offset + position();
-        return (bigEndian
-                ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off))
-                : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
-                                                                 -1,
-                                                                 0,
-                                                                 size,
-                                                                 size,
-                                                                 off)));
-    }
-
-
-    // double
-
-#if[rw]
-
-    public double getDouble() {
-        return Bits.getDouble(this, ix(nextGetIndex(8)), bigEndian);
-    }
-
-    public double getDouble(int i) {
-        return Bits.getDouble(this, ix(checkIndex(i, 8)), bigEndian);
-    }
-
-#end[rw]
-
-    public $Type$Buffer putDouble(double x) {
-#if[rw]
-        Bits.putDouble(this, ix(nextPutIndex(8)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public $Type$Buffer putDouble(int i, double x) {
-#if[rw]
-        Bits.putDouble(this, ix(checkIndex(i, 8)), x, bigEndian);
-        return this;
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
-    public DoubleBuffer asDoubleBuffer() {
-        int size = this.remaining() >> 3;
-        int off = offset + position();
-        return (bigEndian
-                ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
-                                                                   -1,
-                                                                   0,
-                                                                   size,
-                                                                   size,
-                                                                   off))
-                : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
-                                                                   -1,
-                                                                   0,
-                                                                   size,
-                                                                   size,
-                                                                   off)));
-    }
-
-
-#end[byte]
-
-
-#if[char]
-
-    String toString(int start, int end) {               // package-private
-        try {
-            return new String(hb, start + offset, end - start);
-        } catch (StringIndexOutOfBoundsException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-
-    // --- Methods to support CharSequence ---
-
-    public CharBuffer subSequence(int start, int end) {
-        if ((start < 0)
-            || (end > length())
-            || (start > end))
-            throw new IndexOutOfBoundsException();
-        int pos = position();
-        return new HeapCharBuffer$RW$(hb,
-                                      -1,
-                                      pos + start,
-                                      pos + end,
-                                      capacity(),
-                                      offset);
-    }
-
-#end[char]
-
-
-#if[!byte]
-
-    public ByteOrder order() {
-        return ByteOrder.nativeOrder();
-    }
-
-#end[!byte]
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/nio/Heap-X-Buffer.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,595 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+
+/**
+#if[rw]
+ * A read/write Heap$Type$Buffer.
+#else[rw]
+ * A read-only Heap$Type$Buffer.  This class extends the corresponding
+ * read/write class, overriding the mutation methods to throw a {@link
+ * ReadOnlyBufferException} and overriding the view-buffer methods to return an
+ * instance of this class rather than of the superclass.
+#end[rw]
+ */
+
+class Heap$Type$Buffer$RW$
+    extends {#if[ro]?Heap}$Type$Buffer
+{
+
+    // For speed these fields are actually declared in X-Buffer;
+    // these declarations are here as documentation
+    /*
+#if[rw]
+    protected final $type$[] hb;
+    protected final int offset;
+#end[rw]
+    */
+
+    Heap$Type$Buffer$RW$(int cap, int lim) {            // package-private
+#if[rw]
+        super(-1, 0, lim, cap, new $type$[cap], 0);
+        /*
+        hb = new $type$[cap];
+        offset = 0;
+        */
+#else[rw]
+        super(cap, lim);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
+#if[rw]
+        super(-1, off, off + len, buf.length, buf, 0);
+        /*
+        hb = buf;
+        offset = 0;
+        */
+#else[rw]
+        super(buf, off, len);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    protected Heap$Type$Buffer$RW$($type$[] buf,
+                                   int mark, int pos, int lim, int cap,
+                                   int off)
+    {
+#if[rw]
+        super(mark, pos, lim, cap, buf, off);
+        /*
+        hb = buf;
+        offset = off;
+        */
+#else[rw]
+        super(buf, mark, pos, lim, cap, off);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    public $Type$Buffer slice() {
+        return new Heap$Type$Buffer$RW$(hb,
+                                        -1,
+                                        0,
+                                        this.remaining(),
+                                        this.remaining(),
+                                        this.position() + offset);
+    }
+
+    public $Type$Buffer duplicate() {
+        return new Heap$Type$Buffer$RW$(hb,
+                                        this.markValue(),
+                                        this.position(),
+                                        this.limit(),
+                                        this.capacity(),
+                                        offset);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new Heap$Type$BufferR(hb,
+                                     this.markValue(),
+                                     this.position(),
+                                     this.limit(),
+                                     this.capacity(),
+                                     offset);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    protected int ix(int i) {
+        return i + offset;
+    }
+
+    public $type$ get() {
+        return hb[ix(nextGetIndex())];
+    }
+
+    public $type$ get(int i) {
+        return hb[ix(checkIndex(i))];
+    }
+
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+        checkBounds(offset, length, dst.length);
+        if (length > remaining())
+            throw new BufferUnderflowException();
+        System.arraycopy(hb, ix(position()), dst, offset, length);
+        position(position() + length);
+        return this;
+    }
+
+    public boolean isDirect() {
+        return false;
+    }
+
+#end[rw]
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        hb[ix(nextPutIndex())] = x;
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        hb[ix(checkIndex(i))] = x;
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+#if[rw]
+        checkBounds(offset, length, src.length);
+        if (length > remaining())
+            throw new BufferOverflowException();
+        System.arraycopy(src, offset, hb, ix(position()), length);
+        position(position() + length);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($Type$Buffer src) {
+#if[rw]
+        if (src instanceof Heap$Type$Buffer) {
+            if (src == this)
+                throw new IllegalArgumentException();
+            Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
+            int n = sb.remaining();
+            if (n > remaining())
+                throw new BufferOverflowException();
+            System.arraycopy(sb.hb, sb.ix(sb.position()),
+                             hb, ix(position()), n);
+            sb.position(sb.position() + n);
+            position(position() + n);
+        } else if (src.isDirect()) {
+            int n = src.remaining();
+            if (n > remaining())
+                throw new BufferOverflowException();
+            src.get(hb, ix(position()), n);
+            position(position() + n);
+        } else {
+            super.put(src);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
+        position(remaining());
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+
+
+#if[byte]
+
+    byte _get(int i) {                          // package-private
+        return hb[i];
+    }
+
+    void _put(int i, byte b) {                  // package-private
+#if[rw]
+        hb[i] = b;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    // char
+
+#if[rw]
+
+    public char getChar() {
+        return Bits.getChar(this, ix(nextGetIndex(2)), bigEndian);
+    }
+
+    public char getChar(int i) {
+        return Bits.getChar(this, ix(checkIndex(i, 2)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putChar(char x) {
+#if[rw]
+        Bits.putChar(this, ix(nextPutIndex(2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putChar(int i, char x) {
+#if[rw]
+        Bits.putChar(this, ix(checkIndex(i, 2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public CharBuffer asCharBuffer() {
+        int size = this.remaining() >> 1;
+        int off = offset + position();
+        return (bigEndian
+                ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               off))
+                : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               off)));
+    }
+
+
+    // short
+
+#if[rw]
+
+    public short getShort() {
+        return Bits.getShort(this, ix(nextGetIndex(2)), bigEndian);
+    }
+
+    public short getShort(int i) {
+        return Bits.getShort(this, ix(checkIndex(i, 2)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putShort(short x) {
+#if[rw]
+        Bits.putShort(this, ix(nextPutIndex(2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putShort(int i, short x) {
+#if[rw]
+        Bits.putShort(this, ix(checkIndex(i, 2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public ShortBuffer asShortBuffer() {
+        int size = this.remaining() >> 1;
+        int off = offset + position();
+        return (bigEndian
+                ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off))
+                : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off)));
+    }
+
+
+    // int
+
+#if[rw]
+
+    public int getInt() {
+        return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
+    }
+
+    public int getInt(int i) {
+        return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putInt(int x) {
+#if[rw]
+        Bits.putInt(this, ix(nextPutIndex(4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putInt(int i, int x) {
+#if[rw]
+        Bits.putInt(this, ix(checkIndex(i, 4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public IntBuffer asIntBuffer() {
+        int size = this.remaining() >> 2;
+        int off = offset + position();
+        return (bigEndian
+                ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
+                                                             -1,
+                                                             0,
+                                                             size,
+                                                             size,
+                                                             off))
+                : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
+                                                             -1,
+                                                             0,
+                                                             size,
+                                                             size,
+                                                             off)));
+    }
+
+
+    // long
+
+#if[rw]
+
+    public long getLong() {
+        return Bits.getLong(this, ix(nextGetIndex(8)), bigEndian);
+    }
+
+    public long getLong(int i) {
+        return Bits.getLong(this, ix(checkIndex(i, 8)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putLong(long x) {
+#if[rw]
+        Bits.putLong(this, ix(nextPutIndex(8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putLong(int i, long x) {
+#if[rw]
+        Bits.putLong(this, ix(checkIndex(i, 8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public LongBuffer asLongBuffer() {
+        int size = this.remaining() >> 3;
+        int off = offset + position();
+        return (bigEndian
+                ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               off))
+                : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               off)));
+    }
+
+
+    // float
+
+#if[rw]
+
+    public float getFloat() {
+        return Bits.getFloat(this, ix(nextGetIndex(4)), bigEndian);
+    }
+
+    public float getFloat(int i) {
+        return Bits.getFloat(this, ix(checkIndex(i, 4)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putFloat(float x) {
+#if[rw]
+        Bits.putFloat(this, ix(nextPutIndex(4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putFloat(int i, float x) {
+#if[rw]
+        Bits.putFloat(this, ix(checkIndex(i, 4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public FloatBuffer asFloatBuffer() {
+        int size = this.remaining() >> 2;
+        int off = offset + position();
+        return (bigEndian
+                ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off))
+                : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off)));
+    }
+
+
+    // double
+
+#if[rw]
+
+    public double getDouble() {
+        return Bits.getDouble(this, ix(nextGetIndex(8)), bigEndian);
+    }
+
+    public double getDouble(int i) {
+        return Bits.getDouble(this, ix(checkIndex(i, 8)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putDouble(double x) {
+#if[rw]
+        Bits.putDouble(this, ix(nextPutIndex(8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putDouble(int i, double x) {
+#if[rw]
+        Bits.putDouble(this, ix(checkIndex(i, 8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public DoubleBuffer asDoubleBuffer() {
+        int size = this.remaining() >> 3;
+        int off = offset + position();
+        return (bigEndian
+                ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
+                                                                   -1,
+                                                                   0,
+                                                                   size,
+                                                                   size,
+                                                                   off))
+                : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
+                                                                   -1,
+                                                                   0,
+                                                                   size,
+                                                                   size,
+                                                                   off)));
+    }
+
+
+#end[byte]
+
+
+#if[char]
+
+    String toString(int start, int end) {               // package-private
+        try {
+            return new String(hb, start + offset, end - start);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        if ((start < 0)
+            || (end > length())
+            || (start > end))
+            throw new IndexOutOfBoundsException();
+        int pos = position();
+        return new HeapCharBuffer$RW$(hb,
+                                      -1,
+                                      pos + start,
+                                      pos + end,
+                                      capacity(),
+                                      offset);
+    }
+
+#end[char]
+
+
+#if[!byte]
+
+    public ByteOrder order() {
+        return ByteOrder.nativeOrder();
+    }
+
+#end[!byte]
+
+}
--- a/src/share/classes/java/nio/X-Buffer-bin.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright 2000-2002 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#warn This file is preprocessed before being compiled
-
-class XXX {
-
-#begin
-
-    /**
-     * Relative <i>get</i> method for reading $a$ $type$ value.
-     *
-     * <p> Reads the next $nbytes$ bytes at this buffer's current position,
-     * composing them into $a$ $type$ value according to the current byte order,
-     * and then increments the position by $nbytes$.  </p>
-     *
-     * @return  The $type$ value at the buffer's current position
-     *
-     * @throws  BufferUnderflowException
-     *          If there are fewer than $nbytes$ bytes
-     *          remaining in this buffer
-     */
-    public abstract $type$ get$Type$();
-
-    /**
-     * Relative <i>put</i> method for writing $a$ $type$
-     * value&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
-     * current byte order, into this buffer at the current position, and then
-     * increments the position by $nbytes$.  </p>
-     *
-     * @param  value
-     *         The $type$ value to be written
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there are fewer than $nbytes$ bytes
-     *          remaining in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract ByteBuffer put$Type$($type$ value);
-
-    /**
-     * Absolute <i>get</i> method for reading $a$ $type$ value.
-     *
-     * <p> Reads $nbytes$ bytes at the given index, composing them into a
-     * $type$ value according to the current byte order.  </p>
-     *
-     * @param  index
-     *         The index from which the bytes will be read
-     *
-     * @return  The $type$ value at the given index
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>index</tt> is negative
-     *          or not smaller than the buffer's limit,
-     *          minus $nbytesButOne$
-     */
-    public abstract $type$ get$Type$(int index);
-
-    /**
-     * Absolute <i>put</i> method for writing $a$ $type$
-     * value&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
-     * current byte order, into this buffer at the given index.  </p>
-     *
-     * @param  index
-     *         The index at which the bytes will be written
-     *
-     * @param  value
-     *         The $type$ value to be written
-     *
-     * @return  This buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>index</tt> is negative
-     *          or not smaller than the buffer's limit,
-     *          minus $nbytesButOne$
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract ByteBuffer put$Type$(int index, $type$ value);
-
-    /**
-     * Creates a view of this byte buffer as $a$ $type$ buffer.
-     *
-     * <p> The content of the new buffer will start at this buffer's current
-     * position.  Changes to this buffer's content will be visible in the new
-     * buffer, and vice versa; the two buffers' position, limit, and mark
-     * values will be independent.
-     *
-     * <p> The new buffer's position will be zero, its capacity and its limit
-     * will be the number of bytes remaining in this buffer divided by
-     * $nbytes$, and its mark will be undefined.  The new buffer will be direct
-     * if, and only if, this buffer is direct, and it will be read-only if, and
-     * only if, this buffer is read-only.  </p>
-     *
-     * @return  A new $type$ buffer
-     */
-    public abstract $Type$Buffer as$Type$Buffer();
-
-#end
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/nio/X-Buffer-bin.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2002 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+class XXX {
+
+#begin
+
+    /**
+     * Relative <i>get</i> method for reading $a$ $type$ value.
+     *
+     * <p> Reads the next $nbytes$ bytes at this buffer's current position,
+     * composing them into $a$ $type$ value according to the current byte order,
+     * and then increments the position by $nbytes$.  </p>
+     *
+     * @return  The $type$ value at the buffer's current position
+     *
+     * @throws  BufferUnderflowException
+     *          If there are fewer than $nbytes$ bytes
+     *          remaining in this buffer
+     */
+    public abstract $type$ get$Type$();
+
+    /**
+     * Relative <i>put</i> method for writing $a$ $type$
+     * value&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
+     * current byte order, into this buffer at the current position, and then
+     * increments the position by $nbytes$.  </p>
+     *
+     * @param  value
+     *         The $type$ value to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there are fewer than $nbytes$ bytes
+     *          remaining in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract ByteBuffer put$Type$($type$ value);
+
+    /**
+     * Absolute <i>get</i> method for reading $a$ $type$ value.
+     *
+     * <p> Reads $nbytes$ bytes at the given index, composing them into a
+     * $type$ value according to the current byte order.  </p>
+     *
+     * @param  index
+     *         The index from which the bytes will be read
+     *
+     * @return  The $type$ value at the given index
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>index</tt> is negative
+     *          or not smaller than the buffer's limit,
+     *          minus $nbytesButOne$
+     */
+    public abstract $type$ get$Type$(int index);
+
+    /**
+     * Absolute <i>put</i> method for writing $a$ $type$
+     * value&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
+     * current byte order, into this buffer at the given index.  </p>
+     *
+     * @param  index
+     *         The index at which the bytes will be written
+     *
+     * @param  value
+     *         The $type$ value to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>index</tt> is negative
+     *          or not smaller than the buffer's limit,
+     *          minus $nbytesButOne$
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract ByteBuffer put$Type$(int index, $type$ value);
+
+    /**
+     * Creates a view of this byte buffer as $a$ $type$ buffer.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position.  Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of bytes remaining in this buffer divided by
+     * $nbytes$, and its mark will be undefined.  The new buffer will be direct
+     * if, and only if, this buffer is direct, and it will be read-only if, and
+     * only if, this buffer is read-only.  </p>
+     *
+     * @return  A new $type$ buffer
+     */
+    public abstract $Type$Buffer as$Type$Buffer();
+
+#end
+
+}
--- a/src/share/classes/java/nio/X-Buffer.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1428 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio;
-
-#if[char]
-import java.io.IOException;
-#end[char]
-
-/**
- * $A$ $fulltype$ buffer.
- *
- * <p> This class defines {#if[byte]?six:four} categories of operations upon
- * $fulltype$ buffers:
- *
- * <ul>
- *
- *   <li><p> Absolute and relative {@link #get() </code><i>get</i><code>} and
- *   {@link #put($type$) </code><i>put</i><code>} methods that read and write
- *   single $fulltype$s; </p></li>
- *
- *   <li><p> Relative {@link #get($type$[]) </code><i>bulk get</i><code>}
- *   methods that transfer contiguous sequences of $fulltype$s from this buffer
- *   into an array; {#if[!byte]?and}</p></li>
- *
- *   <li><p> Relative {@link #put($type$[]) </code><i>bulk put</i><code>}
- *   methods that transfer contiguous sequences of $fulltype$s from $a$
- *   $fulltype$ array{#if[char]?,&#32;a&#32;string,} or some other $fulltype$
- *   buffer into this buffer;{#if[!byte]?&#32;and} </p></li>
- *
-#if[byte]
- *
- *   <li><p> Absolute and relative {@link #getChar() </code><i>get</i><code>}
- *   and {@link #putChar(char) </code><i>put</i><code>} methods that read and
- *   write values of other primitive types, translating them to and from
- *   sequences of bytes in a particular byte order; </p></li>
- *
- *   <li><p> Methods for creating <i><a href="#views">view buffers</a></i>,
- *   which allow a byte buffer to be viewed as a buffer containing values of
- *   some other primitive type; and </p></li>
- *
-#end[byte]
- *
- *   <li><p> Methods for {@link #compact </code>compacting<code>}, {@link
- *   #duplicate </code>duplicating<code>}, and {@link #slice
- *   </code>slicing<code>} $a$ $fulltype$ buffer.  </p></li>
- *
- * </ul>
- *
- * <p> $Fulltype$ buffers can be created either by {@link #allocate
- * </code><i>allocation</i><code>}, which allocates space for the buffer's
- *
-#if[byte]
- *
- * content, or by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an
- * existing $fulltype$ array {#if[char]?or&#32;string} into a buffer.
- *
-#else[byte]
- *
- * content, by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an existing
- * $fulltype$ array {#if[char]?or&#32;string} into a buffer, or by creating a
- * <a href="ByteBuffer.html#views"><i>view</i></a> of an existing byte buffer.
- *
-#end[byte]
- *
-#if[byte]
- *
- * <a name="direct">
- * <h4> Direct <i>vs.</i> non-direct buffers </h4>
- *
- * <p> A byte buffer is either <i>direct</i> or <i>non-direct</i>.  Given a
- * direct byte buffer, the Java virtual machine will make a best effort to
- * perform native I/O operations directly upon it.  That is, it will attempt to
- * avoid copying the buffer's content to (or from) an intermediate buffer
- * before (or after) each invocation of one of the underlying operating
- * system's native I/O operations.
- *
- * <p> A direct byte buffer may be created by invoking the {@link
- * #allocateDirect(int) allocateDirect} factory method of this class.  The
- * buffers returned by this method typically have somewhat higher allocation
- * and deallocation costs than non-direct buffers.  The contents of direct
- * buffers may reside outside of the normal garbage-collected heap, and so
- * their impact upon the memory footprint of an application might not be
- * obvious.  It is therefore recommended that direct buffers be allocated
- * primarily for large, long-lived buffers that are subject to the underlying
- * system's native I/O operations.  In general it is best to allocate direct
- * buffers only when they yield a measureable gain in program performance.
- *
- * <p> A direct byte buffer may also be created by {@link
- * java.nio.channels.FileChannel#map </code>mapping<code>} a region of a file
- * directly into memory.  An implementation of the Java platform may optionally
- * support the creation of direct byte buffers from native code via JNI.  If an
- * instance of one of these kinds of buffers refers to an inaccessible region
- * of memory then an attempt to access that region will not change the buffer's
- * content and will cause an unspecified exception to be thrown either at the
- * time of the access or at some later time.
- *
- * <p> Whether a byte buffer is direct or non-direct may be determined by
- * invoking its {@link #isDirect isDirect} method.  This method is provided so
- * that explicit buffer management can be done in performance-critical code.
- *
- *
- * <a name="bin">
- * <h4> Access to binary data </h4>
- *
- * <p> This class defines methods for reading and writing values of all other
- * primitive types, except <tt>boolean</tt>.  Primitive values are translated
- * to (or from) sequences of bytes according to the buffer's current byte
- * order, which may be retrieved and modified via the {@link #order order}
- * methods.  Specific byte orders are represented by instances of the {@link
- * ByteOrder} class.  The initial order of a byte buffer is always {@link
- * ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
- *
- * <p> For access to heterogeneous binary data, that is, sequences of values of
- * different types, this class defines a family of absolute and relative
- * <i>get</i> and <i>put</i> methods for each type.  For 32-bit floating-point
- * values, for example, this class defines:
- *
- * <blockquote><pre>
- * float  {@link #getFloat()}
- * float  {@link #getFloat(int) getFloat(int index)}
- *  void  {@link #putFloat(float) putFloat(float f)}
- *  void  {@link #putFloat(int,float) putFloat(int index, float f)}</pre></blockquote>
- *
- * <p> Corresponding methods are defined for the types <tt>char</tt>,
- * <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and <tt>double</tt>.  The index
- * parameters of the absolute <i>get</i> and <i>put</i> methods are in terms of
- * bytes rather than of the type being read or written.
- *
- * <a name="views">
- *
- * <p> For access to homogeneous binary data, that is, sequences of values of
- * the same type, this class defines methods that can create <i>views</i> of a
- * given byte buffer.  A <i>view buffer</i> is simply another buffer whose
- * content is backed by the byte buffer.  Changes to the byte buffer's content
- * will be visible in the view buffer, and vice versa; the two buffers'
- * position, limit, and mark values are independent.  The {@link
- * #asFloatBuffer() asFloatBuffer} method, for example, creates an instance of
- * the {@link FloatBuffer} class that is backed by the byte buffer upon which
- * the method is invoked.  Corresponding view-creation methods are defined for
- * the types <tt>char</tt>, <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and
- * <tt>double</tt>.
- *
- * <p> View buffers have three important advantages over the families of
- * type-specific <i>get</i> and <i>put</i> methods described above:
- *
- * <ul>
- *
- *   <li><p> A view buffer is indexed not in terms of bytes but rather in terms
- *   of the type-specific size of its values;  </p></li>
- *
- *   <li><p> A view buffer provides relative bulk <i>get</i> and <i>put</i>
- *   methods that can transfer contiguous sequences of values between a buffer
- *   and an array or some other buffer of the same type; and  </p></li>
- *
- *   <li><p> A view buffer is potentially much more efficient because it will
- *   be direct if, and only if, its backing byte buffer is direct.  </p></li>
- *
- * </ul>
- *
- * <p> The byte order of a view buffer is fixed to be that of its byte buffer
- * at the time that the view is created.  </p>
- *
-#end[byte]
-*
-#if[!byte]
- *
- * <p> Like a byte buffer, $a$ $fulltype$ buffer is either <a
- * href="ByteBuffer.html#direct"><i>direct</i> or <i>non-direct</i></a>.  A
- * $fulltype$ buffer created via the <tt>wrap</tt> methods of this class will
- * be non-direct.  $A$ $fulltype$ buffer created as a view of a byte buffer will
- * be direct if, and only if, the byte buffer itself is direct.  Whether or not
- * $a$ $fulltype$ buffer is direct may be determined by invoking the {@link
- * #isDirect isDirect} method.  </p>
- *
-#end[!byte]
-*
-#if[char]
- *
- * <p> This class implements the {@link CharSequence} interface so that
- * character buffers may be used wherever character sequences are accepted, for
- * example in the regular-expression package <tt>{@link java.util.regex}</tt>.
- * </p>
- *
-#end[char]
- *
-#if[byte]
- * <h4> Invocation chaining </h4>
-#end[byte]
- *
- * <p> Methods in this class that do not otherwise have a value to return are
- * specified to return the buffer upon which they are invoked.  This allows
- * method invocations to be chained.
- *
-#if[byte]
- *
- * The sequence of statements
- *
- * <blockquote><pre>
- * bb.putInt(0xCAFEBABE);
- * bb.putShort(3);
- * bb.putShort(45);</pre></blockquote>
- *
- * can, for example, be replaced by the single statement
- *
- * <blockquote><pre>
- * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);</pre></blockquote>
- *
-#end[byte]
-#if[char]
- *
- * The sequence of statements
- *
- * <blockquote><pre>
- * cb.put("text/");
- * cb.put(subtype);
- * cb.put("; charset=");
- * cb.put(enc);</pre></blockquote>
- *
- * can, for example, be replaced by the single statement
- *
- * <blockquote><pre>
- * cb.put("text/").put(subtype).put("; charset=").put(enc);</pre></blockquote>
- *
-#end[char]
- *
- *
- * @author Mark Reinhold
- * @author JSR-51 Expert Group
- * @since 1.4
- */
-
-public abstract class $Type$Buffer
-    extends Buffer
-    implements Comparable<$Type$Buffer>{#if[char]?, Appendable, CharSequence, Readable}
-{
-
-    // These fields are declared here rather than in Heap-X-Buffer in order to
-    // reduce the number of virtual method invocations needed to access these
-    // values, which is especially costly when coding small buffers.
-    //
-    final $type$[] hb;                  // Non-null only for heap buffers
-    final int offset;
-    boolean isReadOnly;                 // Valid only for heap buffers
-
-    // Creates a new buffer with the given mark, position, limit, capacity,
-    // backing array, and array offset
-    //
-    $Type$Buffer(int mark, int pos, int lim, int cap,   // package-private
-                 $type$[] hb, int offset)
-    {
-        super(mark, pos, lim, cap);
-        this.hb = hb;
-        this.offset = offset;
-    }
-
-    // Creates a new buffer with the given mark, position, limit, and capacity
-    //
-    $Type$Buffer(int mark, int pos, int lim, int cap) { // package-private
-        this(mark, pos, lim, cap, null, 0);
-    }
-
-#if[byte]
-
-    /**
-     * Allocates a new direct $fulltype$ buffer.
-     *
-     * <p> The new buffer's position will be zero, its limit will be its
-     * capacity, its mark will be undefined, and each of its elements will be
-     * initialized to zero.  Whether or not it has a
-     * {@link #hasArray </code>backing array<code>} is unspecified.
-     *
-     * @param  capacity
-     *         The new buffer's capacity, in $fulltype$s
-     *
-     * @return  The new $fulltype$ buffer
-     *
-     * @throws  IllegalArgumentException
-     *          If the <tt>capacity</tt> is a negative integer
-     */
-    public static $Type$Buffer allocateDirect(int capacity) {
-        return new Direct$Type$Buffer(capacity);
-    }
-
-#end[byte]
-
-    /**
-     * Allocates a new $fulltype$ buffer.
-     *
-     * <p> The new buffer's position will be zero, its limit will be its
-     * capacity, its mark will be undefined, and each of its elements will be
-     * initialized to zero.  It will have a {@link #array
-     * </code>backing array<code>}, and its {@link #arrayOffset </code>array
-     * offset<code>} will be zero.
-     *
-     * @param  capacity
-     *         The new buffer's capacity, in $fulltype$s
-     *
-     * @return  The new $fulltype$ buffer
-     *
-     * @throws  IllegalArgumentException
-     *          If the <tt>capacity</tt> is a negative integer
-     */
-    public static $Type$Buffer allocate(int capacity) {
-        if (capacity < 0)
-            throw new IllegalArgumentException();
-        return new Heap$Type$Buffer(capacity, capacity);
-    }
-
-    /**
-     * Wraps $a$ $fulltype$ array into a buffer.
-     *
-     * <p> The new buffer will be backed by the given $fulltype$ array;
-     * that is, modifications to the buffer will cause the array to be modified
-     * and vice versa.  The new buffer's capacity will be
-     * <tt>array.length</tt>, its position will be <tt>offset</tt>, its limit
-     * will be <tt>offset + length</tt>, and its mark will be undefined.  Its
-     * {@link #array </code>backing array<code>} will be the given array, and
-     * its {@link #arrayOffset </code>array offset<code>} will be zero.  </p>
-     *
-     * @param  array
-     *         The array that will back the new buffer
-     *
-     * @param  offset
-     *         The offset of the subarray to be used; must be non-negative and
-     *         no larger than <tt>array.length</tt>.  The new buffer's position
-     *         will be set to this value.
-     *
-     * @param  length
-     *         The length of the subarray to be used;
-     *         must be non-negative and no larger than
-     *         <tt>array.length - offset</tt>.
-     *         The new buffer's limit will be set to <tt>offset + length</tt>.
-     *
-     * @return  The new $fulltype$ buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
-     *          parameters do not hold
-     */
-    public static $Type$Buffer wrap($type$[] array,
-                                    int offset, int length)
-    {
-        try {
-            return new Heap$Type$Buffer(array, offset, length);
-        } catch (IllegalArgumentException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-    /**
-     * Wraps $a$ $fulltype$ array into a buffer.
-     *
-     * <p> The new buffer will be backed by the given $fulltype$ array;
-     * that is, modifications to the buffer will cause the array to be modified
-     * and vice versa.  The new buffer's capacity and limit will be
-     * <tt>array.length</tt>, its position will be zero, and its mark will be
-     * undefined.  Its {@link #array </code>backing array<code>} will be the
-     * given array, and its {@link #arrayOffset </code>array offset<code>} will
-     * be zero.  </p>
-     *
-     * @param  array
-     *         The array that will back this buffer
-     *
-     * @return  The new $fulltype$ buffer
-     */
-    public static $Type$Buffer wrap($type$[] array) {
-        return wrap(array, 0, array.length);
-    }
-
-#if[char]
-
-    /**
-     * Attempts to read characters into the specified character buffer.
-     * The buffer is used as a repository of characters as-is: the only
-     * changes made are the results of a put operation. No flipping or
-     * rewinding of the buffer is performed.
-     *
-     * @param target the buffer to read characters into
-     * @return The number of characters added to the buffer, or
-     *         -1 if this source of characters is at its end
-     * @throws IOException if an I/O error occurs
-     * @throws NullPointerException if target is null
-     * @throws ReadOnlyBufferException if target is a read only buffer
-     * @since 1.5
-     */
-    public int read(CharBuffer target) throws IOException {
-        // Determine the number of bytes n that can be transferred
-        int targetRemaining = target.remaining();
-        int remaining = remaining();
-        if (remaining == 0)
-            return -1;
-        int n = Math.min(remaining, targetRemaining);
-        int limit = limit();
-        // Set source limit to prevent target overflow
-        if (targetRemaining < remaining)
-            limit(position() + n);
-        try {
-            if (n > 0)
-                target.put(this);
-        } finally {
-            limit(limit); // restore real limit
-        }
-        return n;
-    }
-
-    /**
-     * Wraps a character sequence into a buffer.
-     *
-     * <p> The content of the new, read-only buffer will be the content of the
-     * given character sequence.  The buffer's capacity will be
-     * <tt>csq.length()</tt>, its position will be <tt>start</tt>, its limit
-     * will be <tt>end</tt>, and its mark will be undefined.  </p>
-     *
-     * @param  csq
-     *         The character sequence from which the new character buffer is to
-     *         be created
-     *
-     * @param  start
-     *         The index of the first character to be used;
-     *         must be non-negative and no larger than <tt>csq.length()</tt>.
-     *         The new buffer's position will be set to this value.
-     *
-     * @param  end
-     *         The index of the character following the last character to be
-     *         used; must be no smaller than <tt>start</tt> and no larger
-     *         than <tt>csq.length()</tt>.
-     *         The new buffer's limit will be set to this value.
-     *
-     * @return  The new character buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>start</tt> and <tt>end</tt>
-     *          parameters do not hold
-     */
-    public static CharBuffer wrap(CharSequence csq, int start, int end) {
-        try {
-            return new StringCharBuffer(csq, start, end);
-        } catch (IllegalArgumentException x) {
-            throw new IndexOutOfBoundsException();
-        }
-    }
-
-    /**
-     * Wraps a character sequence into a buffer.
-     *
-     * <p> The content of the new, read-only buffer will be the content of the
-     * given character sequence.  The new buffer's capacity and limit will be
-     * <tt>csq.length()</tt>, its position will be zero, and its mark will be
-     * undefined.  </p>
-     *
-     * @param  csq
-     *         The character sequence from which the new character buffer is to
-     *         be created
-     *
-     * @return  The new character buffer
-     */
-    public static CharBuffer wrap(CharSequence csq) {
-        return wrap(csq, 0, csq.length());
-    }
-
-#end[char]
-
-    /**
-     * Creates a new $fulltype$ buffer whose content is a shared subsequence of
-     * this buffer's content.
-     *
-     * <p> The content of the new buffer will start at this buffer's current
-     * position.  Changes to this buffer's content will be visible in the new
-     * buffer, and vice versa; the two buffers' position, limit, and mark
-     * values will be independent.
-     *
-     * <p> The new buffer's position will be zero, its capacity and its limit
-     * will be the number of $fulltype$s remaining in this buffer, and its mark
-     * will be undefined.  The new buffer will be direct if, and only if, this
-     * buffer is direct, and it will be read-only if, and only if, this buffer
-     * is read-only.  </p>
-     *
-     * @return  The new $fulltype$ buffer
-     */
-    public abstract $Type$Buffer slice();
-
-    /**
-     * Creates a new $fulltype$ buffer that shares this buffer's content.
-     *
-     * <p> The content of the new buffer will be that of this buffer.  Changes
-     * to this buffer's content will be visible in the new buffer, and vice
-     * versa; the two buffers' position, limit, and mark values will be
-     * independent.
-     *
-     * <p> The new buffer's capacity, limit, position, and mark values will be
-     * identical to those of this buffer.  The new buffer will be direct if,
-     * and only if, this buffer is direct, and it will be read-only if, and
-     * only if, this buffer is read-only.  </p>
-     *
-     * @return  The new $fulltype$ buffer
-     */
-    public abstract $Type$Buffer duplicate();
-
-    /**
-     * Creates a new, read-only $fulltype$ buffer that shares this buffer's
-     * content.
-     *
-     * <p> The content of the new buffer will be that of this buffer.  Changes
-     * to this buffer's content will be visible in the new buffer; the new
-     * buffer itself, however, will be read-only and will not allow the shared
-     * content to be modified.  The two buffers' position, limit, and mark
-     * values will be independent.
-     *
-     * <p> The new buffer's capacity, limit, position, and mark values will be
-     * identical to those of this buffer.
-     *
-     * <p> If this buffer is itself read-only then this method behaves in
-     * exactly the same way as the {@link #duplicate duplicate} method.  </p>
-     *
-     * @return  The new, read-only $fulltype$ buffer
-     */
-    public abstract $Type$Buffer asReadOnlyBuffer();
-
-
-    // -- Singleton get/put methods --
-
-    /**
-     * Relative <i>get</i> method.  Reads the $fulltype$ at this buffer's
-     * current position, and then increments the position. </p>
-     *
-     * @return  The $fulltype$ at the buffer's current position
-     *
-     * @throws  BufferUnderflowException
-     *          If the buffer's current position is not smaller than its limit
-     */
-    public abstract $type$ get();
-
-    /**
-     * Relative <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Writes the given $fulltype$ into this buffer at the current
-     * position, and then increments the position. </p>
-     *
-     * @param  $x$
-     *         The $fulltype$ to be written
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If this buffer's current position is not smaller than its limit
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract $Type$Buffer put($type$ $x$);
-
-    /**
-     * Absolute <i>get</i> method.  Reads the $fulltype$ at the given
-     * index. </p>
-     *
-     * @param  index
-     *         The index from which the $fulltype$ will be read
-     *
-     * @return  The $fulltype$ at the given index
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>index</tt> is negative
-     *          or not smaller than the buffer's limit
-     */
-    public abstract $type$ get(int index);
-
-    /**
-     * Absolute <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Writes the given $fulltype$ into this buffer at the given
-     * index. </p>
-     *
-     * @param  index
-     *         The index at which the $fulltype$ will be written
-     *
-     * @param  $x$
-     *         The $fulltype$ value to be written
-     *
-     * @return  This buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>index</tt> is negative
-     *          or not smaller than the buffer's limit
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract $Type$Buffer put(int index, $type$ $x$);
-
-
-    // -- Bulk get operations --
-
-    /**
-     * Relative bulk <i>get</i> method.
-     *
-     * <p> This method transfers $fulltype$s from this buffer into the given
-     * destination array.  If there are fewer $fulltype$s remaining in the
-     * buffer than are required to satisfy the request, that is, if
-     * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
-     * $fulltype$s are transferred and a {@link BufferUnderflowException} is
-     * thrown.
-     *
-     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from this
-     * buffer into the given array, starting at the current position of this
-     * buffer and at the given offset in the array.  The position of this
-     * buffer is then incremented by <tt>length</tt>.
-     *
-     * <p> In other words, an invocation of this method of the form
-     * <tt>src.get(dst,&nbsp;off,&nbsp;len)</tt> has exactly the same effect as
-     * the loop
-     *
-     * <pre>
-     *     for (int i = off; i < off + len; i++)
-     *         dst[i] = src.get(); </pre>
-     *
-     * except that it first checks that there are sufficient $fulltype$s in
-     * this buffer and it is potentially much more efficient. </p>
-     *
-     * @param  dst
-     *         The array into which $fulltype$s are to be written
-     *
-     * @param  offset
-     *         The offset within the array of the first $fulltype$ to be
-     *         written; must be non-negative and no larger than
-     *         <tt>dst.length</tt>
-     *
-     * @param  length
-     *         The maximum number of $fulltype$s to be written to the given
-     *         array; must be non-negative and no larger than
-     *         <tt>dst.length - offset</tt>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferUnderflowException
-     *          If there are fewer than <tt>length</tt> $fulltype$s
-     *          remaining in this buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
-     *          parameters do not hold
-     */
-    public $Type$Buffer get($type$[] dst, int offset, int length) {
-        checkBounds(offset, length, dst.length);
-        if (length > remaining())
-            throw new BufferUnderflowException();
-        int end = offset + length;
-        for (int i = offset; i < end; i++)
-            dst[i] = get();
-        return this;
-    }
-
-    /**
-     * Relative bulk <i>get</i> method.
-     *
-     * <p> This method transfers $fulltype$s from this buffer into the given
-     * destination array.  An invocation of this method of the form
-     * <tt>src.get(a)</tt> behaves in exactly the same way as the invocation
-     *
-     * <pre>
-     *     src.get(a, 0, a.length) </pre>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferUnderflowException
-     *          If there are fewer than <tt>length</tt> $fulltype$s
-     *          remaining in this buffer
-     */
-    public $Type$Buffer get($type$[] dst) {
-        return get(dst, 0, dst.length);
-    }
-
-
-    // -- Bulk put operations --
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers the $fulltype$s remaining in the given source
-     * buffer into this buffer.  If there are more $fulltype$s remaining in the
-     * source buffer than in this buffer, that is, if
-     * <tt>src.remaining()</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
-     * then no $fulltype$s are transferred and a {@link
-     * BufferOverflowException} is thrown.
-     *
-     * <p> Otherwise, this method copies
-     * <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $fulltype$s from the given
-     * buffer into this buffer, starting at each buffer's current position.
-     * The positions of both buffers are then incremented by <i>n</i>.
-     *
-     * <p> In other words, an invocation of this method of the form
-     * <tt>dst.put(src)</tt> has exactly the same effect as the loop
-     *
-     * <pre>
-     *     while (src.hasRemaining())
-     *         dst.put(src.get()); </pre>
-     *
-     * except that it first checks that there is sufficient space in this
-     * buffer and it is potentially much more efficient. </p>
-     *
-     * @param  src
-     *         The source buffer from which $fulltype$s are to be read;
-     *         must not be this buffer
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *          for the remaining $fulltype$s in the source buffer
-     *
-     * @throws  IllegalArgumentException
-     *          If the source buffer is this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public $Type$Buffer put($Type$Buffer src) {
-        if (src == this)
-            throw new IllegalArgumentException();
-        int n = src.remaining();
-        if (n > remaining())
-            throw new BufferOverflowException();
-        for (int i = 0; i < n; i++)
-            put(src.get());
-        return this;
-    }
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers $fulltype$s into this buffer from the given
-     * source array.  If there are more $fulltype$s to be copied from the array
-     * than remain in this buffer, that is, if
-     * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
-     * $fulltype$s are transferred and a {@link BufferOverflowException} is
-     * thrown.
-     *
-     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from the
-     * given array into this buffer, starting at the given offset in the array
-     * and at the current position of this buffer.  The position of this buffer
-     * is then incremented by <tt>length</tt>.
-     *
-     * <p> In other words, an invocation of this method of the form
-     * <tt>dst.put(src,&nbsp;off,&nbsp;len)</tt> has exactly the same effect as
-     * the loop
-     *
-     * <pre>
-     *     for (int i = off; i < off + len; i++)
-     *         dst.put(a[i]); </pre>
-     *
-     * except that it first checks that there is sufficient space in this
-     * buffer and it is potentially much more efficient. </p>
-     *
-     * @param  src
-     *         The array from which $fulltype$s are to be read
-     *
-     * @param  offset
-     *         The offset within the array of the first $fulltype$ to be read;
-     *         must be non-negative and no larger than <tt>array.length</tt>
-     *
-     * @param  length
-     *         The number of $fulltype$s to be read from the given array;
-     *         must be non-negative and no larger than
-     *         <tt>array.length - offset</tt>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
-     *          parameters do not hold
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public $Type$Buffer put($type$[] src, int offset, int length) {
-        checkBounds(offset, length, src.length);
-        if (length > remaining())
-            throw new BufferOverflowException();
-        int end = offset + length;
-        for (int i = offset; i < end; i++)
-            this.put(src[i]);
-        return this;
-    }
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers the entire content of the given source
-     * $fulltype$ array into this buffer.  An invocation of this method of the
-     * form <tt>dst.put(a)</tt> behaves in exactly the same way as the
-     * invocation
-     *
-     * <pre>
-     *     dst.put(a, 0, a.length) </pre>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public final $Type$Buffer put($type$[] src) {
-        return put(src, 0, src.length);
-    }
-
-#if[char]
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers $fulltype$s from the given string into this
-     * buffer.  If there are more $fulltype$s to be copied from the string than
-     * remain in this buffer, that is, if
-     * <tt>end&nbsp;-&nbsp;start</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
-     * then no $fulltype$s are transferred and a {@link
-     * BufferOverflowException} is thrown.
-     *
-     * <p> Otherwise, this method copies
-     * <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $fulltype$s
-     * from the given string into this buffer, starting at the given
-     * <tt>start</tt> index and at the current position of this buffer.  The
-     * position of this buffer is then incremented by <i>n</i>.
-     *
-     * <p> In other words, an invocation of this method of the form
-     * <tt>dst.put(src,&nbsp;start,&nbsp;end)</tt> has exactly the same effect
-     * as the loop
-     *
-     * <pre>
-     *     for (int i = start; i < end; i++)
-     *         dst.put(src.charAt(i)); </pre>
-     *
-     * except that it first checks that there is sufficient space in this
-     * buffer and it is potentially much more efficient. </p>
-     *
-     * @param  src
-     *         The string from which $fulltype$s are to be read
-     *
-     * @param  start
-     *         The offset within the string of the first $fulltype$ to be read;
-     *         must be non-negative and no larger than
-     *         <tt>string.length()</tt>
-     *
-     * @param  end
-     *         The offset within the string of the last $fulltype$ to be read,
-     *         plus one; must be non-negative and no larger than
-     *         <tt>string.length()</tt>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on the <tt>start</tt> and <tt>end</tt>
-     *          parameters do not hold
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public $Type$Buffer put(String src, int start, int end) {
-        checkBounds(start, end - start, src.length());
-        for (int i = start; i < end; i++)
-            this.put(src.charAt(i));
-        return this;
-    }
-
-    /**
-     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> This method transfers the entire content of the given source string
-     * into this buffer.  An invocation of this method of the form
-     * <tt>dst.put(s)</tt> behaves in exactly the same way as the invocation
-     *
-     * <pre>
-     *     dst.put(s, 0, s.length()) </pre>
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public final $Type$Buffer put(String src) {
-        return put(src, 0, src.length());
-    }
-
-#end[char]
-
-
-    // -- Other stuff --
-
-    /**
-     * Tells whether or not this buffer is backed by an accessible $fulltype$
-     * array.
-     *
-     * <p> If this method returns <tt>true</tt> then the {@link #array() array}
-     * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
-     * </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this buffer
-     *          is backed by an array and is not read-only
-     */
-    public final boolean hasArray() {
-        return (hb != null) && !isReadOnly;
-    }
-
-    /**
-     * Returns the $fulltype$ array that backs this
-     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> Modifications to this buffer's content will cause the returned
-     * array's content to be modified, and vice versa.
-     *
-     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
-     * method in order to ensure that this buffer has an accessible backing
-     * array.  </p>
-     *
-     * @return  The array that backs this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is backed by an array but is read-only
-     *
-     * @throws  UnsupportedOperationException
-     *          If this buffer is not backed by an accessible array
-     */
-    public final $type$[] array() {
-        if (hb == null)
-            throw new UnsupportedOperationException();
-        if (isReadOnly)
-            throw new ReadOnlyBufferException();
-        return hb;
-    }
-
-    /**
-     * Returns the offset within this buffer's backing array of the first
-     * element of the buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> If this buffer is backed by an array then buffer position <i>p</i>
-     * corresponds to array index <i>p</i>&nbsp;+&nbsp;<tt>arrayOffset()</tt>.
-     *
-     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
-     * method in order to ensure that this buffer has an accessible backing
-     * array.  </p>
-     *
-     * @return  The offset within this buffer's array
-     *          of the first element of the buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is backed by an array but is read-only
-     *
-     * @throws  UnsupportedOperationException
-     *          If this buffer is not backed by an accessible array
-     */
-    public final int arrayOffset() {
-        if (hb == null)
-            throw new UnsupportedOperationException();
-        if (isReadOnly)
-            throw new ReadOnlyBufferException();
-        return offset;
-    }
-
-    /**
-     * Compacts this buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> The $fulltype$s between the buffer's current position and its limit,
-     * if any, are copied to the beginning of the buffer.  That is, the
-     * $fulltype$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
-     * to index zero, the $fulltype$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
-     * to index one, and so forth until the $fulltype$ at index
-     * <tt>limit()</tt>&nbsp;-&nbsp;1 is copied to index
-     * <i>n</i>&nbsp;=&nbsp;<tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>&nbsp;-&nbsp;<i>p</i>.
-     * The buffer's position is then set to <i>n+1</i> and its limit is set to
-     * its capacity.  The mark, if defined, is discarded.
-     *
-     * <p> The buffer's position is set to the number of $fulltype$s copied,
-     * rather than to zero, so that an invocation of this method can be
-     * followed immediately by an invocation of another relative <i>put</i>
-     * method. </p>
-     *
-#if[byte]
-     *
-     * <p> Invoke this method after writing data from a buffer in case the
-     * write was incomplete.  The following loop, for example, copies bytes
-     * from one channel to another via the buffer <tt>buf</tt>:
-     *
-     * <blockquote><pre>
-     * buf.clear();          // Prepare buffer for use
-     * while (in.read(buf) >= 0 || buf.position != 0) {
-     *     buf.flip();
-     *     out.write(buf);
-     *     buf.compact();    // In case of partial write
-     * }</pre></blockquote>
-     *
-#end[byte]
-     *
-     * @return  This buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     */
-    public abstract $Type$Buffer compact();
-
-    /**
-     * Tells whether or not this $fulltype$ buffer is direct. </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this buffer is direct
-     */
-    public abstract boolean isDirect();
-
-#if[!char]
-
-    /**
-     * Returns a string summarizing the state of this buffer.  </p>
-     *
-     * @return  A summary string
-     */
-    public String toString() {
-        StringBuffer sb = new StringBuffer();
-        sb.append(getClass().getName());
-        sb.append("[pos=");
-        sb.append(position());
-        sb.append(" lim=");
-        sb.append(limit());
-        sb.append(" cap=");
-        sb.append(capacity());
-        sb.append("]");
-        return sb.toString();
-    }
-
-#end[!char]
-
-
-    // ## Should really use unchecked accessors here for speed
-
-    /**
-     * Returns the current hash code of this buffer.
-     *
-     * <p> The hash code of a $type$ buffer depends only upon its remaining
-     * elements; that is, upon the elements from <tt>position()</tt> up to, and
-     * including, the element at <tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>.
-     *
-     * <p> Because buffer hash codes are content-dependent, it is inadvisable
-     * to use buffers as keys in hash maps or similar data structures unless it
-     * is known that their contents will not change.  </p>
-     *
-     * @return  The current hash code of this buffer
-     */
-    public int hashCode() {
-        int h = 1;
-        int p = position();
-        for (int i = limit() - 1; i >= p; i--)
-            h = 31 * h + (int)get(i);
-        return h;
-    }
-
-    /**
-     * Tells whether or not this buffer is equal to another object.
-     *
-     * <p> Two $type$ buffers are equal if, and only if,
-     *
-     * <p><ol>
-     *
-     *   <li><p> They have the same element type,  </p></li>
-     *
-     *   <li><p> They have the same number of remaining elements, and
-     *   </p></li>
-     *
-     *   <li><p> The two sequences of remaining elements, considered
-     *   independently of their starting positions, are pointwise equal.
-     *   </p></li>
-     *
-     * </ol>
-     *
-     * <p> A $type$ buffer is not equal to any other type of object.  </p>
-     *
-     * @param  ob  The object to which this buffer is to be compared
-     *
-     * @return  <tt>true</tt> if, and only if, this buffer is equal to the
-     *           given object
-     */
-    public boolean equals(Object ob) {
-        if (this == ob)
-            return true;
-        if (!(ob instanceof $Type$Buffer))
-            return false;
-        $Type$Buffer that = ($Type$Buffer)ob;
-        if (this.remaining() != that.remaining())
-            return false;
-        int p = this.position();
-        for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
-            $type$ v1 = this.get(i);
-            $type$ v2 = that.get(j);
-            if (v1 != v2) {
-                if ((v1 != v1) && (v2 != v2))   // For float and double
-                    continue;
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Compares this buffer to another.
-     *
-     * <p> Two $type$ buffers are compared by comparing their sequences of
-     * remaining elements lexicographically, without regard to the starting
-     * position of each sequence within its corresponding buffer.
-     *
-     * <p> A $type$ buffer is not comparable to any other type of object.
-     *
-     * @return  A negative integer, zero, or a positive integer as this buffer
-     *          is less than, equal to, or greater than the given buffer
-     */
-    public int compareTo($Type$Buffer that) {
-        int n = this.position() + Math.min(this.remaining(), that.remaining());
-        for (int i = this.position(), j = that.position(); i < n; i++, j++) {
-            $type$ v1 = this.get(i);
-            $type$ v2 = that.get(j);
-            if (v1 == v2)
-                continue;
-            if ((v1 != v1) && (v2 != v2))       // For float and double
-                continue;
-            if (v1 < v2)
-                return -1;
-            return +1;
-        }
-        return this.remaining() - that.remaining();
-    }
-
-
-
-    // -- Other char stuff --
-
-#if[char]
-
-    /**
-     * Returns a string containing the characters in this buffer.
-     *
-     * <p> The first character of the resulting string will be the character at
-     * this buffer's position, while the last character will be the character
-     * at index <tt>limit()</tt>&nbsp;-&nbsp;1.  Invoking this method does not
-     * change the buffer's position. </p>
-     *
-     * @return  The specified string
-     */
-    public String toString() {
-        return toString(position(), limit());
-    }
-
-    abstract String toString(int start, int end);       // package-private
-
-
-    // --- Methods to support CharSequence ---
-
-    /**
-     * Returns the length of this character buffer.
-     *
-     * <p> When viewed as a character sequence, the length of a character
-     * buffer is simply the number of characters between the position
-     * (inclusive) and the limit (exclusive); that is, it is equivalent to
-     * <tt>remaining()</tt>. </p>
-     *
-     * @return  The length of this character buffer
-     */
-    public final int length() {
-        return remaining();
-    }
-
-    /**
-     * Reads the character at the given index relative to the current
-     * position. </p>
-     *
-     * @param  index
-     *         The index of the character to be read, relative to the position;
-     *         must be non-negative and smaller than <tt>remaining()</tt>
-     *
-     * @return  The character at index
-     *          <tt>position()&nbsp;+&nbsp;index</tt>
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on <tt>index</tt> do not hold
-     */
-    public final char charAt(int index) {
-        return get(position() + checkIndex(index, 1));
-    }
-
-    /**
-     * Creates a new character buffer that represents the specified subsequence
-     * of this buffer, relative to the current position.
-     *
-     * <p> The new buffer will share this buffer's content; that is, if the
-     * content of this buffer is mutable then modifications to one buffer will
-     * cause the other to be modified.  The new buffer's capacity will be that
-     * of this buffer, its position will be
-     * <tt>position()</tt>&nbsp;+&nbsp;<tt>start</tt>, and its limit will be
-     * <tt>position()</tt>&nbsp;+&nbsp;<tt>end</tt>.  The new buffer will be
-     * direct if, and only if, this buffer is direct, and it will be read-only
-     * if, and only if, this buffer is read-only.  </p>
-     *
-     * @param  start
-     *         The index, relative to the current position, of the first
-     *         character in the subsequence; must be non-negative and no larger
-     *         than <tt>remaining()</tt>
-     *
-     * @param  end
-     *         The index, relative to the current position, of the character
-     *         following the last character in the subsequence; must be no
-     *         smaller than <tt>start</tt> and no larger than
-     *         <tt>remaining()</tt>
-     *
-     * @return  The new character buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If the preconditions on <tt>start</tt> and <tt>end</tt>
-     *          do not hold
-     */
-    public abstract CharBuffer subSequence(int start, int end);
-
-
-    // --- Methods to support Appendable ---
-
-    /**
-     * Appends the specified character sequence  to this
-     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> An invocation of this method of the form <tt>dst.append(csq)</tt>
-     * behaves in exactly the same way as the invocation
-     *
-     * <pre>
-     *     dst.put(csq.toString()) </pre>
-     *
-     * <p> Depending on the specification of <tt>toString</tt> for the
-     * character sequence <tt>csq</tt>, the entire sequence may not be
-     * appended.  For instance, invoking the {@link $Type$Buffer#toString()
-     * toString} method of a character buffer will return a subsequence whose
-     * content depends upon the buffer's position and limit.
-     *
-     * @param  csq
-     *         The character sequence to append.  If <tt>csq</tt> is
-     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
-     *         appended to this character buffer.
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     *
-     * @since  1.5
-     */
-    public $Type$Buffer append(CharSequence csq) {
-        if (csq == null)
-            return put("null");
-        else
-            return put(csq.toString());
-    }
-
-    /**
-     * Appends a subsequence of the  specified character sequence  to this
-     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> An invocation of this method of the form <tt>dst.append(csq, start,
-     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in exactly the
-     * same way as the invocation
-     *
-     * <pre>
-     *     dst.put(csq.subSequence(start, end).toString()) </pre>
-     *
-     * @param  csq
-     *         The character sequence from which a subsequence will be
-     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
-     *         will be appended as if <tt>csq</tt> contained the four
-     *         characters <tt>"null"</tt>.
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  IndexOutOfBoundsException
-     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
-     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
-     *          <tt>csq.length()</tt>
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     *
-     * @since  1.5
-     */
-    public $Type$Buffer append(CharSequence csq, int start, int end) {
-        CharSequence cs = (csq == null ? "null" : csq);
-        return put(cs.subSequence(start, end).toString());
-    }
-
-    /**
-     * Appends the specified $fulltype$  to this
-     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> An invocation of this method of the form <tt>dst.append($x$)</tt>
-     * behaves in exactly the same way as the invocation
-     *
-     * <pre>
-     *     dst.put($x$) </pre>
-     *
-     * @param  $x$
-     *         The 16-bit $fulltype$ to append
-     *
-     * @return  This buffer
-     *
-     * @throws  BufferOverflowException
-     *          If there is insufficient space in this buffer
-     *
-     * @throws  ReadOnlyBufferException
-     *          If this buffer is read-only
-     *
-     * @since  1.5
-     */
-    public $Type$Buffer append($type$ $x$) {
-        return put($x$);
-    }
-
-#end[char]
-
-
-    // -- Other byte stuff: Access to binary data --
-
-#if[!byte]
-
-    /**
-     * Retrieves this buffer's byte order.
-     *
-     * <p> The byte order of $a$ $fulltype$ buffer created by allocation or by
-     * wrapping an existing <tt>$type$</tt> array is the {@link
-     * ByteOrder#nativeOrder </code>native order<code>} of the underlying
-     * hardware.  The byte order of $a$ $fulltype$ buffer created as a <a
-     * href="ByteBuffer.html#views">view</a> of a byte buffer is that of the
-     * byte buffer at the moment that the view is created.  </p>
-     *
-     * @return  This buffer's byte order
-     */
-    public abstract ByteOrder order();
-
-#end[!byte]
-
-#if[byte]
-
-    boolean bigEndian                                   // package-private
-        = true;
-    boolean nativeByteOrder                             // package-private
-        = (Bits.byteOrder() == ByteOrder.BIG_ENDIAN);
-
-    /**
-     * Retrieves this buffer's byte order.
-     *
-     * <p> The byte order is used when reading or writing multibyte values, and
-     * when creating buffers that are views of this byte buffer.  The order of
-     * a newly-created byte buffer is always {@link ByteOrder#BIG_ENDIAN
-     * BIG_ENDIAN}.  </p>
-     *
-     * @return  This buffer's byte order
-     */
-    public final ByteOrder order() {
-        return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
-    }
-
-    /**
-     * Modifies this buffer's byte order.  </p>
-     *
-     * @param  bo
-     *         The new byte order,
-     *         either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
-     *         or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}
-     *
-     * @return  This buffer
-     */
-    public final $Type$Buffer order(ByteOrder bo) {
-        bigEndian = (bo == ByteOrder.BIG_ENDIAN);
-        nativeByteOrder =
-            (bigEndian == (Bits.byteOrder() == ByteOrder.BIG_ENDIAN));
-        return this;
-    }
-
-    // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
-    //
-    abstract byte _get(int i);                          // package-private
-    abstract void _put(int i, byte b);                  // package-private
-
-    // #BIN
-    //
-    // Binary-data access methods  for short, char, int, long, float,
-    // and double will be inserted here
-
-#end[byte]
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/nio/X-Buffer.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,1428 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+#if[char]
+import java.io.IOException;
+#end[char]
+
+/**
+ * $A$ $fulltype$ buffer.
+ *
+ * <p> This class defines {#if[byte]?six:four} categories of operations upon
+ * $fulltype$ buffers:
+ *
+ * <ul>
+ *
+ *   <li><p> Absolute and relative {@link #get() </code><i>get</i><code>} and
+ *   {@link #put($type$) </code><i>put</i><code>} methods that read and write
+ *   single $fulltype$s; </p></li>
+ *
+ *   <li><p> Relative {@link #get($type$[]) </code><i>bulk get</i><code>}
+ *   methods that transfer contiguous sequences of $fulltype$s from this buffer
+ *   into an array; {#if[!byte]?and}</p></li>
+ *
+ *   <li><p> Relative {@link #put($type$[]) </code><i>bulk put</i><code>}
+ *   methods that transfer contiguous sequences of $fulltype$s from $a$
+ *   $fulltype$ array{#if[char]?,&#32;a&#32;string,} or some other $fulltype$
+ *   buffer into this buffer;{#if[!byte]?&#32;and} </p></li>
+ *
+#if[byte]
+ *
+ *   <li><p> Absolute and relative {@link #getChar() </code><i>get</i><code>}
+ *   and {@link #putChar(char) </code><i>put</i><code>} methods that read and
+ *   write values of other primitive types, translating them to and from
+ *   sequences of bytes in a particular byte order; </p></li>
+ *
+ *   <li><p> Methods for creating <i><a href="#views">view buffers</a></i>,
+ *   which allow a byte buffer to be viewed as a buffer containing values of
+ *   some other primitive type; and </p></li>
+ *
+#end[byte]
+ *
+ *   <li><p> Methods for {@link #compact </code>compacting<code>}, {@link
+ *   #duplicate </code>duplicating<code>}, and {@link #slice
+ *   </code>slicing<code>} $a$ $fulltype$ buffer.  </p></li>
+ *
+ * </ul>
+ *
+ * <p> $Fulltype$ buffers can be created either by {@link #allocate
+ * </code><i>allocation</i><code>}, which allocates space for the buffer's
+ *
+#if[byte]
+ *
+ * content, or by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an
+ * existing $fulltype$ array {#if[char]?or&#32;string} into a buffer.
+ *
+#else[byte]
+ *
+ * content, by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an existing
+ * $fulltype$ array {#if[char]?or&#32;string} into a buffer, or by creating a
+ * <a href="ByteBuffer.html#views"><i>view</i></a> of an existing byte buffer.
+ *
+#end[byte]
+ *
+#if[byte]
+ *
+ * <a name="direct">
+ * <h4> Direct <i>vs.</i> non-direct buffers </h4>
+ *
+ * <p> A byte buffer is either <i>direct</i> or <i>non-direct</i>.  Given a
+ * direct byte buffer, the Java virtual machine will make a best effort to
+ * perform native I/O operations directly upon it.  That is, it will attempt to
+ * avoid copying the buffer's content to (or from) an intermediate buffer
+ * before (or after) each invocation of one of the underlying operating
+ * system's native I/O operations.
+ *
+ * <p> A direct byte buffer may be created by invoking the {@link
+ * #allocateDirect(int) allocateDirect} factory method of this class.  The
+ * buffers returned by this method typically have somewhat higher allocation
+ * and deallocation costs than non-direct buffers.  The contents of direct
+ * buffers may reside outside of the normal garbage-collected heap, and so
+ * their impact upon the memory footprint of an application might not be
+ * obvious.  It is therefore recommended that direct buffers be allocated
+ * primarily for large, long-lived buffers that are subject to the underlying
+ * system's native I/O operations.  In general it is best to allocate direct
+ * buffers only when they yield a measureable gain in program performance.
+ *
+ * <p> A direct byte buffer may also be created by {@link
+ * java.nio.channels.FileChannel#map </code>mapping<code>} a region of a file
+ * directly into memory.  An implementation of the Java platform may optionally
+ * support the creation of direct byte buffers from native code via JNI.  If an
+ * instance of one of these kinds of buffers refers to an inaccessible region
+ * of memory then an attempt to access that region will not change the buffer's
+ * content and will cause an unspecified exception to be thrown either at the
+ * time of the access or at some later time.
+ *
+ * <p> Whether a byte buffer is direct or non-direct may be determined by
+ * invoking its {@link #isDirect isDirect} method.  This method is provided so
+ * that explicit buffer management can be done in performance-critical code.
+ *
+ *
+ * <a name="bin">
+ * <h4> Access to binary data </h4>
+ *
+ * <p> This class defines methods for reading and writing values of all other
+ * primitive types, except <tt>boolean</tt>.  Primitive values are translated
+ * to (or from) sequences of bytes according to the buffer's current byte
+ * order, which may be retrieved and modified via the {@link #order order}
+ * methods.  Specific byte orders are represented by instances of the {@link
+ * ByteOrder} class.  The initial order of a byte buffer is always {@link
+ * ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+ *
+ * <p> For access to heterogeneous binary data, that is, sequences of values of
+ * different types, this class defines a family of absolute and relative
+ * <i>get</i> and <i>put</i> methods for each type.  For 32-bit floating-point
+ * values, for example, this class defines:
+ *
+ * <blockquote><pre>
+ * float  {@link #getFloat()}
+ * float  {@link #getFloat(int) getFloat(int index)}
+ *  void  {@link #putFloat(float) putFloat(float f)}
+ *  void  {@link #putFloat(int,float) putFloat(int index, float f)}</pre></blockquote>
+ *
+ * <p> Corresponding methods are defined for the types <tt>char</tt>,
+ * <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and <tt>double</tt>.  The index
+ * parameters of the absolute <i>get</i> and <i>put</i> methods are in terms of
+ * bytes rather than of the type being read or written.
+ *
+ * <a name="views">
+ *
+ * <p> For access to homogeneous binary data, that is, sequences of values of
+ * the same type, this class defines methods that can create <i>views</i> of a
+ * given byte buffer.  A <i>view buffer</i> is simply another buffer whose
+ * content is backed by the byte buffer.  Changes to the byte buffer's content
+ * will be visible in the view buffer, and vice versa; the two buffers'
+ * position, limit, and mark values are independent.  The {@link
+ * #asFloatBuffer() asFloatBuffer} method, for example, creates an instance of
+ * the {@link FloatBuffer} class that is backed by the byte buffer upon which
+ * the method is invoked.  Corresponding view-creation methods are defined for
+ * the types <tt>char</tt>, <tt>short</tt>, <tt>int</tt>, <tt>long</tt>, and
+ * <tt>double</tt>.
+ *
+ * <p> View buffers have three important advantages over the families of
+ * type-specific <i>get</i> and <i>put</i> methods described above:
+ *
+ * <ul>
+ *
+ *   <li><p> A view buffer is indexed not in terms of bytes but rather in terms
+ *   of the type-specific size of its values;  </p></li>
+ *
+ *   <li><p> A view buffer provides relative bulk <i>get</i> and <i>put</i>
+ *   methods that can transfer contiguous sequences of values between a buffer
+ *   and an array or some other buffer of the same type; and  </p></li>
+ *
+ *   <li><p> A view buffer is potentially much more efficient because it will
+ *   be direct if, and only if, its backing byte buffer is direct.  </p></li>
+ *
+ * </ul>
+ *
+ * <p> The byte order of a view buffer is fixed to be that of its byte buffer
+ * at the time that the view is created.  </p>
+ *
+#end[byte]
+*
+#if[!byte]
+ *
+ * <p> Like a byte buffer, $a$ $fulltype$ buffer is either <a
+ * href="ByteBuffer.html#direct"><i>direct</i> or <i>non-direct</i></a>.  A
+ * $fulltype$ buffer created via the <tt>wrap</tt> methods of this class will
+ * be non-direct.  $A$ $fulltype$ buffer created as a view of a byte buffer will
+ * be direct if, and only if, the byte buffer itself is direct.  Whether or not
+ * $a$ $fulltype$ buffer is direct may be determined by invoking the {@link
+ * #isDirect isDirect} method.  </p>
+ *
+#end[!byte]
+*
+#if[char]
+ *
+ * <p> This class implements the {@link CharSequence} interface so that
+ * character buffers may be used wherever character sequences are accepted, for
+ * example in the regular-expression package <tt>{@link java.util.regex}</tt>.
+ * </p>
+ *
+#end[char]
+ *
+#if[byte]
+ * <h4> Invocation chaining </h4>
+#end[byte]
+ *
+ * <p> Methods in this class that do not otherwise have a value to return are
+ * specified to return the buffer upon which they are invoked.  This allows
+ * method invocations to be chained.
+ *
+#if[byte]
+ *
+ * The sequence of statements
+ *
+ * <blockquote><pre>
+ * bb.putInt(0xCAFEBABE);
+ * bb.putShort(3);
+ * bb.putShort(45);</pre></blockquote>
+ *
+ * can, for example, be replaced by the single statement
+ *
+ * <blockquote><pre>
+ * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);</pre></blockquote>
+ *
+#end[byte]
+#if[char]
+ *
+ * The sequence of statements
+ *
+ * <blockquote><pre>
+ * cb.put("text/");
+ * cb.put(subtype);
+ * cb.put("; charset=");
+ * cb.put(enc);</pre></blockquote>
+ *
+ * can, for example, be replaced by the single statement
+ *
+ * <blockquote><pre>
+ * cb.put("text/").put(subtype).put("; charset=").put(enc);</pre></blockquote>
+ *
+#end[char]
+ *
+ *
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ */
+
+public abstract class $Type$Buffer
+    extends Buffer
+    implements Comparable<$Type$Buffer>{#if[char]?, Appendable, CharSequence, Readable}
+{
+
+    // These fields are declared here rather than in Heap-X-Buffer in order to
+    // reduce the number of virtual method invocations needed to access these
+    // values, which is especially costly when coding small buffers.
+    //
+    final $type$[] hb;                  // Non-null only for heap buffers
+    final int offset;
+    boolean isReadOnly;                 // Valid only for heap buffers
+
+    // Creates a new buffer with the given mark, position, limit, capacity,
+    // backing array, and array offset
+    //
+    $Type$Buffer(int mark, int pos, int lim, int cap,   // package-private
+                 $type$[] hb, int offset)
+    {
+        super(mark, pos, lim, cap);
+        this.hb = hb;
+        this.offset = offset;
+    }
+
+    // Creates a new buffer with the given mark, position, limit, and capacity
+    //
+    $Type$Buffer(int mark, int pos, int lim, int cap) { // package-private
+        this(mark, pos, lim, cap, null, 0);
+    }
+
+#if[byte]
+
+    /**
+     * Allocates a new direct $fulltype$ buffer.
+     *
+     * <p> The new buffer's position will be zero, its limit will be its
+     * capacity, its mark will be undefined, and each of its elements will be
+     * initialized to zero.  Whether or not it has a
+     * {@link #hasArray </code>backing array<code>} is unspecified.
+     *
+     * @param  capacity
+     *         The new buffer's capacity, in $fulltype$s
+     *
+     * @return  The new $fulltype$ buffer
+     *
+     * @throws  IllegalArgumentException
+     *          If the <tt>capacity</tt> is a negative integer
+     */
+    public static $Type$Buffer allocateDirect(int capacity) {
+        return new Direct$Type$Buffer(capacity);
+    }
+
+#end[byte]
+
+    /**
+     * Allocates a new $fulltype$ buffer.
+     *
+     * <p> The new buffer's position will be zero, its limit will be its
+     * capacity, its mark will be undefined, and each of its elements will be
+     * initialized to zero.  It will have a {@link #array
+     * </code>backing array<code>}, and its {@link #arrayOffset </code>array
+     * offset<code>} will be zero.
+     *
+     * @param  capacity
+     *         The new buffer's capacity, in $fulltype$s
+     *
+     * @return  The new $fulltype$ buffer
+     *
+     * @throws  IllegalArgumentException
+     *          If the <tt>capacity</tt> is a negative integer
+     */
+    public static $Type$Buffer allocate(int capacity) {
+        if (capacity < 0)
+            throw new IllegalArgumentException();
+        return new Heap$Type$Buffer(capacity, capacity);
+    }
+
+    /**
+     * Wraps $a$ $fulltype$ array into a buffer.
+     *
+     * <p> The new buffer will be backed by the given $fulltype$ array;
+     * that is, modifications to the buffer will cause the array to be modified
+     * and vice versa.  The new buffer's capacity will be
+     * <tt>array.length</tt>, its position will be <tt>offset</tt>, its limit
+     * will be <tt>offset + length</tt>, and its mark will be undefined.  Its
+     * {@link #array </code>backing array<code>} will be the given array, and
+     * its {@link #arrayOffset </code>array offset<code>} will be zero.  </p>
+     *
+     * @param  array
+     *         The array that will back the new buffer
+     *
+     * @param  offset
+     *         The offset of the subarray to be used; must be non-negative and
+     *         no larger than <tt>array.length</tt>.  The new buffer's position
+     *         will be set to this value.
+     *
+     * @param  length
+     *         The length of the subarray to be used;
+     *         must be non-negative and no larger than
+     *         <tt>array.length - offset</tt>.
+     *         The new buffer's limit will be set to <tt>offset + length</tt>.
+     *
+     * @return  The new $fulltype$ buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
+     *          parameters do not hold
+     */
+    public static $Type$Buffer wrap($type$[] array,
+                                    int offset, int length)
+    {
+        try {
+            return new Heap$Type$Buffer(array, offset, length);
+        } catch (IllegalArgumentException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+    /**
+     * Wraps $a$ $fulltype$ array into a buffer.
+     *
+     * <p> The new buffer will be backed by the given $fulltype$ array;
+     * that is, modifications to the buffer will cause the array to be modified
+     * and vice versa.  The new buffer's capacity and limit will be
+     * <tt>array.length</tt>, its position will be zero, and its mark will be
+     * undefined.  Its {@link #array </code>backing array<code>} will be the
+     * given array, and its {@link #arrayOffset </code>array offset<code>} will
+     * be zero.  </p>
+     *
+     * @param  array
+     *         The array that will back this buffer
+     *
+     * @return  The new $fulltype$ buffer
+     */
+    public static $Type$Buffer wrap($type$[] array) {
+        return wrap(array, 0, array.length);
+    }
+
+#if[char]
+
+    /**
+     * Attempts to read characters into the specified character buffer.
+     * The buffer is used as a repository of characters as-is: the only
+     * changes made are the results of a put operation. No flipping or
+     * rewinding of the buffer is performed.
+     *
+     * @param target the buffer to read characters into
+     * @return The number of characters added to the buffer, or
+     *         -1 if this source of characters is at its end
+     * @throws IOException if an I/O error occurs
+     * @throws NullPointerException if target is null
+     * @throws ReadOnlyBufferException if target is a read only buffer
+     * @since 1.5
+     */
+    public int read(CharBuffer target) throws IOException {
+        // Determine the number of bytes n that can be transferred
+        int targetRemaining = target.remaining();
+        int remaining = remaining();
+        if (remaining == 0)
+            return -1;
+        int n = Math.min(remaining, targetRemaining);
+        int limit = limit();
+        // Set source limit to prevent target overflow
+        if (targetRemaining < remaining)
+            limit(position() + n);
+        try {
+            if (n > 0)
+                target.put(this);
+        } finally {
+            limit(limit); // restore real limit
+        }
+        return n;
+    }
+
+    /**
+     * Wraps a character sequence into a buffer.
+     *
+     * <p> The content of the new, read-only buffer will be the content of the
+     * given character sequence.  The buffer's capacity will be
+     * <tt>csq.length()</tt>, its position will be <tt>start</tt>, its limit
+     * will be <tt>end</tt>, and its mark will be undefined.  </p>
+     *
+     * @param  csq
+     *         The character sequence from which the new character buffer is to
+     *         be created
+     *
+     * @param  start
+     *         The index of the first character to be used;
+     *         must be non-negative and no larger than <tt>csq.length()</tt>.
+     *         The new buffer's position will be set to this value.
+     *
+     * @param  end
+     *         The index of the character following the last character to be
+     *         used; must be no smaller than <tt>start</tt> and no larger
+     *         than <tt>csq.length()</tt>.
+     *         The new buffer's limit will be set to this value.
+     *
+     * @return  The new character buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>start</tt> and <tt>end</tt>
+     *          parameters do not hold
+     */
+    public static CharBuffer wrap(CharSequence csq, int start, int end) {
+        try {
+            return new StringCharBuffer(csq, start, end);
+        } catch (IllegalArgumentException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+    /**
+     * Wraps a character sequence into a buffer.
+     *
+     * <p> The content of the new, read-only buffer will be the content of the
+     * given character sequence.  The new buffer's capacity and limit will be
+     * <tt>csq.length()</tt>, its position will be zero, and its mark will be
+     * undefined.  </p>
+     *
+     * @param  csq
+     *         The character sequence from which the new character buffer is to
+     *         be created
+     *
+     * @return  The new character buffer
+     */
+    public static CharBuffer wrap(CharSequence csq) {
+        return wrap(csq, 0, csq.length());
+    }
+
+#end[char]
+
+    /**
+     * Creates a new $fulltype$ buffer whose content is a shared subsequence of
+     * this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position.  Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of $fulltype$s remaining in this buffer, and its mark
+     * will be undefined.  The new buffer will be direct if, and only if, this
+     * buffer is direct, and it will be read-only if, and only if, this buffer
+     * is read-only.  </p>
+     *
+     * @return  The new $fulltype$ buffer
+     */
+    public abstract $Type$Buffer slice();
+
+    /**
+     * Creates a new $fulltype$ buffer that shares this buffer's content.
+     *
+     * <p> The content of the new buffer will be that of this buffer.  Changes
+     * to this buffer's content will be visible in the new buffer, and vice
+     * versa; the two buffers' position, limit, and mark values will be
+     * independent.
+     *
+     * <p> The new buffer's capacity, limit, position, and mark values will be
+     * identical to those of this buffer.  The new buffer will be direct if,
+     * and only if, this buffer is direct, and it will be read-only if, and
+     * only if, this buffer is read-only.  </p>
+     *
+     * @return  The new $fulltype$ buffer
+     */
+    public abstract $Type$Buffer duplicate();
+
+    /**
+     * Creates a new, read-only $fulltype$ buffer that shares this buffer's
+     * content.
+     *
+     * <p> The content of the new buffer will be that of this buffer.  Changes
+     * to this buffer's content will be visible in the new buffer; the new
+     * buffer itself, however, will be read-only and will not allow the shared
+     * content to be modified.  The two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's capacity, limit, position, and mark values will be
+     * identical to those of this buffer.
+     *
+     * <p> If this buffer is itself read-only then this method behaves in
+     * exactly the same way as the {@link #duplicate duplicate} method.  </p>
+     *
+     * @return  The new, read-only $fulltype$ buffer
+     */
+    public abstract $Type$Buffer asReadOnlyBuffer();
+
+
+    // -- Singleton get/put methods --
+
+    /**
+     * Relative <i>get</i> method.  Reads the $fulltype$ at this buffer's
+     * current position, and then increments the position. </p>
+     *
+     * @return  The $fulltype$ at the buffer's current position
+     *
+     * @throws  BufferUnderflowException
+     *          If the buffer's current position is not smaller than its limit
+     */
+    public abstract $type$ get();
+
+    /**
+     * Relative <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes the given $fulltype$ into this buffer at the current
+     * position, and then increments the position. </p>
+     *
+     * @param  $x$
+     *         The $fulltype$ to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If this buffer's current position is not smaller than its limit
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract $Type$Buffer put($type$ $x$);
+
+    /**
+     * Absolute <i>get</i> method.  Reads the $fulltype$ at the given
+     * index. </p>
+     *
+     * @param  index
+     *         The index from which the $fulltype$ will be read
+     *
+     * @return  The $fulltype$ at the given index
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>index</tt> is negative
+     *          or not smaller than the buffer's limit
+     */
+    public abstract $type$ get(int index);
+
+    /**
+     * Absolute <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes the given $fulltype$ into this buffer at the given
+     * index. </p>
+     *
+     * @param  index
+     *         The index at which the $fulltype$ will be written
+     *
+     * @param  $x$
+     *         The $fulltype$ value to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>index</tt> is negative
+     *          or not smaller than the buffer's limit
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract $Type$Buffer put(int index, $type$ $x$);
+
+
+    // -- Bulk get operations --
+
+    /**
+     * Relative bulk <i>get</i> method.
+     *
+     * <p> This method transfers $fulltype$s from this buffer into the given
+     * destination array.  If there are fewer $fulltype$s remaining in the
+     * buffer than are required to satisfy the request, that is, if
+     * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
+     * $fulltype$s are transferred and a {@link BufferUnderflowException} is
+     * thrown.
+     *
+     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from this
+     * buffer into the given array, starting at the current position of this
+     * buffer and at the given offset in the array.  The position of this
+     * buffer is then incremented by <tt>length</tt>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <tt>src.get(dst,&nbsp;off,&nbsp;len)</tt> has exactly the same effect as
+     * the loop
+     *
+     * <pre>
+     *     for (int i = off; i < off + len; i++)
+     *         dst[i] = src.get(); </pre>
+     *
+     * except that it first checks that there are sufficient $fulltype$s in
+     * this buffer and it is potentially much more efficient. </p>
+     *
+     * @param  dst
+     *         The array into which $fulltype$s are to be written
+     *
+     * @param  offset
+     *         The offset within the array of the first $fulltype$ to be
+     *         written; must be non-negative and no larger than
+     *         <tt>dst.length</tt>
+     *
+     * @param  length
+     *         The maximum number of $fulltype$s to be written to the given
+     *         array; must be non-negative and no larger than
+     *         <tt>dst.length - offset</tt>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferUnderflowException
+     *          If there are fewer than <tt>length</tt> $fulltype$s
+     *          remaining in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
+     *          parameters do not hold
+     */
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+        checkBounds(offset, length, dst.length);
+        if (length > remaining())
+            throw new BufferUnderflowException();
+        int end = offset + length;
+        for (int i = offset; i < end; i++)
+            dst[i] = get();
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>get</i> method.
+     *
+     * <p> This method transfers $fulltype$s from this buffer into the given
+     * destination array.  An invocation of this method of the form
+     * <tt>src.get(a)</tt> behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     src.get(a, 0, a.length) </pre>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferUnderflowException
+     *          If there are fewer than <tt>length</tt> $fulltype$s
+     *          remaining in this buffer
+     */
+    public $Type$Buffer get($type$[] dst) {
+        return get(dst, 0, dst.length);
+    }
+
+
+    // -- Bulk put operations --
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers the $fulltype$s remaining in the given source
+     * buffer into this buffer.  If there are more $fulltype$s remaining in the
+     * source buffer than in this buffer, that is, if
+     * <tt>src.remaining()</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
+     * then no $fulltype$s are transferred and a {@link
+     * BufferOverflowException} is thrown.
+     *
+     * <p> Otherwise, this method copies
+     * <i>n</i>&nbsp;=&nbsp;<tt>src.remaining()</tt> $fulltype$s from the given
+     * buffer into this buffer, starting at each buffer's current position.
+     * The positions of both buffers are then incremented by <i>n</i>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <tt>dst.put(src)</tt> has exactly the same effect as the loop
+     *
+     * <pre>
+     *     while (src.hasRemaining())
+     *         dst.put(src.get()); </pre>
+     *
+     * except that it first checks that there is sufficient space in this
+     * buffer and it is potentially much more efficient. </p>
+     *
+     * @param  src
+     *         The source buffer from which $fulltype$s are to be read;
+     *         must not be this buffer
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *          for the remaining $fulltype$s in the source buffer
+     *
+     * @throws  IllegalArgumentException
+     *          If the source buffer is this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public $Type$Buffer put($Type$Buffer src) {
+        if (src == this)
+            throw new IllegalArgumentException();
+        int n = src.remaining();
+        if (n > remaining())
+            throw new BufferOverflowException();
+        for (int i = 0; i < n; i++)
+            put(src.get());
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers $fulltype$s into this buffer from the given
+     * source array.  If there are more $fulltype$s to be copied from the array
+     * than remain in this buffer, that is, if
+     * <tt>length</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>, then no
+     * $fulltype$s are transferred and a {@link BufferOverflowException} is
+     * thrown.
+     *
+     * <p> Otherwise, this method copies <tt>length</tt> $fulltype$s from the
+     * given array into this buffer, starting at the given offset in the array
+     * and at the current position of this buffer.  The position of this buffer
+     * is then incremented by <tt>length</tt>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <tt>dst.put(src,&nbsp;off,&nbsp;len)</tt> has exactly the same effect as
+     * the loop
+     *
+     * <pre>
+     *     for (int i = off; i < off + len; i++)
+     *         dst.put(a[i]); </pre>
+     *
+     * except that it first checks that there is sufficient space in this
+     * buffer and it is potentially much more efficient. </p>
+     *
+     * @param  src
+     *         The array from which $fulltype$s are to be read
+     *
+     * @param  offset
+     *         The offset within the array of the first $fulltype$ to be read;
+     *         must be non-negative and no larger than <tt>array.length</tt>
+     *
+     * @param  length
+     *         The number of $fulltype$s to be read from the given array;
+     *         must be non-negative and no larger than
+     *         <tt>array.length - offset</tt>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>offset</tt> and <tt>length</tt>
+     *          parameters do not hold
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+        checkBounds(offset, length, src.length);
+        if (length > remaining())
+            throw new BufferOverflowException();
+        int end = offset + length;
+        for (int i = offset; i < end; i++)
+            this.put(src[i]);
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers the entire content of the given source
+     * $fulltype$ array into this buffer.  An invocation of this method of the
+     * form <tt>dst.put(a)</tt> behaves in exactly the same way as the
+     * invocation
+     *
+     * <pre>
+     *     dst.put(a, 0, a.length) </pre>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public final $Type$Buffer put($type$[] src) {
+        return put(src, 0, src.length);
+    }
+
+#if[char]
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers $fulltype$s from the given string into this
+     * buffer.  If there are more $fulltype$s to be copied from the string than
+     * remain in this buffer, that is, if
+     * <tt>end&nbsp;-&nbsp;start</tt>&nbsp;<tt>&gt;</tt>&nbsp;<tt>remaining()</tt>,
+     * then no $fulltype$s are transferred and a {@link
+     * BufferOverflowException} is thrown.
+     *
+     * <p> Otherwise, this method copies
+     * <i>n</i>&nbsp;=&nbsp;<tt>end</tt>&nbsp;-&nbsp;<tt>start</tt> $fulltype$s
+     * from the given string into this buffer, starting at the given
+     * <tt>start</tt> index and at the current position of this buffer.  The
+     * position of this buffer is then incremented by <i>n</i>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <tt>dst.put(src,&nbsp;start,&nbsp;end)</tt> has exactly the same effect
+     * as the loop
+     *
+     * <pre>
+     *     for (int i = start; i < end; i++)
+     *         dst.put(src.charAt(i)); </pre>
+     *
+     * except that it first checks that there is sufficient space in this
+     * buffer and it is potentially much more efficient. </p>
+     *
+     * @param  src
+     *         The string from which $fulltype$s are to be read
+     *
+     * @param  start
+     *         The offset within the string of the first $fulltype$ to be read;
+     *         must be non-negative and no larger than
+     *         <tt>string.length()</tt>
+     *
+     * @param  end
+     *         The offset within the string of the last $fulltype$ to be read,
+     *         plus one; must be non-negative and no larger than
+     *         <tt>string.length()</tt>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the <tt>start</tt> and <tt>end</tt>
+     *          parameters do not hold
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public $Type$Buffer put(String src, int start, int end) {
+        checkBounds(start, end - start, src.length());
+        for (int i = start; i < end; i++)
+            this.put(src.charAt(i));
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers the entire content of the given source string
+     * into this buffer.  An invocation of this method of the form
+     * <tt>dst.put(s)</tt> behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     dst.put(s, 0, s.length()) </pre>
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public final $Type$Buffer put(String src) {
+        return put(src, 0, src.length());
+    }
+
+#end[char]
+
+
+    // -- Other stuff --
+
+    /**
+     * Tells whether or not this buffer is backed by an accessible $fulltype$
+     * array.
+     *
+     * <p> If this method returns <tt>true</tt> then the {@link #array() array}
+     * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
+     * </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this buffer
+     *          is backed by an array and is not read-only
+     */
+    public final boolean hasArray() {
+        return (hb != null) && !isReadOnly;
+    }
+
+    /**
+     * Returns the $fulltype$ array that backs this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Modifications to this buffer's content will cause the returned
+     * array's content to be modified, and vice versa.
+     *
+     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
+     * method in order to ensure that this buffer has an accessible backing
+     * array.  </p>
+     *
+     * @return  The array that backs this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is backed by an array but is read-only
+     *
+     * @throws  UnsupportedOperationException
+     *          If this buffer is not backed by an accessible array
+     */
+    public final $type$[] array() {
+        if (hb == null)
+            throw new UnsupportedOperationException();
+        if (isReadOnly)
+            throw new ReadOnlyBufferException();
+        return hb;
+    }
+
+    /**
+     * Returns the offset within this buffer's backing array of the first
+     * element of the buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> If this buffer is backed by an array then buffer position <i>p</i>
+     * corresponds to array index <i>p</i>&nbsp;+&nbsp;<tt>arrayOffset()</tt>.
+     *
+     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
+     * method in order to ensure that this buffer has an accessible backing
+     * array.  </p>
+     *
+     * @return  The offset within this buffer's array
+     *          of the first element of the buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is backed by an array but is read-only
+     *
+     * @throws  UnsupportedOperationException
+     *          If this buffer is not backed by an accessible array
+     */
+    public final int arrayOffset() {
+        if (hb == null)
+            throw new UnsupportedOperationException();
+        if (isReadOnly)
+            throw new ReadOnlyBufferException();
+        return offset;
+    }
+
+    /**
+     * Compacts this buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> The $fulltype$s between the buffer's current position and its limit,
+     * if any, are copied to the beginning of the buffer.  That is, the
+     * $fulltype$ at index <i>p</i>&nbsp;=&nbsp;<tt>position()</tt> is copied
+     * to index zero, the $fulltype$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
+     * to index one, and so forth until the $fulltype$ at index
+     * <tt>limit()</tt>&nbsp;-&nbsp;1 is copied to index
+     * <i>n</i>&nbsp;=&nbsp;<tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>&nbsp;-&nbsp;<i>p</i>.
+     * The buffer's position is then set to <i>n+1</i> and its limit is set to
+     * its capacity.  The mark, if defined, is discarded.
+     *
+     * <p> The buffer's position is set to the number of $fulltype$s copied,
+     * rather than to zero, so that an invocation of this method can be
+     * followed immediately by an invocation of another relative <i>put</i>
+     * method. </p>
+     *
+#if[byte]
+     *
+     * <p> Invoke this method after writing data from a buffer in case the
+     * write was incomplete.  The following loop, for example, copies bytes
+     * from one channel to another via the buffer <tt>buf</tt>:
+     *
+     * <blockquote><pre>
+     * buf.clear();          // Prepare buffer for use
+     * while (in.read(buf) >= 0 || buf.position != 0) {
+     *     buf.flip();
+     *     out.write(buf);
+     *     buf.compact();    // In case of partial write
+     * }</pre></blockquote>
+     *
+#end[byte]
+     *
+     * @return  This buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract $Type$Buffer compact();
+
+    /**
+     * Tells whether or not this $fulltype$ buffer is direct. </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this buffer is direct
+     */
+    public abstract boolean isDirect();
+
+#if[!char]
+
+    /**
+     * Returns a string summarizing the state of this buffer.  </p>
+     *
+     * @return  A summary string
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append(getClass().getName());
+        sb.append("[pos=");
+        sb.append(position());
+        sb.append(" lim=");
+        sb.append(limit());
+        sb.append(" cap=");
+        sb.append(capacity());
+        sb.append("]");
+        return sb.toString();
+    }
+
+#end[!char]
+
+
+    // ## Should really use unchecked accessors here for speed
+
+    /**
+     * Returns the current hash code of this buffer.
+     *
+     * <p> The hash code of a $type$ buffer depends only upon its remaining
+     * elements; that is, upon the elements from <tt>position()</tt> up to, and
+     * including, the element at <tt>limit()</tt>&nbsp;-&nbsp;<tt>1</tt>.
+     *
+     * <p> Because buffer hash codes are content-dependent, it is inadvisable
+     * to use buffers as keys in hash maps or similar data structures unless it
+     * is known that their contents will not change.  </p>
+     *
+     * @return  The current hash code of this buffer
+     */
+    public int hashCode() {
+        int h = 1;
+        int p = position();
+        for (int i = limit() - 1; i >= p; i--)
+            h = 31 * h + (int)get(i);
+        return h;
+    }
+
+    /**
+     * Tells whether or not this buffer is equal to another object.
+     *
+     * <p> Two $type$ buffers are equal if, and only if,
+     *
+     * <p><ol>
+     *
+     *   <li><p> They have the same element type,  </p></li>
+     *
+     *   <li><p> They have the same number of remaining elements, and
+     *   </p></li>
+     *
+     *   <li><p> The two sequences of remaining elements, considered
+     *   independently of their starting positions, are pointwise equal.
+     *   </p></li>
+     *
+     * </ol>
+     *
+     * <p> A $type$ buffer is not equal to any other type of object.  </p>
+     *
+     * @param  ob  The object to which this buffer is to be compared
+     *
+     * @return  <tt>true</tt> if, and only if, this buffer is equal to the
+     *           given object
+     */
+    public boolean equals(Object ob) {
+        if (this == ob)
+            return true;
+        if (!(ob instanceof $Type$Buffer))
+            return false;
+        $Type$Buffer that = ($Type$Buffer)ob;
+        if (this.remaining() != that.remaining())
+            return false;
+        int p = this.position();
+        for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
+            $type$ v1 = this.get(i);
+            $type$ v2 = that.get(j);
+            if (v1 != v2) {
+                if ((v1 != v1) && (v2 != v2))   // For float and double
+                    continue;
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Compares this buffer to another.
+     *
+     * <p> Two $type$ buffers are compared by comparing their sequences of
+     * remaining elements lexicographically, without regard to the starting
+     * position of each sequence within its corresponding buffer.
+     *
+     * <p> A $type$ buffer is not comparable to any other type of object.
+     *
+     * @return  A negative integer, zero, or a positive integer as this buffer
+     *          is less than, equal to, or greater than the given buffer
+     */
+    public int compareTo($Type$Buffer that) {
+        int n = this.position() + Math.min(this.remaining(), that.remaining());
+        for (int i = this.position(), j = that.position(); i < n; i++, j++) {
+            $type$ v1 = this.get(i);
+            $type$ v2 = that.get(j);
+            if (v1 == v2)
+                continue;
+            if ((v1 != v1) && (v2 != v2))       // For float and double
+                continue;
+            if (v1 < v2)
+                return -1;
+            return +1;
+        }
+        return this.remaining() - that.remaining();
+    }
+
+
+
+    // -- Other char stuff --
+
+#if[char]
+
+    /**
+     * Returns a string containing the characters in this buffer.
+     *
+     * <p> The first character of the resulting string will be the character at
+     * this buffer's position, while the last character will be the character
+     * at index <tt>limit()</tt>&nbsp;-&nbsp;1.  Invoking this method does not
+     * change the buffer's position. </p>
+     *
+     * @return  The specified string
+     */
+    public String toString() {
+        return toString(position(), limit());
+    }
+
+    abstract String toString(int start, int end);       // package-private
+
+
+    // --- Methods to support CharSequence ---
+
+    /**
+     * Returns the length of this character buffer.
+     *
+     * <p> When viewed as a character sequence, the length of a character
+     * buffer is simply the number of characters between the position
+     * (inclusive) and the limit (exclusive); that is, it is equivalent to
+     * <tt>remaining()</tt>. </p>
+     *
+     * @return  The length of this character buffer
+     */
+    public final int length() {
+        return remaining();
+    }
+
+    /**
+     * Reads the character at the given index relative to the current
+     * position. </p>
+     *
+     * @param  index
+     *         The index of the character to be read, relative to the position;
+     *         must be non-negative and smaller than <tt>remaining()</tt>
+     *
+     * @return  The character at index
+     *          <tt>position()&nbsp;+&nbsp;index</tt>
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on <tt>index</tt> do not hold
+     */
+    public final char charAt(int index) {
+        return get(position() + checkIndex(index, 1));
+    }
+
+    /**
+     * Creates a new character buffer that represents the specified subsequence
+     * of this buffer, relative to the current position.
+     *
+     * <p> The new buffer will share this buffer's content; that is, if the
+     * content of this buffer is mutable then modifications to one buffer will
+     * cause the other to be modified.  The new buffer's capacity will be that
+     * of this buffer, its position will be
+     * <tt>position()</tt>&nbsp;+&nbsp;<tt>start</tt>, and its limit will be
+     * <tt>position()</tt>&nbsp;+&nbsp;<tt>end</tt>.  The new buffer will be
+     * direct if, and only if, this buffer is direct, and it will be read-only
+     * if, and only if, this buffer is read-only.  </p>
+     *
+     * @param  start
+     *         The index, relative to the current position, of the first
+     *         character in the subsequence; must be non-negative and no larger
+     *         than <tt>remaining()</tt>
+     *
+     * @param  end
+     *         The index, relative to the current position, of the character
+     *         following the last character in the subsequence; must be no
+     *         smaller than <tt>start</tt> and no larger than
+     *         <tt>remaining()</tt>
+     *
+     * @return  The new character buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on <tt>start</tt> and <tt>end</tt>
+     *          do not hold
+     */
+    public abstract CharBuffer subSequence(int start, int end);
+
+
+    // --- Methods to support Appendable ---
+
+    /**
+     * Appends the specified character sequence  to this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> An invocation of this method of the form <tt>dst.append(csq)</tt>
+     * behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     dst.put(csq.toString()) </pre>
+     *
+     * <p> Depending on the specification of <tt>toString</tt> for the
+     * character sequence <tt>csq</tt>, the entire sequence may not be
+     * appended.  For instance, invoking the {@link $Type$Buffer#toString()
+     * toString} method of a character buffer will return a subsequence whose
+     * content depends upon the buffer's position and limit.
+     *
+     * @param  csq
+     *         The character sequence to append.  If <tt>csq</tt> is
+     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
+     *         appended to this character buffer.
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     *
+     * @since  1.5
+     */
+    public $Type$Buffer append(CharSequence csq) {
+        if (csq == null)
+            return put("null");
+        else
+            return put(csq.toString());
+    }
+
+    /**
+     * Appends a subsequence of the  specified character sequence  to this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> An invocation of this method of the form <tt>dst.append(csq, start,
+     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in exactly the
+     * same way as the invocation
+     *
+     * <pre>
+     *     dst.put(csq.subSequence(start, end).toString()) </pre>
+     *
+     * @param  csq
+     *         The character sequence from which a subsequence will be
+     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
+     *         will be appended as if <tt>csq</tt> contained the four
+     *         characters <tt>"null"</tt>.
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
+     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
+     *          <tt>csq.length()</tt>
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     *
+     * @since  1.5
+     */
+    public $Type$Buffer append(CharSequence csq, int start, int end) {
+        CharSequence cs = (csq == null ? "null" : csq);
+        return put(cs.subSequence(start, end).toString());
+    }
+
+    /**
+     * Appends the specified $fulltype$  to this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> An invocation of this method of the form <tt>dst.append($x$)</tt>
+     * behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     dst.put($x$) </pre>
+     *
+     * @param  $x$
+     *         The 16-bit $fulltype$ to append
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     *
+     * @since  1.5
+     */
+    public $Type$Buffer append($type$ $x$) {
+        return put($x$);
+    }
+
+#end[char]
+
+
+    // -- Other byte stuff: Access to binary data --
+
+#if[!byte]
+
+    /**
+     * Retrieves this buffer's byte order.
+     *
+     * <p> The byte order of $a$ $fulltype$ buffer created by allocation or by
+     * wrapping an existing <tt>$type$</tt> array is the {@link
+     * ByteOrder#nativeOrder </code>native order<code>} of the underlying
+     * hardware.  The byte order of $a$ $fulltype$ buffer created as a <a
+     * href="ByteBuffer.html#views">view</a> of a byte buffer is that of the
+     * byte buffer at the moment that the view is created.  </p>
+     *
+     * @return  This buffer's byte order
+     */
+    public abstract ByteOrder order();
+
+#end[!byte]
+
+#if[byte]
+
+    boolean bigEndian                                   // package-private
+        = true;
+    boolean nativeByteOrder                             // package-private
+        = (Bits.byteOrder() == ByteOrder.BIG_ENDIAN);
+
+    /**
+     * Retrieves this buffer's byte order.
+     *
+     * <p> The byte order is used when reading or writing multibyte values, and
+     * when creating buffers that are views of this byte buffer.  The order of
+     * a newly-created byte buffer is always {@link ByteOrder#BIG_ENDIAN
+     * BIG_ENDIAN}.  </p>
+     *
+     * @return  This buffer's byte order
+     */
+    public final ByteOrder order() {
+        return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+    }
+
+    /**
+     * Modifies this buffer's byte order.  </p>
+     *
+     * @param  bo
+     *         The new byte order,
+     *         either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
+     *         or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}
+     *
+     * @return  This buffer
+     */
+    public final $Type$Buffer order(ByteOrder bo) {
+        bigEndian = (bo == ByteOrder.BIG_ENDIAN);
+        nativeByteOrder =
+            (bigEndian == (Bits.byteOrder() == ByteOrder.BIG_ENDIAN));
+        return this;
+    }
+
+    // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
+    //
+    abstract byte _get(int i);                          // package-private
+    abstract void _put(int i, byte b);                  // package-private
+
+    // #BIN
+    //
+    // Binary-data access methods  for short, char, int, long, float,
+    // and double will be inserted here
+
+#end[byte]
+
+}
--- a/src/share/classes/java/nio/charset/Charset-X-Coder.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,972 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#warn This file is preprocessed before being compiled
-
-package java.nio.charset;
-
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.BufferOverflowException;
-import java.nio.BufferUnderflowException;
-import java.lang.ref.WeakReference;
-import java.nio.charset.CoderMalfunctionError;                  // javadoc
-
-
-/**
- * An engine that can transform a sequence of $itypesPhrase$ into a sequence of
- * $otypesPhrase$.
- *
- * <a name="steps">
- *
- * <p> The input $itype$ sequence is provided in a $itype$ buffer or a series
- * of such buffers.  The output $otype$ sequence is written to a $otype$ buffer
- * or a series of such buffers.  $A$ $coder$ should always be used by making
- * the following sequence of method invocations, hereinafter referred to as $a$
- * <i>$coding$ operation</i>:
- *
- * <ol>
- *
- *   <li><p> Reset the $coder$ via the {@link #reset reset} method, unless it
- *   has not been used before; </p></li>
- *
- *   <li><p> Invoke the {@link #$code$ $code$} method zero or more times, as
- *   long as additional input may be available, passing <tt>false</tt> for the
- *   <tt>endOfInput</tt> argument and filling the input buffer and flushing the
- *   output buffer between invocations; </p></li>
- *
- *   <li><p> Invoke the {@link #$code$ $code$} method one final time, passing
- *   <tt>true</tt> for the <tt>endOfInput</tt> argument; and then </p></li>
- *
- *   <li><p> Invoke the {@link #flush flush} method so that the $coder$ can
- *   flush any internal state to the output buffer. </p></li>
- *
- * </ol>
- *
- * Each invocation of the {@link #$code$ $code$} method will $code$ as many
- * $itype$s as possible from the input buffer, writing the resulting $otype$s
- * to the output buffer.  The {@link #$code$ $code$} method returns when more
- * input is required, when there is not enough room in the output buffer, or
- * when $a$ $coding$ error has occurred.  In each case a {@link CoderResult}
- * object is returned to describe the reason for termination.  An invoker can
- * examine this object and fill the input buffer, flush the output buffer, or
- * attempt to recover from $a$ $coding$ error, as appropriate, and try again.
- *
- * <a name="ce">
- *
- * <p> There are two general types of $coding$ errors.  If the input $itype$
- * sequence is $notLegal$ then the input is considered <i>malformed</i>.  If
- * the input $itype$ sequence is legal but cannot be mapped to a valid
- * $outSequence$ then an <i>unmappable character</i> has been encountered.
- *
- * <a name="cae">
- *
- * <p> How $a$ $coding$ error is handled depends upon the action requested for
- * that type of error, which is described by an instance of the {@link
- * CodingErrorAction} class.  The possible error actions are to {@link
- * CodingErrorAction#IGNORE </code>ignore<code>} the erroneous input, {@link
- * CodingErrorAction#REPORT </code>report<code>} the error to the invoker via
- * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE
- * </code>replace<code>} the erroneous input with the current value of the
- * replacement $replTypeName$.  The replacement
- *
-#if[encoder]
- * is initially set to the $coder$'s default replacement, which often
- * (but not always) has the initial value&nbsp;$defaultReplName$;
-#end[encoder]
-#if[decoder]
- * has the initial value $defaultReplName$;
-#end[decoder]
- *
- * its value may be changed via the {@link #replaceWith($replFQType$)
- * replaceWith} method.
- *
- * <p> The default action for malformed-input and unmappable-character errors
- * is to {@link CodingErrorAction#REPORT </code>report<code>} them.  The
- * malformed-input error action may be changed via the {@link
- * #onMalformedInput(CodingErrorAction) onMalformedInput} method; the
- * unmappable-character action may be changed via the {@link
- * #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter} method.
- *
- * <p> This class is designed to handle many of the details of the $coding$
- * process, including the implementation of error actions.  $A$ $coder$ for a
- * specific charset, which is a concrete subclass of this class, need only
- * implement the abstract {@link #$code$Loop $code$Loop} method, which
- * encapsulates the basic $coding$ loop.  A subclass that maintains internal
- * state should, additionally, override the {@link #implFlush implFlush} and
- * {@link #implReset implReset} methods.
- *
- * <p> Instances of this class are not safe for use by multiple concurrent
- * threads.  </p>
- *
- *
- * @author Mark Reinhold
- * @author JSR-51 Expert Group
- * @since 1.4
- *
- * @see ByteBuffer
- * @see CharBuffer
- * @see Charset
- * @see Charset$OtherCoder$
- */
-
-public abstract class Charset$Coder$ {
-
-    private final Charset charset;
-    private final float average$ItypesPerOtype$;
-    private final float max$ItypesPerOtype$;
-
-    private $replType$ replacement;
-    private CodingErrorAction malformedInputAction
-        = CodingErrorAction.REPORT;
-    private CodingErrorAction unmappableCharacterAction
-        = CodingErrorAction.REPORT;
-
-    // Internal states
-    //
-    private static final int ST_RESET   = 0;
-    private static final int ST_CODING  = 1;
-    private static final int ST_END     = 2;
-    private static final int ST_FLUSHED = 3;
-
-    private int state = ST_RESET;
-
-    private static String stateNames[]
-        = { "RESET", "CODING", "CODING_END", "FLUSHED" };
-
-
-    /**
-     * Initializes a new $coder$.  The new $coder$ will have the given
-     * $otypes-per-itype$ and replacement values. </p>
-     *
-     * @param  average$ItypesPerOtype$
-     *         A positive float value indicating the expected number of
-     *         $otype$s that will be produced for each input $itype$
-     *
-     * @param  max$ItypesPerOtype$
-     *         A positive float value indicating the maximum number of
-     *         $otype$s that will be produced for each input $itype$
-     *
-     * @param  replacement
-     *         The initial replacement; must not be <tt>null</tt>, must have
-     *         non-zero length, must not be longer than max$ItypesPerOtype$,
-     *         and must be {@link #isLegalReplacement </code>legal<code>}
-     *
-     * @throws  IllegalArgumentException
-     *          If the preconditions on the parameters do not hold
-     */
-    {#if[encoder]?protected:private}
-    Charset$Coder$(Charset cs,
-                   float average$ItypesPerOtype$,
-                   float max$ItypesPerOtype$,
-                   $replType$ replacement)
-    {
-        this.charset = cs;
-        if (average$ItypesPerOtype$ <= 0.0f)
-            throw new IllegalArgumentException("Non-positive "
-                                               + "average$ItypesPerOtype$");
-        if (max$ItypesPerOtype$ <= 0.0f)
-            throw new IllegalArgumentException("Non-positive "
-                                               + "max$ItypesPerOtype$");
-        if (!Charset.atBugLevel("1.4")) {
-            if (average$ItypesPerOtype$ > max$ItypesPerOtype$)
-                throw new IllegalArgumentException("average$ItypesPerOtype$"
-                                                   + " exceeds "
-                                                   + "max$ItypesPerOtype$");
-        }
-        this.replacement = replacement;
-        this.average$ItypesPerOtype$ = average$ItypesPerOtype$;
-        this.max$ItypesPerOtype$ = max$ItypesPerOtype$;
-        replaceWith(replacement);
-    }
-
-    /**
-     * Initializes a new $coder$.  The new $coder$ will have the given
-     * $otypes-per-itype$ values and its replacement will be the
-     * $replTypeName$ $defaultReplName$. </p>
-     *
-     * @param  average$ItypesPerOtype$
-     *         A positive float value indicating the expected number of
-     *         $otype$s that will be produced for each input $itype$
-     *
-     * @param  max$ItypesPerOtype$
-     *         A positive float value indicating the maximum number of
-     *         $otype$s that will be produced for each input $itype$
-     *
-     * @throws  IllegalArgumentException
-     *          If the preconditions on the parameters do not hold
-     */
-    protected Charset$Coder$(Charset cs,
-                             float average$ItypesPerOtype$,
-                             float max$ItypesPerOtype$)
-    {
-        this(cs,
-             average$ItypesPerOtype$, max$ItypesPerOtype$,
-             $defaultRepl$);
-    }
-
-    /**
-     * Returns the charset that created this $coder$.  </p>
-     *
-     * @return  This $coder$'s charset
-     */
-    public final Charset charset() {
-        return charset;
-    }
-
-    /**
-     * Returns this $coder$'s replacement value. </p>
-     *
-     * @return  This $coder$'s current replacement,
-     *          which is never <tt>null</tt> and is never empty
-     */
-    public final $replType$ replacement() {
-        return replacement;
-    }
-
-    /**
-     * Changes this $coder$'s replacement value.
-     *
-     * <p> This method invokes the {@link #implReplaceWith implReplaceWith}
-     * method, passing the new replacement, after checking that the new
-     * replacement is acceptable.  </p>
-     *
-     * @param  newReplacement
-     *
-#if[decoder]
-     *         The new replacement; must not be <tt>null</tt>
-     *         and must have non-zero length
-#end[decoder]
-#if[encoder]
-     *         The new replacement; must not be <tt>null</tt>, must have
-     *         non-zero length, must not be longer than the value returned by
-     *         the {@link #max$ItypesPerOtype$() max$ItypesPerOtype$} method, and
-     *         must be {@link #isLegalReplacement </code>legal<code>}
-#end[encoder]
-     *
-     * @return  This $coder$
-     *
-     * @throws  IllegalArgumentException
-     *          If the preconditions on the parameter do not hold
-     */
-    public final Charset$Coder$ replaceWith($replType$ newReplacement) {
-        if (newReplacement == null)
-            throw new IllegalArgumentException("Null replacement");
-        int len = newReplacement.$replLength$;
-        if (len == 0)
-            throw new IllegalArgumentException("Empty replacement");
-        if (len > max$ItypesPerOtype$)
-            throw new IllegalArgumentException("Replacement too long");
-#if[encoder]
-        if (!isLegalReplacement(newReplacement))
-            throw new IllegalArgumentException("Illegal replacement");
-#end[encoder]
-        this.replacement = newReplacement;
-        implReplaceWith(newReplacement);
-        return this;
-    }
-
-    /**
-     * Reports a change to this $coder$'s replacement value.
-     *
-     * <p> The default implementation of this method does nothing.  This method
-     * should be overridden by $coder$s that require notification of changes to
-     * the replacement.  </p>
-     *
-     * @param  newReplacement
-     */
-    protected void implReplaceWith($replType$ newReplacement) {
-    }
-
-#if[encoder]
-
-    private WeakReference<CharsetDecoder> cachedDecoder = null;
-
-    /**
-     * Tells whether or not the given byte array is a legal replacement value
-     * for this encoder.
-     *
-     * <p> A replacement is legal if, and only if, it is a legal sequence of
-     * bytes in this encoder's charset; that is, it must be possible to decode
-     * the replacement into one or more sixteen-bit Unicode characters.
-     *
-     * <p> The default implementation of this method is not very efficient; it
-     * should generally be overridden to improve performance.  </p>
-     *
-     * @param  repl  The byte array to be tested
-     *
-     * @return  <tt>true</tt> if, and only if, the given byte array
-     *          is a legal replacement value for this encoder
-     */
-    public boolean isLegalReplacement(byte[] repl) {
-        WeakReference<CharsetDecoder> wr = cachedDecoder;
-        CharsetDecoder dec = null;
-        if ((wr == null) || ((dec = wr.get()) == null)) {
-            dec = charset().newDecoder();
-            dec.onMalformedInput(CodingErrorAction.REPORT);
-            dec.onUnmappableCharacter(CodingErrorAction.REPORT);
-            cachedDecoder = new WeakReference<CharsetDecoder>(dec);
-        } else {
-            dec.reset();
-        }
-        ByteBuffer bb = ByteBuffer.wrap(repl);
-        CharBuffer cb = CharBuffer.allocate((int)(bb.remaining()
-                                                  * dec.maxCharsPerByte()));
-        CoderResult cr = dec.decode(bb, cb, true);
-        return !cr.isError();
-    }
-
-#end[encoder]
-
-    /**
-     * Returns this $coder$'s current action for malformed-input errors.  </p>
-     *
-     * @return The current malformed-input action, which is never <tt>null</tt>
-     */
-    public CodingErrorAction malformedInputAction() {
-        return malformedInputAction;
-    }
-
-    /**
-     * Changes this $coder$'s action for malformed-input errors.  </p>
-     *
-     * <p> This method invokes the {@link #implOnMalformedInput
-     * implOnMalformedInput} method, passing the new action.  </p>
-     *
-     * @param  newAction  The new action; must not be <tt>null</tt>
-     *
-     * @return  This $coder$
-     *
-     * @throws IllegalArgumentException
-     *         If the precondition on the parameter does not hold
-     */
-    public final Charset$Coder$ onMalformedInput(CodingErrorAction newAction) {
-        if (newAction == null)
-            throw new IllegalArgumentException("Null action");
-        malformedInputAction = newAction;
-        implOnMalformedInput(newAction);
-        return this;
-    }
-
-    /**
-     * Reports a change to this $coder$'s malformed-input action.
-     *
-     * <p> The default implementation of this method does nothing.  This method
-     * should be overridden by $coder$s that require notification of changes to
-     * the malformed-input action.  </p>
-     */
-    protected void implOnMalformedInput(CodingErrorAction newAction) { }
-
-    /**
-     * Returns this $coder$'s current action for unmappable-character errors.
-     * </p>
-     *
-     * @return The current unmappable-character action, which is never
-     *         <tt>null</tt>
-     */
-    public CodingErrorAction unmappableCharacterAction() {
-        return unmappableCharacterAction;
-    }
-
-    /**
-     * Changes this $coder$'s action for unmappable-character errors.
-     *
-     * <p> This method invokes the {@link #implOnUnmappableCharacter
-     * implOnUnmappableCharacter} method, passing the new action.  </p>
-     *
-     * @param  newAction  The new action; must not be <tt>null</tt>
-     *
-     * @return  This $coder$
-     *
-     * @throws IllegalArgumentException
-     *         If the precondition on the parameter does not hold
-     */
-    public final Charset$Coder$ onUnmappableCharacter(CodingErrorAction
-                                                      newAction)
-    {
-        if (newAction == null)
-            throw new IllegalArgumentException("Null action");
-        unmappableCharacterAction = newAction;
-        implOnUnmappableCharacter(newAction);
-        return this;
-    }
-
-    /**
-     * Reports a change to this $coder$'s unmappable-character action.
-     *
-     * <p> The default implementation of this method does nothing.  This method
-     * should be overridden by $coder$s that require notification of changes to
-     * the unmappable-character action.  </p>
-     */
-    protected void implOnUnmappableCharacter(CodingErrorAction newAction) { }
-
-    /**
-     * Returns the average number of $otype$s that will be produced for each
-     * $itype$ of input.  This heuristic value may be used to estimate the size
-     * of the output buffer required for a given input sequence. </p>
-     *
-     * @return  The average number of $otype$s produced
-     *          per $itype$ of input
-     */
-    public final float average$ItypesPerOtype$() {
-        return average$ItypesPerOtype$;
-    }
-
-    /**
-     * Returns the maximum number of $otype$s that will be produced for each
-     * $itype$ of input.  This value may be used to compute the worst-case size
-     * of the output buffer required for a given input sequence. </p>
-     *
-     * @return  The maximum number of $otype$s that will be produced per
-     *          $itype$ of input
-     */
-    public final float max$ItypesPerOtype$() {
-        return max$ItypesPerOtype$;
-    }
-
-    /**
-     * $Code$s as many $itype$s as possible from the given input buffer,
-     * writing the results to the given output buffer.
-     *
-     * <p> The buffers are read from, and written to, starting at their current
-     * positions.  At most {@link Buffer#remaining in.remaining()} $itype$s
-     * will be read and at most {@link Buffer#remaining out.remaining()}
-     * $otype$s will be written.  The buffers' positions will be advanced to
-     * reflect the $itype$s read and the $otype$s written, but their marks and
-     * limits will not be modified.
-     *
-     * <p> In addition to reading $itype$s from the input buffer and writing
-     * $otype$s to the output buffer, this method returns a {@link CoderResult}
-     * object to describe its reason for termination:
-     *
-     * <ul>
-     *
-     *   <li><p> {@link CoderResult#UNDERFLOW} indicates that as much of the
-     *   input buffer as possible has been $code$d.  If there is no further
-     *   input then the invoker can proceed to the next step of the
-     *   <a href="#steps">$coding$ operation</a>.  Otherwise this method
-     *   should be invoked again with further input.  </p></li>
-     *
-     *   <li><p> {@link CoderResult#OVERFLOW} indicates that there is
-     *   insufficient space in the output buffer to $code$ any more $itype$s.
-     *   This method should be invoked again with an output buffer that has
-     *   more {@linkplain Buffer#remaining remaining} $otype$s. This is
-     *   typically done by draining any $code$d $otype$s from the output
-     *   buffer.  </p></li>
-     *
-     *   <li><p> A {@link CoderResult#malformedForLength
-     *   </code>malformed-input<code>} result indicates that a malformed-input
-     *   error has been detected.  The malformed $itype$s begin at the input
-     *   buffer's (possibly incremented) position; the number of malformed
-     *   $itype$s may be determined by invoking the result object's {@link
-     *   CoderResult#length() length} method.  This case applies only if the
-     *   {@link #onMalformedInput </code>malformed action<code>} of this $coder$
-     *   is {@link CodingErrorAction#REPORT}; otherwise the malformed input
-     *   will be ignored or replaced, as requested.  </p></li>
-     *
-     *   <li><p> An {@link CoderResult#unmappableForLength
-     *   </code>unmappable-character<code>} result indicates that an
-     *   unmappable-character error has been detected.  The $itype$s that
-     *   $code$ the unmappable character begin at the input buffer's (possibly
-     *   incremented) position; the number of such $itype$s may be determined
-     *   by invoking the result object's {@link CoderResult#length() length}
-     *   method.  This case applies only if the {@link #onUnmappableCharacter
-     *   </code>unmappable action<code>} of this $coder$ is {@link
-     *   CodingErrorAction#REPORT}; otherwise the unmappable character will be
-     *   ignored or replaced, as requested.  </p></li>
-     *
-     * </ul>
-     *
-     * In any case, if this method is to be reinvoked in the same $coding$
-     * operation then care should be taken to preserve any $itype$s remaining
-     * in the input buffer so that they are available to the next invocation.
-     *
-     * <p> The <tt>endOfInput</tt> parameter advises this method as to whether
-     * the invoker can provide further input beyond that contained in the given
-     * input buffer.  If there is a possibility of providing additional input
-     * then the invoker should pass <tt>false</tt> for this parameter; if there
-     * is no possibility of providing further input then the invoker should
-     * pass <tt>true</tt>.  It is not erroneous, and in fact it is quite
-     * common, to pass <tt>false</tt> in one invocation and later discover that
-     * no further input was actually available.  It is critical, however, that
-     * the final invocation of this method in a sequence of invocations always
-     * pass <tt>true</tt> so that any remaining un$code$d input will be treated
-     * as being malformed.
-     *
-     * <p> This method works by invoking the {@link #$code$Loop $code$Loop}
-     * method, interpreting its results, handling error conditions, and
-     * reinvoking it as necessary.  </p>
-     *
-     *
-     * @param  in
-     *         The input $itype$ buffer
-     *
-     * @param  out
-     *         The output $otype$ buffer
-     *
-     * @param  endOfInput
-     *         <tt>true</tt> if, and only if, the invoker can provide no
-     *         additional input $itype$s beyond those in the given buffer
-     *
-     * @return  A coder-result object describing the reason for termination
-     *
-     * @throws  IllegalStateException
-     *          If $a$ $coding$ operation is already in progress and the previous
-     *          step was an invocation neither of the {@link #reset reset}
-     *          method, nor of this method with a value of <tt>false</tt> for
-     *          the <tt>endOfInput</tt> parameter, nor of this method with a
-     *          value of <tt>true</tt> for the <tt>endOfInput</tt> parameter
-     *          but a return value indicating an incomplete $coding$ operation
-     *
-     * @throws  CoderMalfunctionError
-     *          If an invocation of the $code$Loop method threw
-     *          an unexpected exception
-     */
-    public final CoderResult $code$($Itype$Buffer in, $Otype$Buffer out,
-                                    boolean endOfInput)
-    {
-        int newState = endOfInput ? ST_END : ST_CODING;
-        if ((state != ST_RESET) && (state != ST_CODING)
-            && !(endOfInput && (state == ST_END)))
-            throwIllegalStateException(state, newState);
-        state = newState;
-
-        for (;;) {
-
-            CoderResult cr;
-            try {
-                cr = $code$Loop(in, out);
-            } catch (BufferUnderflowException x) {
-                throw new CoderMalfunctionError(x);
-            } catch (BufferOverflowException x) {
-                throw new CoderMalfunctionError(x);
-            }
-
-            if (cr.isOverflow())
-                return cr;
-
-            if (cr.isUnderflow()) {
-                if (endOfInput && in.hasRemaining()) {
-                    cr = CoderResult.malformedForLength(in.remaining());
-                    // Fall through to malformed-input case
-                } else {
-                    return cr;
-                }
-            }
-
-            CodingErrorAction action = null;
-            if (cr.isMalformed())
-                action = malformedInputAction;
-            else if (cr.isUnmappable())
-                action = unmappableCharacterAction;
-            else
-                assert false : cr.toString();
-
-            if (action == CodingErrorAction.REPORT)
-                return cr;
-
-            if (action == CodingErrorAction.REPLACE) {
-                if (out.remaining() < replacement.$replLength$)
-                    return CoderResult.OVERFLOW;
-                out.put(replacement);
-            }
-
-            if ((action == CodingErrorAction.IGNORE)
-                || (action == CodingErrorAction.REPLACE)) {
-                // Skip erroneous input either way
-                in.position(in.position() + cr.length());
-                continue;
-            }
-
-            assert false;
-        }
-
-    }
-
-    /**
-     * Flushes this $coder$.
-     *
-     * <p> Some $coder$s maintain internal state and may need to write some
-     * final $otype$s to the output buffer once the overall input sequence has
-     * been read.
-     *
-     * <p> Any additional output is written to the output buffer beginning at
-     * its current position.  At most {@link Buffer#remaining out.remaining()}
-     * $otype$s will be written.  The buffer's position will be advanced
-     * appropriately, but its mark and limit will not be modified.
-     *
-     * <p> If this method completes successfully then it returns {@link
-     * CoderResult#UNDERFLOW}.  If there is insufficient room in the output
-     * buffer then it returns {@link CoderResult#OVERFLOW}.  If this happens
-     * then this method must be invoked again, with an output buffer that has
-     * more room, in order to complete the current <a href="#steps">$coding$
-     * operation</a>.
-     *
-     * <p> If this $coder$ has already been flushed then invoking this method
-     * has no effect.
-     *
-     * <p> This method invokes the {@link #implFlush implFlush} method to
-     * perform the actual flushing operation.  </p>
-     *
-     * @param  out
-     *         The output $otype$ buffer
-     *
-     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
-     *          {@link CoderResult#OVERFLOW}
-     *
-     * @throws  IllegalStateException
-     *          If the previous step of the current $coding$ operation was an
-     *          invocation neither of the {@link #flush flush} method nor of
-     *          the three-argument {@link
-     *          #$code$($Itype$Buffer,$Otype$Buffer,boolean) $code$} method
-     *          with a value of <tt>true</tt> for the <tt>endOfInput</tt>
-     *          parameter
-     */
-    public final CoderResult flush($Otype$Buffer out) {
-        if (state == ST_END) {
-            CoderResult cr = implFlush(out);
-            if (cr.isUnderflow())
-                state = ST_FLUSHED;
-            return cr;
-        }
-
-        if (state != ST_FLUSHED)
-            throwIllegalStateException(state, ST_FLUSHED);
-
-        return CoderResult.UNDERFLOW; // Already flushed
-    }
-
-    /**
-     * Flushes this $coder$.
-     *
-     * <p> The default implementation of this method does nothing, and always
-     * returns {@link CoderResult#UNDERFLOW}.  This method should be overridden
-     * by $coder$s that may need to write final $otype$s to the output buffer
-     * once the entire input sequence has been read. </p>
-     *
-     * @param  out
-     *         The output $otype$ buffer
-     *
-     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
-     *          {@link CoderResult#OVERFLOW}
-     */
-    protected CoderResult implFlush($Otype$Buffer out) {
-        return CoderResult.UNDERFLOW;
-    }
-
-    /**
-     * Resets this $coder$, clearing any internal state.
-     *
-     * <p> This method resets charset-independent state and also invokes the
-     * {@link #implReset() implReset} method in order to perform any
-     * charset-specific reset actions.  </p>
-     *
-     * @return  This $coder$
-     *
-     */
-    public final Charset$Coder$ reset() {
-        implReset();
-        state = ST_RESET;
-        return this;
-    }
-
-    /**
-     * Resets this $coder$, clearing any charset-specific internal state.
-     *
-     * <p> The default implementation of this method does nothing.  This method
-     * should be overridden by $coder$s that maintain internal state.  </p>
-     */
-    protected void implReset() { }
-
-    /**
-     * $Code$s one or more $itype$s into one or more $otype$s.
-     *
-     * <p> This method encapsulates the basic $coding$ loop, $coding$ as many
-     * $itype$s as possible until it either runs out of input, runs out of room
-     * in the output buffer, or encounters $a$ $coding$ error.  This method is
-     * invoked by the {@link #$code$ $code$} method, which handles result
-     * interpretation and error recovery.
-     *
-     * <p> The buffers are read from, and written to, starting at their current
-     * positions.  At most {@link Buffer#remaining in.remaining()} $itype$s
-     * will be read, and at most {@link Buffer#remaining out.remaining()}
-     * $otype$s will be written.  The buffers' positions will be advanced to
-     * reflect the $itype$s read and the $otype$s written, but their marks and
-     * limits will not be modified.
-     *
-     * <p> This method returns a {@link CoderResult} object to describe its
-     * reason for termination, in the same manner as the {@link #$code$ $code$}
-     * method.  Most implementations of this method will handle $coding$ errors
-     * by returning an appropriate result object for interpretation by the
-     * {@link #$code$ $code$} method.  An optimized implementation may instead
-     * examine the relevant error action and implement that action itself.
-     *
-     * <p> An implementation of this method may perform arbitrary lookahead by
-     * returning {@link CoderResult#UNDERFLOW} until it receives sufficient
-     * input.  </p>
-     *
-     * @param  in
-     *         The input $itype$ buffer
-     *
-     * @param  out
-     *         The output $otype$ buffer
-     *
-     * @return  A coder-result object describing the reason for termination
-     */
-    protected abstract CoderResult $code$Loop($Itype$Buffer in,
-                                              $Otype$Buffer out);
-
-    /**
-     * Convenience method that $code$s the remaining content of a single input
-     * $itype$ buffer into a newly-allocated $otype$ buffer.
-     *
-     * <p> This method implements an entire <a href="#steps">$coding$
-     * operation</a>; that is, it resets this $coder$, then it $code$s the
-     * $itype$s in the given $itype$ buffer, and finally it flushes this
-     * $coder$.  This method should therefore not be invoked if $a$ $coding$
-     * operation is already in progress.  </p>
-     *
-     * @param  in
-     *         The input $itype$ buffer
-     *
-     * @return A newly-allocated $otype$ buffer containing the result of the
-     *         $coding$ operation.  The buffer's position will be zero and its
-     *         limit will follow the last $otype$ written.
-     *
-     * @throws  IllegalStateException
-     *          If $a$ $coding$ operation is already in progress
-     *
-     * @throws  MalformedInputException
-     *          If the $itype$ sequence starting at the input buffer's current
-     *          position is $notLegal$ and the current malformed-input action
-     *          is {@link CodingErrorAction#REPORT}
-     *
-     * @throws  UnmappableCharacterException
-     *          If the $itype$ sequence starting at the input buffer's current
-     *          position cannot be mapped to an equivalent $otype$ sequence and
-     *          the current unmappable-character action is {@link
-     *          CodingErrorAction#REPORT}
-     */
-    public final $Otype$Buffer $code$($Itype$Buffer in)
-        throws CharacterCodingException
-    {
-        int n = (int)(in.remaining() * average$ItypesPerOtype$());
-        $Otype$Buffer out = $Otype$Buffer.allocate(n);
-
-        if ((n == 0) && (in.remaining() == 0))
-            return out;
-        reset();
-        for (;;) {
-            CoderResult cr = in.hasRemaining() ?
-                $code$(in, out, true) : CoderResult.UNDERFLOW;
-            if (cr.isUnderflow())
-                cr = flush(out);
-
-            if (cr.isUnderflow())
-                break;
-            if (cr.isOverflow()) {
-                n = 2*n + 1;    // Ensure progress; n might be 0!
-                $Otype$Buffer o = $Otype$Buffer.allocate(n);
-                out.flip();
-                o.put(out);
-                out = o;
-                continue;
-            }
-            cr.throwException();
-        }
-        out.flip();
-        return out;
-    }
-
-#if[decoder]
-
-    /**
-     * Tells whether or not this decoder implements an auto-detecting charset.
-     *
-     * <p> The default implementation of this method always returns
-     * <tt>false</tt>; it should be overridden by auto-detecting decoders to
-     * return <tt>true</tt>.  </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this decoder implements an
-     *          auto-detecting charset
-     */
-    public boolean isAutoDetecting() {
-        return false;
-    }
-
-    /**
-     * Tells whether or not this decoder has yet detected a
-     * charset&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> If this decoder implements an auto-detecting charset then at a
-     * single point during a decoding operation this method may start returning
-     * <tt>true</tt> to indicate that a specific charset has been detected in
-     * the input byte sequence.  Once this occurs, the {@link #detectedCharset
-     * detectedCharset} method may be invoked to retrieve the detected charset.
-     *
-     * <p> That this method returns <tt>false</tt> does not imply that no bytes
-     * have yet been decoded.  Some auto-detecting decoders are capable of
-     * decoding some, or even all, of an input byte sequence without fixing on
-     * a particular charset.
-     *
-     * <p> The default implementation of this method always throws an {@link
-     * UnsupportedOperationException}; it should be overridden by
-     * auto-detecting decoders to return <tt>true</tt> once the input charset
-     * has been determined.  </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this decoder has detected a
-     *          specific charset
-     *
-     * @throws  UnsupportedOperationException
-     *          If this decoder does not implement an auto-detecting charset
-     */
-    public boolean isCharsetDetected() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Retrieves the charset that was detected by this
-     * decoder&nbsp;&nbsp;<i>(optional operation)</i>.
-     *
-     * <p> If this decoder implements an auto-detecting charset then this
-     * method returns the actual charset once it has been detected.  After that
-     * point, this method returns the same value for the duration of the
-     * current decoding operation.  If not enough input bytes have yet been
-     * read to determine the actual charset then this method throws an {@link
-     * IllegalStateException}.
-     *
-     * <p> The default implementation of this method always throws an {@link
-     * UnsupportedOperationException}; it should be overridden by
-     * auto-detecting decoders to return the appropriate value.  </p>
-     *
-     * @return  The charset detected by this auto-detecting decoder,
-     *          or <tt>null</tt> if the charset has not yet been determined
-     *
-     * @throws  IllegalStateException
-     *          If insufficient bytes have been read to determine a charset
-     *
-     * @throws  UnsupportedOperationException
-     *          If this decoder does not implement an auto-detecting charset
-     */
-    public Charset detectedCharset() {
-        throw new UnsupportedOperationException();
-    }
-
-#end[decoder]
-
-#if[encoder]
-
-    private boolean canEncode(CharBuffer cb) {
-        if (state == ST_FLUSHED)
-            reset();
-        else if (state != ST_RESET)
-            throwIllegalStateException(state, ST_CODING);
-        CodingErrorAction ma = malformedInputAction();
-        CodingErrorAction ua = unmappableCharacterAction();
-        try {
-            onMalformedInput(CodingErrorAction.REPORT);
-            onUnmappableCharacter(CodingErrorAction.REPORT);
-            encode(cb);
-        } catch (CharacterCodingException x) {
-            return false;
-        } finally {
-            onMalformedInput(ma);
-            onUnmappableCharacter(ua);
-            reset();
-        }
-        return true;
-    }
-
-    /**
-     * Tells whether or not this encoder can encode the given character.
-     *
-     * <p> This method returns <tt>false</tt> if the given character is a
-     * surrogate character; such characters can be interpreted only when they
-     * are members of a pair consisting of a high surrogate followed by a low
-     * surrogate.  The {@link #canEncode(java.lang.CharSequence)
-     * canEncode(CharSequence)} method may be used to test whether or not a
-     * character sequence can be encoded.
-     *
-     * <p> This method may modify this encoder's state; it should therefore not
-     * be invoked if an <a href="#steps">encoding operation</a> is already in
-     * progress.
-     *
-     * <p> The default implementation of this method is not very efficient; it
-     * should generally be overridden to improve performance.  </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this encoder can encode
-     *          the given character
-     *
-     * @throws  IllegalStateException
-     *          If $a$ $coding$ operation is already in progress
-     */
-    public boolean canEncode(char c) {
-        CharBuffer cb = CharBuffer.allocate(1);
-        cb.put(c);
-        cb.flip();
-        return canEncode(cb);
-    }
-
-    /**
-     * Tells whether or not this encoder can encode the given character
-     * sequence.
-     *
-     * <p> If this method returns <tt>false</tt> for a particular character
-     * sequence then more information about why the sequence cannot be encoded
-     * may be obtained by performing a full <a href="#steps">encoding
-     * operation</a>.
-     *
-     * <p> This method may modify this encoder's state; it should therefore not
-     * be invoked if an encoding operation is already in progress.
-     *
-     * <p> The default implementation of this method is not very efficient; it
-     * should generally be overridden to improve performance.  </p>
-     *
-     * @return  <tt>true</tt> if, and only if, this encoder can encode
-     *          the given character without throwing any exceptions and without
-     *          performing any replacements
-     *
-     * @throws  IllegalStateException
-     *          If $a$ $coding$ operation is already in progress
-     */
-    public boolean canEncode(CharSequence cs) {
-        CharBuffer cb;
-        if (cs instanceof CharBuffer)
-            cb = ((CharBuffer)cs).duplicate();
-        else
-            cb = CharBuffer.wrap(cs.toString());
-        return canEncode(cb);
-    }
-
-#end[encoder]
-
-
-    private void throwIllegalStateException(int from, int to) {
-        throw new IllegalStateException("Current state = " + stateNames[from]
-                                        + ", new state = " + stateNames[to]);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/nio/charset/Charset-X-Coder.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,972 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio.charset;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.lang.ref.WeakReference;
+import java.nio.charset.CoderMalfunctionError;                  // javadoc
+
+
+/**
+ * An engine that can transform a sequence of $itypesPhrase$ into a sequence of
+ * $otypesPhrase$.
+ *
+ * <a name="steps">
+ *
+ * <p> The input $itype$ sequence is provided in a $itype$ buffer or a series
+ * of such buffers.  The output $otype$ sequence is written to a $otype$ buffer
+ * or a series of such buffers.  $A$ $coder$ should always be used by making
+ * the following sequence of method invocations, hereinafter referred to as $a$
+ * <i>$coding$ operation</i>:
+ *
+ * <ol>
+ *
+ *   <li><p> Reset the $coder$ via the {@link #reset reset} method, unless it
+ *   has not been used before; </p></li>
+ *
+ *   <li><p> Invoke the {@link #$code$ $code$} method zero or more times, as
+ *   long as additional input may be available, passing <tt>false</tt> for the
+ *   <tt>endOfInput</tt> argument and filling the input buffer and flushing the
+ *   output buffer between invocations; </p></li>
+ *
+ *   <li><p> Invoke the {@link #$code$ $code$} method one final time, passing
+ *   <tt>true</tt> for the <tt>endOfInput</tt> argument; and then </p></li>
+ *
+ *   <li><p> Invoke the {@link #flush flush} method so that the $coder$ can
+ *   flush any internal state to the output buffer. </p></li>
+ *
+ * </ol>
+ *
+ * Each invocation of the {@link #$code$ $code$} method will $code$ as many
+ * $itype$s as possible from the input buffer, writing the resulting $otype$s
+ * to the output buffer.  The {@link #$code$ $code$} method returns when more
+ * input is required, when there is not enough room in the output buffer, or
+ * when $a$ $coding$ error has occurred.  In each case a {@link CoderResult}
+ * object is returned to describe the reason for termination.  An invoker can
+ * examine this object and fill the input buffer, flush the output buffer, or
+ * attempt to recover from $a$ $coding$ error, as appropriate, and try again.
+ *
+ * <a name="ce">
+ *
+ * <p> There are two general types of $coding$ errors.  If the input $itype$
+ * sequence is $notLegal$ then the input is considered <i>malformed</i>.  If
+ * the input $itype$ sequence is legal but cannot be mapped to a valid
+ * $outSequence$ then an <i>unmappable character</i> has been encountered.
+ *
+ * <a name="cae">
+ *
+ * <p> How $a$ $coding$ error is handled depends upon the action requested for
+ * that type of error, which is described by an instance of the {@link
+ * CodingErrorAction} class.  The possible error actions are to {@link
+ * CodingErrorAction#IGNORE </code>ignore<code>} the erroneous input, {@link
+ * CodingErrorAction#REPORT </code>report<code>} the error to the invoker via
+ * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE
+ * </code>replace<code>} the erroneous input with the current value of the
+ * replacement $replTypeName$.  The replacement
+ *
+#if[encoder]
+ * is initially set to the $coder$'s default replacement, which often
+ * (but not always) has the initial value&nbsp;$defaultReplName$;
+#end[encoder]
+#if[decoder]
+ * has the initial value $defaultReplName$;
+#end[decoder]
+ *
+ * its value may be changed via the {@link #replaceWith($replFQType$)
+ * replaceWith} method.
+ *
+ * <p> The default action for malformed-input and unmappable-character errors
+ * is to {@link CodingErrorAction#REPORT </code>report<code>} them.  The
+ * malformed-input error action may be changed via the {@link
+ * #onMalformedInput(CodingErrorAction) onMalformedInput} method; the
+ * unmappable-character action may be changed via the {@link
+ * #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter} method.
+ *
+ * <p> This class is designed to handle many of the details of the $coding$
+ * process, including the implementation of error actions.  $A$ $coder$ for a
+ * specific charset, which is a concrete subclass of this class, need only
+ * implement the abstract {@link #$code$Loop $code$Loop} method, which
+ * encapsulates the basic $coding$ loop.  A subclass that maintains internal
+ * state should, additionally, override the {@link #implFlush implFlush} and
+ * {@link #implReset implReset} methods.
+ *
+ * <p> Instances of this class are not safe for use by multiple concurrent
+ * threads.  </p>
+ *
+ *
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ *
+ * @see ByteBuffer
+ * @see CharBuffer
+ * @see Charset
+ * @see Charset$OtherCoder$
+ */
+
+public abstract class Charset$Coder$ {
+
+    private final Charset charset;
+    private final float average$ItypesPerOtype$;
+    private final float max$ItypesPerOtype$;
+
+    private $replType$ replacement;
+    private CodingErrorAction malformedInputAction
+        = CodingErrorAction.REPORT;
+    private CodingErrorAction unmappableCharacterAction
+        = CodingErrorAction.REPORT;
+
+    // Internal states
+    //
+    private static final int ST_RESET   = 0;
+    private static final int ST_CODING  = 1;
+    private static final int ST_END     = 2;
+    private static final int ST_FLUSHED = 3;
+
+    private int state = ST_RESET;
+
+    private static String stateNames[]
+        = { "RESET", "CODING", "CODING_END", "FLUSHED" };
+
+
+    /**
+     * Initializes a new $coder$.  The new $coder$ will have the given
+     * $otypes-per-itype$ and replacement values. </p>
+     *
+     * @param  average$ItypesPerOtype$
+     *         A positive float value indicating the expected number of
+     *         $otype$s that will be produced for each input $itype$
+     *
+     * @param  max$ItypesPerOtype$
+     *         A positive float value indicating the maximum number of
+     *         $otype$s that will be produced for each input $itype$
+     *
+     * @param  replacement
+     *         The initial replacement; must not be <tt>null</tt>, must have
+     *         non-zero length, must not be longer than max$ItypesPerOtype$,
+     *         and must be {@link #isLegalReplacement </code>legal<code>}
+     *
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameters do not hold
+     */
+    {#if[encoder]?protected:private}
+    Charset$Coder$(Charset cs,
+                   float average$ItypesPerOtype$,
+                   float max$ItypesPerOtype$,
+                   $replType$ replacement)
+    {
+        this.charset = cs;
+        if (average$ItypesPerOtype$ <= 0.0f)
+            throw new IllegalArgumentException("Non-positive "
+                                               + "average$ItypesPerOtype$");
+        if (max$ItypesPerOtype$ <= 0.0f)
+            throw new IllegalArgumentException("Non-positive "
+                                               + "max$ItypesPerOtype$");
+        if (!Charset.atBugLevel("1.4")) {
+            if (average$ItypesPerOtype$ > max$ItypesPerOtype$)
+                throw new IllegalArgumentException("average$ItypesPerOtype$"
+                                                   + " exceeds "
+                                                   + "max$ItypesPerOtype$");
+        }
+        this.replacement = replacement;
+        this.average$ItypesPerOtype$ = average$ItypesPerOtype$;
+        this.max$ItypesPerOtype$ = max$ItypesPerOtype$;
+        replaceWith(replacement);
+    }
+
+    /**
+     * Initializes a new $coder$.  The new $coder$ will have the given
+     * $otypes-per-itype$ values and its replacement will be the
+     * $replTypeName$ $defaultReplName$. </p>
+     *
+     * @param  average$ItypesPerOtype$
+     *         A positive float value indicating the expected number of
+     *         $otype$s that will be produced for each input $itype$
+     *
+     * @param  max$ItypesPerOtype$
+     *         A positive float value indicating the maximum number of
+     *         $otype$s that will be produced for each input $itype$
+     *
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameters do not hold
+     */
+    protected Charset$Coder$(Charset cs,
+                             float average$ItypesPerOtype$,
+                             float max$ItypesPerOtype$)
+    {
+        this(cs,
+             average$ItypesPerOtype$, max$ItypesPerOtype$,
+             $defaultRepl$);
+    }
+
+    /**
+     * Returns the charset that created this $coder$.  </p>
+     *
+     * @return  This $coder$'s charset
+     */
+    public final Charset charset() {
+        return charset;
+    }
+
+    /**
+     * Returns this $coder$'s replacement value. </p>
+     *
+     * @return  This $coder$'s current replacement,
+     *          which is never <tt>null</tt> and is never empty
+     */
+    public final $replType$ replacement() {
+        return replacement;
+    }
+
+    /**
+     * Changes this $coder$'s replacement value.
+     *
+     * <p> This method invokes the {@link #implReplaceWith implReplaceWith}
+     * method, passing the new replacement, after checking that the new
+     * replacement is acceptable.  </p>
+     *
+     * @param  newReplacement
+     *
+#if[decoder]
+     *         The new replacement; must not be <tt>null</tt>
+     *         and must have non-zero length
+#end[decoder]
+#if[encoder]
+     *         The new replacement; must not be <tt>null</tt>, must have
+     *         non-zero length, must not be longer than the value returned by
+     *         the {@link #max$ItypesPerOtype$() max$ItypesPerOtype$} method, and
+     *         must be {@link #isLegalReplacement </code>legal<code>}
+#end[encoder]
+     *
+     * @return  This $coder$
+     *
+     * @throws  IllegalArgumentException
+     *          If the preconditions on the parameter do not hold
+     */
+    public final Charset$Coder$ replaceWith($replType$ newReplacement) {
+        if (newReplacement == null)
+            throw new IllegalArgumentException("Null replacement");
+        int len = newReplacement.$replLength$;
+        if (len == 0)
+            throw new IllegalArgumentException("Empty replacement");
+        if (len > max$ItypesPerOtype$)
+            throw new IllegalArgumentException("Replacement too long");
+#if[encoder]
+        if (!isLegalReplacement(newReplacement))
+            throw new IllegalArgumentException("Illegal replacement");
+#end[encoder]
+        this.replacement = newReplacement;
+        implReplaceWith(newReplacement);
+        return this;
+    }
+
+    /**
+     * Reports a change to this $coder$'s replacement value.
+     *
+     * <p> The default implementation of this method does nothing.  This method
+     * should be overridden by $coder$s that require notification of changes to
+     * the replacement.  </p>
+     *
+     * @param  newReplacement
+     */
+    protected void implReplaceWith($replType$ newReplacement) {
+    }
+
+#if[encoder]
+
+    private WeakReference<CharsetDecoder> cachedDecoder = null;
+
+    /**
+     * Tells whether or not the given byte array is a legal replacement value
+     * for this encoder.
+     *
+     * <p> A replacement is legal if, and only if, it is a legal sequence of
+     * bytes in this encoder's charset; that is, it must be possible to decode
+     * the replacement into one or more sixteen-bit Unicode characters.
+     *
+     * <p> The default implementation of this method is not very efficient; it
+     * should generally be overridden to improve performance.  </p>
+     *
+     * @param  repl  The byte array to be tested
+     *
+     * @return  <tt>true</tt> if, and only if, the given byte array
+     *          is a legal replacement value for this encoder
+     */
+    public boolean isLegalReplacement(byte[] repl) {
+        WeakReference<CharsetDecoder> wr = cachedDecoder;
+        CharsetDecoder dec = null;
+        if ((wr == null) || ((dec = wr.get()) == null)) {
+            dec = charset().newDecoder();
+            dec.onMalformedInput(CodingErrorAction.REPORT);
+            dec.onUnmappableCharacter(CodingErrorAction.REPORT);
+            cachedDecoder = new WeakReference<CharsetDecoder>(dec);
+        } else {
+            dec.reset();
+        }
+        ByteBuffer bb = ByteBuffer.wrap(repl);
+        CharBuffer cb = CharBuffer.allocate((int)(bb.remaining()
+                                                  * dec.maxCharsPerByte()));
+        CoderResult cr = dec.decode(bb, cb, true);
+        return !cr.isError();
+    }
+
+#end[encoder]
+
+    /**
+     * Returns this $coder$'s current action for malformed-input errors.  </p>
+     *
+     * @return The current malformed-input action, which is never <tt>null</tt>
+     */
+    public CodingErrorAction malformedInputAction() {
+        return malformedInputAction;
+    }
+
+    /**
+     * Changes this $coder$'s action for malformed-input errors.  </p>
+     *
+     * <p> This method invokes the {@link #implOnMalformedInput
+     * implOnMalformedInput} method, passing the new action.  </p>
+     *
+     * @param  newAction  The new action; must not be <tt>null</tt>
+     *
+     * @return  This $coder$
+     *
+     * @throws IllegalArgumentException
+     *         If the precondition on the parameter does not hold
+     */
+    public final Charset$Coder$ onMalformedInput(CodingErrorAction newAction) {
+        if (newAction == null)
+            throw new IllegalArgumentException("Null action");
+        malformedInputAction = newAction;
+        implOnMalformedInput(newAction);
+        return this;
+    }
+
+    /**
+     * Reports a change to this $coder$'s malformed-input action.
+     *
+     * <p> The default implementation of this method does nothing.  This method
+     * should be overridden by $coder$s that require notification of changes to
+     * the malformed-input action.  </p>
+     */
+    protected void implOnMalformedInput(CodingErrorAction newAction) { }
+
+    /**
+     * Returns this $coder$'s current action for unmappable-character errors.
+     * </p>
+     *
+     * @return The current unmappable-character action, which is never
+     *         <tt>null</tt>
+     */
+    public CodingErrorAction unmappableCharacterAction() {
+        return unmappableCharacterAction;
+    }
+
+    /**
+     * Changes this $coder$'s action for unmappable-character errors.
+     *
+     * <p> This method invokes the {@link #implOnUnmappableCharacter
+     * implOnUnmappableCharacter} method, passing the new action.  </p>
+     *
+     * @param  newAction  The new action; must not be <tt>null</tt>
+     *
+     * @return  This $coder$
+     *
+     * @throws IllegalArgumentException
+     *         If the precondition on the parameter does not hold
+     */
+    public final Charset$Coder$ onUnmappableCharacter(CodingErrorAction
+                                                      newAction)
+    {
+        if (newAction == null)
+            throw new IllegalArgumentException("Null action");
+        unmappableCharacterAction = newAction;
+        implOnUnmappableCharacter(newAction);
+        return this;
+    }
+
+    /**
+     * Reports a change to this $coder$'s unmappable-character action.
+     *
+     * <p> The default implementation of this method does nothing.  This method
+     * should be overridden by $coder$s that require notification of changes to
+     * the unmappable-character action.  </p>
+     */
+    protected void implOnUnmappableCharacter(CodingErrorAction newAction) { }
+
+    /**
+     * Returns the average number of $otype$s that will be produced for each
+     * $itype$ of input.  This heuristic value may be used to estimate the size
+     * of the output buffer required for a given input sequence. </p>
+     *
+     * @return  The average number of $otype$s produced
+     *          per $itype$ of input
+     */
+    public final float average$ItypesPerOtype$() {
+        return average$ItypesPerOtype$;
+    }
+
+    /**
+     * Returns the maximum number of $otype$s that will be produced for each
+     * $itype$ of input.  This value may be used to compute the worst-case size
+     * of the output buffer required for a given input sequence. </p>
+     *
+     * @return  The maximum number of $otype$s that will be produced per
+     *          $itype$ of input
+     */
+    public final float max$ItypesPerOtype$() {
+        return max$ItypesPerOtype$;
+    }
+
+    /**
+     * $Code$s as many $itype$s as possible from the given input buffer,
+     * writing the results to the given output buffer.
+     *
+     * <p> The buffers are read from, and written to, starting at their current
+     * positions.  At most {@link Buffer#remaining in.remaining()} $itype$s
+     * will be read and at most {@link Buffer#remaining out.remaining()}
+     * $otype$s will be written.  The buffers' positions will be advanced to
+     * reflect the $itype$s read and the $otype$s written, but their marks and
+     * limits will not be modified.
+     *
+     * <p> In addition to reading $itype$s from the input buffer and writing
+     * $otype$s to the output buffer, this method returns a {@link CoderResult}
+     * object to describe its reason for termination:
+     *
+     * <ul>
+     *
+     *   <li><p> {@link CoderResult#UNDERFLOW} indicates that as much of the
+     *   input buffer as possible has been $code$d.  If there is no further
+     *   input then the invoker can proceed to the next step of the
+     *   <a href="#steps">$coding$ operation</a>.  Otherwise this method
+     *   should be invoked again with further input.  </p></li>
+     *
+     *   <li><p> {@link CoderResult#OVERFLOW} indicates that there is
+     *   insufficient space in the output buffer to $code$ any more $itype$s.
+     *   This method should be invoked again with an output buffer that has
+     *   more {@linkplain Buffer#remaining remaining} $otype$s. This is
+     *   typically done by draining any $code$d $otype$s from the output
+     *   buffer.  </p></li>
+     *
+     *   <li><p> A {@link CoderResult#malformedForLength
+     *   </code>malformed-input<code>} result indicates that a malformed-input
+     *   error has been detected.  The malformed $itype$s begin at the input
+     *   buffer's (possibly incremented) position; the number of malformed
+     *   $itype$s may be determined by invoking the result object's {@link
+     *   CoderResult#length() length} method.  This case applies only if the
+     *   {@link #onMalformedInput </code>malformed action<code>} of this $coder$
+     *   is {@link CodingErrorAction#REPORT}; otherwise the malformed input
+     *   will be ignored or replaced, as requested.  </p></li>
+     *
+     *   <li><p> An {@link CoderResult#unmappableForLength
+     *   </code>unmappable-character<code>} result indicates that an
+     *   unmappable-character error has been detected.  The $itype$s that
+     *   $code$ the unmappable character begin at the input buffer's (possibly
+     *   incremented) position; the number of such $itype$s may be determined
+     *   by invoking the result object's {@link CoderResult#length() length}
+     *   method.  This case applies only if the {@link #onUnmappableCharacter
+     *   </code>unmappable action<code>} of this $coder$ is {@link
+     *   CodingErrorAction#REPORT}; otherwise the unmappable character will be
+     *   ignored or replaced, as requested.  </p></li>
+     *
+     * </ul>
+     *
+     * In any case, if this method is to be reinvoked in the same $coding$
+     * operation then care should be taken to preserve any $itype$s remaining
+     * in the input buffer so that they are available to the next invocation.
+     *
+     * <p> The <tt>endOfInput</tt> parameter advises this method as to whether
+     * the invoker can provide further input beyond that contained in the given
+     * input buffer.  If there is a possibility of providing additional input
+     * then the invoker should pass <tt>false</tt> for this parameter; if there
+     * is no possibility of providing further input then the invoker should
+     * pass <tt>true</tt>.  It is not erroneous, and in fact it is quite
+     * common, to pass <tt>false</tt> in one invocation and later discover that
+     * no further input was actually available.  It is critical, however, that
+     * the final invocation of this method in a sequence of invocations always
+     * pass <tt>true</tt> so that any remaining un$code$d input will be treated
+     * as being malformed.
+     *
+     * <p> This method works by invoking the {@link #$code$Loop $code$Loop}
+     * method, interpreting its results, handling error conditions, and
+     * reinvoking it as necessary.  </p>
+     *
+     *
+     * @param  in
+     *         The input $itype$ buffer
+     *
+     * @param  out
+     *         The output $otype$ buffer
+     *
+     * @param  endOfInput
+     *         <tt>true</tt> if, and only if, the invoker can provide no
+     *         additional input $itype$s beyond those in the given buffer
+     *
+     * @return  A coder-result object describing the reason for termination
+     *
+     * @throws  IllegalStateException
+     *          If $a$ $coding$ operation is already in progress and the previous
+     *          step was an invocation neither of the {@link #reset reset}
+     *          method, nor of this method with a value of <tt>false</tt> for
+     *          the <tt>endOfInput</tt> parameter, nor of this method with a
+     *          value of <tt>true</tt> for the <tt>endOfInput</tt> parameter
+     *          but a return value indicating an incomplete $coding$ operation
+     *
+     * @throws  CoderMalfunctionError
+     *          If an invocation of the $code$Loop method threw
+     *          an unexpected exception
+     */
+    public final CoderResult $code$($Itype$Buffer in, $Otype$Buffer out,
+                                    boolean endOfInput)
+    {
+        int newState = endOfInput ? ST_END : ST_CODING;
+        if ((state != ST_RESET) && (state != ST_CODING)
+            && !(endOfInput && (state == ST_END)))
+            throwIllegalStateException(state, newState);
+        state = newState;
+
+        for (;;) {
+
+            CoderResult cr;
+            try {
+                cr = $code$Loop(in, out);
+            } catch (BufferUnderflowException x) {
+                throw new CoderMalfunctionError(x);
+            } catch (BufferOverflowException x) {
+                throw new CoderMalfunctionError(x);
+            }
+
+            if (cr.isOverflow())
+                return cr;
+
+            if (cr.isUnderflow()) {
+                if (endOfInput && in.hasRemaining()) {
+                    cr = CoderResult.malformedForLength(in.remaining());
+                    // Fall through to malformed-input case
+                } else {
+                    return cr;
+                }
+            }
+
+            CodingErrorAction action = null;
+            if (cr.isMalformed())
+                action = malformedInputAction;
+            else if (cr.isUnmappable())
+                action = unmappableCharacterAction;
+            else
+                assert false : cr.toString();
+
+            if (action == CodingErrorAction.REPORT)
+                return cr;
+
+            if (action == CodingErrorAction.REPLACE) {
+                if (out.remaining() < replacement.$replLength$)
+                    return CoderResult.OVERFLOW;
+                out.put(replacement);
+            }
+
+            if ((action == CodingErrorAction.IGNORE)
+                || (action == CodingErrorAction.REPLACE)) {
+                // Skip erroneous input either way
+                in.position(in.position() + cr.length());
+                continue;
+            }
+
+            assert false;
+        }
+
+    }
+
+    /**
+     * Flushes this $coder$.
+     *
+     * <p> Some $coder$s maintain internal state and may need to write some
+     * final $otype$s to the output buffer once the overall input sequence has
+     * been read.
+     *
+     * <p> Any additional output is written to the output buffer beginning at
+     * its current position.  At most {@link Buffer#remaining out.remaining()}
+     * $otype$s will be written.  The buffer's position will be advanced
+     * appropriately, but its mark and limit will not be modified.
+     *
+     * <p> If this method completes successfully then it returns {@link
+     * CoderResult#UNDERFLOW}.  If there is insufficient room in the output
+     * buffer then it returns {@link CoderResult#OVERFLOW}.  If this happens
+     * then this method must be invoked again, with an output buffer that has
+     * more room, in order to complete the current <a href="#steps">$coding$
+     * operation</a>.
+     *
+     * <p> If this $coder$ has already been flushed then invoking this method
+     * has no effect.
+     *
+     * <p> This method invokes the {@link #implFlush implFlush} method to
+     * perform the actual flushing operation.  </p>
+     *
+     * @param  out
+     *         The output $otype$ buffer
+     *
+     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
+     *          {@link CoderResult#OVERFLOW}
+     *
+     * @throws  IllegalStateException
+     *          If the previous step of the current $coding$ operation was an
+     *          invocation neither of the {@link #flush flush} method nor of
+     *          the three-argument {@link
+     *          #$code$($Itype$Buffer,$Otype$Buffer,boolean) $code$} method
+     *          with a value of <tt>true</tt> for the <tt>endOfInput</tt>
+     *          parameter
+     */
+    public final CoderResult flush($Otype$Buffer out) {
+        if (state == ST_END) {
+            CoderResult cr = implFlush(out);
+            if (cr.isUnderflow())
+                state = ST_FLUSHED;
+            return cr;
+        }
+
+        if (state != ST_FLUSHED)
+            throwIllegalStateException(state, ST_FLUSHED);
+
+        return CoderResult.UNDERFLOW; // Already flushed
+    }
+
+    /**
+     * Flushes this $coder$.
+     *
+     * <p> The default implementation of this method does nothing, and always
+     * returns {@link CoderResult#UNDERFLOW}.  This method should be overridden
+     * by $coder$s that may need to write final $otype$s to the output buffer
+     * once the entire input sequence has been read. </p>
+     *
+     * @param  out
+     *         The output $otype$ buffer
+     *
+     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
+     *          {@link CoderResult#OVERFLOW}
+     */
+    protected CoderResult implFlush($Otype$Buffer out) {
+        return CoderResult.UNDERFLOW;
+    }
+
+    /**
+     * Resets this $coder$, clearing any internal state.
+     *
+     * <p> This method resets charset-independent state and also invokes the
+     * {@link #implReset() implReset} method in order to perform any
+     * charset-specific reset actions.  </p>
+     *
+     * @return  This $coder$
+     *
+     */
+    public final Charset$Coder$ reset() {
+        implReset();
+        state = ST_RESET;
+        return this;
+    }
+
+    /**
+     * Resets this $coder$, clearing any charset-specific internal state.
+     *
+     * <p> The default implementation of this method does nothing.  This method
+     * should be overridden by $coder$s that maintain internal state.  </p>
+     */
+    protected void implReset() { }
+
+    /**
+     * $Code$s one or more $itype$s into one or more $otype$s.
+     *
+     * <p> This method encapsulates the basic $coding$ loop, $coding$ as many
+     * $itype$s as possible until it either runs out of input, runs out of room
+     * in the output buffer, or encounters $a$ $coding$ error.  This method is
+     * invoked by the {@link #$code$ $code$} method, which handles result
+     * interpretation and error recovery.
+     *
+     * <p> The buffers are read from, and written to, starting at their current
+     * positions.  At most {@link Buffer#remaining in.remaining()} $itype$s
+     * will be read, and at most {@link Buffer#remaining out.remaining()}
+     * $otype$s will be written.  The buffers' positions will be advanced to
+     * reflect the $itype$s read and the $otype$s written, but their marks and
+     * limits will not be modified.
+     *
+     * <p> This method returns a {@link CoderResult} object to describe its
+     * reason for termination, in the same manner as the {@link #$code$ $code$}
+     * method.  Most implementations of this method will handle $coding$ errors
+     * by returning an appropriate result object for interpretation by the
+     * {@link #$code$ $code$} method.  An optimized implementation may instead
+     * examine the relevant error action and implement that action itself.
+     *
+     * <p> An implementation of this method may perform arbitrary lookahead by
+     * returning {@link CoderResult#UNDERFLOW} until it receives sufficient
+     * input.  </p>
+     *
+     * @param  in
+     *         The input $itype$ buffer
+     *
+     * @param  out
+     *         The output $otype$ buffer
+     *
+     * @return  A coder-result object describing the reason for termination
+     */
+    protected abstract CoderResult $code$Loop($Itype$Buffer in,
+                                              $Otype$Buffer out);
+
+    /**
+     * Convenience method that $code$s the remaining content of a single input
+     * $itype$ buffer into a newly-allocated $otype$ buffer.
+     *
+     * <p> This method implements an entire <a href="#steps">$coding$
+     * operation</a>; that is, it resets this $coder$, then it $code$s the
+     * $itype$s in the given $itype$ buffer, and finally it flushes this
+     * $coder$.  This method should therefore not be invoked if $a$ $coding$
+     * operation is already in progress.  </p>
+     *
+     * @param  in
+     *         The input $itype$ buffer
+     *
+     * @return A newly-allocated $otype$ buffer containing the result of the
+     *         $coding$ operation.  The buffer's position will be zero and its
+     *         limit will follow the last $otype$ written.
+     *
+     * @throws  IllegalStateException
+     *          If $a$ $coding$ operation is already in progress
+     *
+     * @throws  MalformedInputException
+     *          If the $itype$ sequence starting at the input buffer's current
+     *          position is $notLegal$ and the current malformed-input action
+     *          is {@link CodingErrorAction#REPORT}
+     *
+     * @throws  UnmappableCharacterException
+     *          If the $itype$ sequence starting at the input buffer's current
+     *          position cannot be mapped to an equivalent $otype$ sequence and
+     *          the current unmappable-character action is {@link
+     *          CodingErrorAction#REPORT}
+     */
+    public final $Otype$Buffer $code$($Itype$Buffer in)
+        throws CharacterCodingException
+    {
+        int n = (int)(in.remaining() * average$ItypesPerOtype$());
+        $Otype$Buffer out = $Otype$Buffer.allocate(n);
+
+        if ((n == 0) && (in.remaining() == 0))
+            return out;
+        reset();
+        for (;;) {
+            CoderResult cr = in.hasRemaining() ?
+                $code$(in, out, true) : CoderResult.UNDERFLOW;
+            if (cr.isUnderflow())
+                cr = flush(out);
+
+            if (cr.isUnderflow())
+                break;
+            if (cr.isOverflow()) {
+                n = 2*n + 1;    // Ensure progress; n might be 0!
+                $Otype$Buffer o = $Otype$Buffer.allocate(n);
+                out.flip();
+                o.put(out);
+                out = o;
+                continue;
+            }
+            cr.throwException();
+        }
+        out.flip();
+        return out;
+    }
+
+#if[decoder]
+
+    /**
+     * Tells whether or not this decoder implements an auto-detecting charset.
+     *
+     * <p> The default implementation of this method always returns
+     * <tt>false</tt>; it should be overridden by auto-detecting decoders to
+     * return <tt>true</tt>.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this decoder implements an
+     *          auto-detecting charset
+     */
+    public boolean isAutoDetecting() {
+        return false;
+    }
+
+    /**
+     * Tells whether or not this decoder has yet detected a
+     * charset&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> If this decoder implements an auto-detecting charset then at a
+     * single point during a decoding operation this method may start returning
+     * <tt>true</tt> to indicate that a specific charset has been detected in
+     * the input byte sequence.  Once this occurs, the {@link #detectedCharset
+     * detectedCharset} method may be invoked to retrieve the detected charset.
+     *
+     * <p> That this method returns <tt>false</tt> does not imply that no bytes
+     * have yet been decoded.  Some auto-detecting decoders are capable of
+     * decoding some, or even all, of an input byte sequence without fixing on
+     * a particular charset.
+     *
+     * <p> The default implementation of this method always throws an {@link
+     * UnsupportedOperationException}; it should be overridden by
+     * auto-detecting decoders to return <tt>true</tt> once the input charset
+     * has been determined.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this decoder has detected a
+     *          specific charset
+     *
+     * @throws  UnsupportedOperationException
+     *          If this decoder does not implement an auto-detecting charset
+     */
+    public boolean isCharsetDetected() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Retrieves the charset that was detected by this
+     * decoder&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> If this decoder implements an auto-detecting charset then this
+     * method returns the actual charset once it has been detected.  After that
+     * point, this method returns the same value for the duration of the
+     * current decoding operation.  If not enough input bytes have yet been
+     * read to determine the actual charset then this method throws an {@link
+     * IllegalStateException}.
+     *
+     * <p> The default implementation of this method always throws an {@link
+     * UnsupportedOperationException}; it should be overridden by
+     * auto-detecting decoders to return the appropriate value.  </p>
+     *
+     * @return  The charset detected by this auto-detecting decoder,
+     *          or <tt>null</tt> if the charset has not yet been determined
+     *
+     * @throws  IllegalStateException
+     *          If insufficient bytes have been read to determine a charset
+     *
+     * @throws  UnsupportedOperationException
+     *          If this decoder does not implement an auto-detecting charset
+     */
+    public Charset detectedCharset() {
+        throw new UnsupportedOperationException();
+    }
+
+#end[decoder]
+
+#if[encoder]
+
+    private boolean canEncode(CharBuffer cb) {
+        if (state == ST_FLUSHED)
+            reset();
+        else if (state != ST_RESET)
+            throwIllegalStateException(state, ST_CODING);
+        CodingErrorAction ma = malformedInputAction();
+        CodingErrorAction ua = unmappableCharacterAction();
+        try {
+            onMalformedInput(CodingErrorAction.REPORT);
+            onUnmappableCharacter(CodingErrorAction.REPORT);
+            encode(cb);
+        } catch (CharacterCodingException x) {
+            return false;
+        } finally {
+            onMalformedInput(ma);
+            onUnmappableCharacter(ua);
+            reset();
+        }
+        return true;
+    }
+
+    /**
+     * Tells whether or not this encoder can encode the given character.
+     *
+     * <p> This method returns <tt>false</tt> if the given character is a
+     * surrogate character; such characters can be interpreted only when they
+     * are members of a pair consisting of a high surrogate followed by a low
+     * surrogate.  The {@link #canEncode(java.lang.CharSequence)
+     * canEncode(CharSequence)} method may be used to test whether or not a
+     * character sequence can be encoded.
+     *
+     * <p> This method may modify this encoder's state; it should therefore not
+     * be invoked if an <a href="#steps">encoding operation</a> is already in
+     * progress.
+     *
+     * <p> The default implementation of this method is not very efficient; it
+     * should generally be overridden to improve performance.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this encoder can encode
+     *          the given character
+     *
+     * @throws  IllegalStateException
+     *          If $a$ $coding$ operation is already in progress
+     */
+    public boolean canEncode(char c) {
+        CharBuffer cb = CharBuffer.allocate(1);
+        cb.put(c);
+        cb.flip();
+        return canEncode(cb);
+    }
+
+    /**
+     * Tells whether or not this encoder can encode the given character
+     * sequence.
+     *
+     * <p> If this method returns <tt>false</tt> for a particular character
+     * sequence then more information about why the sequence cannot be encoded
+     * may be obtained by performing a full <a href="#steps">encoding
+     * operation</a>.
+     *
+     * <p> This method may modify this encoder's state; it should therefore not
+     * be invoked if an encoding operation is already in progress.
+     *
+     * <p> The default implementation of this method is not very efficient; it
+     * should generally be overridden to improve performance.  </p>
+     *
+     * @return  <tt>true</tt> if, and only if, this encoder can encode
+     *          the given character without throwing any exceptions and without
+     *          performing any replacements
+     *
+     * @throws  IllegalStateException
+     *          If $a$ $coding$ operation is already in progress
+     */
+    public boolean canEncode(CharSequence cs) {
+        CharBuffer cb;
+        if (cs instanceof CharBuffer)
+            cb = ((CharBuffer)cs).duplicate();
+        else
+            cb = CharBuffer.wrap(cs.toString());
+        return canEncode(cb);
+    }
+
+#end[encoder]
+
+
+    private void throwIllegalStateException(int from, int to) {
+        throw new IllegalStateException("Current state = " + stateNames[from]
+                                        + ", new state = " + stateNames[to]);
+    }
+
+}
--- a/src/share/classes/java/security/MessageDigest.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/security/MessageDigest.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -414,16 +414,17 @@
      *
      * @return true if the digests are equal, false otherwise.
      */
-    public static boolean isEqual(byte digesta[], byte digestb[]) {
-        if (digesta.length != digestb.length)
+    public static boolean isEqual(byte[] digesta, byte[] digestb) {
+        if (digesta.length != digestb.length) {
             return false;
+        }
 
+        int result = 0;
+        // time-constant comparison
         for (int i = 0; i < digesta.length; i++) {
-            if (digesta[i] != digestb[i]) {
-                return false;
-            }
+            result |= digesta[i] ^ digestb[i];
         }
-        return true;
+        return result == 0;
     }
 
     /**
--- a/src/share/classes/java/util/AbstractList.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/AbstractList.java	Thu Nov 12 23:04:42 2009 +0000
@@ -256,9 +256,8 @@
     public boolean addAll(int index, Collection<? extends E> c) {
         rangeCheckForAdd(index);
         boolean modified = false;
-        Iterator<? extends E> e = c.iterator();
-        while (e.hasNext()) {
-            add(index++, e.next());
+        for (E e : c) {
+            add(index++, e);
             modified = true;
         }
         return modified;
--- a/src/share/classes/java/util/AbstractQueue.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/AbstractQueue.java	Thu Nov 12 23:04:42 2009 +0000
@@ -183,11 +183,9 @@
         if (c == this)
             throw new IllegalArgumentException();
         boolean modified = false;
-        Iterator<? extends E> e = c.iterator();
-        while (e.hasNext()) {
-            if (add(e.next()))
+        for (E e : c)
+            if (add(e))
                 modified = true;
-        }
         return modified;
     }
 
--- a/src/share/classes/java/util/Arrays.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/Arrays.java	Thu Nov 12 23:04:42 2009 +0000
@@ -57,51 +57,14 @@
     // Suppresses default constructor, ensuring non-instantiability.
     private Arrays() {}
 
-    // Sorting
+    /*
+     * Sorting of primitive type arrays.
+     */
 
     /**
      * Sorts the specified array into ascending numerical order.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
-     * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
-     * offers O(n log(n)) performance on many data sets that cause other
-     * quicksorts to degrade to quadratic performance, and is typically
-     * faster than traditional (one-pivot) Quicksort implementations.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(long[] a) {
-        sort(a, 0, a.length);
-    }
-
-    /**
-     * Sorts the specified range of the specified array into ascending order. The
-     * range of to be sorted extends from the index {@code fromIndex}, inclusive,
-     * to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
-     *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
-     * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
-     * offers O(n log(n)) performance on many data sets that cause other
-     * quicksorts to degrade to quadratic performance, and is typically
-     * faster than traditional (one-pivot) Quicksort implementations.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusively, to be sorted
-     * @param toIndex the index of the last element, exclusively, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
-     */
-    public static void sort(long[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
@@ -110,37 +73,76 @@
      * @param a the array to be sorted
      */
     public static void sort(int[] a) {
-        sort(a, 0, a.length);
+        DualPivotQuicksort.sort(a);
     }
 
     /**
-     * Sorts the specified range of the specified array into ascending order. The
-     * range of to be sorted extends from the index {@code fromIndex}, inclusive,
-     * to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
      * the range to be sorted is empty.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
      * faster than traditional (one-pivot) Quicksort implementations.
      *
      * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusively, to be sorted
-     * @param toIndex the index of the last element, exclusively, to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
      * @throws IllegalArgumentException if {@code fromIndex > toIndex}
      * @throws ArrayIndexOutOfBoundsException
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(int[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex);
     }
 
     /**
      * Sorts the specified array into ascending numerical order.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
+     * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
+     * offers O(n log(n)) performance on many data sets that cause other
+     * quicksorts to degrade to quadratic performance, and is typically
+     * faster than traditional (one-pivot) Quicksort implementations.
+     *
+     * @param a the array to be sorted
+     */
+    public static void sort(long[] a) {
+        DualPivotQuicksort.sort(a);
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * the range to be sorted is empty.
+     *
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
+     * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
+     * offers O(n log(n)) performance on many data sets that cause other
+     * quicksorts to degrade to quadratic performance, and is typically
+     * faster than traditional (one-pivot) Quicksort implementations.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     */
+    public static void sort(long[] a, int fromIndex, int toIndex) {
+        DualPivotQuicksort.sort(a, fromIndex, toIndex);
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
@@ -149,37 +151,37 @@
      * @param a the array to be sorted
      */
     public static void sort(short[] a) {
-        sort(a, 0, a.length);
+        DualPivotQuicksort.sort(a);
     }
 
     /**
-     * Sorts the specified range of the specified array into ascending order. The
-     * range of to be sorted extends from the index {@code fromIndex}, inclusive,
-     * to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
      * the range to be sorted is empty.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
      * faster than traditional (one-pivot) Quicksort implementations.
      *
      * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusively, to be sorted
-     * @param toIndex the index of the last element, exclusively, to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
      * @throws IllegalArgumentException if {@code fromIndex > toIndex}
      * @throws ArrayIndexOutOfBoundsException
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(short[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex);
     }
 
     /**
      * Sorts the specified array into ascending numerical order.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
@@ -188,37 +190,37 @@
      * @param a the array to be sorted
      */
     public static void sort(char[] a) {
-        sort(a, 0, a.length);
+        DualPivotQuicksort.sort(a);
     }
 
     /**
-     * Sorts the specified range of the specified array into ascending order. The
-     * range of to be sorted extends from the index {@code fromIndex}, inclusive,
-     * to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
      * the range to be sorted is empty.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
      * faster than traditional (one-pivot) Quicksort implementations.
      *
      * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusively, to be sorted
-     * @param toIndex the index of the last element, exclusively, to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
      * @throws IllegalArgumentException if {@code fromIndex > toIndex}
      * @throws ArrayIndexOutOfBoundsException
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(char[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex);
     }
 
     /**
      * Sorts the specified array into ascending numerical order.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
@@ -227,49 +229,100 @@
      * @param a the array to be sorted
      */
     public static void sort(byte[] a) {
-        sort(a, 0, a.length);
+        DualPivotQuicksort.sort(a);
     }
 
     /**
-     * Sorts the specified range of the specified array into ascending order. The
-     * range of to be sorted extends from the index {@code fromIndex}, inclusive,
-     * to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
      * the range to be sorted is empty.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
+     * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
+     * offers O(n log(n)) performance on many data sets that cause other
+     * quicksorts to degrade to quadratic performance, and is typically
+     * faster than traditional (one-pivot) Quicksort implementations.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     */
+    public static void sort(byte[] a, int fromIndex, int toIndex) {
+        DualPivotQuicksort.sort(a, fromIndex, toIndex);
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * <p>The {@code <} relation does not provide a total order on all float
+     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+     * other value and all {@code Float.NaN} values are considered equal.
+     *
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
      * faster than traditional (one-pivot) Quicksort implementations.
      *
      * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusively, to be sorted
-     * @param toIndex the index of the last element, exclusively, to be sorted
+     */
+    public static void sort(float[] a) {
+        DualPivotQuicksort.sort(a);
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * the range to be sorted is empty.
+     *
+     * <p>The {@code <} relation does not provide a total order on all float
+     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+     * other value and all {@code Float.NaN} values are considered equal.
+     *
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
+     * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
+     * offers O(n log(n)) performance on many data sets that cause other
+     * quicksorts to degrade to quadratic performance, and is typically
+     * faster than traditional (one-pivot) Quicksort implementations.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
      * @throws IllegalArgumentException if {@code fromIndex > toIndex}
      * @throws ArrayIndexOutOfBoundsException
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
-    public static void sort(byte[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        DualPivotQuicksort.sort(a, fromIndex, toIndex - 1);
+    public static void sort(float[] a, int fromIndex, int toIndex) {
+        DualPivotQuicksort.sort(a, fromIndex, toIndex);
     }
 
     /**
      * Sorts the specified array into ascending numerical order.
      *
-     * <p>The {@code <} relation does not provide a total order on
-     * all floating-point values; although they are distinct numbers
-     * {@code -0.0d == 0.0d} is {@code true} and a NaN value compares
-     * neither less than, greater than, nor equal to any floating-point
-     * value, even itself. To allow the sort to proceed, instead of using
-     * the {@code <} relation to determine ascending numerical order,
-     * this method uses the total order imposed by {@link Double#compareTo}.
-     * This ordering differs from the {@code <} relation in that {@code -0.0d}
-     * is treated as less than {@code 0.0d} and NaN is considered greater than
-     * any other floating-point value. For the purposes of sorting, all NaN
-     * values are considered equivalent and equal.
+     * <p>The {@code <} relation does not provide a total order on all double
+     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+     * other value and all {@code Double.NaN} values are considered equal.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
@@ -278,203 +331,45 @@
      * @param a the array to be sorted
      */
     public static void sort(double[] a) {
-        sort(a, 0, a.length);
+        DualPivotQuicksort.sort(a);
     }
 
     /**
-     * Sorts the specified range of the specified array into ascending order. The
-     * range of to be sorted extends from the index {@code fromIndex}, inclusive,
-     * to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
      * the range to be sorted is empty.
      *
-     * <p>The {@code <} relation does not provide a total order on
-     * all floating-point values; although they are distinct numbers
-     * {@code -0.0d == 0.0d} is {@code true} and a NaN value compares
-     * neither less than, greater than, nor equal to any floating-point
-     * value, even itself. To allow the sort to proceed, instead of using
-     * the {@code <} relation to determine ascending numerical order,
-     * this method uses the total order imposed by {@link Double#compareTo}.
-     * This ordering differs from the {@code <} relation in that {@code -0.0d}
-     * is treated as less than {@code 0.0d} and NaN is considered greater than
-     * any other floating-point value. For the purposes of sorting, all NaN
-     * values are considered equivalent and equal.
+     * <p>The {@code <} relation does not provide a total order on all double
+     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+     * other value and all {@code Double.NaN} values are considered equal.
      *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
+     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
      * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
      * offers O(n log(n)) performance on many data sets that cause other
      * quicksorts to degrade to quadratic performance, and is typically
      * faster than traditional (one-pivot) Quicksort implementations.
      *
      * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusively, to be sorted
-     * @param toIndex the index of the last element, exclusively, to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     *
      * @throws IllegalArgumentException if {@code fromIndex > toIndex}
      * @throws ArrayIndexOutOfBoundsException
      *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
     public static void sort(double[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        sortNegZeroAndNaN(a, fromIndex, toIndex);
-    }
-
-    private static void sortNegZeroAndNaN(double[] a, int fromIndex, int toIndex) {
-        final long NEG_ZERO_BITS = Double.doubleToLongBits(-0.0d);
-        /*
-         * The sort is done in three phases to avoid the expense of using
-         * NaN and -0.0d aware comparisons during the main sort.
-         *
-         * Preprocessing phase: move any NaN's to end of array, count the
-         * number of -0.0d's, and turn them into 0.0d's.
-         */
-        int numNegZeros = 0;
-        int i = fromIndex;
-        int n = toIndex;
-        double temp;
-
-        while (i < n) {
-            if (a[i] != a[i]) {
-                n--;
-                temp = a[i];
-                a[i] = a[n];
-                a[n] = temp;
-            }
-            else {
-                if (a[i] == 0 && Double.doubleToLongBits(a[i]) == NEG_ZERO_BITS) {
-                    a[i] = 0.0d;
-                    numNegZeros++;
-                }
-                i++;
-            }
-        }
-        // Main sort phase: quicksort everything but the NaN's
-        DualPivotQuicksort.sort(a, fromIndex, n - 1);
-
-        // Postprocessing phase: change 0.0d's to -0.0d's as required
-        if (numNegZeros != 0) {
-            int j = binarySearch0(a, fromIndex, n, 0.0d); // position of ANY zero
-
-            do {
-                j--;
-            }
-            while (j >= fromIndex && a[j] == 0.0d);
-
-            // j is now one less than the index of the FIRST zero
-            for (int k = 0; k < numNegZeros; k++) {
-                a[++j] = -0.0d;
-            }
-        }
-    }
-
-    /**
-     * Sorts the specified array into ascending numerical order.
-     *
-     * <p>The {@code <} relation does not provide a total order on
-     * all floating-point values; although they are distinct numbers
-     * {@code -0.0f == 0.0f} is {@code true} and a NaN value compares
-     * neither less than, greater than, nor equal to any floating-point
-     * value, even itself. To allow the sort to proceed, instead of using
-     * the {@code <} relation to determine ascending numerical order,
-     * this method uses the total order imposed by {@link Float#compareTo}.
-     * This ordering differs from the {@code <} relation in that {@code -0.0f}
-     * is treated as less than {@code 0.0f} and NaN is considered greater than
-     * any other floating-point value. For the purposes of sorting, all NaN
-     * values are considered equivalent and equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
-     * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
-     * offers O(n log(n)) performance on many data sets that cause other
-     * quicksorts to degrade to quadratic performance, and is typically
-     * faster than traditional (one-pivot) Quicksort implementations.
-     *
-     * @param a the array to be sorted
-     */
-    public static void sort(float[] a) {
-        sort(a, 0, a.length);
+        DualPivotQuicksort.sort(a, fromIndex, toIndex);
     }
 
-    /**
-     * Sorts the specified range of the specified array into ascending order. The
-     * range of to be sorted extends from the index {@code fromIndex}, inclusive,
-     * to the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
-     * the range to be sorted is empty.
+    /*
+     * Sorting of complex type arrays.
      *
-     * <p>The {@code <} relation does not provide a total order on
-     * all floating-point values; although they are distinct numbers
-     * {@code -0.0f == 0.0f} is {@code true} and a NaN value compares
-     * neither less than, greater than, nor equal to any floating-point
-     * value, even itself. To allow the sort to proceed, instead of using
-     * the {@code <} relation to determine ascending numerical order,
-     * this method uses the total order imposed by {@link Float#compareTo}.
-     * This ordering differs from the {@code <} relation in that {@code -0.0f}
-     * is treated as less than {@code 0.0f} and NaN is considered greater than
-     * any other floating-point value. For the purposes of sorting, all NaN
-     * values are considered equivalent and equal.
-     *
-     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort,
-     * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
-     * offers O(n log(n)) performance on many data sets that cause other
-     * quicksorts to degrade to quadratic performance, and is typically
-     * faster than traditional (one-pivot) Quicksort implementations.
-     *
-     * @param a the array to be sorted
-     * @param fromIndex the index of the first element, inclusively, to be sorted
-     * @param toIndex the index of the last element, exclusively, to be sorted
-     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
-     * @throws ArrayIndexOutOfBoundsException
-     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
-    public static void sort(float[] a, int fromIndex, int toIndex) {
-        rangeCheck(a.length, fromIndex, toIndex);
-        sortNegZeroAndNaN(a, fromIndex, toIndex);
-    }
-
-    private static void sortNegZeroAndNaN(float[] a, int fromIndex, int toIndex) {
-        final int NEG_ZERO_BITS = Float.floatToIntBits(-0.0f);
-        /*
-         * The sort is done in three phases to avoid the expense of using
-         * NaN and -0.0f aware comparisons during the main sort.
-         *
-         * Preprocessing phase: move any NaN's to end of array, count the
-         * number of -0.0f's, and turn them into 0.0f's.
-         */
-        int numNegZeros = 0;
-        int i = fromIndex;
-        int n = toIndex;
-        float temp;
-
-        while (i < n) {
-            if (a[i] != a[i]) {
-                n--;
-                temp = a[i];
-                a[i] = a[n];
-                a[n] = temp;
-            }
-            else {
-                if (a[i] == 0 && Float.floatToIntBits(a[i]) == NEG_ZERO_BITS) {
-                    a[i] = 0.0f;
-                    numNegZeros++;
-                }
-                i++;
-            }
-        }
-        // Main sort phase: quicksort everything but the NaN's
-        DualPivotQuicksort.sort(a, fromIndex, n - 1);
-
-        // Postprocessing phase: change 0.0f's to -0.0f's as required
-        if (numNegZeros != 0) {
-            int j = binarySearch0(a, fromIndex, n, 0.0f); // position of ANY zero
-
-            do {
-                j--;
-            }
-            while (j >= fromIndex && a[j] == 0.0f);
-
-            // j is now one less than the index of the FIRST zero
-            for (int k = 0; k < numNegZeros; k++) {
-                a[++j] = -0.0f;
-            }
-        }
-    }
 
     /**
      * Old merge sort implementation can be selected (for
--- a/src/share/classes/java/util/DualPivotQuicksort.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/DualPivotQuicksort.java	Thu Nov 12 23:04:42 2009 +0000
@@ -36,11 +36,11 @@
  * @author Jon Bentley
  * @author Josh Bloch
  *
- * @version 2009.10.29 m765.827.v5
+ * @version 2009.11.09 m765.827.v8
  */
 final class DualPivotQuicksort {
 
-    // Suppresses default constructor, ensuring non-instantiability.
+    // Suppresses default constructor
     private DualPivotQuicksort() {}
 
     /*
@@ -70,13 +70,43 @@
      */
 
     /**
-     * Sorts the specified range of the array into ascending order.
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @param a the array to be sorted
+     */
+    public static void sort(int[] a) {
+        doSort(a, 0, a.length - 1);
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * the range to be sorted is empty.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
-    static void sort(int[] a, int left, int right) {
+    public static void sort(int[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        doSort(a, fromIndex, toIndex - 1);
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. This
+     * method differs from the public {@code sort} method in that the
+     * {@code right} index is inclusive, and it does no range checking on
+     * {@code left} or {@code right}.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     */
+    private static void doSort(int[] a, int left, int right) {
         // Use insertion sort on tiny arrays
         if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
             for (int k = left + 1; k <= right; k++) {
@@ -94,12 +124,12 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order
-     * by Dual-Pivot Quicksort.
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
     private static void dualPivotQuicksort(int[] a, int left, int right) {
         // Compute indices of five evenly spaced elements
@@ -234,8 +264,8 @@
         a[right] = a[great + 1]; a[great + 1] = pivot2;
 
         // Sort left and right parts recursively, excluding known pivot values
-        sort(a, left,   less - 2);
-        sort(a, great + 2, right);
+        doSort(a, left,   less - 2);
+        doSort(a, great + 2, right);
 
         /*
          * If pivot1 == pivot2, all elements from center
@@ -271,17 +301,47 @@
         }
 
         // Sort center part recursively, excluding known pivot values
-        sort(a, less, great);
+        doSort(a, less, great);
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @param a the array to be sorted
+     */
+    public static void sort(long[] a) {
+        doSort(a, 0, a.length - 1);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order.
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * the range to be sorted is empty.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
-    static void sort(long[] a, int left, int right) {
+    public static void sort(long[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        doSort(a, fromIndex, toIndex - 1);
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. This
+     * method differs from the public {@code sort} method in that the
+     * {@code right} index is inclusive, and it does no range checking on
+     * {@code left} or {@code right}.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     */
+    private static void doSort(long[] a, int left, int right) {
         // Use insertion sort on tiny arrays
         if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
             for (int k = left + 1; k <= right; k++) {
@@ -299,12 +359,12 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order
-     * by Dual-Pivot Quicksort.
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
     private static void dualPivotQuicksort(long[] a, int left, int right) {
         // Compute indices of five evenly spaced elements
@@ -439,8 +499,8 @@
         a[right] = a[great + 1]; a[great + 1] = pivot2;
 
         // Sort left and right parts recursively, excluding known pivot values
-        sort(a, left,   less - 2);
-        sort(a, great + 2, right);
+        doSort(a, left,   less - 2);
+        doSort(a, great + 2, right);
 
         /*
          * If pivot1 == pivot2, all elements from center
@@ -476,20 +536,50 @@
         }
 
         // Sort center part recursively, excluding known pivot values
-        sort(a, less, great);
+        doSort(a, less, great);
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @param a the array to be sorted
+     */
+    public static void sort(short[] a) {
+        doSort(a, 0, a.length - 1);
     }
 
-    /** The number of distinct short values */
+    /**
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * the range to be sorted is empty.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     */
+    public static void sort(short[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        doSort(a, fromIndex, toIndex - 1);
+    }
+
+    /** The number of distinct short values. */
     private static final int NUM_SHORT_VALUES = 1 << 16;
 
     /**
-     * Sorts the specified range of the array into ascending order.
+     * Sorts the specified range of the array into ascending order. This
+     * method differs from the public {@code sort} method in that the
+     * {@code right} index is inclusive, and it does no range checking on
+     * {@code left} or {@code right}.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
-    static void sort(short[] a, int left, int right) {
+    private static void doSort(short[] a, int left, int right) {
         // Use insertion sort on tiny arrays
         if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
             for (int k = left + 1; k <= right; k++) {
@@ -501,7 +591,7 @@
                 }
                 a[j + 1] = ak;
             }
-        } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+        } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
             // Use counting sort on huge arrays
             int[] count = new int[NUM_SHORT_VALUES];
 
@@ -521,12 +611,12 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order
-     * by Dual-Pivot Quicksort.
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
     private static void dualPivotQuicksort(short[] a, int left, int right) {
         // Compute indices of five evenly spaced elements
@@ -661,8 +751,8 @@
         a[right] = a[great + 1]; a[great + 1] = pivot2;
 
         // Sort left and right parts recursively, excluding known pivot values
-        sort(a, left,   less - 2);
-        sort(a, great + 2, right);
+        doSort(a, left,   less - 2);
+        doSort(a, great + 2, right);
 
         /*
          * If pivot1 == pivot2, all elements from center
@@ -698,242 +788,50 @@
         }
 
         // Sort center part recursively, excluding known pivot values
-        sort(a, less, great);
+        doSort(a, less, great);
     }
 
-    /** The number of distinct byte values */
-    private static final int NUM_BYTE_VALUES = 1 << 8;
-
     /**
-     * Sorts the specified range of the array into ascending order.
+     * Sorts the specified array into ascending numerical order.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
      */
-    static void sort(byte[] a, int left, int right) {
-        // Use insertion sort on tiny arrays
-        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
-            for (int k = left + 1; k <= right; k++) {
-                byte ak = a[k];
-                int j;
-
-                for (j = k - 1; j >= left && ak < a[j]; j--) {
-                    a[j + 1] = a[j];
-                }
-                a[j + 1] = ak;
-            }
-        } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
-            // Use counting sort on huge arrays
-            int[] count = new int[NUM_BYTE_VALUES];
-
-            for (int i = left; i <= right; i++) {
-                count[a[i] - Byte.MIN_VALUE]++;
-            }
-            for (int i = 0, k = left; i < count.length && k <= right; i++) {
-                byte value = (byte) (i + Byte.MIN_VALUE);
-
-                for (int s = count[i]; s > 0; s--) {
-                    a[k++] = value;
-               }
-            }
-        } else { // Use Dual-Pivot Quicksort on large arrays
-            dualPivotQuicksort(a, left, right);
-        }
+    public static void sort(char[] a) {
+        doSort(a, 0, a.length - 1);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order
-     * by Dual-Pivot Quicksort.
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * the range to be sorted is empty.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
      */
-    private static void dualPivotQuicksort(byte[] a, int left, int right) {
-        // Compute indices of five evenly spaced elements
-        int sixth = (right - left + 1) / 6;
-        int e1 = left  + sixth;
-        int e5 = right - sixth;
-        int e3 = (left + right) >>> 1; // The midpoint
-        int e4 = e3 + sixth;
-        int e2 = e3 - sixth;
-
-        // Sort these elements in place using a 5-element sorting network
-        if (a[e1] > a[e2]) { byte t = a[e1]; a[e1] = a[e2]; a[e2] = t; }
-        if (a[e4] > a[e5]) { byte t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
-        if (a[e1] > a[e3]) { byte t = a[e1]; a[e1] = a[e3]; a[e3] = t; }
-        if (a[e2] > a[e3]) { byte t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
-        if (a[e1] > a[e4]) { byte t = a[e1]; a[e1] = a[e4]; a[e4] = t; }
-        if (a[e3] > a[e4]) { byte t = a[e3]; a[e3] = a[e4]; a[e4] = t; }
-        if (a[e2] > a[e5]) { byte t = a[e2]; a[e2] = a[e5]; a[e5] = t; }
-        if (a[e2] > a[e3]) { byte t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
-        if (a[e4] > a[e5]) { byte t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
-
-        /*
-         * Use the second and fourth of the five sorted elements as pivots.
-         * These values are inexpensive approximations of the first and
-         * second terciles of the array. Note that pivot1 <= pivot2.
-         *
-         * The pivots are stored in local variables, and the first and
-         * the last of the sorted elements are moved to the locations
-         * formerly occupied by the pivots. When partitioning is complete,
-         * the pivots are swapped back into their final positions, and
-         * excluded from subsequent sorting.
-         */
-        byte pivot1 = a[e2]; a[e2] = a[left];
-        byte pivot2 = a[e4]; a[e4] = a[right];
-
-        /*
-         * Partitioning
-         *
-         *   left part         center part                  right part
-         * ------------------------------------------------------------
-         * [ < pivot1  |  pivot1 <= && <= pivot2  |   ?   |  > pivot2 ]
-         * ------------------------------------------------------------
-         *              ^                          ^     ^
-         *              |                          |     |
-         *             less                        k   great
-         */
-
-        // Pointers
-        int less  = left  + 1; // The index of first element of center part
-        int great = right - 1; // The index before first element of right part
-
-        boolean pivotsDiffer = pivot1 != pivot2;
-
-        if (pivotsDiffer) {
-            /*
-             * Invariants:
-             *              all in (left, less)   < pivot1
-             *    pivot1 <= all in [less, k)     <= pivot2
-             *              all in (great, right) > pivot2
-             *
-             * Pointer k is the first index of ?-part
-             */
-            for (int k = less; k <= great; k++) {
-                byte ak = a[k];
-
-                if (ak < pivot1) {
-                    a[k] = a[less];
-                    a[less++] = ak;
-                } else if (ak > pivot2) {
-                    while (a[great] > pivot2 && k < great) {
-                        great--;
-                    }
-                    a[k] = a[great];
-                    a[great--] = ak;
-                    ak = a[k];
-
-                    if (ak < pivot1) {
-                        a[k] = a[less];
-                        a[less++] = ak;
-                    }
-                }
-            }
-        } else { // Pivots are equal
-            /*
-             * Partition degenerates to the traditional 3-way
-             * (or "Dutch National Flag") partition:
-             *
-             *   left part   center part            right part
-             * -------------------------------------------------
-             * [  < pivot  |  == pivot  |    ?    |  > pivot   ]
-             * -------------------------------------------------
-             *
-             *              ^            ^       ^
-             *              |            |       |
-             *             less          k     great
-             *
-             * Invariants:
-             *
-             *   all in (left, less)   < pivot
-             *   all in [less, k)     == pivot
-             *   all in (great, right) > pivot
-             *
-             * Pointer k is the first index of ?-part
-             */
-            for (int k = less; k <= great; k++) {
-                byte ak = a[k];
-
-                if (ak == pivot1) {
-                  continue;
-                }
-                if (ak < pivot1) {
-                    a[k] = a[less];
-                    a[less++] = ak;
-                } else {
-                    while (a[great] > pivot1) {
-                        great--;
-                    }
-                    a[k] = a[great];
-                    a[great--] = ak;
-                    ak = a[k];
-
-                    if (ak < pivot1) {
-                        a[k] = a[less];
-                        a[less++] = ak;
-                    }
-                }
-            }
-        }
-
-        // Swap pivots into their final positions
-        a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
-        a[right] = a[great + 1]; a[great + 1] = pivot2;
-
-        // Sort left and right parts recursively, excluding known pivot values
-        sort(a, left,   less - 2);
-        sort(a, great + 2, right);
-
-        /*
-         * If pivot1 == pivot2, all elements from center
-         * part are equal and, therefore, already sorted
-         */
-        if (!pivotsDiffer) {
-            return;
-        }
-
-        /*
-         * If center part is too large (comprises > 5/6 of
-         * the array), swap internal pivot values to ends
-         */
-        if (less < e1 && e5 < great) {
-            while (a[less] == pivot1) {
-                less++;
-            }
-            for (int k = less + 1; k <= great; k++) {
-                if (a[k] == pivot1) {
-                    a[k] = a[less];
-                    a[less++] = pivot1;
-                }
-            }
-            while (a[great] == pivot2) {
-                great--;
-            }
-            for (int k = great - 1; k >= less; k--) {
-                if (a[k] == pivot2) {
-                    a[k] = a[great];
-                    a[great--] = pivot2;
-                }
-            }
-        }
-
-        // Sort center part recursively, excluding known pivot values
-        sort(a, less, great);
+    public static void sort(char[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        doSort(a, fromIndex, toIndex - 1);
     }
 
-    /** The number of distinct char values */
+    /** The number of distinct char values. */
     private static final int NUM_CHAR_VALUES = 1 << 16;
 
     /**
-     * Sorts the specified range of the array into ascending order.
+     * Sorts the specified range of the array into ascending order. This
+     * method differs from the public {@code sort} method in that the
+     * {@code right} index is inclusive, and it does no range checking on
+     * {@code left} or {@code right}.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
-    static void sort(char[] a, int left, int right) {
+    private static void doSort(char[] a, int left, int right) {
         // Use insertion sort on tiny arrays
         if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
             for (int k = left + 1; k <= right; k++) {
@@ -945,7 +843,7 @@
                 }
                 a[j + 1] = ak;
             }
-        } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
+        } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
             // Use counting sort on huge arrays
             int[] count = new int[NUM_CHAR_VALUES];
 
@@ -963,12 +861,12 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order
-     * by Dual-Pivot Quicksort.
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
     private static void dualPivotQuicksort(char[] a, int left, int right) {
         // Compute indices of five evenly spaced elements
@@ -1103,8 +1001,8 @@
         a[right] = a[great + 1]; a[great + 1] = pivot2;
 
         // Sort left and right parts recursively, excluding known pivot values
-        sort(a, left,   less - 2);
-        sort(a, great + 2, right);
+        doSort(a, left,   less - 2);
+        doSort(a, great + 2, right);
 
         /*
          * If pivot1 == pivot2, all elements from center
@@ -1140,17 +1038,395 @@
         }
 
         // Sort center part recursively, excluding known pivot values
-        sort(a, less, great);
+        doSort(a, less, great);
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * @param a the array to be sorted
+     */
+    public static void sort(byte[] a) {
+        doSort(a, 0, a.length - 1);
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * the range to be sorted is empty.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     */
+    public static void sort(byte[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        doSort(a, fromIndex, toIndex - 1);
+    }
+
+    /** The number of distinct byte values. */
+    private static final int NUM_BYTE_VALUES = 1 << 8;
+
+    /**
+     * Sorts the specified range of the array into ascending order. This
+     * method differs from the public {@code sort} method in that the
+     * {@code right} index is inclusive, and it does no range checking on
+     * {@code left} or {@code right}.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     */
+    private static void doSort(byte[] a, int left, int right) {
+        // Use insertion sort on tiny arrays
+        if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
+            for (int k = left + 1; k <= right; k++) {
+                byte ak = a[k];
+                int j;
+
+                for (j = k - 1; j >= left && ak < a[j]; j--) {
+                    a[j + 1] = a[j];
+                }
+                a[j + 1] = ak;
+            }
+        } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
+            // Use counting sort on huge arrays
+            int[] count = new int[NUM_BYTE_VALUES];
+
+            for (int i = left; i <= right; i++) {
+                count[a[i] - Byte.MIN_VALUE]++;
+            }
+            for (int i = 0, k = left; i < count.length && k <= right; i++) {
+                byte value = (byte) (i + Byte.MIN_VALUE);
+
+                for (int s = count[i]; s > 0; s--) {
+                    a[k++] = value;
+               }
+            }
+        } else { // Use Dual-Pivot Quicksort on large arrays
+            dualPivotQuicksort(a, left, right);
+        }
     }
 
     /**
-     * Sorts the specified range of the array into ascending order.
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
-    static void sort(float[] a, int left, int right) {
+    private static void dualPivotQuicksort(byte[] a, int left, int right) {
+        // Compute indices of five evenly spaced elements
+        int sixth = (right - left + 1) / 6;
+        int e1 = left  + sixth;
+        int e5 = right - sixth;
+        int e3 = (left + right) >>> 1; // The midpoint
+        int e4 = e3 + sixth;
+        int e2 = e3 - sixth;
+
+        // Sort these elements in place using a 5-element sorting network
+        if (a[e1] > a[e2]) { byte t = a[e1]; a[e1] = a[e2]; a[e2] = t; }
+        if (a[e4] > a[e5]) { byte t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
+        if (a[e1] > a[e3]) { byte t = a[e1]; a[e1] = a[e3]; a[e3] = t; }
+        if (a[e2] > a[e3]) { byte t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
+        if (a[e1] > a[e4]) { byte t = a[e1]; a[e1] = a[e4]; a[e4] = t; }
+        if (a[e3] > a[e4]) { byte t = a[e3]; a[e3] = a[e4]; a[e4] = t; }
+        if (a[e2] > a[e5]) { byte t = a[e2]; a[e2] = a[e5]; a[e5] = t; }
+        if (a[e2] > a[e3]) { byte t = a[e2]; a[e2] = a[e3]; a[e3] = t; }
+        if (a[e4] > a[e5]) { byte t = a[e4]; a[e4] = a[e5]; a[e5] = t; }
+
+        /*
+         * Use the second and fourth of the five sorted elements as pivots.
+         * These values are inexpensive approximations of the first and
+         * second terciles of the array. Note that pivot1 <= pivot2.
+         *
+         * The pivots are stored in local variables, and the first and
+         * the last of the sorted elements are moved to the locations
+         * formerly occupied by the pivots. When partitioning is complete,
+         * the pivots are swapped back into their final positions, and
+         * excluded from subsequent sorting.
+         */
+        byte pivot1 = a[e2]; a[e2] = a[left];
+        byte pivot2 = a[e4]; a[e4] = a[right];
+
+        /*
+         * Partitioning
+         *
+         *   left part         center part                  right part
+         * ------------------------------------------------------------
+         * [ < pivot1  |  pivot1 <= && <= pivot2  |   ?   |  > pivot2 ]
+         * ------------------------------------------------------------
+         *              ^                          ^     ^
+         *              |                          |     |
+         *             less                        k   great
+         */
+
+        // Pointers
+        int less  = left  + 1; // The index of first element of center part
+        int great = right - 1; // The index before first element of right part
+
+        boolean pivotsDiffer = pivot1 != pivot2;
+
+        if (pivotsDiffer) {
+            /*
+             * Invariants:
+             *              all in (left, less)   < pivot1
+             *    pivot1 <= all in [less, k)     <= pivot2
+             *              all in (great, right) > pivot2
+             *
+             * Pointer k is the first index of ?-part
+             */
+            for (int k = less; k <= great; k++) {
+                byte ak = a[k];
+
+                if (ak < pivot1) {
+                    a[k] = a[less];
+                    a[less++] = ak;
+                } else if (ak > pivot2) {
+                    while (a[great] > pivot2 && k < great) {
+                        great--;
+                    }
+                    a[k] = a[great];
+                    a[great--] = ak;
+                    ak = a[k];
+
+                    if (ak < pivot1) {
+                        a[k] = a[less];
+                        a[less++] = ak;
+                    }
+                }
+            }
+        } else { // Pivots are equal
+            /*
+             * Partition degenerates to the traditional 3-way
+             * (or "Dutch National Flag") partition:
+             *
+             *   left part   center part            right part
+             * -------------------------------------------------
+             * [  < pivot  |  == pivot  |    ?    |  > pivot   ]
+             * -------------------------------------------------
+             *
+             *              ^            ^       ^
+             *              |            |       |
+             *             less          k     great
+             *
+             * Invariants:
+             *
+             *   all in (left, less)   < pivot
+             *   all in [less, k)     == pivot
+             *   all in (great, right) > pivot
+             *
+             * Pointer k is the first index of ?-part
+             */
+            for (int k = less; k <= great; k++) {
+                byte ak = a[k];
+
+                if (ak == pivot1) {
+                  continue;
+                }
+                if (ak < pivot1) {
+                    a[k] = a[less];
+                    a[less++] = ak;
+                } else {
+                    while (a[great] > pivot1) {
+                        great--;
+                    }
+                    a[k] = a[great];
+                    a[great--] = ak;
+                    ak = a[k];
+
+                    if (ak < pivot1) {
+                        a[k] = a[less];
+                        a[less++] = ak;
+                    }
+                }
+            }
+        }
+
+        // Swap pivots into their final positions
+        a[left]  = a[less  - 1]; a[less  - 1] = pivot1;
+        a[right] = a[great + 1]; a[great + 1] = pivot2;
+
+        // Sort left and right parts recursively, excluding known pivot values
+        doSort(a, left,   less - 2);
+        doSort(a, great + 2, right);
+
+        /*
+         * If pivot1 == pivot2, all elements from center
+         * part are equal and, therefore, already sorted
+         */
+        if (!pivotsDiffer) {
+            return;
+        }
+
+        /*
+         * If center part is too large (comprises > 5/6 of
+         * the array), swap internal pivot values to ends
+         */
+        if (less < e1 && e5 < great) {
+            while (a[less] == pivot1) {
+                less++;
+            }
+            for (int k = less + 1; k <= great; k++) {
+                if (a[k] == pivot1) {
+                    a[k] = a[less];
+                    a[less++] = pivot1;
+                }
+            }
+            while (a[great] == pivot2) {
+                great--;
+            }
+            for (int k = great - 1; k >= less; k--) {
+                if (a[k] == pivot2) {
+                    a[k] = a[great];
+                    a[great--] = pivot2;
+                }
+            }
+        }
+
+        // Sort center part recursively, excluding known pivot values
+        doSort(a, less, great);
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * <p>The {@code <} relation does not provide a total order on all float
+     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+     * other value and all {@code Float.NaN} values are considered equal.
+     *
+     * @param a the array to be sorted
+     */
+    public static void sort(float[] a) {
+        sortNegZeroAndNaN(a, 0, a.length - 1);
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * the range to be sorted is empty.
+     *
+     * <p>The {@code <} relation does not provide a total order on all float
+     * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
+     * {@code 0.0f} and {@code Float.NaN} is considered greater than any
+     * other value and all {@code Float.NaN} values are considered equal.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     */
+    public static void sort(float[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        sortNegZeroAndNaN(a, fromIndex, toIndex - 1);
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. The
+     * sort is done in three phases to avoid expensive comparisons in the
+     * inner loop. The comparisons would be expensive due to anomalies
+     * associated with negative zero {@code -0.0f} and {@code Float.NaN}.
+     *
+     * @param a the array to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     */
+    private static void sortNegZeroAndNaN(float[] a, int left, int right) {
+        /*
+         * Phase 1: Count negative zeros and move NaNs to end of array
+         */
+        final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f);
+        int numNegativeZeros = 0;
+        int n = right;
+
+        for (int k = left; k <= n; k++) {
+            float ak = a[k];
+
+            if (ak == 0.0f && NEGATIVE_ZERO == Float.floatToIntBits(ak)) {
+                a[k] = 0.0f;
+                numNegativeZeros++;
+            } else if (ak != ak) { // i.e., ak is NaN
+                a[k--] = a[n];
+                a[n--] = Float.NaN;
+            }
+        }
+
+        /*
+         * Phase 2: Sort everything except NaNs (which are already in place)
+         */
+        doSort(a, left, n);
+
+        /*
+         * Phase 3: Turn positive zeros back into negative zeros as appropriate
+         */
+        if (numNegativeZeros == 0) {
+            return;
+        }
+
+        // Find first zero element
+        int zeroIndex = findAnyZero(a, left, n);
+
+        for (int i = zeroIndex - 1; i >= left && a[i] == 0.0f; i--) {
+            zeroIndex = i;
+        }
+
+        // Turn the right number of positive zeros back into negative zeros
+        for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) {
+            a[i] = -0.0f;
+        }
+    }
+
+    /**
+     * Returns the index of some zero element in the specified range via
+     * binary search. The range is assumed to be sorted, and must contain
+     * at least one zero.
+     *
+     * @param a the array to be searched
+     * @param low the index of the first element, inclusive, to be searched
+     * @param high the index of the last element, inclusive, to be searched
+     */
+    private static int findAnyZero(float[] a, int low, int high) {
+        while (true) {
+            int middle = (low + high) >>> 1;
+            float middleValue = a[middle];
+
+            if (middleValue < 0.0f) {
+                low = middle + 1;
+            } else if (middleValue > 0.0f) {
+                high = middle - 1;
+            } else { // middleValue == 0.0f
+                return middle;
+            }
+        }
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. This
+     * method differs from the public {@code sort} method in three ways:
+     * {@code right} index is inclusive, it does no range checking on
+     * {@code left} or {@code right}, and it does not handle negative
+     * zeros or NaNs in the array.
+     *
+     * @param a the array to be sorted, which must not contain -0.0f or NaN
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     */
+    private static void doSort(float[] a, int left, int right) {
         // Use insertion sort on tiny arrays
         if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
             for (int k = left + 1; k <= right; k++) {
@@ -1168,12 +1444,12 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order
-     * by Dual-Pivot Quicksort.
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
     private static void dualPivotQuicksort(float[] a, int left, int right) {
         // Compute indices of five evenly spaced elements
@@ -1308,8 +1584,8 @@
         a[right] = a[great + 1]; a[great + 1] = pivot2;
 
         // Sort left and right parts recursively, excluding known pivot values
-        sort(a, left,   less - 2);
-        sort(a, great + 2, right);
+        doSort(a, left,   less - 2);
+        doSort(a, great + 2, right);
 
         /*
          * If pivot1 == pivot2, all elements from center
@@ -1345,17 +1621,143 @@
         }
 
         // Sort center part recursively, excluding known pivot values
-        sort(a, less, great);
+        doSort(a, less, great);
+    }
+
+    /**
+     * Sorts the specified array into ascending numerical order.
+     *
+     * <p>The {@code <} relation does not provide a total order on all double
+     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+     * other value and all {@code Double.NaN} values are considered equal.
+     *
+     * @param a the array to be sorted
+     */
+    public static void sort(double[] a) {
+        sortNegZeroAndNaN(a, 0, a.length - 1);
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. The range
+     * to be sorted extends from the index {@code fromIndex}, inclusive, to
+     * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
+     * the range to be sorted is empty.
+     *
+     * <p>The {@code <} relation does not provide a total order on all double
+     * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
+     * value compares neither less than, greater than, nor equal to any value,
+     * even itself. This method uses the total order imposed by the method
+     * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
+     * {@code 0.0d} and {@code Double.NaN} is considered greater than any
+     * other value and all {@code Double.NaN} values are considered equal.
+     *
+     * @param a the array to be sorted
+     * @param fromIndex the index of the first element, inclusive, to be sorted
+     * @param toIndex the index of the last element, exclusive, to be sorted
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *     if {@code fromIndex < 0} or {@code toIndex > a.length}
+     */
+    public static void sort(double[] a, int fromIndex, int toIndex) {
+        rangeCheck(a.length, fromIndex, toIndex);
+        sortNegZeroAndNaN(a, fromIndex, toIndex - 1);
     }
 
     /**
-     * Sorts the specified range of the array into ascending order.
+     * Sorts the specified range of the array into ascending order. The
+     * sort is done in three phases to avoid expensive comparisons in the
+     * inner loop. The comparisons would be expensive due to anomalies
+     * associated with negative zero {@code -0.0d} and {@code Double.NaN}.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
-    static void sort(double[] a, int left, int right) {
+    private static void sortNegZeroAndNaN(double[] a, int left, int right) {
+        /*
+         * Phase 1: Count negative zeros and move NaNs to end of array
+         */
+        final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d);
+        int numNegativeZeros = 0;
+        int n = right;
+
+        for (int k = left; k <= n; k++) {
+            double ak = a[k];
+
+            if (ak == 0.0d && NEGATIVE_ZERO == Double.doubleToLongBits(ak)) {
+                a[k] = 0.0d;
+                numNegativeZeros++;
+            } else if (ak != ak) { // i.e., ak is NaN
+                a[k--] = a[n];
+                a[n--] = Double.NaN;
+            }
+        }
+
+        /*
+         * Phase 2: Sort everything except NaNs (which are already in place)
+         */
+        doSort(a, left, n);
+
+        /*
+         * Phase 3: Turn positive zeros back into negative zeros as appropriate
+         */
+        if (numNegativeZeros == 0) {
+            return;
+        }
+
+        // Find first zero element
+        int zeroIndex = findAnyZero(a, left, n);
+
+        for (int i = zeroIndex - 1; i >= left && a[i] == 0.0d; i--) {
+            zeroIndex = i;
+        }
+
+        // Turn the right number of positive zeros back into negative zeros
+        for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) {
+            a[i] = -0.0d;
+        }
+    }
+
+    /**
+     * Returns the index of some zero element in the specified range via
+     * binary search. The range is assumed to be sorted, and must contain
+     * at least one zero.
+     *
+     * @param a the array to be searched
+     * @param low the index of the first element, inclusive, to be searched
+     * @param high the index of the last element, inclusive, to be searched
+     */
+    private static int findAnyZero(double[] a, int low, int high) {
+        while (true) {
+            int middle = (low + high) >>> 1;
+            double middleValue = a[middle];
+
+            if (middleValue < 0.0d) {
+                low = middle + 1;
+            } else if (middleValue > 0.0d) {
+                high = middle - 1;
+            } else { // middleValue == 0.0d
+                return middle;
+            }
+        }
+    }
+
+    /**
+     * Sorts the specified range of the array into ascending order. This
+     * method differs from the public {@code sort} method in three ways:
+     * {@code right} index is inclusive, it does no range checking on
+     * {@code left} or {@code right}, and it does not handle negative
+     * zeros or NaNs in the array.
+     *
+     * @param a the array to be sorted, which must not contain -0.0d and NaN
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
+     */
+    private static void doSort(double[] a, int left, int right) {
         // Use insertion sort on tiny arrays
         if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
             for (int k = left + 1; k <= right; k++) {
@@ -1373,12 +1775,12 @@
     }
 
     /**
-     * Sorts the specified range of the array into ascending order
-     * by Dual-Pivot Quicksort.
+     * Sorts the specified range of the array into ascending order by the
+     * Dual-Pivot Quicksort algorithm.
      *
      * @param a the array to be sorted
-     * @param left the index of the first element, inclusively, to be sorted
-     * @param right the index of the last element, inclusively, to be sorted
+     * @param left the index of the first element, inclusive, to be sorted
+     * @param right the index of the last element, inclusive, to be sorted
      */
     private static void dualPivotQuicksort(double[] a, int left, int right) {
         // Compute indices of five evenly spaced elements
@@ -1513,8 +1915,8 @@
         a[right] = a[great + 1]; a[great + 1] = pivot2;
 
         // Sort left and right parts recursively, excluding known pivot values
-        sort(a, left,   less - 2);
-        sort(a, great + 2, right);
+        doSort(a, left,   less - 2);
+        doSort(a, great + 2, right);
 
         /*
          * If pivot1 == pivot2, all elements from center
@@ -1550,6 +1952,23 @@
         }
 
         // Sort center part recursively, excluding known pivot values
-        sort(a, less, great);
+        doSort(a, less, great);
+    }
+
+    /**
+     * Checks that {@code fromIndex} and {@code toIndex} are in
+     * the range and throws an appropriate exception, if they aren't.
+     */
+    private static void rangeCheck(int length, int fromIndex, int toIndex) {
+        if (fromIndex > toIndex) {
+            throw new IllegalArgumentException(
+                "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
+        }
+        if (fromIndex < 0) {
+            throw new ArrayIndexOutOfBoundsException(fromIndex);
+        }
+        if (toIndex > length) {
+            throw new ArrayIndexOutOfBoundsException(toIndex);
+        }
     }
 }
--- a/src/share/classes/java/util/Formatter.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/Formatter.java	Thu Nov 12 23:04:42 2009 +0000
@@ -2485,55 +2485,45 @@
 
     private static Pattern fsPattern = Pattern.compile(formatSpecifier);
 
-    // Look for format specifiers in the format string.
+    /**
+     * Finds format specifiers in the format string.
+     */
     private FormatString[] parse(String s) {
-        ArrayList al = new ArrayList();
+        ArrayList<FormatString> al = new ArrayList<FormatString>();
         Matcher m = fsPattern.matcher(s);
-        int i = 0;
-        while (i < s.length()) {
+        for (int i = 0, len = s.length(); i < len; ) {
             if (m.find(i)) {
                 // Anything between the start of the string and the beginning
                 // of the format specifier is either fixed text or contains
                 // an invalid format string.
                 if (m.start() != i) {
                     // Make sure we didn't miss any invalid format specifiers
-                    checkText(s.substring(i, m.start()));
+                    checkText(s, i, m.start());
                     // Assume previous characters were fixed text
                     al.add(new FixedString(s.substring(i, m.start())));
                 }
 
-                // Expect 6 groups in regular expression
-                String[] sa = new String[6];
-                for (int j = 0; j < m.groupCount(); j++)
-                    {
-                    sa[j] = m.group(j + 1);
-//                  System.out.print(sa[j] + " ");
-                    }
-//              System.out.println();
-                al.add(new FormatSpecifier(this, sa));
+                al.add(new FormatSpecifier(m));
                 i = m.end();
             } else {
                 // No more valid format specifiers.  Check for possible invalid
                 // format specifiers.
-                checkText(s.substring(i));
+                checkText(s, i, len);
                 // The rest of the string is fixed text
                 al.add(new FixedString(s.substring(i)));
                 break;
             }
         }
-//      FormatString[] fs = new FormatString[al.size()];
-//      for (int j = 0; j < al.size(); j++)
-//          System.out.println(((FormatString) al.get(j)).toString());
-        return (FormatString[]) al.toArray(new FormatString[0]);
+        return al.toArray(new FormatString[al.size()]);
     }
 
-    private void checkText(String s) {
-        int idx;
-        // If there are any '%' in the given string, we got a bad format
-        // specifier.
-        if ((idx = s.indexOf('%')) != -1) {
-            char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1));
-            throw new UnknownFormatConversionException(String.valueOf(c));
+    private static void checkText(String s, int start, int end) {
+        for (int i = start; i < end; i++) {
+            // Any '%' found in the region starts an invalid format specifier.
+            if (s.charAt(i) == '%') {
+                char c = (i == end - 1) ? '%' : s.charAt(i + 1);
+                throw new UnknownFormatConversionException(String.valueOf(c));
+            }
         }
     }
 
@@ -2562,8 +2552,6 @@
         private boolean dt = false;
         private char c;
 
-        private Formatter formatter;
-
         // cache the line separator
         private String ls;
 
@@ -2650,21 +2638,22 @@
             return c;
         }
 
-        FormatSpecifier(Formatter formatter, String[] sa) {
-            this.formatter = formatter;
-            int idx = 0;
-
-            index(sa[idx++]);
-            flags(sa[idx++]);
-            width(sa[idx++]);
-            precision(sa[idx++]);
-
-            if (sa[idx] != null) {
+        FormatSpecifier(Matcher m) {
+            int idx = 1;
+
+            index(m.group(idx++));
+            flags(m.group(idx++));
+            width(m.group(idx++));
+            precision(m.group(idx++));
+
+            String tT = m.group(idx++);
+            if (tT != null) {
                 dt = true;
-                if (sa[idx].equals("T"))
+                if (tT.equals("T"))
                     f.add(Flags.UPPERCASE);
             }
-            conversion(sa[++idx]);
+
+            conversion(m.group(idx));
 
             if (dt)
                 checkDateTime();
@@ -2819,9 +2808,9 @@
 
         private void printString(Object arg, Locale l) throws IOException {
             if (arg instanceof Formattable) {
-                Formatter fmt = formatter;
-                if (formatter.locale() != l)
-                    fmt = new Formatter(formatter.out(), l);
+                Formatter fmt = Formatter.this;
+                if (fmt.locale() != l)
+                    fmt = new Formatter(fmt.out(), l);
                 ((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision);
             } else {
                 if (f.contains(Flags.ALTERNATE))
--- a/src/share/classes/java/util/HashMap.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/HashMap.java	Thu Nov 12 23:04:42 2009 +0000
@@ -448,10 +448,8 @@
     }
 
     private void putAllForCreate(Map<? extends K, ? extends V> m) {
-        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
-            Map.Entry<? extends K, ? extends V> e = i.next();
+        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
             putForCreate(e.getKey(), e.getValue());
-        }
     }
 
     /**
@@ -536,10 +534,8 @@
                 resize(newCapacity);
         }
 
-        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
-            Map.Entry<? extends K, ? extends V> e = i.next();
+        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
             put(e.getKey(), e.getValue());
-        }
     }
 
     /**
--- a/src/share/classes/java/util/HashSet.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/HashSet.java	Thu Nov 12 23:04:42 2009 +0000
@@ -280,8 +280,8 @@
         s.writeInt(map.size());
 
         // Write out all elements in the proper order.
-        for (Iterator i=map.keySet().iterator(); i.hasNext(); )
-            s.writeObject(i.next());
+        for (E e : map.keySet())
+            s.writeObject(e);
     }
 
     /**
--- a/src/share/classes/java/util/LinkedList.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/LinkedList.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,22 +26,22 @@
 package java.util;
 
 /**
- * Linked list implementation of the <tt>List</tt> interface.  Implements all
+ * Linked list implementation of the {@code List} interface.  Implements all
  * optional list operations, and permits all elements (including
- * <tt>null</tt>).  In addition to implementing the <tt>List</tt> interface,
- * the <tt>LinkedList</tt> class provides uniformly named methods to
- * <tt>get</tt>, <tt>remove</tt> and <tt>insert</tt> an element at the
+ * {@code null}).  In addition to implementing the {@code List} interface,
+ * the {@code LinkedList} class provides uniformly named methods to
+ * {@code get}, {@code remove} and {@code insert} an element at the
  * beginning and end of the list.  These operations allow linked lists to be
  * used as a stack, {@linkplain Queue queue}, or {@linkplain Deque
- * double-ended queue}. <p>
+ * double-ended queue}.
  *
- * The class implements the <tt>Deque</tt> interface, providing
- * first-in-first-out queue operations for <tt>add</tt>,
- * <tt>poll</tt>, along with other stack and deque operations.<p>
+ * <p>The class implements the {@code Deque} interface, providing
+ * first-in-first-out queue operations for {@code add},
+ * {@code poll}, along with other stack and deque operations.
  *
- * All of the operations perform as could be expected for a doubly-linked
+ * <p>All of the operations perform as could be expected for a doubly-linked
  * list.  Operations that index into the list will traverse the list from
- * the beginning or the end, whichever is closer to the specified index.<p>
+ * the beginning or the end, whichever is closer to the specified index.
  *
  * <p><strong>Note that this implementation is not synchronized.</strong>
  * If multiple threads access a linked list concurrently, and at least
@@ -58,11 +58,11 @@
  * unsynchronized access to the list:<pre>
  *   List list = Collections.synchronizedList(new LinkedList(...));</pre>
  *
- * <p>The iterators returned by this class's <tt>iterator</tt> and
- * <tt>listIterator</tt> methods are <i>fail-fast</i>: if the list is
+ * <p>The iterators returned by this class's {@code iterator} and
+ * {@code listIterator} methods are <i>fail-fast</i>: if the list is
  * structurally modified at any time after the iterator is created, in
- * any way except through the Iterator's own <tt>remove</tt> or
- * <tt>add</tt> methods, the iterator will throw a {@link
+ * any way except through the Iterator's own {@code remove} or
+ * {@code add} methods, the iterator will throw a {@link
  * ConcurrentModificationException}.  Thus, in the face of concurrent
  * modification, the iterator fails quickly and cleanly, rather than
  * risking arbitrary, non-deterministic behavior at an undetermined
@@ -71,7 +71,7 @@
  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  * as it is, generally speaking, impossible to make any hard guarantees in the
  * presence of unsynchronized concurrent modification.  Fail-fast iterators
- * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
+ * throw {@code ConcurrentModificationException} on a best-effort basis.
  * Therefore, it would be wrong to write a program that depended on this
  * exception for its correctness:   <i>the fail-fast behavior of iterators
  * should be used only to detect bugs.</i>
@@ -83,7 +83,6 @@
  * @author  Josh Bloch
  * @see     List
  * @see     ArrayList
- * @see     Vector
  * @since 1.2
  * @param <E> the type of elements held in this collection
  */
@@ -92,14 +91,26 @@
     extends AbstractSequentialList<E>
     implements List<E>, Deque<E>, Cloneable, java.io.Serializable
 {
-    private transient Entry<E> header = new Entry<E>(null, null, null);
-    private transient int size = 0;
+    transient int size = 0;
+
+    /**
+     * Pointer to first node.
+     * Invariant: (first == null && last == null) ||
+     *            (first.prev == null && first.item != null)
+     */
+    transient Node<E> first;
+
+    /**
+     * Pointer to last node.
+     * Invariant: (first == null && last == null) ||
+     *            (last.next == null && last.item != null)
+     */
+    transient Node<E> last;
 
     /**
      * Constructs an empty list.
      */
     public LinkedList() {
-        header.next = header.previous = header;
     }
 
     /**
@@ -116,16 +127,129 @@
     }
 
     /**
+     * Links e as first element.
+     */
+    private void linkFirst(E e) {
+        final Node<E> f = first;
+        final Node<E> newNode = new Node<E>(null, e, f);
+        first = newNode;
+        if (f == null)
+            last = newNode;
+        else
+            f.prev = newNode;
+        size++;
+        modCount++;
+    }
+
+    /**
+     * Links e as last element.
+     */
+    void linkLast(E e) {
+        final Node<E> l = last;
+        final Node<E> newNode = new Node<E>(l, e, null);
+        last = newNode;
+        if (l == null)
+            first = newNode;
+        else
+            l.next = newNode;
+        size++;
+        modCount++;
+    }
+
+    /**
+     * Inserts element e before non-null Node succ.
+     */
+    void linkBefore(E e, Node<E> succ) {
+        // assert succ != null;
+        final Node<E> pred = succ.prev;
+        final Node<E> newNode = new Node<E>(pred, e, succ);
+        succ.prev = newNode;
+        if (pred == null)
+            first = newNode;
+        else
+            pred.next = newNode;
+        size++;
+        modCount++;
+    }
+
+    /**
+     * Unlinks non-null first node f.
+     */
+    private E unlinkFirst(Node<E> f) {
+        // assert f == first && f != null;
+        final E element = f.item;
+        final Node<E> next = f.next;
+        f.item = null;
+        f.next = null; // help GC
+        first = next;
+        if (next == null)
+            last = null;
+        else
+            next.prev = null;
+        size--;
+        modCount++;
+        return element;
+    }
+
+    /**
+     * Unlinks non-null last node l.
+     */
+    private E unlinkLast(Node<E> l) {
+        // assert l == last && l != null;
+        final E element = l.item;
+        final Node<E> prev = l.prev;
+        l.item = null;
+        l.prev = null; // help GC
+        last = prev;
+        if (prev == null)
+            first = null;
+        else
+            prev.next = null;
+        size--;
+        modCount++;
+        return element;
+    }
+
+    /**
+     * Unlinks non-null node x.
+     */
+    E unlink(Node<E> x) {
+        // assert x != null;
+        final E element = x.item;
+        final Node<E> next = x.next;
+        final Node<E> prev = x.prev;
+
+        if (prev == null) {
+            first = next;
+        } else {
+            prev.next = next;
+            x.prev = null;
+        }
+
+        if (next == null) {
+            last = prev;
+        } else {
+            next.prev = prev;
+            x.next = null;
+        }
+
+        x.item = null;
+        size--;
+        modCount++;
+        return element;
+    }
+
+    /**
      * Returns the first element in this list.
      *
      * @return the first element in this list
      * @throws NoSuchElementException if this list is empty
      */
     public E getFirst() {
-        if (size==0)
+        final Node<E> f = first;
+        if (f == null)
             throw new NoSuchElementException();
-
-        return header.next.element;
+        return f.item;
     }
 
     /**
@@ -135,10 +259,10 @@
      * @throws NoSuchElementException if this list is empty
      */
     public E getLast()  {
-        if (size==0)
+        final Node<E> l = last;
+        if (l == null)
             throw new NoSuchElementException();
-
-        return header.previous.element;
+        return l.item;
     }
 
     /**
@@ -148,7 +272,10 @@
      * @throws NoSuchElementException if this list is empty
      */
     public E removeFirst() {
-        return remove(header.next);
+        final Node<E> f = first;
+        if (f == null)
+            throw new NoSuchElementException();
+        return unlinkFirst(f);
     }
 
     /**
@@ -158,7 +285,10 @@
      * @throws NoSuchElementException if this list is empty
      */
     public E removeLast() {
-        return remove(header.previous);
+        final Node<E> l = last;
+        if (l == null)
+            throw new NoSuchElementException();
+        return unlinkLast(l);
     }
 
     /**
@@ -167,7 +297,7 @@
      * @param e the element to add
      */
     public void addFirst(E e) {
-        addBefore(e, header.next);
+        linkFirst(e);
     }
 
     /**
@@ -178,17 +308,17 @@
      * @param e the element to add
      */
     public void addLast(E e) {
-        addBefore(e, header);
+        linkLast(e);
     }
 
     /**
-     * Returns <tt>true</tt> if this list contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this list contains
-     * at least one element <tt>e</tt> such that
+     * Returns {@code true} if this list contains the specified element.
+     * More formally, returns {@code true} if and only if this list contains
+     * at least one element {@code e} such that
      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
      *
      * @param o element whose presence in this list is to be tested
-     * @return <tt>true</tt> if this list contains the specified element
+     * @return {@code true} if this list contains the specified element
      */
     public boolean contains(Object o) {
         return indexOf(o) != -1;
@@ -209,10 +339,10 @@
      * <p>This method is equivalent to {@link #addLast}.
      *
      * @param e element to be appended to this list
-     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @return {@code true} (as specified by {@link Collection#add})
      */
     public boolean add(E e) {
-        addBefore(e, header);
+        linkLast(e);
         return true;
     }
 
@@ -220,27 +350,27 @@
      * Removes the first occurrence of the specified element from this list,
      * if it is present.  If this list does not contain the element, it is
      * unchanged.  More formally, removes the element with the lowest index
-     * <tt>i</tt> such that
+     * {@code i} such that
      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
-     * (if such an element exists).  Returns <tt>true</tt> if this list
+     * (if such an element exists).  Returns {@code true} if this list
      * contained the specified element (or equivalently, if this list
      * changed as a result of the call).
      *
      * @param o element to be removed from this list, if present
-     * @return <tt>true</tt> if this list contained the specified element
+     * @return {@code true} if this list contained the specified element
      */
     public boolean remove(Object o) {
-        if (o==null) {
-            for (Entry<E> e = header.next; e != header; e = e.next) {
-                if (e.element==null) {
-                    remove(e);
+        if (o == null) {
+            for (Node<E> x = first; x != null; x = x.next) {
+                if (x.item == null) {
+                    unlink(x);
                     return true;
                 }
             }
         } else {
-            for (Entry<E> e = header.next; e != header; e = e.next) {
-                if (o.equals(e.element)) {
-                    remove(e);
+            for (Node<E> x = first; x != null; x = x.next) {
+                if (o.equals(x.item)) {
+                    unlink(x);
                     return true;
                 }
             }
@@ -257,7 +387,7 @@
      * this list, and it's nonempty.)
      *
      * @param c collection containing elements to be added to this list
-     * @return <tt>true</tt> if this list changed as a result of the call
+     * @return {@code true} if this list changed as a result of the call
      * @throws NullPointerException if the specified collection is null
      */
     public boolean addAll(Collection<? extends E> c) {
@@ -275,45 +405,66 @@
      * @param index index at which to insert the first element
      *              from the specified collection
      * @param c collection containing elements to be added to this list
-     * @return <tt>true</tt> if this list changed as a result of the call
+     * @return {@code true} if this list changed as a result of the call
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @throws NullPointerException if the specified collection is null
      */
     public boolean addAll(int index, Collection<? extends E> c) {
-        if (index < 0 || index > size)
-            throw new IndexOutOfBoundsException("Index: "+index+
-                                                ", Size: "+size);
+        checkPositionIndex(index);
+
         Object[] a = c.toArray();
         int numNew = a.length;
-        if (numNew==0)
+        if (numNew == 0)
             return false;
-        modCount++;
+
+        Node<E> pred, succ;
+        if (index == size) {
+            succ = null;
+            pred = last;
+        } else {
+            succ = node(index);
+            pred = succ.prev;
+        }
 
-        Entry<E> successor = (index==size ? header : entry(index));
-        Entry<E> predecessor = successor.previous;
-        for (int i=0; i<numNew; i++) {
-            Entry<E> e = new Entry<E>((E)a[i], successor, predecessor);
-            predecessor.next = e;
-            predecessor = e;
+        for (Object o : a) {
+            @SuppressWarnings("unchecked") E e = (E) o;
+            Node<E> newNode = new Node<E>(pred, e, null);
+            if (pred == null)
+                first = newNode;
+            else
+                pred.next = newNode;
+            pred = newNode;
         }
-        successor.previous = predecessor;
+
+        if (succ == null) {
+            last = pred;
+        } else {
+            pred.next = succ;
+            succ.prev = pred;
+        }
 
         size += numNew;
+        modCount++;
         return true;
     }
 
     /**
      * Removes all of the elements from this list.
+     * The list will be empty after this call returns.
      */
     public void clear() {
-        Entry<E> e = header.next;
-        while (e != header) {
-            Entry<E> next = e.next;
-            e.next = e.previous = null;
-            e.element = null;
-            e = next;
+        // Clearing all of the links between nodes is "unnecessary", but:
+        // - helps a generational GC if the discarded nodes inhabit
+        //   more than one generation
+        // - is sure to free memory even if there is a reachable Iterator
+        for (Node<E> x = first; x != null; ) {
+            Node<E> next = x.next;
+            x.item = null;
+            x.next = null;
+            x.prev = null;
+            x = next;
         }
-        header.next = header.previous = header;
+        first = last = null;
         size = 0;
         modCount++;
     }
@@ -329,7 +480,8 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public E get(int index) {
-        return entry(index).element;
+        checkElementIndex(index);
+        return node(index).item;
     }
 
     /**
@@ -342,9 +494,10 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public E set(int index, E element) {
-        Entry<E> e = entry(index);
-        E oldVal = e.element;
-        e.element = element;
+        checkElementIndex(index);
+        Node<E> x = node(index);
+        E oldVal = x.item;
+        x.item = element;
         return oldVal;
     }
 
@@ -358,7 +511,12 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public void add(int index, E element) {
-        addBefore(element, (index==size ? header : entry(index)));
+        checkPositionIndex(index);
+
+        if (index == size)
+            linkLast(element);
+        else
+            linkBefore(element, node(index));
     }
 
     /**
@@ -371,34 +529,69 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public E remove(int index) {
-        return remove(entry(index));
+        checkElementIndex(index);
+        return unlink(node(index));
+    }
+
+    /**
+     * Tells if the argument is the index of an existing element.
+     */
+    private boolean isElementIndex(int index) {
+        return index >= 0 && index < size;
+    }
+
+    /**
+     * Tells if the argument is the index of a valid position for an
+     * iterator or an add operation.
+     */
+    private boolean isPositionIndex(int index) {
+        return index >= 0 && index <= size;
     }
 
     /**
-     * Returns the indexed entry.
+     * Constructs an IndexOutOfBoundsException detail message.
+     * Of the many possible refactorings of the error handling code,
+     * this "outlining" performs best with both server and client VMs.
      */
-    private Entry<E> entry(int index) {
-        if (index < 0 || index >= size)
-            throw new IndexOutOfBoundsException("Index: "+index+
-                                                ", Size: "+size);
-        Entry<E> e = header;
-        if (index < (size >> 1)) {
-            for (int i = 0; i <= index; i++)
-                e = e.next;
-        } else {
-            for (int i = size; i > index; i--)
-                e = e.previous;
-        }
-        return e;
+    private String outOfBoundsMsg(int index) {
+        return "Index: "+index+", Size: "+size;
+    }
+
+    private void checkElementIndex(int index) {
+        if (!isElementIndex(index))
+            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
+    }
+
+    private void checkPositionIndex(int index) {
+        if (!isPositionIndex(index))
+            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
     }
 
+    /**
+     * Returns the (non-null) Node at the specified element index.
+     */
+    Node<E> node(int index) {
+        // assert isElementIndex(index);
+
+        if (index < (size >> 1)) {
+            Node<E> x = first;
+            for (int i = 0; i < index; i++)
+                x = x.next;
+            return x;
+        } else {
+            Node<E> x = last;
+            for (int i = size - 1; i > index; i--)
+                x = x.prev;
+            return x;
+        }
+    }
 
     // Search Operations
 
     /**
      * Returns the index of the first occurrence of the specified element
      * in this list, or -1 if this list does not contain the element.
-     * More formally, returns the lowest index <tt>i</tt> such that
+     * More formally, returns the lowest index {@code i} such that
      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
      * or -1 if there is no such index.
      *
@@ -408,15 +601,15 @@
      */
     public int indexOf(Object o) {
         int index = 0;
-        if (o==null) {
-            for (Entry e = header.next; e != header; e = e.next) {
-                if (e.element==null)
+        if (o == null) {
+            for (Node<E> x = first; x != null; x = x.next) {
+                if (x.item == null)
                     return index;
                 index++;
             }
         } else {
-            for (Entry e = header.next; e != header; e = e.next) {
-                if (o.equals(e.element))
+            for (Node<E> x = first; x != null; x = x.next) {
+                if (o.equals(x.item))
                     return index;
                 index++;
             }
@@ -427,7 +620,7 @@
     /**
      * Returns the index of the last occurrence of the specified element
      * in this list, or -1 if this list does not contain the element.
-     * More formally, returns the highest index <tt>i</tt> such that
+     * More formally, returns the highest index {@code i} such that
      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
      * or -1 if there is no such index.
      *
@@ -437,16 +630,16 @@
      */
     public int lastIndexOf(Object o) {
         int index = size;
-        if (o==null) {
-            for (Entry e = header.previous; e != header; e = e.previous) {
+        if (o == null) {
+            for (Node<E> x = last; x != null; x = x.prev) {
                 index--;
-                if (e.element==null)
+                if (x.item == null)
                     return index;
             }
         } else {
-            for (Entry e = header.previous; e != header; e = e.previous) {
+            for (Node<E> x = last; x != null; x = x.prev) {
                 index--;
-                if (o.equals(e.element))
+                if (o.equals(x.item))
                     return index;
             }
         }
@@ -457,17 +650,18 @@
 
     /**
      * Retrieves, but does not remove, the head (first element) of this list.
-     * @return the head of this list, or <tt>null</tt> if this list is empty
+     *
+     * @return the head of this list, or {@code null} if this list is empty
      * @since 1.5
      */
     public E peek() {
-        if (size==0)
-            return null;
-        return getFirst();
+        final Node<E> f = first;
+        return (f == null) ? null : f.item;
     }
 
     /**
      * Retrieves, but does not remove, the head (first element) of this list.
+     *
      * @return the head of this list
      * @throws NoSuchElementException if this list is empty
      * @since 1.5
@@ -477,14 +671,14 @@
     }
 
     /**
-     * Retrieves and removes the head (first element) of this list
-     * @return the head of this list, or <tt>null</tt> if this list is empty
+     * Retrieves and removes the head (first element) of this list.
+     *
+     * @return the head of this list, or {@code null} if this list is empty
      * @since 1.5
      */
     public E poll() {
-        if (size==0)
-            return null;
-        return removeFirst();
+        final Node<E> f = first;
+        return (f == null) ? null : unlinkFirst(f);
     }
 
     /**
@@ -502,7 +696,7 @@
      * Adds the specified element as the tail (last element) of this list.
      *
      * @param e the element to add
-     * @return <tt>true</tt> (as specified by {@link Queue#offer})
+     * @return {@code true} (as specified by {@link Queue#offer})
      * @since 1.5
      */
     public boolean offer(E e) {
@@ -514,7 +708,7 @@
      * Inserts the specified element at the front of this list.
      *
      * @param e the element to insert
-     * @return <tt>true</tt> (as specified by {@link Deque#offerFirst})
+     * @return {@code true} (as specified by {@link Deque#offerFirst})
      * @since 1.6
      */
     public boolean offerFirst(E e) {
@@ -526,7 +720,7 @@
      * Inserts the specified element at the end of this list.
      *
      * @param e the element to insert
-     * @return <tt>true</tt> (as specified by {@link Deque#offerLast})
+     * @return {@code true} (as specified by {@link Deque#offerLast})
      * @since 1.6
      */
     public boolean offerLast(E e) {
@@ -536,58 +730,54 @@
 
     /**
      * Retrieves, but does not remove, the first element of this list,
-     * or returns <tt>null</tt> if this list is empty.
+     * or returns {@code null} if this list is empty.
      *
-     * @return the first element of this list, or <tt>null</tt>
+     * @return the first element of this list, or {@code null}
      *         if this list is empty
      * @since 1.6
      */
     public E peekFirst() {
-        if (size==0)
-            return null;
-        return getFirst();
-    }
+        final Node<E> f = first;
+        return (f == null) ? null : f.item;
+     }
 
     /**
      * Retrieves, but does not remove, the last element of this list,
-     * or returns <tt>null</tt> if this list is empty.
+     * or returns {@code null} if this list is empty.
      *
-     * @return the last element of this list, or <tt>null</tt>
+     * @return the last element of this list, or {@code null}
      *         if this list is empty
      * @since 1.6
      */
     public E peekLast() {
-        if (size==0)
-            return null;
-        return getLast();
+        final Node<E> l = last;
+        return (l == null) ? null : l.item;
     }
 
     /**
      * Retrieves and removes the first element of this list,
-     * or returns <tt>null</tt> if this list is empty.
+     * or returns {@code null} if this list is empty.
      *
-     * @return the first element of this list, or <tt>null</tt> if
+     * @return the first element of this list, or {@code null} if
      *     this list is empty
      * @since 1.6
      */
     public E pollFirst() {
-        if (size==0)
-            return null;
-        return removeFirst();
+        final Node<E> f = first;
+        return (f == null) ? null : unlinkFirst(f);
     }
 
     /**
      * Retrieves and removes the last element of this list,
-     * or returns <tt>null</tt> if this list is empty.
+     * or returns {@code null} if this list is empty.
      *
-     * @return the last element of this list, or <tt>null</tt> if
+     * @return the last element of this list, or {@code null} if
      *     this list is empty
      * @since 1.6
      */
     public E pollLast() {
-        if (size==0)
-            return null;
-        return removeLast();
+        final Node<E> l = last;
+        return (l == null) ? null : unlinkLast(l);
     }
 
     /**
@@ -624,7 +814,7 @@
      * does not contain the element, it is unchanged.
      *
      * @param o element to be removed from this list, if present
-     * @return <tt>true</tt> if the list contained the specified element
+     * @return {@code true} if the list contained the specified element
      * @since 1.6
      */
     public boolean removeFirstOccurrence(Object o) {
@@ -637,21 +827,21 @@
      * does not contain the element, it is unchanged.
      *
      * @param o element to be removed from this list, if present
-     * @return <tt>true</tt> if the list contained the specified element
+     * @return {@code true} if the list contained the specified element
      * @since 1.6
      */
     public boolean removeLastOccurrence(Object o) {
-        if (o==null) {
-            for (Entry<E> e = header.previous; e != header; e = e.previous) {
-                if (e.element==null) {
-                    remove(e);
+        if (o == null) {
+            for (Node<E> x = last; x != null; x = x.prev) {
+                if (x.item == null) {
+                    unlink(x);
                     return true;
                 }
             }
         } else {
-            for (Entry<E> e = header.previous; e != header; e = e.previous) {
-                if (o.equals(e.element)) {
-                    remove(e);
+            for (Node<E> x = last; x != null; x = x.prev) {
+                if (o.equals(x.item)) {
+                    unlink(x);
                     return true;
                 }
             }
@@ -662,76 +852,68 @@
     /**
      * Returns a list-iterator of the elements in this list (in proper
      * sequence), starting at the specified position in the list.
-     * Obeys the general contract of <tt>List.listIterator(int)</tt>.<p>
+     * Obeys the general contract of {@code List.listIterator(int)}.<p>
      *
      * The list-iterator is <i>fail-fast</i>: if the list is structurally
      * modified at any time after the Iterator is created, in any way except
-     * through the list-iterator's own <tt>remove</tt> or <tt>add</tt>
+     * through the list-iterator's own {@code remove} or {@code add}
      * methods, the list-iterator will throw a
-     * <tt>ConcurrentModificationException</tt>.  Thus, in the face of
+     * {@code ConcurrentModificationException}.  Thus, in the face of
      * concurrent modification, the iterator fails quickly and cleanly, rather
      * than risking arbitrary, non-deterministic behavior at an undetermined
      * time in the future.
      *
      * @param index index of the first element to be returned from the
-     *              list-iterator (by a call to <tt>next</tt>)
+     *              list-iterator (by a call to {@code next})
      * @return a ListIterator of the elements in this list (in proper
      *         sequence), starting at the specified position in the list
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @see List#listIterator(int)
      */
     public ListIterator<E> listIterator(int index) {
+        checkPositionIndex(index);
         return new ListItr(index);
     }
 
     private class ListItr implements ListIterator<E> {
-        private Entry<E> lastReturned = header;
-        private Entry<E> next;
+        private Node<E> lastReturned = null;
+        private Node<E> next;
         private int nextIndex;
         private int expectedModCount = modCount;
 
         ListItr(int index) {
-            if (index < 0 || index > size)
-                throw new IndexOutOfBoundsException("Index: "+index+
-                                                    ", Size: "+size);
-            if (index < (size >> 1)) {
-                next = header.next;
-                for (nextIndex=0; nextIndex<index; nextIndex++)
-                    next = next.next;
-            } else {
-                next = header;
-                for (nextIndex=size; nextIndex>index; nextIndex--)
-                    next = next.previous;
-            }
+            // assert isPositionIndex(index);
+            next = (index == size) ? null : node(index);
+            nextIndex = index;
         }
 
         public boolean hasNext() {
-            return nextIndex != size;
+            return nextIndex < size;
         }
 
         public E next() {
             checkForComodification();
-            if (nextIndex == size)
+            if (!hasNext())
                 throw new NoSuchElementException();
 
             lastReturned = next;
             next = next.next;
             nextIndex++;
-            return lastReturned.element;
+            return lastReturned.item;
         }
 
         public boolean hasPrevious() {
-            return nextIndex != 0;
+            return nextIndex > 0;
         }
 
         public E previous() {
-            if (nextIndex == 0)
+            checkForComodification();
+            if (!hasPrevious())
                 throw new NoSuchElementException();
 
-            lastReturned = next = next.previous;
+            lastReturned = next = (next == null) ? last : next.prev;
             nextIndex--;
-            checkForComodification();
-            return lastReturned.element;
+            return lastReturned.item;
         }
 
         public int nextIndex() {
@@ -739,36 +921,38 @@
         }
 
         public int previousIndex() {
-            return nextIndex-1;
+            return nextIndex - 1;
         }
 
         public void remove() {
             checkForComodification();
-            Entry<E> lastNext = lastReturned.next;
-            try {
-                LinkedList.this.remove(lastReturned);
-            } catch (NoSuchElementException e) {
+            if (lastReturned == null)
                 throw new IllegalStateException();
-            }
-            if (next==lastReturned)
+
+            Node<E> lastNext = lastReturned.next;
+            unlink(lastReturned);
+            if (next == lastReturned)
                 next = lastNext;
             else
                 nextIndex--;
-            lastReturned = header;
+            lastReturned = null;
             expectedModCount++;
         }
 
         public void set(E e) {
-            if (lastReturned == header)
+            if (lastReturned == null)
                 throw new IllegalStateException();
             checkForComodification();
-            lastReturned.element = e;
+            lastReturned.item = e;
         }
 
         public void add(E e) {
             checkForComodification();
-            lastReturned = header;
-            addBefore(e, next);
+            lastReturned = null;
+            if (next == null)
+                linkLast(e);
+            else
+                linkBefore(e, next);
             nextIndex++;
             expectedModCount++;
         }
@@ -779,39 +963,16 @@
         }
     }
 
-    private static class Entry<E> {
-        E element;
-        Entry<E> next;
-        Entry<E> previous;
-
-        Entry(E element, Entry<E> next, Entry<E> previous) {
-            this.element = element;
-            this.next = next;
-            this.previous = previous;
-        }
-    }
+    private static class Node<E> {
+        E item;
+        Node<E> next;
+        Node<E> prev;
 
-    private Entry<E> addBefore(E e, Entry<E> entry) {
-        Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
-        newEntry.previous.next = newEntry;
-        newEntry.next.previous = newEntry;
-        size++;
-        modCount++;
-        return newEntry;
-    }
-
-    private E remove(Entry<E> e) {
-        if (e == header)
-            throw new NoSuchElementException();
-
-        E result = e.element;
-        e.previous.next = e.next;
-        e.next.previous = e.previous;
-        e.next = e.previous = null;
-        e.element = null;
-        size--;
-        modCount++;
-        return result;
+        Node(Node<E> prev, E element, Node<E> next) {
+            this.item = element;
+            this.next = next;
+            this.prev = prev;
+        }
     }
 
     /**
@@ -821,9 +982,11 @@
         return new DescendingIterator();
     }
 
-    /** Adapter to provide descending iterators via ListItr.previous */
-    private class DescendingIterator implements Iterator {
-        final ListItr itr = new ListItr(size());
+    /**
+     * Adapter to provide descending iterators via ListItr.previous
+     */
+    private class DescendingIterator implements Iterator<E> {
+        private final ListItr itr = new ListItr(size());
         public boolean hasNext() {
             return itr.hasPrevious();
         }
@@ -835,29 +998,32 @@
         }
     }
 
-    /**
-     * Returns a shallow copy of this <tt>LinkedList</tt>. (The elements
-     * themselves are not cloned.)
-     *
-     * @return a shallow copy of this <tt>LinkedList</tt> instance
-     */
-    public Object clone() {
-        LinkedList<E> clone = null;
+    @SuppressWarnings("unchecked")
+    private LinkedList<E> superClone() {
         try {
-            clone = (LinkedList<E>) super.clone();
+            return (LinkedList<E>) super.clone();
         } catch (CloneNotSupportedException e) {
             throw new InternalError();
         }
+    }
+
+    /**
+     * Returns a shallow copy of this {@code LinkedList}. (The elements
+     * themselves are not cloned.)
+     *
+     * @return a shallow copy of this {@code LinkedList} instance
+     */
+    public Object clone() {
+        LinkedList<E> clone = superClone();
 
         // Put clone into "virgin" state
-        clone.header = new Entry<E>(null, null, null);
-        clone.header.next = clone.header.previous = clone.header;
+        clone.first = clone.last = null;
         clone.size = 0;
         clone.modCount = 0;
 
         // Initialize clone with our elements
-        for (Entry<E> e = header.next; e != header; e = e.next)
-            clone.add(e.element);
+        for (Node<E> x = first; x != null; x = x.next)
+            clone.add(x.item);
 
         return clone;
     }
@@ -879,8 +1045,8 @@
     public Object[] toArray() {
         Object[] result = new Object[size];
         int i = 0;
-        for (Entry<E> e = header.next; e != header; e = e.next)
-            result[i++] = e.element;
+        for (Node<E> x = first; x != null; x = x.next)
+            result[i++] = x.item;
         return result;
     }
 
@@ -894,7 +1060,7 @@
      *
      * <p>If the list fits in the specified array with room to spare (i.e.,
      * the array has more elements than the list), the element in the array
-     * immediately following the end of the list is set to <tt>null</tt>.
+     * immediately following the end of the list is set to {@code null}.
      * (This is useful in determining the length of the list <i>only</i> if
      * the caller knows that the list does not contain any null elements.)
      *
@@ -903,15 +1069,15 @@
      * precise control over the runtime type of the output array, and may,
      * under certain circumstances, be used to save allocation costs.
      *
-     * <p>Suppose <tt>x</tt> is a list known to contain only strings.
+     * <p>Suppose {@code x} is a list known to contain only strings.
      * The following code can be used to dump the list into a newly
-     * allocated array of <tt>String</tt>:
+     * allocated array of {@code String}:
      *
      * <pre>
      *     String[] y = x.toArray(new String[0]);</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
      *
      * @param a the array into which the elements of the list are to
      *          be stored, if it is big enough; otherwise, a new array of the
@@ -922,14 +1088,15 @@
      *         this list
      * @throws NullPointerException if the specified array is null
      */
+    @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
         if (a.length < size)
             a = (T[])java.lang.reflect.Array.newInstance(
                                 a.getClass().getComponentType(), size);
         int i = 0;
         Object[] result = a;
-        for (Entry<E> e = header.next; e != header; e = e.next)
-            result[i++] = e.element;
+        for (Node<E> x = first; x != null; x = x.next)
+            result[i++] = x.item;
 
         if (a.length > size)
             a[size] = null;
@@ -940,8 +1107,8 @@
     private static final long serialVersionUID = 876323262645176354L;
 
     /**
-     * Save the state of this <tt>LinkedList</tt> instance to a stream (that
-     * is, serialize it).
+     * Saves the state of this {@code LinkedList} instance to a stream
+     * (that is, serializes it).
      *
      * @serialData The size of the list (the number of elements it
      *             contains) is emitted (int), followed by all of its
@@ -956,14 +1123,15 @@
         s.writeInt(size);
 
         // Write out all elements in the proper order.
-        for (Entry e = header.next; e != header; e = e.next)
-            s.writeObject(e.element);
+        for (Node<E> x = first; x != null; x = x.next)
+            s.writeObject(x.item);
     }
 
     /**
-     * Reconstitute this <tt>LinkedList</tt> instance from a stream (that is
-     * deserialize it).
+     * Reconstitutes this {@code LinkedList} instance from a stream
+     * (that is, deserializes it).
      */
+    @SuppressWarnings("unchecked")
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         // Read in any hidden serialization magic
@@ -972,12 +1140,8 @@
         // Read in size
         int size = s.readInt();
 
-        // Initialize header
-        header = new Entry<E>(null, null, null);
-        header.next = header.previous = header;
-
         // Read in all elements in the proper order.
-        for (int i=0; i<size; i++)
-            addBefore((E)s.readObject(), header);
+        for (int i = 0; i < size; i++)
+            linkLast((E)s.readObject());
     }
 }
--- a/src/share/classes/java/util/Random.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/Random.java	Thu Nov 12 23:04:42 2009 +0000
@@ -50,6 +50,18 @@
  * <p>
  * Many applications will find the method {@link Math#random} simpler to use.
  *
+ * <p>Instances of {@code java.util.Random} are threadsafe.
+ * However, the concurrent use of the same {@code java.util.Random}
+ * instance across threads may encounter contention and consequent
+ * poor performance. Consider instead using
+ * {@link java.util.concurrent.ThreadLocalRandom} in multithreaded
+ * designs.
+ *
+ * <p>Instances of {@code java.util.Random} are not cryptographically
+ * secure.  Consider instead using {@link java.security.SecureRandom} to
+ * get a cryptographically secure pseudo-random number generator for use
+ * by security-sensitive applications.
+ *
  * @author  Frank Yellin
  * @since   1.0
  */
--- a/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java	Thu Nov 12 23:04:42 2009 +0000
@@ -218,8 +218,8 @@
         if (capacity < c.size())
             throw new IllegalArgumentException();
 
-        for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
-            add(it.next());
+        for (E e : c)
+            add(e);
     }
 
     /**
--- a/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Thu Nov 12 23:04:42 2009 +0000
@@ -250,8 +250,8 @@
      *         of its elements are null
      */
     public ConcurrentLinkedQueue(Collection<? extends E> c) {
-        for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
-            add(it.next());
+        for (E e : c)
+            add(e);
     }
 
     // Have to override just to update the javadoc
--- a/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu Nov 12 23:04:42 2009 +0000
@@ -895,7 +895,7 @@
                 if (n != null) {
                     Node<K,V> f = n.next;
                     if (n != b.next)               // inconsistent read
-                        break;;
+                        break;
                     Object v = n.value;
                     if (v == null) {               // n is deleted
                         n.helpDelete(b, f);
--- a/src/share/classes/java/util/concurrent/CountDownLatch.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/concurrent/CountDownLatch.java	Thu Nov 12 23:04:42 2009 +0000
@@ -148,7 +148,8 @@
  *
  * </pre>
  *
- * <p>Memory consistency effects: Actions in a thread prior to calling
+ * <p>Memory consistency effects: Until the count reaches
+ * zero, actions in a thread prior to calling
  * {@code countDown()}
  * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
  * actions following a successful return from a corresponding
--- a/src/share/classes/java/util/concurrent/ExecutorService.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/concurrent/ExecutorService.java	Thu Nov 12 23:04:42 2009 +0000
@@ -332,8 +332,8 @@
      * @param tasks the collection of tasks
      * @return the result returned by one of the tasks
      * @throws InterruptedException if interrupted while waiting
-     * @throws NullPointerException if tasks or any of its elements
-     *         are <tt>null</tt>
+     * @throws NullPointerException if tasks or any element task
+     *         subject to execution is <tt>null</tt>
      * @throws IllegalArgumentException if tasks is empty
      * @throws ExecutionException if no task successfully completes
      * @throws RejectedExecutionException if tasks cannot be scheduled
@@ -356,8 +356,8 @@
      * @param unit the time unit of the timeout argument
      * @return the result returned by one of the tasks.
      * @throws InterruptedException if interrupted while waiting
-     * @throws NullPointerException if tasks, any of its elements, or
-     *         unit are <tt>null</tt>
+     * @throws NullPointerException if tasks, or unit, or any element
+     *         task subject to execution is <tt>null</tt>
      * @throws TimeoutException if the given timeout elapses before
      *         any task successfully completes
      * @throws ExecutionException if no task successfully completes
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,1988 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * An {@link ExecutorService} for running {@link ForkJoinTask}s.
+ * A {@code ForkJoinPool} provides the entry point for submissions
+ * from non-{@code ForkJoinTask}s, as well as management and
+ * monitoring operations.
+ *
+ * <p>A {@code ForkJoinPool} differs from other kinds of {@link
+ * ExecutorService} mainly by virtue of employing
+ * <em>work-stealing</em>: all threads in the pool attempt to find and
+ * execute subtasks created by other active tasks (eventually blocking
+ * waiting for work if none exist). This enables efficient processing
+ * when most tasks spawn other subtasks (as do most {@code
+ * ForkJoinTask}s). A {@code ForkJoinPool} may also be used for mixed
+ * execution of some plain {@code Runnable}- or {@code Callable}-
+ * based activities along with {@code ForkJoinTask}s. When setting
+ * {@linkplain #setAsyncMode async mode}, a {@code ForkJoinPool} may
+ * also be appropriate for use with fine-grained tasks of any form
+ * that are never joined. Otherwise, other {@code ExecutorService}
+ * implementations are typically more appropriate choices.
+ *
+ * <p>A {@code ForkJoinPool} is constructed with a given target
+ * parallelism level; by default, equal to the number of available
+ * processors. Unless configured otherwise via {@link
+ * #setMaintainsParallelism}, the pool attempts to maintain this
+ * number of active (or available) threads by dynamically adding,
+ * suspending, or resuming internal worker threads, even if some tasks
+ * are stalled waiting to join others. However, no such adjustments
+ * are performed in the face of blocked IO or other unmanaged
+ * synchronization. The nested {@link ManagedBlocker} interface
+ * enables extension of the kinds of synchronization accommodated.
+ * The target parallelism level may also be changed dynamically
+ * ({@link #setParallelism}). The total number of threads may be
+ * limited using method {@link #setMaximumPoolSize}, in which case it
+ * may become possible for the activities of a pool to stall due to
+ * the lack of available threads to process new tasks.
+ *
+ * <p>In addition to execution and lifecycle control methods, this
+ * class provides status check methods (for example
+ * {@link #getStealCount}) that are intended to aid in developing,
+ * tuning, and monitoring fork/join applications. Also, method
+ * {@link #toString} returns indications of pool state in a
+ * convenient form for informal monitoring.
+ *
+ * <p><b>Sample Usage.</b> Normally a single {@code ForkJoinPool} is
+ * used for all parallel task execution in a program or subsystem.
+ * Otherwise, use would not usually outweigh the construction and
+ * bookkeeping overhead of creating a large set of threads. For
+ * example, a common pool could be used for the {@code SortTasks}
+ * illustrated in {@link RecursiveAction}. Because {@code
+ * ForkJoinPool} uses threads in {@linkplain java.lang.Thread#isDaemon
+ * daemon} mode, there is typically no need to explicitly {@link
+ * #shutdown} such a pool upon program exit.
+ *
+ * <pre>
+ * static final ForkJoinPool mainPool = new ForkJoinPool();
+ * ...
+ * public void sort(long[] array) {
+ *   mainPool.invoke(new SortTask(array, 0, array.length));
+ * }
+ * </pre>
+ *
+ * <p><b>Implementation notes</b>: This implementation restricts the
+ * maximum number of running threads to 32767. Attempts to create
+ * pools with greater than the maximum number result in
+ * {@code IllegalArgumentException}.
+ *
+ * <p>This implementation rejects submitted tasks (that is, by throwing
+ * {@link RejectedExecutionException}) only when the pool is shut down.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public class ForkJoinPool extends AbstractExecutorService {
+
+    /*
+     * See the extended comments interspersed below for design,
+     * rationale, and walkthroughs.
+     */
+
+    /** Mask for packing and unpacking shorts */
+    private static final int  shortMask = 0xffff;
+
+    /** Max pool size -- must be a power of two minus 1 */
+    private static final int MAX_THREADS =  0x7FFF;
+
+    /**
+     * Factory for creating new {@link ForkJoinWorkerThread}s.
+     * A {@code ForkJoinWorkerThreadFactory} must be defined and used
+     * for {@code ForkJoinWorkerThread} subclasses that extend base
+     * functionality or initialize threads with different contexts.
+     */
+    public static interface ForkJoinWorkerThreadFactory {
+        /**
+         * Returns a new worker thread operating in the given pool.
+         *
+         * @param pool the pool this thread works in
+         * @throws NullPointerException if the pool is null
+         */
+        public ForkJoinWorkerThread newThread(ForkJoinPool pool);
+    }
+
+    /**
+     * Default ForkJoinWorkerThreadFactory implementation; creates a
+     * new ForkJoinWorkerThread.
+     */
+    static class  DefaultForkJoinWorkerThreadFactory
+        implements ForkJoinWorkerThreadFactory {
+        public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
+            try {
+                return new ForkJoinWorkerThread(pool);
+            } catch (OutOfMemoryError oom)  {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Creates a new ForkJoinWorkerThread. This factory is used unless
+     * overridden in ForkJoinPool constructors.
+     */
+    public static final ForkJoinWorkerThreadFactory
+        defaultForkJoinWorkerThreadFactory =
+        new DefaultForkJoinWorkerThreadFactory();
+
+    /**
+     * Permission required for callers of methods that may start or
+     * kill threads.
+     */
+    private static final RuntimePermission modifyThreadPermission =
+        new RuntimePermission("modifyThread");
+
+    /**
+     * If there is a security manager, makes sure caller has
+     * permission to modify threads.
+     */
+    private static void checkPermission() {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null)
+            security.checkPermission(modifyThreadPermission);
+    }
+
+    /**
+     * Generator for assigning sequence numbers as pool names.
+     */
+    private static final AtomicInteger poolNumberGenerator =
+        new AtomicInteger();
+
+    /**
+     * Array holding all worker threads in the pool. Initialized upon
+     * first use. Array size must be a power of two.  Updates and
+     * replacements are protected by workerLock, but it is always kept
+     * in a consistent enough state to be randomly accessed without
+     * locking by workers performing work-stealing.
+     */
+    volatile ForkJoinWorkerThread[] workers;
+
+    /**
+     * Lock protecting access to workers.
+     */
+    private final ReentrantLock workerLock;
+
+    /**
+     * Condition for awaitTermination.
+     */
+    private final Condition termination;
+
+    /**
+     * The uncaught exception handler used when any worker
+     * abruptly terminates
+     */
+    private Thread.UncaughtExceptionHandler ueh;
+
+    /**
+     * Creation factory for worker threads.
+     */
+    private final ForkJoinWorkerThreadFactory factory;
+
+    /**
+     * Head of stack of threads that were created to maintain
+     * parallelism when other threads blocked, but have since
+     * suspended when the parallelism level rose.
+     */
+    private volatile WaitQueueNode spareStack;
+
+    /**
+     * Sum of per-thread steal counts, updated only when threads are
+     * idle or terminating.
+     */
+    private final AtomicLong stealCount;
+
+    /**
+     * Queue for external submissions.
+     */
+    private final LinkedTransferQueue<ForkJoinTask<?>> submissionQueue;
+
+    /**
+     * Head of Treiber stack for barrier sync. See below for explanation.
+     */
+    private volatile WaitQueueNode syncStack;
+
+    /**
+     * The count for event barrier
+     */
+    private volatile long eventCount;
+
+    /**
+     * Pool number, just for assigning useful names to worker threads
+     */
+    private final int poolNumber;
+
+    /**
+     * The maximum allowed pool size
+     */
+    private volatile int maxPoolSize;
+
+    /**
+     * The desired parallelism level, updated only under workerLock.
+     */
+    private volatile int parallelism;
+
+    /**
+     * True if use local fifo, not default lifo, for local polling
+     */
+    private volatile boolean locallyFifo;
+
+    /**
+     * Holds number of total (i.e., created and not yet terminated)
+     * and running (i.e., not blocked on joins or other managed sync)
+     * threads, packed into one int to ensure consistent snapshot when
+     * making decisions about creating and suspending spare
+     * threads. Updated only by CAS.  Note: CASes in
+     * updateRunningCount and preJoin assume that running active count
+     * is in low word, so need to be modified if this changes.
+     */
+    private volatile int workerCounts;
+
+    private static int totalCountOf(int s)           { return s >>> 16;  }
+    private static int runningCountOf(int s)         { return s & shortMask; }
+    private static int workerCountsFor(int t, int r) { return (t << 16) + r; }
+
+    /**
+     * Adds delta (which may be negative) to running count.  This must
+     * be called before (with negative arg) and after (with positive)
+     * any managed synchronization (i.e., mainly, joins).
+     *
+     * @param delta the number to add
+     */
+    final void updateRunningCount(int delta) {
+        int s;
+        do {} while (!casWorkerCounts(s = workerCounts, s + delta));
+    }
+
+    /**
+     * Adds delta (which may be negative) to both total and running
+     * count.  This must be called upon creation and termination of
+     * worker threads.
+     *
+     * @param delta the number to add
+     */
+    private void updateWorkerCount(int delta) {
+        int d = delta + (delta << 16); // add to both lo and hi parts
+        int s;
+        do {} while (!casWorkerCounts(s = workerCounts, s + d));
+    }
+
+    /**
+     * Lifecycle control. High word contains runState, low word
+     * contains the number of workers that are (probably) executing
+     * tasks. This value is atomically incremented before a worker
+     * gets a task to run, and decremented when worker has no tasks
+     * and cannot find any. These two fields are bundled together to
+     * support correct termination triggering.  Note: activeCount
+     * CAS'es cheat by assuming active count is in low word, so need
+     * to be modified if this changes
+     */
+    private volatile int runControl;
+
+    // RunState values. Order among values matters
+    private static final int RUNNING     = 0;
+    private static final int SHUTDOWN    = 1;
+    private static final int TERMINATING = 2;
+    private static final int TERMINATED  = 3;
+
+    private static int runStateOf(int c)             { return c >>> 16; }
+    private static int activeCountOf(int c)          { return c & shortMask; }
+    private static int runControlFor(int r, int a)   { return (r << 16) + a; }
+
+    /**
+     * Tries incrementing active count; fails on contention.
+     * Called by workers before/during executing tasks.
+     *
+     * @return true on success
+     */
+    final boolean tryIncrementActiveCount() {
+        int c = runControl;
+        return casRunControl(c, c+1);
+    }
+
+    /**
+     * Tries decrementing active count; fails on contention.
+     * Possibly triggers termination on success.
+     * Called by workers when they can't find tasks.
+     *
+     * @return true on success
+     */
+    final boolean tryDecrementActiveCount() {
+        int c = runControl;
+        int nextc = c - 1;
+        if (!casRunControl(c, nextc))
+            return false;
+        if (canTerminateOnShutdown(nextc))
+            terminateOnShutdown();
+        return true;
+    }
+
+    /**
+     * Returns {@code true} if argument represents zero active count
+     * and nonzero runstate, which is the triggering condition for
+     * terminating on shutdown.
+     */
+    private static boolean canTerminateOnShutdown(int c) {
+        // i.e. least bit is nonzero runState bit
+        return ((c & -c) >>> 16) != 0;
+    }
+
+    /**
+     * Transition run state to at least the given state. Return true
+     * if not already at least given state.
+     */
+    private boolean transitionRunStateTo(int state) {
+        for (;;) {
+            int c = runControl;
+            if (runStateOf(c) >= state)
+                return false;
+            if (casRunControl(c, runControlFor(state, activeCountOf(c))))
+                return true;
+        }
+    }
+
+    /**
+     * Controls whether to add spares to maintain parallelism
+     */
+    private volatile boolean maintainsParallelism;
+
+    // Constructors
+
+    /**
+     * Creates a {@code ForkJoinPool} with parallelism equal to {@link
+     * java.lang.Runtime#availableProcessors}, and using the {@linkplain
+     * #defaultForkJoinWorkerThreadFactory default thread factory}.
+     *
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public ForkJoinPool() {
+        this(Runtime.getRuntime().availableProcessors(),
+             defaultForkJoinWorkerThreadFactory);
+    }
+
+    /**
+     * Creates a {@code ForkJoinPool} with the indicated parallelism
+     * level and using the {@linkplain
+     * #defaultForkJoinWorkerThreadFactory default thread factory}.
+     *
+     * @param parallelism the parallelism level
+     * @throws IllegalArgumentException if parallelism less than or
+     *         equal to zero, or greater than implementation limit
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public ForkJoinPool(int parallelism) {
+        this(parallelism, defaultForkJoinWorkerThreadFactory);
+    }
+
+    /**
+     * Creates a {@code ForkJoinPool} with parallelism equal to {@link
+     * java.lang.Runtime#availableProcessors}, and using the given
+     * thread factory.
+     *
+     * @param factory the factory for creating new threads
+     * @throws NullPointerException if the factory is null
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public ForkJoinPool(ForkJoinWorkerThreadFactory factory) {
+        this(Runtime.getRuntime().availableProcessors(), factory);
+    }
+
+    /**
+     * Creates a {@code ForkJoinPool} with the given parallelism and
+     * thread factory.
+     *
+     * @param parallelism the parallelism level
+     * @param factory the factory for creating new threads
+     * @throws IllegalArgumentException if parallelism less than or
+     *         equal to zero, or greater than implementation limit
+     * @throws NullPointerException if the factory is null
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory) {
+        if (parallelism <= 0 || parallelism > MAX_THREADS)
+            throw new IllegalArgumentException();
+        if (factory == null)
+            throw new NullPointerException();
+        checkPermission();
+        this.factory = factory;
+        this.parallelism = parallelism;
+        this.maxPoolSize = MAX_THREADS;
+        this.maintainsParallelism = true;
+        this.poolNumber = poolNumberGenerator.incrementAndGet();
+        this.workerLock = new ReentrantLock();
+        this.termination = workerLock.newCondition();
+        this.stealCount = new AtomicLong();
+        this.submissionQueue = new LinkedTransferQueue<ForkJoinTask<?>>();
+        // worker array and workers are lazily constructed
+    }
+
+    /**
+     * Creates a new worker thread using factory.
+     *
+     * @param index the index to assign worker
+     * @return new worker, or null if factory failed
+     */
+    private ForkJoinWorkerThread createWorker(int index) {
+        Thread.UncaughtExceptionHandler h = ueh;
+        ForkJoinWorkerThread w = factory.newThread(this);
+        if (w != null) {
+            w.poolIndex = index;
+            w.setDaemon(true);
+            w.setAsyncMode(locallyFifo);
+            w.setName("ForkJoinPool-" + poolNumber + "-worker-" + index);
+            if (h != null)
+                w.setUncaughtExceptionHandler(h);
+        }
+        return w;
+    }
+
+    /**
+     * Returns a good size for worker array given pool size.
+     * Currently requires size to be a power of two.
+     */
+    private static int arraySizeFor(int poolSize) {
+        if (poolSize <= 1)
+            return 1;
+        // See Hackers Delight, sec 3.2
+        int c = poolSize >= MAX_THREADS ? MAX_THREADS : (poolSize - 1);
+        c |= c >>>  1;
+        c |= c >>>  2;
+        c |= c >>>  4;
+        c |= c >>>  8;
+        c |= c >>> 16;
+        return c + 1;
+    }
+
+    /**
+     * Creates or resizes array if necessary to hold newLength.
+     * Call only under exclusion.
+     *
+     * @return the array
+     */
+    private ForkJoinWorkerThread[] ensureWorkerArrayCapacity(int newLength) {
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws == null)
+            return workers = new ForkJoinWorkerThread[arraySizeFor(newLength)];
+        else if (newLength > ws.length)
+            return workers = Arrays.copyOf(ws, arraySizeFor(newLength));
+        else
+            return ws;
+    }
+
+    /**
+     * Tries to shrink workers into smaller array after one or more terminate.
+     */
+    private void tryShrinkWorkerArray() {
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws != null) {
+            int len = ws.length;
+            int last = len - 1;
+            while (last >= 0 && ws[last] == null)
+                --last;
+            int newLength = arraySizeFor(last+1);
+            if (newLength < len)
+                workers = Arrays.copyOf(ws, newLength);
+        }
+    }
+
+    /**
+     * Initializes workers if necessary.
+     */
+    final void ensureWorkerInitialization() {
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws == null) {
+            final ReentrantLock lock = this.workerLock;
+            lock.lock();
+            try {
+                ws = workers;
+                if (ws == null) {
+                    int ps = parallelism;
+                    ws = ensureWorkerArrayCapacity(ps);
+                    for (int i = 0; i < ps; ++i) {
+                        ForkJoinWorkerThread w = createWorker(i);
+                        if (w != null) {
+                            ws[i] = w;
+                            w.start();
+                            updateWorkerCount(1);
+                        }
+                    }
+                }
+            } finally {
+                lock.unlock();
+            }
+        }
+    }
+
+    /**
+     * Worker creation and startup for threads added via setParallelism.
+     */
+    private void createAndStartAddedWorkers() {
+        resumeAllSpares();  // Allow spares to convert to nonspare
+        int ps = parallelism;
+        ForkJoinWorkerThread[] ws = ensureWorkerArrayCapacity(ps);
+        int len = ws.length;
+        // Sweep through slots, to keep lowest indices most populated
+        int k = 0;
+        while (k < len) {
+            if (ws[k] != null) {
+                ++k;
+                continue;
+            }
+            int s = workerCounts;
+            int tc = totalCountOf(s);
+            int rc = runningCountOf(s);
+            if (rc >= ps || tc >= ps)
+                break;
+            if (casWorkerCounts (s, workerCountsFor(tc+1, rc+1))) {
+                ForkJoinWorkerThread w = createWorker(k);
+                if (w != null) {
+                    ws[k++] = w;
+                    w.start();
+                }
+                else {
+                    updateWorkerCount(-1); // back out on failed creation
+                    break;
+                }
+            }
+        }
+    }
+
+    // Execution methods
+
+    /**
+     * Common code for execute, invoke and submit
+     */
+    private <T> void doSubmit(ForkJoinTask<T> task) {
+        if (task == null)
+            throw new NullPointerException();
+        if (isShutdown())
+            throw new RejectedExecutionException();
+        if (workers == null)
+            ensureWorkerInitialization();
+        submissionQueue.offer(task);
+        signalIdleWorkers();
+    }
+
+    /**
+     * Performs the given task, returning its result upon completion.
+     *
+     * @param task the task
+     * @return the task's result
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public <T> T invoke(ForkJoinTask<T> task) {
+        doSubmit(task);
+        return task.join();
+    }
+
+    /**
+     * Arranges for (asynchronous) execution of the given task.
+     *
+     * @param task the task
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public void execute(ForkJoinTask<?> task) {
+        doSubmit(task);
+    }
+
+    // AbstractExecutorService methods
+
+    /**
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public void execute(Runnable task) {
+        ForkJoinTask<?> job;
+        if (task instanceof ForkJoinTask<?>) // avoid re-wrap
+            job = (ForkJoinTask<?>) task;
+        else
+            job = ForkJoinTask.adapt(task, null);
+        doSubmit(job);
+    }
+
+    /**
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public <T> ForkJoinTask<T> submit(Callable<T> task) {
+        ForkJoinTask<T> job = ForkJoinTask.adapt(task);
+        doSubmit(job);
+        return job;
+    }
+
+    /**
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public <T> ForkJoinTask<T> submit(Runnable task, T result) {
+        ForkJoinTask<T> job = ForkJoinTask.adapt(task, result);
+        doSubmit(job);
+        return job;
+    }
+
+    /**
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public ForkJoinTask<?> submit(Runnable task) {
+        ForkJoinTask<?> job;
+        if (task instanceof ForkJoinTask<?>) // avoid re-wrap
+            job = (ForkJoinTask<?>) task;
+        else
+            job = ForkJoinTask.adapt(task, null);
+        doSubmit(job);
+        return job;
+    }
+
+    /**
+     * Submits a ForkJoinTask for execution.
+     *
+     * @param task the task to submit
+     * @return the task
+     * @throws NullPointerException if the task is null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     */
+    public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
+        doSubmit(task);
+        return task;
+    }
+
+
+    /**
+     * @throws NullPointerException       {@inheritDoc}
+     * @throws RejectedExecutionException {@inheritDoc}
+     */
+    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
+        ArrayList<ForkJoinTask<T>> forkJoinTasks =
+            new ArrayList<ForkJoinTask<T>>(tasks.size());
+        for (Callable<T> task : tasks)
+            forkJoinTasks.add(ForkJoinTask.adapt(task));
+        invoke(new InvokeAll<T>(forkJoinTasks));
+
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        List<Future<T>> futures = (List<Future<T>>) (List) forkJoinTasks;
+        return futures;
+    }
+
+    static final class InvokeAll<T> extends RecursiveAction {
+        final ArrayList<ForkJoinTask<T>> tasks;
+        InvokeAll(ArrayList<ForkJoinTask<T>> tasks) { this.tasks = tasks; }
+        public void compute() {
+            try { invokeAll(tasks); }
+            catch (Exception ignore) {}
+        }
+        private static final long serialVersionUID = -7914297376763021607L;
+    }
+
+    // Configuration and status settings and queries
+
+    /**
+     * Returns the factory used for constructing new workers.
+     *
+     * @return the factory used for constructing new workers
+     */
+    public ForkJoinWorkerThreadFactory getFactory() {
+        return factory;
+    }
+
+    /**
+     * Returns the handler for internal worker threads that terminate
+     * due to unrecoverable errors encountered while executing tasks.
+     *
+     * @return the handler, or {@code null} if none
+     */
+    public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
+        Thread.UncaughtExceptionHandler h;
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            h = ueh;
+        } finally {
+            lock.unlock();
+        }
+        return h;
+    }
+
+    /**
+     * Sets the handler for internal worker threads that terminate due
+     * to unrecoverable errors encountered while executing tasks.
+     * Unless set, the current default or ThreadGroup handler is used
+     * as handler.
+     *
+     * @param h the new handler
+     * @return the old handler, or {@code null} if none
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public Thread.UncaughtExceptionHandler
+        setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler h) {
+        checkPermission();
+        Thread.UncaughtExceptionHandler old = null;
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            old = ueh;
+            ueh = h;
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                for (int i = 0; i < ws.length; ++i) {
+                    ForkJoinWorkerThread w = ws[i];
+                    if (w != null)
+                        w.setUncaughtExceptionHandler(h);
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+        return old;
+    }
+
+
+    /**
+     * Sets the target parallelism level of this pool.
+     *
+     * @param parallelism the target parallelism
+     * @throws IllegalArgumentException if parallelism less than or
+     * equal to zero or greater than maximum size bounds
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public void setParallelism(int parallelism) {
+        checkPermission();
+        if (parallelism <= 0 || parallelism > maxPoolSize)
+            throw new IllegalArgumentException();
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            if (isProcessingTasks()) {
+                int p = this.parallelism;
+                this.parallelism = parallelism;
+                if (parallelism > p)
+                    createAndStartAddedWorkers();
+                else
+                    trimSpares();
+            }
+        } finally {
+            lock.unlock();
+        }
+        signalIdleWorkers();
+    }
+
+    /**
+     * Returns the targeted parallelism level of this pool.
+     *
+     * @return the targeted parallelism level of this pool
+     */
+    public int getParallelism() {
+        return parallelism;
+    }
+
+    /**
+     * Returns the number of worker threads that have started but not
+     * yet terminated.  This result returned by this method may differ
+     * from {@link #getParallelism} when threads are created to
+     * maintain parallelism when others are cooperatively blocked.
+     *
+     * @return the number of worker threads
+     */
+    public int getPoolSize() {
+        return totalCountOf(workerCounts);
+    }
+
+    /**
+     * Returns the maximum number of threads allowed to exist in the
+     * pool. Unless set using {@link #setMaximumPoolSize}, the
+     * maximum is an implementation-defined value designed only to
+     * prevent runaway growth.
+     *
+     * @return the maximum
+     */
+    public int getMaximumPoolSize() {
+        return maxPoolSize;
+    }
+
+    /**
+     * Sets the maximum number of threads allowed to exist in the
+     * pool. The given value should normally be greater than or equal
+     * to the {@link #getParallelism parallelism} level. Setting this
+     * value has no effect on current pool size. It controls
+     * construction of new threads.
+     *
+     * @throws IllegalArgumentException if negative or greater than
+     * internal implementation limit
+     */
+    public void setMaximumPoolSize(int newMax) {
+        if (newMax < 0 || newMax > MAX_THREADS)
+            throw new IllegalArgumentException();
+        maxPoolSize = newMax;
+    }
+
+
+    /**
+     * Returns {@code true} if this pool dynamically maintains its
+     * target parallelism level. If false, new threads are added only
+     * to avoid possible starvation.  This setting is by default true.
+     *
+     * @return {@code true} if maintains parallelism
+     */
+    public boolean getMaintainsParallelism() {
+        return maintainsParallelism;
+    }
+
+    /**
+     * Sets whether this pool dynamically maintains its target
+     * parallelism level. If false, new threads are added only to
+     * avoid possible starvation.
+     *
+     * @param enable {@code true} to maintain parallelism
+     */
+    public void setMaintainsParallelism(boolean enable) {
+        maintainsParallelism = enable;
+    }
+
+    /**
+     * Establishes local first-in-first-out scheduling mode for forked
+     * tasks that are never joined. This mode may be more appropriate
+     * than default locally stack-based mode in applications in which
+     * worker threads only process asynchronous tasks.  This method is
+     * designed to be invoked only when the pool is quiescent, and
+     * typically only before any tasks are submitted. The effects of
+     * invocations at other times may be unpredictable.
+     *
+     * @param async if {@code true}, use locally FIFO scheduling
+     * @return the previous mode
+     * @see #getAsyncMode
+     */
+    public boolean setAsyncMode(boolean async) {
+        boolean oldMode = locallyFifo;
+        locallyFifo = async;
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws != null) {
+            for (int i = 0; i < ws.length; ++i) {
+                ForkJoinWorkerThread t = ws[i];
+                if (t != null)
+                    t.setAsyncMode(async);
+            }
+        }
+        return oldMode;
+    }
+
+    /**
+     * Returns {@code true} if this pool uses local first-in-first-out
+     * scheduling mode for forked tasks that are never joined.
+     *
+     * @return {@code true} if this pool uses async mode
+     * @see #setAsyncMode
+     */
+    public boolean getAsyncMode() {
+        return locallyFifo;
+    }
+
+    /**
+     * Returns an estimate of the number of worker threads that are
+     * not blocked waiting to join tasks or for other managed
+     * synchronization.
+     *
+     * @return the number of worker threads
+     */
+    public int getRunningThreadCount() {
+        return runningCountOf(workerCounts);
+    }
+
+    /**
+     * Returns an estimate of the number of threads that are currently
+     * stealing or executing tasks. This method may overestimate the
+     * number of active threads.
+     *
+     * @return the number of active threads
+     */
+    public int getActiveThreadCount() {
+        return activeCountOf(runControl);
+    }
+
+    /**
+     * Returns an estimate of the number of threads that are currently
+     * idle waiting for tasks. This method may underestimate the
+     * number of idle threads.
+     *
+     * @return the number of idle threads
+     */
+    final int getIdleThreadCount() {
+        int c = runningCountOf(workerCounts) - activeCountOf(runControl);
+        return (c <= 0) ? 0 : c;
+    }
+
+    /**
+     * Returns {@code true} if all worker threads are currently idle.
+     * An idle worker is one that cannot obtain a task to execute
+     * because none are available to steal from other threads, and
+     * there are no pending submissions to the pool. This method is
+     * conservative; it might not return {@code true} immediately upon
+     * idleness of all threads, but will eventually become true if
+     * threads remain inactive.
+     *
+     * @return {@code true} if all threads are currently idle
+     */
+    public boolean isQuiescent() {
+        return activeCountOf(runControl) == 0;
+    }
+
+    /**
+     * Returns an estimate of the total number of tasks stolen from
+     * one thread's work queue by another. The reported value
+     * underestimates the actual total number of steals when the pool
+     * is not quiescent. This value may be useful for monitoring and
+     * tuning fork/join programs: in general, steal counts should be
+     * high enough to keep threads busy, but low enough to avoid
+     * overhead and contention across threads.
+     *
+     * @return the number of steals
+     */
+    public long getStealCount() {
+        return stealCount.get();
+    }
+
+    /**
+     * Accumulates steal count from a worker.
+     * Call only when worker known to be idle.
+     */
+    private void updateStealCount(ForkJoinWorkerThread w) {
+        int sc = w.getAndClearStealCount();
+        if (sc != 0)
+            stealCount.addAndGet(sc);
+    }
+
+    /**
+     * Returns an estimate of the total number of tasks currently held
+     * in queues by worker threads (but not including tasks submitted
+     * to the pool that have not begun executing). This value is only
+     * an approximation, obtained by iterating across all threads in
+     * the pool. This method may be useful for tuning task
+     * granularities.
+     *
+     * @return the number of queued tasks
+     */
+    public long getQueuedTaskCount() {
+        long count = 0;
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws != null) {
+            for (int i = 0; i < ws.length; ++i) {
+                ForkJoinWorkerThread t = ws[i];
+                if (t != null)
+                    count += t.getQueueSize();
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Returns an estimate of the number of tasks submitted to this
+     * pool that have not yet begun executing.  This method takes time
+     * proportional to the number of submissions.
+     *
+     * @return the number of queued submissions
+     */
+    public int getQueuedSubmissionCount() {
+        return submissionQueue.size();
+    }
+
+    /**
+     * Returns {@code true} if there are any tasks submitted to this
+     * pool that have not yet begun executing.
+     *
+     * @return {@code true} if there are any queued submissions
+     */
+    public boolean hasQueuedSubmissions() {
+        return !submissionQueue.isEmpty();
+    }
+
+    /**
+     * Removes and returns the next unexecuted submission if one is
+     * available.  This method may be useful in extensions to this
+     * class that re-assign work in systems with multiple pools.
+     *
+     * @return the next submission, or {@code null} if none
+     */
+    protected ForkJoinTask<?> pollSubmission() {
+        return submissionQueue.poll();
+    }
+
+    /**
+     * Removes all available unexecuted submitted and forked tasks
+     * from scheduling queues and adds them to the given collection,
+     * without altering their execution status. These may include
+     * artificially generated or wrapped tasks. This method is
+     * designed to be invoked only when the pool is known to be
+     * quiescent. Invocations at other times may not remove all
+     * tasks. A failure encountered while attempting to add elements
+     * to collection {@code c} may result in elements being in
+     * neither, either or both collections when the associated
+     * exception is thrown.  The behavior of this operation is
+     * undefined if the specified collection is modified while the
+     * operation is in progress.
+     *
+     * @param c the collection to transfer elements into
+     * @return the number of elements transferred
+     */
+    protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
+        int n = submissionQueue.drainTo(c);
+        ForkJoinWorkerThread[] ws = workers;
+        if (ws != null) {
+            for (int i = 0; i < ws.length; ++i) {
+                ForkJoinWorkerThread w = ws[i];
+                if (w != null)
+                    n += w.drainTasksTo(c);
+            }
+        }
+        return n;
+    }
+
+    /**
+     * Returns a string identifying this pool, as well as its state,
+     * including indications of run state, parallelism level, and
+     * worker and task counts.
+     *
+     * @return a string identifying this pool, as well as its state
+     */
+    public String toString() {
+        int ps = parallelism;
+        int wc = workerCounts;
+        int rc = runControl;
+        long st = getStealCount();
+        long qt = getQueuedTaskCount();
+        long qs = getQueuedSubmissionCount();
+        return super.toString() +
+            "[" + runStateToString(runStateOf(rc)) +
+            ", parallelism = " + ps +
+            ", size = " + totalCountOf(wc) +
+            ", active = " + activeCountOf(rc) +
+            ", running = " + runningCountOf(wc) +
+            ", steals = " + st +
+            ", tasks = " + qt +
+            ", submissions = " + qs +
+            "]";
+    }
+
+    private static String runStateToString(int rs) {
+        switch(rs) {
+        case RUNNING: return "Running";
+        case SHUTDOWN: return "Shutting down";
+        case TERMINATING: return "Terminating";
+        case TERMINATED: return "Terminated";
+        default: throw new Error("Unknown run state");
+        }
+    }
+
+    // lifecycle control
+
+    /**
+     * Initiates an orderly shutdown in which previously submitted
+     * tasks are executed, but no new tasks will be accepted.
+     * Invocation has no additional effect if already shut down.
+     * Tasks that are in the process of being submitted concurrently
+     * during the course of this method may or may not be rejected.
+     *
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public void shutdown() {
+        checkPermission();
+        transitionRunStateTo(SHUTDOWN);
+        if (canTerminateOnShutdown(runControl)) {
+            if (workers == null) { // shutting down before workers created
+                final ReentrantLock lock = this.workerLock;
+                lock.lock();
+                try {
+                    if (workers == null) {
+                        terminate();
+                        transitionRunStateTo(TERMINATED);
+                        termination.signalAll();
+                    }
+                } finally {
+                    lock.unlock();
+                }
+            }
+            terminateOnShutdown();
+        }
+    }
+
+    /**
+     * Attempts to cancel and/or stop all tasks, and reject all
+     * subsequently submitted tasks.  Tasks that are in the process of
+     * being submitted or executed concurrently during the course of
+     * this method may or may not be rejected. This method cancels
+     * both existing and unexecuted tasks, in order to permit
+     * termination in the presence of task dependencies. So the method
+     * always returns an empty list (unlike the case for some other
+     * Executors).
+     *
+     * @return an empty list
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     */
+    public List<Runnable> shutdownNow() {
+        checkPermission();
+        terminate();
+        return Collections.emptyList();
+    }
+
+    /**
+     * Returns {@code true} if all tasks have completed following shut down.
+     *
+     * @return {@code true} if all tasks have completed following shut down
+     */
+    public boolean isTerminated() {
+        return runStateOf(runControl) == TERMINATED;
+    }
+
+    /**
+     * Returns {@code true} if the process of termination has
+     * commenced but not yet completed.  This method may be useful for
+     * debugging. A return of {@code true} reported a sufficient
+     * period after shutdown may indicate that submitted tasks have
+     * ignored or suppressed interruption, causing this executor not
+     * to properly terminate.
+     *
+     * @return {@code true} if terminating but not yet terminated
+     */
+    public boolean isTerminating() {
+        return runStateOf(runControl) == TERMINATING;
+    }
+
+    /**
+     * Returns {@code true} if this pool has been shut down.
+     *
+     * @return {@code true} if this pool has been shut down
+     */
+    public boolean isShutdown() {
+        return runStateOf(runControl) >= SHUTDOWN;
+    }
+
+    /**
+     * Returns true if pool is not terminating or terminated.
+     * Used internally to suppress execution when terminating.
+     */
+    final boolean isProcessingTasks() {
+        return runStateOf(runControl) < TERMINATING;
+    }
+
+    /**
+     * Blocks until all tasks have completed execution after a shutdown
+     * request, or the timeout occurs, or the current thread is
+     * interrupted, whichever happens first.
+     *
+     * @param timeout the maximum time to wait
+     * @param unit the time unit of the timeout argument
+     * @return {@code true} if this executor terminated and
+     *         {@code false} if the timeout elapsed before termination
+     * @throws InterruptedException if interrupted while waiting
+     */
+    public boolean awaitTermination(long timeout, TimeUnit unit)
+        throws InterruptedException {
+        long nanos = unit.toNanos(timeout);
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            for (;;) {
+                if (isTerminated())
+                    return true;
+                if (nanos <= 0)
+                    return false;
+                nanos = termination.awaitNanos(nanos);
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    // Shutdown and termination support
+
+    /**
+     * Callback from terminating worker. Nulls out the corresponding
+     * workers slot, and if terminating, tries to terminate; else
+     * tries to shrink workers array.
+     *
+     * @param w the worker
+     */
+    final void workerTerminated(ForkJoinWorkerThread w) {
+        updateStealCount(w);
+        updateWorkerCount(-1);
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                int idx = w.poolIndex;
+                if (idx >= 0 && idx < ws.length && ws[idx] == w)
+                    ws[idx] = null;
+                if (totalCountOf(workerCounts) == 0) {
+                    terminate(); // no-op if already terminating
+                    transitionRunStateTo(TERMINATED);
+                    termination.signalAll();
+                }
+                else if (isProcessingTasks()) {
+                    tryShrinkWorkerArray();
+                    tryResumeSpare(true); // allow replacement
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+        signalIdleWorkers();
+    }
+
+    /**
+     * Initiates termination.
+     */
+    private void terminate() {
+        if (transitionRunStateTo(TERMINATING)) {
+            stopAllWorkers();
+            resumeAllSpares();
+            signalIdleWorkers();
+            cancelQueuedSubmissions();
+            cancelQueuedWorkerTasks();
+            interruptUnterminatedWorkers();
+            signalIdleWorkers(); // resignal after interrupt
+        }
+    }
+
+    /**
+     * Possibly terminates when on shutdown state.
+     */
+    private void terminateOnShutdown() {
+        if (!hasQueuedSubmissions() && canTerminateOnShutdown(runControl))
+            terminate();
+    }
+
+    /**
+     * Clears out and cancels submissions.
+     */
+    private void cancelQueuedSubmissions() {
+        ForkJoinTask<?> task;
+        while ((task = pollSubmission()) != null)
+            task.cancel(false);
+    }
+
+    /**
+     * Cleans out worker queues.
+     */
+    private void cancelQueuedWorkerTasks() {
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                for (int i = 0; i < ws.length; ++i) {
+                    ForkJoinWorkerThread t = ws[i];
+                    if (t != null)
+                        t.cancelTasks();
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Sets each worker's status to terminating. Requires lock to avoid
+     * conflicts with add/remove.
+     */
+    private void stopAllWorkers() {
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                for (int i = 0; i < ws.length; ++i) {
+                    ForkJoinWorkerThread t = ws[i];
+                    if (t != null)
+                        t.shutdownNow();
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Interrupts all unterminated workers.  This is not required for
+     * sake of internal control, but may help unstick user code during
+     * shutdown.
+     */
+    private void interruptUnterminatedWorkers() {
+        final ReentrantLock lock = this.workerLock;
+        lock.lock();
+        try {
+            ForkJoinWorkerThread[] ws = workers;
+            if (ws != null) {
+                for (int i = 0; i < ws.length; ++i) {
+                    ForkJoinWorkerThread t = ws[i];
+                    if (t != null && !t.isTerminated()) {
+                        try {
+                            t.interrupt();
+                        } catch (SecurityException ignore) {
+                        }
+                    }
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+
+    /*
+     * Nodes for event barrier to manage idle threads.  Queue nodes
+     * are basic Treiber stack nodes, also used for spare stack.
+     *
+     * The event barrier has an event count and a wait queue (actually
+     * a Treiber stack).  Workers are enabled to look for work when
+     * the eventCount is incremented. If they fail to find work, they
+     * may wait for next count. Upon release, threads help others wake
+     * up.
+     *
+     * Synchronization events occur only in enough contexts to
+     * maintain overall liveness:
+     *
+     *   - Submission of a new task to the pool
+     *   - Resizes or other changes to the workers array
+     *   - pool termination
+     *   - A worker pushing a task on an empty queue
+     *
+     * The case of pushing a task occurs often enough, and is heavy
+     * enough compared to simple stack pushes, to require special
+     * handling: Method signalWork returns without advancing count if
+     * the queue appears to be empty.  This would ordinarily result in
+     * races causing some queued waiters not to be woken up. To avoid
+     * this, the first worker enqueued in method sync (see
+     * syncIsReleasable) rescans for tasks after being enqueued, and
+     * helps signal if any are found. This works well because the
+     * worker has nothing better to do, and so might as well help
+     * alleviate the overhead and contention on the threads actually
+     * doing work.  Also, since event counts increments on task
+     * availability exist to maintain liveness (rather than to force
+     * refreshes etc), it is OK for callers to exit early if
+     * contending with another signaller.
+     */
+    static final class WaitQueueNode {
+        WaitQueueNode next; // only written before enqueued
+        volatile ForkJoinWorkerThread thread; // nulled to cancel wait
+        final long count; // unused for spare stack
+
+        WaitQueueNode(long c, ForkJoinWorkerThread w) {
+            count = c;
+            thread = w;
+        }
+
+        /**
+         * Wakes up waiter, returning false if known to already
+         */
+        boolean signal() {
+            ForkJoinWorkerThread t = thread;
+            if (t == null)
+                return false;
+            thread = null;
+            LockSupport.unpark(t);
+            return true;
+        }
+
+        /**
+         * Awaits release on sync.
+         */
+        void awaitSyncRelease(ForkJoinPool p) {
+            while (thread != null && !p.syncIsReleasable(this))
+                LockSupport.park(this);
+        }
+
+        /**
+         * Awaits resumption as spare.
+         */
+        void awaitSpareRelease() {
+            while (thread != null) {
+                if (!Thread.interrupted())
+                    LockSupport.park(this);
+            }
+        }
+    }
+
+    /**
+     * Ensures that no thread is waiting for count to advance from the
+     * current value of eventCount read on entry to this method, by
+     * releasing waiting threads if necessary.
+     *
+     * @return the count
+     */
+    final long ensureSync() {
+        long c = eventCount;
+        WaitQueueNode q;
+        while ((q = syncStack) != null && q.count < c) {
+            if (casBarrierStack(q, null)) {
+                do {
+                    q.signal();
+                } while ((q = q.next) != null);
+                break;
+            }
+        }
+        return c;
+    }
+
+    /**
+     * Increments event count and releases waiting threads.
+     */
+    private void signalIdleWorkers() {
+        long c;
+        do {} while (!casEventCount(c = eventCount, c+1));
+        ensureSync();
+    }
+
+    /**
+     * Signals threads waiting to poll a task. Because method sync
+     * rechecks availability, it is OK to only proceed if queue
+     * appears to be non-empty, and OK to skip under contention to
+     * increment count (since some other thread succeeded).
+     */
+    final void signalWork() {
+        long c;
+        WaitQueueNode q;
+        if (syncStack != null &&
+            casEventCount(c = eventCount, c+1) &&
+            (((q = syncStack) != null && q.count <= c) &&
+             (!casBarrierStack(q, q.next) || !q.signal())))
+            ensureSync();
+    }
+
+    /**
+     * Waits until event count advances from last value held by
+     * caller, or if excess threads, caller is resumed as spare, or
+     * caller or pool is terminating. Updates caller's event on exit.
+     *
+     * @param w the calling worker thread
+     */
+    final void sync(ForkJoinWorkerThread w) {
+        updateStealCount(w); // Transfer w's count while it is idle
+
+        while (!w.isShutdown() && isProcessingTasks() && !suspendIfSpare(w)) {
+            long prev = w.lastEventCount;
+            WaitQueueNode node = null;
+            WaitQueueNode h;
+            while (eventCount == prev &&
+                   ((h = syncStack) == null || h.count == prev)) {
+                if (node == null)
+                    node = new WaitQueueNode(prev, w);
+                if (casBarrierStack(node.next = h, node)) {
+                    node.awaitSyncRelease(this);
+                    break;
+                }
+            }
+            long ec = ensureSync();
+            if (ec != prev) {
+                w.lastEventCount = ec;
+                break;
+            }
+        }
+    }
+
+    /**
+     * Returns {@code true} if worker waiting on sync can proceed:
+     *  - on signal (thread == null)
+     *  - on event count advance (winning race to notify vs signaller)
+     *  - on interrupt
+     *  - if the first queued node, we find work available
+     * If node was not signalled and event count not advanced on exit,
+     * then we also help advance event count.
+     *
+     * @return {@code true} if node can be released
+     */
+    final boolean syncIsReleasable(WaitQueueNode node) {
+        long prev = node.count;
+        if (!Thread.interrupted() && node.thread != null &&
+            (node.next != null ||
+             !ForkJoinWorkerThread.hasQueuedTasks(workers)) &&
+            eventCount == prev)
+            return false;
+        if (node.thread != null) {
+            node.thread = null;
+            long ec = eventCount;
+            if (prev <= ec) // help signal
+                casEventCount(ec, ec+1);
+        }
+        return true;
+    }
+
+    /**
+     * Returns {@code true} if a new sync event occurred since last
+     * call to sync or this method, if so, updating caller's count.
+     */
+    final boolean hasNewSyncEvent(ForkJoinWorkerThread w) {
+        long lc = w.lastEventCount;
+        long ec = ensureSync();
+        if (ec == lc)
+            return false;
+        w.lastEventCount = ec;
+        return true;
+    }
+
+    //  Parallelism maintenance
+
+    /**
+     * Decrements running count; if too low, adds spare.
+     *
+     * Conceptually, all we need to do here is add or resume a
+     * spare thread when one is about to block (and remove or
+     * suspend it later when unblocked -- see suspendIfSpare).
+     * However, implementing this idea requires coping with
+     * several problems: we have imperfect information about the
+     * states of threads. Some count updates can and usually do
+     * lag run state changes, despite arrangements to keep them
+     * accurate (for example, when possible, updating counts
+     * before signalling or resuming), especially when running on
+     * dynamic JVMs that don't optimize the infrequent paths that
+     * update counts. Generating too many threads can make these
+     * problems become worse, because excess threads are more
+     * likely to be context-switched with others, slowing them all
+     * down, especially if there is no work available, so all are
+     * busy scanning or idling.  Also, excess spare threads can
+     * only be suspended or removed when they are idle, not
+     * immediately when they aren't needed. So adding threads will
+     * raise parallelism level for longer than necessary.  Also,
+     * FJ applications often encounter highly transient peaks when
+     * many threads are blocked joining, but for less time than it
+     * takes to create or resume spares.
+     *
+     * @param joinMe if non-null, return early if done
+     * @param maintainParallelism if true, try to stay within
+     * target counts, else create only to avoid starvation
+     * @return true if joinMe known to be done
+     */
+    final boolean preJoin(ForkJoinTask<?> joinMe,
+                          boolean maintainParallelism) {
+        maintainParallelism &= maintainsParallelism; // overrride
+        boolean dec = false;  // true when running count decremented
+        while (spareStack == null || !tryResumeSpare(dec)) {
+            int counts = workerCounts;
+            if (dec || (dec = casWorkerCounts(counts, --counts))) {
+                if (!needSpare(counts, maintainParallelism))
+                    break;
+                if (joinMe.status < 0)
+                    return true;
+                if (tryAddSpare(counts))
+                    break;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Same idea as preJoin
+     */
+    final boolean preBlock(ManagedBlocker blocker,
+                           boolean maintainParallelism) {
+        maintainParallelism &= maintainsParallelism;
+        boolean dec = false;
+        while (spareStack == null || !tryResumeSpare(dec)) {
+            int counts = workerCounts;
+            if (dec || (dec = casWorkerCounts(counts, --counts))) {
+                if (!needSpare(counts, maintainParallelism))
+                    break;
+                if (blocker.isReleasable())
+                    return true;
+                if (tryAddSpare(counts))
+                    break;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if a spare thread appears to be needed.
+     * If maintaining parallelism, returns true when the deficit in
+     * running threads is more than the surplus of total threads, and
+     * there is apparently some work to do.  This self-limiting rule
+     * means that the more threads that have already been added, the
+     * less parallelism we will tolerate before adding another.
+     *
+     * @param counts current worker counts
+     * @param maintainParallelism try to maintain parallelism
+     */
+    private boolean needSpare(int counts, boolean maintainParallelism) {
+        int ps = parallelism;
+        int rc = runningCountOf(counts);
+        int tc = totalCountOf(counts);
+        int runningDeficit = ps - rc;
+        int totalSurplus = tc - ps;
+        return (tc < maxPoolSize &&
+                (rc == 0 || totalSurplus < 0 ||
+                 (maintainParallelism &&
+                  runningDeficit > totalSurplus &&
+                  ForkJoinWorkerThread.hasQueuedTasks(workers))));
+    }
+
+    /**
+     * Adds a spare worker if lock available and no more than the
+     * expected numbers of threads exist.
+     *
+     * @return true if successful
+     */
+    private boolean tryAddSpare(int expectedCounts) {
+        final ReentrantLock lock = this.workerLock;
+        int expectedRunning = runningCountOf(expectedCounts);
+        int expectedTotal = totalCountOf(expectedCounts);
+        boolean success = false;
+        boolean locked = false;
+        // confirm counts while locking; CAS after obtaining lock
+        try {
+            for (;;) {
+                int s = workerCounts;
+                int tc = totalCountOf(s);
+                int rc = runningCountOf(s);
+                if (rc > expectedRunning || tc > expectedTotal)
+                    break;
+                if (!locked && !(locked = lock.tryLock()))
+                    break;
+                if (casWorkerCounts(s, workerCountsFor(tc+1, rc+1))) {
+                    createAndStartSpare(tc);
+                    success = true;
+                    break;
+                }
+            }
+        } finally {
+            if (locked)
+                lock.unlock();
+        }
+        return success;
+    }
+
+    /**
+     * Adds the kth spare worker. On entry, pool counts are already
+     * adjusted to reflect addition.
+     */
+    private void createAndStartSpare(int k) {
+        ForkJoinWorkerThread w = null;
+        ForkJoinWorkerThread[] ws = ensureWorkerArrayCapacity(k + 1);
+        int len = ws.length;
+        // Probably, we can place at slot k. If not, find empty slot
+        if (k < len && ws[k] != null) {
+            for (k = 0; k < len && ws[k] != null; ++k)
+                ;
+        }
+        if (k < len && isProcessingTasks() && (w = createWorker(k)) != null) {
+            ws[k] = w;
+            w.start();
+        }
+        else
+            updateWorkerCount(-1); // adjust on failure
+        signalIdleWorkers();
+    }
+
+    /**
+     * Suspends calling thread w if there are excess threads.  Called
+     * only from sync.  Spares are enqueued in a Treiber stack using
+     * the same WaitQueueNodes as barriers.  They are resumed mainly
+     * in preJoin, but are also woken on pool events that require all
+     * threads to check run state.
+     *
+     * @param w the caller
+     */
+    private boolean suspendIfSpare(ForkJoinWorkerThread w) {
+        WaitQueueNode node = null;
+        int s;
+        while (parallelism < runningCountOf(s = workerCounts)) {
+            if (node == null)
+                node = new WaitQueueNode(0, w);
+            if (casWorkerCounts(s, s-1)) { // representation-dependent
+                // push onto stack
+                do {} while (!casSpareStack(node.next = spareStack, node));
+                // block until released by resumeSpare
+                node.awaitSpareRelease();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Tries to pop and resume a spare thread.
+     *
+     * @param updateCount if true, increment running count on success
+     * @return true if successful
+     */
+    private boolean tryResumeSpare(boolean updateCount) {
+        WaitQueueNode q;
+        while ((q = spareStack) != null) {
+            if (casSpareStack(q, q.next)) {
+                if (updateCount)
+                    updateRunningCount(1);
+                q.signal();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Pops and resumes all spare threads. Same idea as ensureSync.
+     *
+     * @return true if any spares released
+     */
+    private boolean resumeAllSpares() {
+        WaitQueueNode q;
+        while ( (q = spareStack) != null) {
+            if (casSpareStack(q, null)) {
+                do {
+                    updateRunningCount(1);
+                    q.signal();
+                } while ((q = q.next) != null);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Pops and shuts down excessive spare threads. Call only while
+     * holding lock. This is not guaranteed to eliminate all excess
+     * threads, only those suspended as spares, which are the ones
+     * unlikely to be needed in the future.
+     */
+    private void trimSpares() {
+        int surplus = totalCountOf(workerCounts) - parallelism;
+        WaitQueueNode q;
+        while (surplus > 0 && (q = spareStack) != null) {
+            if (casSpareStack(q, null)) {
+                do {
+                    updateRunningCount(1);
+                    ForkJoinWorkerThread w = q.thread;
+                    if (w != null && surplus > 0 &&
+                        runningCountOf(workerCounts) > 0 && w.shutdown())
+                        --surplus;
+                    q.signal();
+                } while ((q = q.next) != null);
+            }
+        }
+    }
+
+    /**
+     * Interface for extending managed parallelism for tasks running
+     * in {@link ForkJoinPool}s.
+     *
+     * <p>A {@code ManagedBlocker} provides two methods.
+     * Method {@code isReleasable} must return {@code true} if
+     * blocking is not necessary. Method {@code block} blocks the
+     * current thread if necessary (perhaps internally invoking
+     * {@code isReleasable} before actually blocking).
+     *
+     * <p>For example, here is a ManagedBlocker based on a
+     * ReentrantLock:
+     *  <pre> {@code
+     * class ManagedLocker implements ManagedBlocker {
+     *   final ReentrantLock lock;
+     *   boolean hasLock = false;
+     *   ManagedLocker(ReentrantLock lock) { this.lock = lock; }
+     *   public boolean block() {
+     *     if (!hasLock)
+     *       lock.lock();
+     *     return true;
+     *   }
+     *   public boolean isReleasable() {
+     *     return hasLock || (hasLock = lock.tryLock());
+     *   }
+     * }}</pre>
+     */
+    public static interface ManagedBlocker {
+        /**
+         * Possibly blocks the current thread, for example waiting for
+         * a lock or condition.
+         *
+         * @return {@code true} if no additional blocking is necessary
+         * (i.e., if isReleasable would return true)
+         * @throws InterruptedException if interrupted while waiting
+         * (the method is not required to do so, but is allowed to)
+         */
+        boolean block() throws InterruptedException;
+
+        /**
+         * Returns {@code true} if blocking is unnecessary.
+         */
+        boolean isReleasable();
+    }
+
+    /**
+     * Blocks in accord with the given blocker.  If the current thread
+     * is a {@link ForkJoinWorkerThread}, this method possibly
+     * arranges for a spare thread to be activated if necessary to
+     * ensure parallelism while the current thread is blocked.
+     *
+     * <p>If {@code maintainParallelism} is {@code true} and the pool
+     * supports it ({@link #getMaintainsParallelism}), this method
+     * attempts to maintain the pool's nominal parallelism. Otherwise
+     * it activates a thread only if necessary to avoid complete
+     * starvation. This option may be preferable when blockages use
+     * timeouts, or are almost always brief.
+     *
+     * <p>If the caller is not a {@link ForkJoinTask}, this method is
+     * behaviorally equivalent to
+     *  <pre> {@code
+     * while (!blocker.isReleasable())
+     *   if (blocker.block())
+     *     return;
+     * }</pre>
+     *
+     * If the caller is a {@code ForkJoinTask}, then the pool may
+     * first be expanded to ensure parallelism, and later adjusted.
+     *
+     * @param blocker the blocker
+     * @param maintainParallelism if {@code true} and supported by
+     * this pool, attempt to maintain the pool's nominal parallelism;
+     * otherwise activate a thread only if necessary to avoid
+     * complete starvation.
+     * @throws InterruptedException if blocker.block did so
+     */
+    public static void managedBlock(ManagedBlocker blocker,
+                                    boolean maintainParallelism)
+        throws InterruptedException {
+        Thread t = Thread.currentThread();
+        ForkJoinPool pool = ((t instanceof ForkJoinWorkerThread) ?
+                             ((ForkJoinWorkerThread) t).pool : null);
+        if (!blocker.isReleasable()) {
+            try {
+                if (pool == null ||
+                    !pool.preBlock(blocker, maintainParallelism))
+                    awaitBlocker(blocker);
+            } finally {
+                if (pool != null)
+                    pool.updateRunningCount(1);
+            }
+        }
+    }
+
+    private static void awaitBlocker(ManagedBlocker blocker)
+        throws InterruptedException {
+        do {} while (!blocker.isReleasable() && !blocker.block());
+    }
+
+    // AbstractExecutorService overrides.  These rely on undocumented
+    // fact that ForkJoinTask.adapt returns ForkJoinTasks that also
+    // implement RunnableFuture.
+
+    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
+        return (RunnableFuture<T>) ForkJoinTask.adapt(runnable, value);
+    }
+
+    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
+        return (RunnableFuture<T>) ForkJoinTask.adapt(callable);
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long eventCountOffset =
+        objectFieldOffset("eventCount", ForkJoinPool.class);
+    private static final long workerCountsOffset =
+        objectFieldOffset("workerCounts", ForkJoinPool.class);
+    private static final long runControlOffset =
+        objectFieldOffset("runControl", ForkJoinPool.class);
+    private static final long syncStackOffset =
+        objectFieldOffset("syncStack",ForkJoinPool.class);
+    private static final long spareStackOffset =
+        objectFieldOffset("spareStack", ForkJoinPool.class);
+
+    private boolean casEventCount(long cmp, long val) {
+        return UNSAFE.compareAndSwapLong(this, eventCountOffset, cmp, val);
+    }
+    private boolean casWorkerCounts(int cmp, int val) {
+        return UNSAFE.compareAndSwapInt(this, workerCountsOffset, cmp, val);
+    }
+    private boolean casRunControl(int cmp, int val) {
+        return UNSAFE.compareAndSwapInt(this, runControlOffset, cmp, val);
+    }
+    private boolean casSpareStack(WaitQueueNode cmp, WaitQueueNode val) {
+        return UNSAFE.compareAndSwapObject(this, spareStackOffset, cmp, val);
+    }
+    private boolean casBarrierStack(WaitQueueNode cmp, WaitQueueNode val) {
+        return UNSAFE.compareAndSwapObject(this, syncStackOffset, cmp, val);
+    }
+
+    private static long objectFieldOffset(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;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/concurrent/ForkJoinTask.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,1292 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.RandomAccess;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * Abstract base class for tasks that run within a {@link ForkJoinPool}.
+ * A {@code ForkJoinTask} is a thread-like entity that is much
+ * lighter weight than a normal thread.  Huge numbers of tasks and
+ * subtasks may be hosted by a small number of actual threads in a
+ * ForkJoinPool, at the price of some usage limitations.
+ *
+ * <p>A "main" {@code ForkJoinTask} begins execution when submitted
+ * to a {@link ForkJoinPool}.  Once started, it will usually in turn
+ * 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.
+ *
+ * <p>A {@code ForkJoinTask} is a lightweight form of {@link Future}.
+ * The efficiency of {@code ForkJoinTask}s stems from a set of
+ * restrictions (that are only partially statically enforceable)
+ * reflecting their intended use as computational tasks calculating
+ * pure functions or operating on purely isolated objects.  The
+ * primary coordination mechanisms are {@link #fork}, that arranges
+ * asynchronous execution, and {@link #join}, that doesn't proceed
+ * until the task's result has been computed.  Computations should
+ * avoid {@code synchronized} methods or blocks, and should minimize
+ * other blocking synchronization apart from joining other tasks or
+ * using synchronizers such as Phasers that are advertised to
+ * cooperate with fork/join scheduling. Tasks should also not perform
+ * blocking IO, and should ideally access variables that are
+ * completely independent of those accessed by other running
+ * tasks. Minor breaches of these restrictions, for example using
+ * shared output streams, may be tolerable in practice, but frequent
+ * use may result in poor performance, and the potential to
+ * indefinitely stall if the number of threads not waiting for IO or
+ * other external synchronization becomes exhausted. This usage
+ * restriction is in part enforced by not permitting checked
+ * exceptions such as {@code IOExceptions} to be thrown. However,
+ * computations may still encounter unchecked exceptions, that are
+ * rethrown to callers attempting to join them. These exceptions may
+ * additionally include {@link RejectedExecutionException} stemming
+ * from internal resource exhaustion, such as failure to allocate
+ * internal task queues.
+ *
+ * <p>The primary method for awaiting completion and extracting
+ * results of a task is {@link #join}, but there are several variants:
+ * The {@link Future#get} methods support interruptible and/or timed
+ * waits for completion and report results using {@code Future}
+ * conventions. Method {@link #helpJoin} enables callers to actively
+ * execute other tasks while awaiting joins, which is sometimes more
+ * efficient but only applies when all subtasks are known to be
+ * strictly tree-structured. Method {@link #invoke} is semantically
+ * equivalent to {@code fork(); join()} but always attempts to begin
+ * execution in the current thread. The "<em>quiet</em>" forms of
+ * these methods do not extract results or report exceptions. These
+ * may be useful when a set of tasks are being executed, and you need
+ * to delay processing of results or exceptions until all complete.
+ * Method {@code invokeAll} (available in multiple versions)
+ * performs the most common form of parallel invocation: forking a set
+ * of tasks and joining them all.
+ *
+ * <p>The execution status of tasks may be queried at several levels
+ * of detail: {@link #isDone} is true if a task completed in any way
+ * (including the case where a task was cancelled without executing);
+ * {@link #isCompletedNormally} is true if a task completed without
+ * cancellation or encountering an exception; {@link #isCancelled} is
+ * true if the task was cancelled (in which case {@link #getException}
+ * returns a {@link java.util.concurrent.CancellationException}); and
+ * {@link #isCompletedAbnormally} is true if a task was either
+ * cancelled or encountered an exception, in which case {@link
+ * #getException} will return either the encountered exception or
+ * {@link java.util.concurrent.CancellationException}.
+ *
+ * <p>The ForkJoinTask class is not usually directly subclassed.
+ * Instead, you subclass one of the abstract classes that support a
+ * particular style of fork/join processing, typically {@link
+ * RecursiveAction} for computations that do not return results, or
+ * {@link RecursiveTask} for those that do.  Normally, a concrete
+ * ForkJoinTask subclass declares fields comprising its parameters,
+ * established in a constructor, and then defines a {@code compute}
+ * method that somehow uses the control methods supplied by this base
+ * class. While these methods have {@code public} access (to allow
+ * instances of different task subclasses to call each other's
+ * methods), some of them may only be called from within other
+ * ForkJoinTasks (as may be determined using method {@link
+ * #inForkJoinPool}).  Attempts to invoke them in other contexts
+ * result in exceptions or errors, possibly including
+ * ClassCastException.
+ *
+ * <p>Most base support methods are {@code final}, to prevent
+ * overriding of implementations that are intrinsically tied to the
+ * underlying lightweight task scheduling framework.  Developers
+ * creating new basic styles of fork/join processing should minimally
+ * implement {@code protected} methods {@link #exec}, {@link
+ * #setRawResult}, and {@link #getRawResult}, while also introducing
+ * an abstract computational method that can be implemented in its
+ * subclasses, possibly relying on other {@code protected} methods
+ * provided by this class.
+ *
+ * <p>ForkJoinTasks should perform relatively small amounts of
+ * computation. Large tasks should be split into smaller subtasks,
+ * usually via recursive decomposition. As a very rough rule of thumb,
+ * a task should perform more than 100 and less than 10000 basic
+ * computational steps. If tasks are too big, then parallelism cannot
+ * improve throughput. If too small, then memory and internal task
+ * maintenance overhead may overwhelm processing.
+ *
+ * <p>This class provides {@code adapt} methods for {@link Runnable}
+ * and {@link Callable}, that may be of use when mixing execution of
+ * {@code ForkJoinTasks} with other kinds of tasks. When all tasks
+ * are of this form, consider using a pool in
+ * {@linkplain ForkJoinPool#setAsyncMode async mode}.
+ *
+ * <p>ForkJoinTasks are {@code Serializable}, which enables them to be
+ * used in extensions such as remote execution frameworks. It is
+ * sensible to serialize tasks only before or after, but not during,
+ * execution. Serialization is not relied on during execution itself.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
+
+    /**
+     * Run control status bits packed into a single int to minimize
+     * footprint and to ensure atomicity (via CAS).  Status is
+     * initially zero, and takes on nonnegative values until
+     * completed, upon which status holds COMPLETED. CANCELLED, or
+     * EXCEPTIONAL, which use the top 3 bits.  Tasks undergoing
+     * blocking waits by other threads have SIGNAL_MASK bits set --
+     * bit 15 for external (nonFJ) waits, and the rest a count of
+     * waiting FJ threads.  (This representation relies on
+     * ForkJoinPool max thread limits). Completion of a stolen task
+     * with SIGNAL_MASK bits set awakens waiter via notifyAll. Even
+     * though suboptimal for some purposes, we use basic builtin
+     * wait/notify to take advantage of "monitor inflation" in JVMs
+     * that we would otherwise need to emulate to avoid adding further
+     * per-task bookkeeping overhead. Note that bits 16-28 are
+     * currently unused. Also value 0x80000000 is available as spare
+     * completion value.
+     */
+    volatile int status; // accessed directly by pool and workers
+
+    static final int COMPLETION_MASK      = 0xe0000000;
+    static final int NORMAL               = 0xe0000000; // == mask
+    static final int CANCELLED            = 0xc0000000;
+    static final int EXCEPTIONAL          = 0xa0000000;
+    static final int SIGNAL_MASK          = 0x0000ffff;
+    static final int INTERNAL_SIGNAL_MASK = 0x00007fff;
+    static final int EXTERNAL_SIGNAL      = 0x00008000; // top bit of low word
+
+    /**
+     * Table of exceptions thrown by tasks, to enable reporting by
+     * callers. Because exceptions are rare, we don't directly keep
+     * them with task objects, but instead use a weak ref table.  Note
+     * that cancellation exceptions don't appear in the table, but are
+     * instead recorded as status values.
+     * TODO: Use ConcurrentReferenceHashMap
+     */
+    static final Map<ForkJoinTask<?>, Throwable> exceptionMap =
+        Collections.synchronizedMap
+        (new WeakHashMap<ForkJoinTask<?>, Throwable>());
+
+    // within-package utilities
+
+    /**
+     * Gets current worker thread, or null if not a worker thread.
+     */
+    static ForkJoinWorkerThread getWorker() {
+        Thread t = Thread.currentThread();
+        return ((t instanceof ForkJoinWorkerThread) ?
+                (ForkJoinWorkerThread) t : null);
+    }
+
+    final boolean casStatus(int cmp, int val) {
+        return UNSAFE.compareAndSwapInt(this, statusOffset, cmp, val);
+    }
+
+    /**
+     * Workaround for not being able to rethrow unchecked exceptions.
+     */
+    static void rethrowException(Throwable ex) {
+        if (ex != null)
+            UNSAFE.throwException(ex);
+    }
+
+    // Setting completion status
+
+    /**
+     * Marks completion and wakes up threads waiting to join this task.
+     *
+     * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
+     */
+    final void setCompletion(int completion) {
+        ForkJoinPool pool = getPool();
+        if (pool != null) {
+            int s; // Clear signal bits while setting completion status
+            do {} while ((s = status) >= 0 && !casStatus(s, completion));
+
+            if ((s & SIGNAL_MASK) != 0) {
+                if ((s &= INTERNAL_SIGNAL_MASK) != 0)
+                    pool.updateRunningCount(s);
+                synchronized (this) { notifyAll(); }
+            }
+        }
+        else
+            externallySetCompletion(completion);
+    }
+
+    /**
+     * Version of setCompletion for non-FJ threads.  Leaves signal
+     * bits for unblocked threads to adjust, and always notifies.
+     */
+    private void externallySetCompletion(int completion) {
+        int s;
+        do {} while ((s = status) >= 0 &&
+                     !casStatus(s, (s & SIGNAL_MASK) | completion));
+        synchronized (this) { notifyAll(); }
+    }
+
+    /**
+     * Sets status to indicate normal completion.
+     */
+    final void setNormalCompletion() {
+        // Try typical fast case -- single CAS, no signal, not already done.
+        // Manually expand casStatus to improve chances of inlining it
+        if (!UNSAFE.compareAndSwapInt(this, statusOffset, 0, NORMAL))
+            setCompletion(NORMAL);
+    }
+
+    // internal waiting and notification
+
+    /**
+     * Performs the actual monitor wait for awaitDone.
+     */
+    private void doAwaitDone() {
+        // Minimize lock bias and in/de-flation effects by maximizing
+        // chances of waiting inside sync
+        try {
+            while (status >= 0)
+                synchronized (this) { if (status >= 0) wait(); }
+        } catch (InterruptedException ie) {
+            onInterruptedWait();
+        }
+    }
+
+    /**
+     * Performs the actual timed monitor wait for awaitDone.
+     */
+    private void doAwaitDone(long startTime, long nanos) {
+        synchronized (this) {
+            try {
+                while (status >= 0) {
+                    long nt = nanos - (System.nanoTime() - startTime);
+                    if (nt <= 0)
+                        break;
+                    wait(nt / 1000000, (int) (nt % 1000000));
+                }
+            } catch (InterruptedException ie) {
+                onInterruptedWait();
+            }
+        }
+    }
+
+    // Awaiting completion
+
+    /**
+     * Sets status to indicate there is joiner, then waits for join,
+     * surrounded with pool notifications.
+     *
+     * @return status upon exit
+     */
+    private int awaitDone(ForkJoinWorkerThread w,
+                          boolean maintainParallelism) {
+        ForkJoinPool pool = (w == null) ? null : w.pool;
+        int s;
+        while ((s = status) >= 0) {
+            if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
+                if (pool == null || !pool.preJoin(this, maintainParallelism))
+                    doAwaitDone();
+                if (((s = status) & INTERNAL_SIGNAL_MASK) != 0)
+                    adjustPoolCountsOnUnblock(pool);
+                break;
+            }
+        }
+        return s;
+    }
+
+    /**
+     * Timed version of awaitDone
+     *
+     * @return status upon exit
+     */
+    private int awaitDone(ForkJoinWorkerThread w, long nanos) {
+        ForkJoinPool pool = (w == null) ? null : w.pool;
+        int s;
+        while ((s = status) >= 0) {
+            if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
+                long startTime = System.nanoTime();
+                if (pool == null || !pool.preJoin(this, false))
+                    doAwaitDone(startTime, nanos);
+                if ((s = status) >= 0) {
+                    adjustPoolCountsOnCancelledWait(pool);
+                    s = status;
+                }
+                if (s < 0 && (s & INTERNAL_SIGNAL_MASK) != 0)
+                    adjustPoolCountsOnUnblock(pool);
+                break;
+            }
+        }
+        return s;
+    }
+
+    /**
+     * Notifies pool that thread is unblocked. Called by signalled
+     * threads when woken by non-FJ threads (which is atypical).
+     */
+    private void adjustPoolCountsOnUnblock(ForkJoinPool pool) {
+        int s;
+        do {} while ((s = status) < 0 && !casStatus(s, s & COMPLETION_MASK));
+        if (pool != null && (s &= INTERNAL_SIGNAL_MASK) != 0)
+            pool.updateRunningCount(s);
+    }
+
+    /**
+     * Notifies pool to adjust counts on cancelled or timed out wait.
+     */
+    private void adjustPoolCountsOnCancelledWait(ForkJoinPool pool) {
+        if (pool != null) {
+            int s;
+            while ((s = status) >= 0 && (s & INTERNAL_SIGNAL_MASK) != 0) {
+                if (casStatus(s, s - 1)) {
+                    pool.updateRunningCount(1);
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Handles interruptions during waits.
+     */
+    private void onInterruptedWait() {
+        ForkJoinWorkerThread w = getWorker();
+        if (w == null)
+            Thread.currentThread().interrupt(); // re-interrupt
+        else if (w.isTerminating())
+            cancelIgnoringExceptions();
+        // else if FJworker, ignore interrupt
+    }
+
+    // Recording and reporting exceptions
+
+    private void setDoneExceptionally(Throwable rex) {
+        exceptionMap.put(this, rex);
+        setCompletion(EXCEPTIONAL);
+    }
+
+    /**
+     * Throws the exception associated with status s.
+     *
+     * @throws the exception
+     */
+    private void reportException(int s) {
+        if ((s &= COMPLETION_MASK) < NORMAL) {
+            if (s == CANCELLED)
+                throw new CancellationException();
+            else
+                rethrowException(exceptionMap.get(this));
+        }
+    }
+
+    /**
+     * Returns result or throws exception using j.u.c.Future conventions.
+     * Only call when {@code isDone} known to be true or thread known
+     * to be interrupted.
+     */
+    private V reportFutureResult()
+        throws InterruptedException, ExecutionException {
+        if (Thread.interrupted())
+            throw new InterruptedException();
+        int s = status & COMPLETION_MASK;
+        if (s < NORMAL) {
+            Throwable ex;
+            if (s == CANCELLED)
+                throw new CancellationException();
+            if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
+                throw new ExecutionException(ex);
+        }
+        return getRawResult();
+    }
+
+    /**
+     * Returns result or throws exception using j.u.c.Future conventions
+     * with timeouts.
+     */
+    private V reportTimedFutureResult()
+        throws InterruptedException, ExecutionException, TimeoutException {
+        if (Thread.interrupted())
+            throw new InterruptedException();
+        Throwable ex;
+        int s = status & COMPLETION_MASK;
+        if (s == NORMAL)
+            return getRawResult();
+        else if (s == CANCELLED)
+            throw new CancellationException();
+        else if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
+            throw new ExecutionException(ex);
+        else
+            throw new TimeoutException();
+    }
+
+    // internal execution methods
+
+    /**
+     * Calls exec, recording completion, and rethrowing exception if
+     * encountered. Caller should normally check status before calling.
+     *
+     * @return true if completed normally
+     */
+    private boolean tryExec() {
+        try { // try block must contain only call to exec
+            if (!exec())
+                return false;
+        } catch (Throwable rex) {
+            setDoneExceptionally(rex);
+            rethrowException(rex);
+            return false; // not reached
+        }
+        setNormalCompletion();
+        return true;
+    }
+
+    /**
+     * Main execution method used by worker threads. Invokes
+     * base computation unless already complete.
+     */
+    final void quietlyExec() {
+        if (status >= 0) {
+            try {
+                if (!exec())
+                    return;
+            } catch (Throwable rex) {
+                setDoneExceptionally(rex);
+                return;
+            }
+            setNormalCompletion();
+        }
+    }
+
+    /**
+     * Calls exec(), recording but not rethrowing exception.
+     * Caller should normally check status before calling.
+     *
+     * @return true if completed normally
+     */
+    private boolean tryQuietlyInvoke() {
+        try {
+            if (!exec())
+                return false;
+        } catch (Throwable rex) {
+            setDoneExceptionally(rex);
+            return false;
+        }
+        setNormalCompletion();
+        return true;
+    }
+
+    /**
+     * Cancels, ignoring any exceptions it throws.
+     */
+    final void cancelIgnoringExceptions() {
+        try {
+            cancel(false);
+        } catch (Throwable ignore) {
+        }
+    }
+
+    /**
+     * Main implementation of helpJoin
+     */
+    private int busyJoin(ForkJoinWorkerThread w) {
+        int s;
+        ForkJoinTask<?> t;
+        while ((s = status) >= 0 && (t = w.scanWhileJoining(this)) != null)
+            t.quietlyExec();
+        return (s >= 0) ? awaitDone(w, false) : s; // block if no work
+    }
+
+    // public methods
+
+    /**
+     * Arranges to asynchronously execute this task.  While it is not
+     * necessarily enforced, it is a usage error to fork a task more
+     * than once unless it has completed and been reinitialized.
+     * Subsequent modifications to the state of this task or any data
+     * it operates on are not necessarily consistently observable by
+     * any thread other than the one executing it unless preceded by a
+     * call to {@link #join} or related methods, or a call to {@link
+     * #isDone} returning {@code true}.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return {@code this}, to simplify usage
+     */
+    public final ForkJoinTask<V> fork() {
+        ((ForkJoinWorkerThread) Thread.currentThread())
+            .pushTask(this);
+        return this;
+    }
+
+    /**
+     * Returns the result of the computation when it {@link #isDone is done}.
+     * This method differs from {@link #get()} in that
+     * abnormal completion results in {@code RuntimeException} or
+     * {@code Error}, not {@code ExecutionException}.
+     *
+     * @return the computed result
+     */
+    public final V join() {
+        ForkJoinWorkerThread w = getWorker();
+        if (w == null || status < 0 || !w.unpushTask(this) || !tryExec())
+            reportException(awaitDone(w, true));
+        return getRawResult();
+    }
+
+    /**
+     * Commences performing this task, awaits its completion if
+     * necessary, and return its result, or throws an (unchecked)
+     * exception if the underlying computation did so.
+     *
+     * @return the computed result
+     */
+    public final V invoke() {
+        if (status >= 0 && tryExec())
+            return getRawResult();
+        else
+            return join();
+    }
+
+    /**
+     * Forks the given tasks, returning when {@code isDone} holds for
+     * each task or an (unchecked) exception is encountered, in which
+     * case the exception is rethrown.  If either task encounters an
+     * exception, the other one may be, but is not guaranteed to be,
+     * cancelled.  If both tasks throw an exception, then this method
+     * throws one of them.  The individual status of each task may be
+     * checked using {@link #getException()} and related methods.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @param t1 the first task
+     * @param t2 the second task
+     * @throws NullPointerException if any task is null
+     */
+    public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {
+        t2.fork();
+        t1.invoke();
+        t2.join();
+    }
+
+    /**
+     * Forks the given tasks, returning when {@code isDone} holds for
+     * each task or an (unchecked) exception is encountered, in which
+     * case the exception is rethrown. If any task encounters an
+     * exception, others may be, but are not guaranteed to be,
+     * cancelled.  If more than one task encounters an exception, then
+     * this method throws any one of these exceptions.  The individual
+     * status of each task may be checked using {@link #getException()}
+     * and related methods.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @param tasks the tasks
+     * @throws NullPointerException if any task is null
+     */
+    public static void invokeAll(ForkJoinTask<?>... tasks) {
+        Throwable ex = null;
+        int last = tasks.length - 1;
+        for (int i = last; i >= 0; --i) {
+            ForkJoinTask<?> t = tasks[i];
+            if (t == null) {
+                if (ex == null)
+                    ex = new NullPointerException();
+            }
+            else if (i != 0)
+                t.fork();
+            else {
+                t.quietlyInvoke();
+                if (ex == null)
+                    ex = t.getException();
+            }
+        }
+        for (int i = 1; i <= last; ++i) {
+            ForkJoinTask<?> t = tasks[i];
+            if (t != null) {
+                if (ex != null)
+                    t.cancel(false);
+                else {
+                    t.quietlyJoin();
+                    if (ex == null)
+                        ex = t.getException();
+                }
+            }
+        }
+        if (ex != null)
+            rethrowException(ex);
+    }
+
+    /**
+     * Forks all tasks in the specified collection, returning when
+     * {@code isDone} holds for each task or an (unchecked) exception
+     * is encountered.  If any task encounters an exception, others
+     * may be, but are not guaranteed to be, cancelled.  If more than
+     * one task encounters an exception, then this method throws any
+     * one of these exceptions.  The individual status of each task
+     * may be checked using {@link #getException()} and related
+     * methods.  The behavior of this operation is undefined if the
+     * specified collection is modified while the operation is in
+     * progress.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @param tasks the collection of tasks
+     * @return the tasks argument, to simplify usage
+     * @throws NullPointerException if tasks or any element are null
+     */
+    public static <T extends ForkJoinTask<?>> Collection<T> invokeAll(Collection<T> tasks) {
+        if (!(tasks instanceof RandomAccess) || !(tasks instanceof List<?>)) {
+            invokeAll(tasks.toArray(new ForkJoinTask<?>[tasks.size()]));
+            return tasks;
+        }
+        @SuppressWarnings("unchecked")
+        List<? extends ForkJoinTask<?>> ts =
+            (List<? extends ForkJoinTask<?>>) tasks;
+        Throwable ex = null;
+        int last = ts.size() - 1;
+        for (int i = last; i >= 0; --i) {
+            ForkJoinTask<?> t = ts.get(i);
+            if (t == null) {
+                if (ex == null)
+                    ex = new NullPointerException();
+            }
+            else if (i != 0)
+                t.fork();
+            else {
+                t.quietlyInvoke();
+                if (ex == null)
+                    ex = t.getException();
+            }
+        }
+        for (int i = 1; i <= last; ++i) {
+            ForkJoinTask<?> t = ts.get(i);
+            if (t != null) {
+                if (ex != null)
+                    t.cancel(false);
+                else {
+                    t.quietlyJoin();
+                    if (ex == null)
+                        ex = t.getException();
+                }
+            }
+        }
+        if (ex != null)
+            rethrowException(ex);
+        return tasks;
+    }
+
+    /**
+     * Attempts to cancel execution of this task. This attempt will
+     * fail if the task has already completed, has already been
+     * cancelled, or could not be cancelled for some other reason. If
+     * successful, and this task has not started when cancel is
+     * called, execution of this task is suppressed, {@link
+     * #isCancelled} will report true, and {@link #join} will result
+     * in a {@code CancellationException} being thrown.
+     *
+     * <p>This method may be overridden in subclasses, but if so, must
+     * still ensure that these minimal properties hold. In particular,
+     * the {@code cancel} method itself must not throw exceptions.
+     *
+     * <p>This method is designed to be invoked by <em>other</em>
+     * tasks. To terminate the current task, you can just return or
+     * throw an unchecked exception from its computation method, or
+     * invoke {@link #completeExceptionally}.
+     *
+     * @param mayInterruptIfRunning this value is ignored in the
+     * default implementation because tasks are not
+     * cancelled via interruption
+     *
+     * @return {@code true} if this task is now cancelled
+     */
+    public boolean cancel(boolean mayInterruptIfRunning) {
+        setCompletion(CANCELLED);
+        return (status & COMPLETION_MASK) == CANCELLED;
+    }
+
+    public final boolean isDone() {
+        return status < 0;
+    }
+
+    public final boolean isCancelled() {
+        return (status & COMPLETION_MASK) == CANCELLED;
+    }
+
+    /**
+     * Returns {@code true} if this task threw an exception or was cancelled.
+     *
+     * @return {@code true} if this task threw an exception or was cancelled
+     */
+    public final boolean isCompletedAbnormally() {
+        return (status & COMPLETION_MASK) < NORMAL;
+    }
+
+    /**
+     * Returns {@code true} if this task completed without throwing an
+     * exception and was not cancelled.
+     *
+     * @return {@code true} if this task completed without throwing an
+     * exception and was not cancelled
+     */
+    public final boolean isCompletedNormally() {
+        return (status & COMPLETION_MASK) == NORMAL;
+    }
+
+    /**
+     * Returns the exception thrown by the base computation, or a
+     * {@code CancellationException} if cancelled, or {@code null} if
+     * none or if the method has not yet completed.
+     *
+     * @return the exception, or {@code null} if none
+     */
+    public final Throwable getException() {
+        int s = status & COMPLETION_MASK;
+        return ((s >= NORMAL)    ? null :
+                (s == CANCELLED) ? new CancellationException() :
+                exceptionMap.get(this));
+    }
+
+    /**
+     * Completes this task abnormally, and if not already aborted or
+     * cancelled, causes it to throw the given exception upon
+     * {@code join} and related operations. This method may be used
+     * to induce exceptions in asynchronous tasks, or to force
+     * completion of tasks that would not otherwise complete.  Its use
+     * in other situations is discouraged.  This method is
+     * overridable, but overridden versions must invoke {@code super}
+     * implementation to maintain guarantees.
+     *
+     * @param ex the exception to throw. If this exception is not a
+     * {@code RuntimeException} or {@code Error}, the actual exception
+     * thrown will be a {@code RuntimeException} with cause {@code ex}.
+     */
+    public void completeExceptionally(Throwable ex) {
+        setDoneExceptionally((ex instanceof RuntimeException) ||
+                             (ex instanceof Error) ? ex :
+                             new RuntimeException(ex));
+    }
+
+    /**
+     * Completes this task, and if not already aborted or cancelled,
+     * returning a {@code null} result upon {@code join} and related
+     * operations. This method may be used to provide results for
+     * asynchronous tasks, or to provide alternative handling for
+     * tasks that would not otherwise complete normally. Its use in
+     * other situations is discouraged. This method is
+     * overridable, but overridden versions must invoke {@code super}
+     * implementation to maintain guarantees.
+     *
+     * @param value the result value for this task
+     */
+    public void complete(V value) {
+        try {
+            setRawResult(value);
+        } catch (Throwable rex) {
+            setDoneExceptionally(rex);
+            return;
+        }
+        setNormalCompletion();
+    }
+
+    public final V get() throws InterruptedException, ExecutionException {
+        ForkJoinWorkerThread w = getWorker();
+        if (w == null || status < 0 || !w.unpushTask(this) || !tryQuietlyInvoke())
+            awaitDone(w, true);
+        return reportFutureResult();
+    }
+
+    public final V get(long timeout, TimeUnit unit)
+        throws InterruptedException, ExecutionException, TimeoutException {
+        long nanos = unit.toNanos(timeout);
+        ForkJoinWorkerThread w = getWorker();
+        if (w == null || status < 0 || !w.unpushTask(this) || !tryQuietlyInvoke())
+            awaitDone(w, nanos);
+        return reportTimedFutureResult();
+    }
+
+    /**
+     * Possibly executes other tasks until this task {@link #isDone is
+     * done}, then returns the result of the computation.  This method
+     * may be more efficient than {@code join}, but is only applicable
+     * when there are no potential dependencies between continuation
+     * of the current task and that of any other task that might be
+     * executed while helping. (This usually holds for pure
+     * divide-and-conquer tasks).
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the computed result
+     */
+    public final V helpJoin() {
+        ForkJoinWorkerThread w = (ForkJoinWorkerThread) Thread.currentThread();
+        if (status < 0 || !w.unpushTask(this) || !tryExec())
+            reportException(busyJoin(w));
+        return getRawResult();
+    }
+
+    /**
+     * Possibly executes other tasks until this task {@link #isDone is
+     * done}.  This method may be useful when processing collections
+     * of tasks when some have been cancelled or otherwise known to
+     * have aborted.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     */
+    public final void quietlyHelpJoin() {
+        if (status >= 0) {
+            ForkJoinWorkerThread w =
+                (ForkJoinWorkerThread) Thread.currentThread();
+            if (!w.unpushTask(this) || !tryQuietlyInvoke())
+                busyJoin(w);
+        }
+    }
+
+    /**
+     * Joins this task, without returning its result or throwing an
+     * exception. This method may be useful when processing
+     * collections of tasks when some have been cancelled or otherwise
+     * known to have aborted.
+     */
+    public final void quietlyJoin() {
+        if (status >= 0) {
+            ForkJoinWorkerThread w = getWorker();
+            if (w == null || !w.unpushTask(this) || !tryQuietlyInvoke())
+                awaitDone(w, true);
+        }
+    }
+
+    /**
+     * Commences performing this task and awaits its completion if
+     * necessary, without returning its result or throwing an
+     * exception. This method may be useful when processing
+     * collections of tasks when some have been cancelled or otherwise
+     * known to have aborted.
+     */
+    public final void quietlyInvoke() {
+        if (status >= 0 && !tryQuietlyInvoke())
+            quietlyJoin();
+    }
+
+    /**
+     * Possibly executes tasks until the pool hosting the current task
+     * {@link ForkJoinPool#isQuiescent is quiescent}. This method may
+     * be of use in designs in which many tasks are forked, but none
+     * are explicitly joined, instead executing them until all are
+     * processed.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     */
+    public static void helpQuiesce() {
+        ((ForkJoinWorkerThread) Thread.currentThread())
+            .helpQuiescePool();
+    }
+
+    /**
+     * Resets the internal bookkeeping state of this task, allowing a
+     * subsequent {@code fork}. This method allows repeated reuse of
+     * this task, but only if reuse occurs when this task has either
+     * never been forked, or has been forked, then completed and all
+     * outstanding joins of this task have also completed. Effects
+     * under any other usage conditions are not guaranteed.
+     * This method may be useful when executing
+     * pre-constructed trees of subtasks in loops.
+     */
+    public void reinitialize() {
+        if ((status & COMPLETION_MASK) == EXCEPTIONAL)
+            exceptionMap.remove(this);
+        status = 0;
+    }
+
+    /**
+     * Returns the pool hosting the current task execution, or null
+     * if this task is executing outside of any ForkJoinPool.
+     *
+     * @see #inForkJoinPool
+     * @return the pool, or {@code null} if none
+     */
+    public static ForkJoinPool getPool() {
+        Thread t = Thread.currentThread();
+        return (t instanceof ForkJoinWorkerThread) ?
+            ((ForkJoinWorkerThread) t).pool : null;
+    }
+
+    /**
+     * Returns {@code true} if the current thread is executing as a
+     * ForkJoinPool computation.
+     *
+     * @return {@code true} if the current thread is executing as a
+     * ForkJoinPool computation, or false otherwise
+     */
+    public static boolean inForkJoinPool() {
+        return Thread.currentThread() instanceof ForkJoinWorkerThread;
+    }
+
+    /**
+     * Tries to unschedule this task for execution. This method will
+     * typically succeed if this task is the most recently forked task
+     * by the current thread, and has not commenced executing in
+     * another thread.  This method may be useful when arranging
+     * alternative local processing of tasks that could have been, but
+     * were not, stolen.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return {@code true} if unforked
+     */
+    public boolean tryUnfork() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .unpushTask(this);
+    }
+
+    /**
+     * Returns an estimate of the number of tasks that have been
+     * forked by the current worker thread but not yet executed. This
+     * value may be useful for heuristic decisions about whether to
+     * fork other tasks.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the number of tasks
+     */
+    public static int getQueuedTaskCount() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .getQueueSize();
+    }
+
+    /**
+     * Returns an estimate of how many more locally queued tasks are
+     * held by the current worker thread than there are other worker
+     * threads that might steal them.  This value may be useful for
+     * heuristic decisions about whether to fork other tasks. In many
+     * usages of ForkJoinTasks, at steady state, each worker should
+     * aim to maintain a small constant surplus (for example, 3) of
+     * tasks, and to process computations locally if this threshold is
+     * exceeded.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the surplus number of tasks, which may be negative
+     */
+    public static int getSurplusQueuedTaskCount() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .getEstimatedSurplusTaskCount();
+    }
+
+    // Extension methods
+
+    /**
+     * Returns the result that would be returned by {@link #join}, even
+     * if this task completed abnormally, or {@code null} if this task
+     * is not known to have been completed.  This method is designed
+     * to aid debugging, as well as to support extensions. Its use in
+     * any other context is discouraged.
+     *
+     * @return the result, or {@code null} if not completed
+     */
+    public abstract V getRawResult();
+
+    /**
+     * Forces the given value to be returned as a result.  This method
+     * is designed to support extensions, and should not in general be
+     * called otherwise.
+     *
+     * @param value the value
+     */
+    protected abstract void setRawResult(V value);
+
+    /**
+     * Immediately performs the base action of this task.  This method
+     * is designed to support extensions, and should not in general be
+     * called otherwise. The return value controls whether this task
+     * is considered to be done normally. It may return false in
+     * asynchronous actions that require explicit invocations of
+     * {@link #complete} to become joinable. It may also throw an
+     * (unchecked) exception to indicate abnormal exit.
+     *
+     * @return {@code true} if completed normally
+     */
+    protected abstract boolean exec();
+
+    /**
+     * Returns, but does not unschedule or execute, a task queued by
+     * the current thread but not yet executed, if one is immediately
+     * available. There is no guarantee that this task will actually
+     * be polled or executed next. Conversely, this method may return
+     * null even if a task exists but cannot be accessed without
+     * contention with other threads.  This method is designed
+     * primarily to support extensions, and is unlikely to be useful
+     * otherwise.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the next task, or {@code null} if none are available
+     */
+    protected static ForkJoinTask<?> peekNextLocalTask() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .peekTask();
+    }
+
+    /**
+     * Unschedules and returns, without executing, the next task
+     * queued by the current thread but not yet executed.  This method
+     * is designed primarily to support extensions, and is unlikely to
+     * be useful otherwise.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return the next task, or {@code null} if none are available
+     */
+    protected static ForkJoinTask<?> pollNextLocalTask() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .pollLocalTask();
+    }
+
+    /**
+     * Unschedules and returns, without executing, the next task
+     * queued by the current thread but not yet executed, if one is
+     * available, or if not available, a task that was forked by some
+     * other thread, if available. Availability may be transient, so a
+     * {@code null} result does not necessarily imply quiescence
+     * of the pool this task is operating in.  This method is designed
+     * primarily to support extensions, and is unlikely to be useful
+     * otherwise.
+     *
+     * <p>This method may be invoked only from within {@code
+     * ForkJoinTask} computations (as may be determined using method
+     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
+     * result in exceptions or errors, possibly including {@code
+     * ClassCastException}.
+     *
+     * @return a task, or {@code null} if none are available
+     */
+    protected static ForkJoinTask<?> pollTask() {
+        return ((ForkJoinWorkerThread) Thread.currentThread())
+            .pollTask();
+    }
+
+    /**
+     * Adaptor for Runnables. This implements RunnableFuture
+     * to be compliant with AbstractExecutorService constraints
+     * when used in ForkJoinPool.
+     */
+    static final class AdaptedRunnable<T> extends ForkJoinTask<T>
+        implements RunnableFuture<T> {
+        final Runnable runnable;
+        final T resultOnCompletion;
+        T result;
+        AdaptedRunnable(Runnable runnable, T result) {
+            if (runnable == null) throw new NullPointerException();
+            this.runnable = runnable;
+            this.resultOnCompletion = result;
+        }
+        public T getRawResult() { return result; }
+        public void setRawResult(T v) { result = v; }
+        public boolean exec() {
+            runnable.run();
+            result = resultOnCompletion;
+            return true;
+        }
+        public void run() { invoke(); }
+        private static final long serialVersionUID = 5232453952276885070L;
+    }
+
+    /**
+     * Adaptor for Callables
+     */
+    static final class AdaptedCallable<T> extends ForkJoinTask<T>
+        implements RunnableFuture<T> {
+        final Callable<? extends T> callable;
+        T result;
+        AdaptedCallable(Callable<? extends T> callable) {
+            if (callable == null) throw new NullPointerException();
+            this.callable = callable;
+        }
+        public T getRawResult() { return result; }
+        public void setRawResult(T v) { result = v; }
+        public boolean exec() {
+            try {
+                result = callable.call();
+                return true;
+            } catch (Error err) {
+                throw err;
+            } catch (RuntimeException rex) {
+                throw rex;
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+        public void run() { invoke(); }
+        private static final long serialVersionUID = 2838392045355241008L;
+    }
+
+    /**
+     * Returns a new {@code ForkJoinTask} that performs the {@code run}
+     * method of the given {@code Runnable} as its action, and returns
+     * a null result upon {@link #join}.
+     *
+     * @param runnable the runnable action
+     * @return the task
+     */
+    public static ForkJoinTask<?> adapt(Runnable runnable) {
+        return new AdaptedRunnable<Void>(runnable, null);
+    }
+
+    /**
+     * Returns a new {@code ForkJoinTask} that performs the {@code run}
+     * method of the given {@code Runnable} as its action, and returns
+     * the given result upon {@link #join}.
+     *
+     * @param runnable the runnable action
+     * @param result the result upon completion
+     * @return the task
+     */
+    public static <T> ForkJoinTask<T> adapt(Runnable runnable, T result) {
+        return new AdaptedRunnable<T>(runnable, result);
+    }
+
+    /**
+     * Returns a new {@code ForkJoinTask} that performs the {@code call}
+     * method of the given {@code Callable} as its action, and returns
+     * its result upon {@link #join}, translating any checked exceptions
+     * encountered into {@code RuntimeException}.
+     *
+     * @param callable the callable action
+     * @return the task
+     */
+    public static <T> ForkJoinTask<T> adapt(Callable<? extends T> callable) {
+        return new AdaptedCallable<T>(callable);
+    }
+
+    // Serialization support
+
+    private static final long serialVersionUID = -7721805057305804111L;
+
+    /**
+     * Saves the state to a stream.
+     *
+     * @serialData the current run status and the exception thrown
+     * during execution, or {@code null} if none
+     * @param s the stream
+     */
+    private void writeObject(java.io.ObjectOutputStream s)
+        throws java.io.IOException {
+        s.defaultWriteObject();
+        s.writeObject(getException());
+    }
+
+    /**
+     * Reconstitutes the instance from a stream.
+     *
+     * @param s the stream
+     */
+    private void readObject(java.io.ObjectInputStream s)
+        throws java.io.IOException, ClassNotFoundException {
+        s.defaultReadObject();
+        status &= ~INTERNAL_SIGNAL_MASK; // clear internal signal counts
+        status |= EXTERNAL_SIGNAL; // conservatively set external signal
+        Object ex = s.readObject();
+        if (ex != null)
+            setDoneExceptionally((Throwable) ex);
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long statusOffset =
+        objectFieldOffset("status", ForkJoinTask.class);
+
+    private static long objectFieldOffset(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;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,827 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.Collection;
+
+/**
+ * A thread managed by a {@link ForkJoinPool}.  This class is
+ * subclassable solely for the sake of adding functionality -- there
+ * are no overridable methods dealing with scheduling or execution.
+ * However, you can override initialization and termination methods
+ * surrounding the main task processing loop.  If you do create such a
+ * subclass, you will also need to supply a custom {@link
+ * ForkJoinPool.ForkJoinWorkerThreadFactory} to use it in a {@code
+ * ForkJoinPool}.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public class ForkJoinWorkerThread extends Thread {
+    /*
+     * Algorithm overview:
+     *
+     * 1. Work-Stealing: Work-stealing queues are special forms of
+     * Deques that support only three of the four possible
+     * end-operations -- push, pop, and deq (aka steal), and only do
+     * so under the constraints that push and pop are called only from
+     * the owning thread, while deq may be called from other threads.
+     * (If you are unfamiliar with them, you probably want to read
+     * Herlihy and Shavit's book "The Art of Multiprocessor
+     * programming", chapter 16 describing these in more detail before
+     * proceeding.)  The main work-stealing queue design is roughly
+     * similar to "Dynamic Circular Work-Stealing Deque" by David
+     * Chase and Yossi Lev, SPAA 2005
+     * (http://research.sun.com/scalable/pubs/index.html).  The main
+     * difference ultimately stems from gc requirements that we null
+     * out taken slots as soon as we can, to maintain as small a
+     * footprint as possible even in programs generating huge numbers
+     * of tasks. To accomplish this, we shift the CAS arbitrating pop
+     * vs deq (steal) from being on the indices ("base" and "sp") to
+     * the slots themselves (mainly via method "casSlotNull()"). So,
+     * both a successful pop and deq mainly entail CAS'ing a non-null
+     * slot to null.  Because we rely on CASes of references, we do
+     * not need tag bits on base or sp.  They are simple ints as used
+     * in any circular array-based queue (see for example ArrayDeque).
+     * Updates to the indices must still be ordered in a way that
+     * guarantees that (sp - base) > 0 means the queue is empty, but
+     * otherwise may err on the side of possibly making the queue
+     * appear nonempty when a push, pop, or deq have not fully
+     * committed. Note that this means that the deq operation,
+     * considered individually, is not wait-free. One thief cannot
+     * successfully continue until another in-progress one (or, if
+     * previously empty, a push) completes.  However, in the
+     * aggregate, we ensure at least probabilistic
+     * non-blockingness. If an attempted steal fails, a thief always
+     * chooses a different random victim target to try next. So, in
+     * order for one thief to progress, it suffices for any
+     * in-progress deq or new push on any empty queue to complete. One
+     * reason this works well here is that apparently-nonempty often
+     * means soon-to-be-stealable, which gives threads a chance to
+     * activate if necessary before stealing (see below).
+     *
+     * This approach also enables support for "async mode" where local
+     * task processing is in FIFO, not LIFO order; simply by using a
+     * version of deq rather than pop when locallyFifo is true (as set
+     * by the ForkJoinPool).  This allows use in message-passing
+     * frameworks in which tasks are never joined.
+     *
+     * Efficient implementation of this approach currently relies on
+     * an uncomfortable amount of "Unsafe" mechanics. To maintain
+     * correct orderings, reads and writes of variable base require
+     * volatile ordering.  Variable sp does not require volatile write
+     * but needs cheaper store-ordering on writes.  Because they are
+     * protected by volatile base reads, reads of the queue array and
+     * its slots do not need volatile load semantics, but writes (in
+     * push) require store order and CASes (in pop and deq) require
+     * (volatile) CAS semantics.  (See "Idempotent work stealing" by
+     * Michael, Saraswat, and Vechev, PPoPP 2009
+     * http://portal.acm.org/citation.cfm?id=1504186 for an algorithm
+     * with similar properties, but without support for nulling
+     * slots.)  Since these combinations aren't supported using
+     * ordinary volatiles, the only way to accomplish these
+     * efficiently is to use direct Unsafe calls. (Using external
+     * AtomicIntegers and AtomicReferenceArrays for the indices and
+     * array is significantly slower because of memory locality and
+     * indirection effects.)
+     *
+     * Further, performance on most platforms is very sensitive to
+     * placement and sizing of the (resizable) queue array.  Even
+     * though these queues don't usually become all that big, the
+     * initial size must be large enough to counteract cache
+     * contention effects across multiple queues (especially in the
+     * presence of GC cardmarking). Also, to improve thread-locality,
+     * queues are currently initialized immediately after the thread
+     * gets the initial signal to start processing tasks.  However,
+     * all queue-related methods except pushTask are written in a way
+     * that allows them to instead be lazily allocated and/or disposed
+     * of when empty. All together, these low-level implementation
+     * choices produce as much as a factor of 4 performance
+     * improvement compared to naive implementations, and enable the
+     * processing of billions of tasks per second, sometimes at the
+     * expense of ugliness.
+     *
+     * 2. Run control: The primary run control is based on a global
+     * counter (activeCount) held by the pool. It uses an algorithm
+     * similar to that in Herlihy and Shavit section 17.6 to cause
+     * threads to eventually block when all threads declare they are
+     * inactive. For this to work, threads must be declared active
+     * when executing tasks, and before stealing a task. They must be
+     * inactive before blocking on the Pool Barrier (awaiting a new
+     * submission or other Pool event). In between, there is some free
+     * play which we take advantage of to avoid contention and rapid
+     * flickering of the global activeCount: If inactive, we activate
+     * only if a victim queue appears to be nonempty (see above).
+     * Similarly, a thread tries to inactivate only after a full scan
+     * of other threads.  The net effect is that contention on
+     * activeCount is rarely a measurable performance issue. (There
+     * are also a few other cases where we scan for work rather than
+     * retry/block upon contention.)
+     *
+     * 3. Selection control. We maintain policy of always choosing to
+     * run local tasks rather than stealing, and always trying to
+     * steal tasks before trying to run a new submission. All steals
+     * are currently performed in randomly-chosen deq-order. It may be
+     * worthwhile to bias these with locality / anti-locality
+     * information, but doing this well probably requires more
+     * lower-level information from JVMs than currently provided.
+     */
+
+    /**
+     * Capacity of work-stealing queue array upon initialization.
+     * Must be a power of two. Initial size must be at least 2, but is
+     * padded to minimize cache effects.
+     */
+    private static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
+
+    /**
+     * Maximum work-stealing queue array size.  Must be less than or
+     * equal to 1 << 28 to ensure lack of index wraparound. (This
+     * is less than usual bounds, because we need leftshift by 3
+     * to be in int range).
+     */
+    private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 28;
+
+    /**
+     * The pool this thread works in. Accessed directly by ForkJoinTask.
+     */
+    final ForkJoinPool pool;
+
+    /**
+     * The work-stealing queue array. Size must be a power of two.
+     * Initialized when thread starts, to improve memory locality.
+     */
+    private ForkJoinTask<?>[] queue;
+
+    /**
+     * Index (mod queue.length) of next queue slot to push to or pop
+     * from. It is written only by owner thread, via ordered store.
+     * Both sp and base are allowed to wrap around on overflow, but
+     * (sp - base) still estimates size.
+     */
+    private volatile int sp;
+
+    /**
+     * Index (mod queue.length) of least valid queue slot, which is
+     * always the next position to steal from if nonempty.
+     */
+    private volatile int base;
+
+    /**
+     * Activity status. When true, this worker is considered active.
+     * Must be false upon construction. It must be true when executing
+     * tasks, and BEFORE stealing a task. It must be false before
+     * calling pool.sync.
+     */
+    private boolean active;
+
+    /**
+     * Run state of this worker. Supports simple versions of the usual
+     * shutdown/shutdownNow control.
+     */
+    private volatile int runState;
+
+    /**
+     * Seed for random number generator for choosing steal victims.
+     * Uses Marsaglia xorshift. Must be nonzero upon initialization.
+     */
+    private int seed;
+
+    /**
+     * Number of steals, transferred to pool when idle
+     */
+    private int stealCount;
+
+    /**
+     * Index of this worker in pool array. Set once by pool before
+     * running, and accessed directly by pool during cleanup etc.
+     */
+    int poolIndex;
+
+    /**
+     * The last barrier event waited for. Accessed in pool callback
+     * methods, but only by current thread.
+     */
+    long lastEventCount;
+
+    /**
+     * True if use local fifo, not default lifo, for local polling
+     */
+    private boolean locallyFifo;
+
+    /**
+     * Creates a ForkJoinWorkerThread operating in the given pool.
+     *
+     * @param pool the pool this thread works in
+     * @throws NullPointerException if pool is null
+     */
+    protected ForkJoinWorkerThread(ForkJoinPool pool) {
+        if (pool == null) throw new NullPointerException();
+        this.pool = pool;
+        // Note: poolIndex is set by pool during construction
+        // Remaining initialization is deferred to onStart
+    }
+
+    // Public access methods
+
+    /**
+     * Returns the pool hosting this thread.
+     *
+     * @return the pool
+     */
+    public ForkJoinPool getPool() {
+        return pool;
+    }
+
+    /**
+     * Returns the index number of this thread in its pool.  The
+     * returned value ranges from zero to the maximum number of
+     * threads (minus one) that have ever been created in the pool.
+     * This method may be useful for applications that track status or
+     * collect results per-worker rather than per-task.
+     *
+     * @return the index number
+     */
+    public int getPoolIndex() {
+        return poolIndex;
+    }
+
+    /**
+     * Establishes local first-in-first-out scheduling mode for forked
+     * tasks that are never joined.
+     *
+     * @param async if true, use locally FIFO scheduling
+     */
+    void setAsyncMode(boolean async) {
+        locallyFifo = async;
+    }
+
+    // Runstate management
+
+    // Runstate values. Order matters
+    private static final int RUNNING     = 0;
+    private static final int SHUTDOWN    = 1;
+    private static final int TERMINATING = 2;
+    private static final int TERMINATED  = 3;
+
+    final boolean isShutdown()    { return runState >= SHUTDOWN;  }
+    final boolean isTerminating() { return runState >= TERMINATING;  }
+    final boolean isTerminated()  { return runState == TERMINATED; }
+    final boolean shutdown()      { return transitionRunStateTo(SHUTDOWN); }
+    final boolean shutdownNow()   { return transitionRunStateTo(TERMINATING); }
+
+    /**
+     * Transitions to at least the given state.
+     *
+     * @return {@code true} if not already at least at given state
+     */
+    private boolean transitionRunStateTo(int state) {
+        for (;;) {
+            int s = runState;
+            if (s >= state)
+                return false;
+            if (UNSAFE.compareAndSwapInt(this, runStateOffset, s, state))
+                return true;
+        }
+    }
+
+    /**
+     * Tries to set status to active; fails on contention.
+     */
+    private boolean tryActivate() {
+        if (!active) {
+            if (!pool.tryIncrementActiveCount())
+                return false;
+            active = true;
+        }
+        return true;
+    }
+
+    /**
+     * Tries to set status to inactive; fails on contention.
+     */
+    private boolean tryInactivate() {
+        if (active) {
+            if (!pool.tryDecrementActiveCount())
+                return false;
+            active = false;
+        }
+        return true;
+    }
+
+    /**
+     * Computes next value for random victim probe.  Scans don't
+     * require a very high quality generator, but also not a crummy
+     * one.  Marsaglia xor-shift is cheap and works well.
+     */
+    private static int xorShift(int r) {
+        r ^= (r << 13);
+        r ^= (r >>> 17);
+        return r ^ (r << 5);
+    }
+
+    // Lifecycle methods
+
+    /**
+     * This method is required to be public, but should never be
+     * called explicitly. It performs the main run loop to execute
+     * ForkJoinTasks.
+     */
+    public void run() {
+        Throwable exception = null;
+        try {
+            onStart();
+            pool.sync(this); // await first pool event
+            mainLoop();
+        } catch (Throwable ex) {
+            exception = ex;
+        } finally {
+            onTermination(exception);
+        }
+    }
+
+    /**
+     * Executes tasks until shut down.
+     */
+    private void mainLoop() {
+        while (!isShutdown()) {
+            ForkJoinTask<?> t = pollTask();
+            if (t != null || (t = pollSubmission()) != null)
+                t.quietlyExec();
+            else if (tryInactivate())
+                pool.sync(this);
+        }
+    }
+
+    /**
+     * Initializes internal state after construction but before
+     * processing any tasks. If you override this method, you must
+     * invoke super.onStart() at the beginning of the method.
+     * Initialization requires care: Most fields must have legal
+     * default values, to ensure that attempted accesses from other
+     * threads work correctly even before this thread starts
+     * processing tasks.
+     */
+    protected void onStart() {
+        // Allocate while starting to improve chances of thread-local
+        // isolation
+        queue = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
+        // Initial value of seed need not be especially random but
+        // should differ across workers and must be nonzero
+        int p = poolIndex + 1;
+        seed = p + (p << 8) + (p << 16) + (p << 24); // spread bits
+    }
+
+    /**
+     * Performs cleanup associated with termination of this worker
+     * thread.  If you override this method, you must invoke
+     * {@code super.onTermination} at the end of the overridden method.
+     *
+     * @param exception the exception causing this thread to abort due
+     * to an unrecoverable error, or {@code null} if completed normally
+     */
+    protected void onTermination(Throwable exception) {
+        // Execute remaining local tasks unless aborting or terminating
+        while (exception == null && pool.isProcessingTasks() && base != sp) {
+            try {
+                ForkJoinTask<?> t = popTask();
+                if (t != null)
+                    t.quietlyExec();
+            } catch (Throwable ex) {
+                exception = ex;
+            }
+        }
+        // Cancel other tasks, transition status, notify pool, and
+        // propagate exception to uncaught exception handler
+        try {
+            do {} while (!tryInactivate()); // ensure inactive
+            cancelTasks();
+            runState = TERMINATED;
+            pool.workerTerminated(this);
+        } catch (Throwable ex) {        // Shouldn't ever happen
+            if (exception == null)      // but if so, at least rethrown
+                exception = ex;
+        } finally {
+            if (exception != null)
+                ForkJoinTask.rethrowException(exception);
+        }
+    }
+
+    // Intrinsics-based support for queue operations.
+
+    private static long slotOffset(int i) {
+        return ((long) i << qShift) + qBase;
+    }
+
+    /**
+     * Adds in store-order the given task at given slot of q to null.
+     * Caller must ensure q is non-null and index is in range.
+     */
+    private static void setSlot(ForkJoinTask<?>[] q, int i,
+                                ForkJoinTask<?> t) {
+        UNSAFE.putOrderedObject(q, slotOffset(i), t);
+    }
+
+    /**
+     * CAS given slot of q to null. Caller must ensure q is non-null
+     * and index is in range.
+     */
+    private static boolean casSlotNull(ForkJoinTask<?>[] q, int i,
+                                       ForkJoinTask<?> t) {
+        return UNSAFE.compareAndSwapObject(q, slotOffset(i), t, null);
+    }
+
+    /**
+     * Sets sp in store-order.
+     */
+    private void storeSp(int s) {
+        UNSAFE.putOrderedInt(this, spOffset, s);
+    }
+
+    // Main queue methods
+
+    /**
+     * Pushes a task. Called only by current thread.
+     *
+     * @param t the task. Caller must ensure non-null.
+     */
+    final void pushTask(ForkJoinTask<?> t) {
+        ForkJoinTask<?>[] q = queue;
+        int mask = q.length - 1;
+        int s = sp;
+        setSlot(q, s & mask, t);
+        storeSp(++s);
+        if ((s -= base) == 1)
+            pool.signalWork();
+        else if (s >= mask)
+            growQueue();
+    }
+
+    /**
+     * Tries to take a task from the base of the queue, failing if
+     * either empty or contended.
+     *
+     * @return a task, or null if none or contended
+     */
+    final ForkJoinTask<?> deqTask() {
+        ForkJoinTask<?> t;
+        ForkJoinTask<?>[] q;
+        int i;
+        int b;
+        if (sp != (b = base) &&
+            (q = queue) != null && // must read q after b
+            (t = q[i = (q.length - 1) & b]) != null &&
+            casSlotNull(q, i, t)) {
+            base = b + 1;
+            return t;
+        }
+        return null;
+    }
+
+    /**
+     * Tries to take a task from the base of own queue, activating if
+     * necessary, failing only if empty. Called only by current thread.
+     *
+     * @return a task, or null if none
+     */
+    final ForkJoinTask<?> locallyDeqTask() {
+        int b;
+        while (sp != (b = base)) {
+            if (tryActivate()) {
+                ForkJoinTask<?>[] q = queue;
+                int i = (q.length - 1) & b;
+                ForkJoinTask<?> t = q[i];
+                if (t != null && casSlotNull(q, i, t)) {
+                    base = b + 1;
+                    return t;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a popped task, or null if empty. Ensures active status
+     * if non-null. Called only by current thread.
+     */
+    final ForkJoinTask<?> popTask() {
+        int s = sp;
+        while (s != base) {
+            if (tryActivate()) {
+                ForkJoinTask<?>[] q = queue;
+                int mask = q.length - 1;
+                int i = (s - 1) & mask;
+                ForkJoinTask<?> t = q[i];
+                if (t == null || !casSlotNull(q, i, t))
+                    break;
+                storeSp(s - 1);
+                return t;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Specialized version of popTask to pop only if
+     * topmost element is the given task. Called only
+     * by current thread while active.
+     *
+     * @param t the task. Caller must ensure non-null.
+     */
+    final boolean unpushTask(ForkJoinTask<?> t) {
+        ForkJoinTask<?>[] q = queue;
+        int mask = q.length - 1;
+        int s = sp - 1;
+        if (casSlotNull(q, s & mask, t)) {
+            storeSp(s);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns next task or null if empty or contended
+     */
+    final ForkJoinTask<?> peekTask() {
+        ForkJoinTask<?>[] q = queue;
+        if (q == null)
+            return null;
+        int mask = q.length - 1;
+        int i = locallyFifo ? base : (sp - 1);
+        return q[i & mask];
+    }
+
+    /**
+     * Doubles queue array size. Transfers elements by emulating
+     * steals (deqs) from old array and placing, oldest first, into
+     * new array.
+     */
+    private void growQueue() {
+        ForkJoinTask<?>[] oldQ = queue;
+        int oldSize = oldQ.length;
+        int newSize = oldSize << 1;
+        if (newSize > MAXIMUM_QUEUE_CAPACITY)
+            throw new RejectedExecutionException("Queue capacity exceeded");
+        ForkJoinTask<?>[] newQ = queue = new ForkJoinTask<?>[newSize];
+
+        int b = base;
+        int bf = b + oldSize;
+        int oldMask = oldSize - 1;
+        int newMask = newSize - 1;
+        do {
+            int oldIndex = b & oldMask;
+            ForkJoinTask<?> t = oldQ[oldIndex];
+            if (t != null && !casSlotNull(oldQ, oldIndex, t))
+                t = null;
+            setSlot(newQ, b & newMask, t);
+        } while (++b != bf);
+        pool.signalWork();
+    }
+
+    /**
+     * Tries to steal a task from another worker. Starts at a random
+     * index of workers array, and probes workers until finding one
+     * with non-empty queue or finding that all are empty.  It
+     * randomly selects the first n probes. If these are empty, it
+     * resorts to a full circular traversal, which is necessary to
+     * accurately set active status by caller. Also restarts if pool
+     * events occurred since last scan, which forces refresh of
+     * workers array, in case barrier was associated with resize.
+     *
+     * This method must be both fast and quiet -- usually avoiding
+     * memory accesses that could disrupt cache sharing etc other than
+     * those needed to check for and take tasks. This accounts for,
+     * among other things, updating random seed in place without
+     * storing it until exit.
+     *
+     * @return a task, or null if none found
+     */
+    private ForkJoinTask<?> scan() {
+        ForkJoinTask<?> t = null;
+        int r = seed;                    // extract once to keep scan quiet
+        ForkJoinWorkerThread[] ws;       // refreshed on outer loop
+        int mask;                        // must be power 2 minus 1 and > 0
+        outer:do {
+            if ((ws = pool.workers) != null && (mask = ws.length - 1) > 0) {
+                int idx = r;
+                int probes = ~mask;      // use random index while negative
+                for (;;) {
+                    r = xorShift(r);     // update random seed
+                    ForkJoinWorkerThread v = ws[mask & idx];
+                    if (v == null || v.sp == v.base) {
+                        if (probes <= mask)
+                            idx = (probes++ < 0) ? r : (idx + 1);
+                        else
+                            break;
+                    }
+                    else if (!tryActivate() || (t = v.deqTask()) == null)
+                        continue outer;  // restart on contention
+                    else
+                        break outer;
+                }
+            }
+        } while (pool.hasNewSyncEvent(this)); // retry on pool events
+        seed = r;
+        return t;
+    }
+
+    /**
+     * Gets and removes a local or stolen task.
+     *
+     * @return a task, if available
+     */
+    final ForkJoinTask<?> pollTask() {
+        ForkJoinTask<?> t = locallyFifo ? locallyDeqTask() : popTask();
+        if (t == null && (t = scan()) != null)
+            ++stealCount;
+        return t;
+    }
+
+    /**
+     * Gets a local task.
+     *
+     * @return a task, if available
+     */
+    final ForkJoinTask<?> pollLocalTask() {
+        return locallyFifo ? locallyDeqTask() : popTask();
+    }
+
+    /**
+     * Returns a pool submission, if one exists, activating first.
+     *
+     * @return a submission, if available
+     */
+    private ForkJoinTask<?> pollSubmission() {
+        ForkJoinPool p = pool;
+        while (p.hasQueuedSubmissions()) {
+            ForkJoinTask<?> t;
+            if (tryActivate() && (t = p.pollSubmission()) != null)
+                return t;
+        }
+        return null;
+    }
+
+    // Methods accessed only by Pool
+
+    /**
+     * Removes and cancels all tasks in queue.  Can be called from any
+     * thread.
+     */
+    final void cancelTasks() {
+        ForkJoinTask<?> t;
+        while (base != sp && (t = deqTask()) != null)
+            t.cancelIgnoringExceptions();
+    }
+
+    /**
+     * Drains tasks to given collection c.
+     *
+     * @return the number of tasks drained
+     */
+    final int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
+        int n = 0;
+        ForkJoinTask<?> t;
+        while (base != sp && (t = deqTask()) != null) {
+            c.add(t);
+            ++n;
+        }
+        return n;
+    }
+
+    /**
+     * Gets and clears steal count for accumulation by pool.  Called
+     * only when known to be idle (in pool.sync and termination).
+     */
+    final int getAndClearStealCount() {
+        int sc = stealCount;
+        stealCount = 0;
+        return sc;
+    }
+
+    /**
+     * Returns {@code true} if at least one worker in the given array
+     * appears to have at least one queued task.
+     *
+     * @param ws array of workers
+     */
+    static boolean hasQueuedTasks(ForkJoinWorkerThread[] ws) {
+        if (ws != null) {
+            int len = ws.length;
+            for (int j = 0; j < 2; ++j) { // need two passes for clean sweep
+                for (int i = 0; i < len; ++i) {
+                    ForkJoinWorkerThread w = ws[i];
+                    if (w != null && w.sp != w.base)
+                        return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    // Support methods for ForkJoinTask
+
+    /**
+     * Returns an estimate of the number of tasks in the queue.
+     */
+    final int getQueueSize() {
+        // suppress momentarily negative values
+        return Math.max(0, sp - base);
+    }
+
+    /**
+     * Returns an estimate of the number of tasks, offset by a
+     * function of number of idle workers.
+     */
+    final int getEstimatedSurplusTaskCount() {
+        // The halving approximates weighting idle vs non-idle workers
+        return (sp - base) - (pool.getIdleThreadCount() >>> 1);
+    }
+
+    /**
+     * Scans, returning early if joinMe done.
+     */
+    final ForkJoinTask<?> scanWhileJoining(ForkJoinTask<?> joinMe) {
+        ForkJoinTask<?> t = pollTask();
+        if (t != null && joinMe.status < 0 && sp == base) {
+            pushTask(t); // unsteal if done and this task would be stealable
+            t = null;
+        }
+        return t;
+    }
+
+    /**
+     * Runs tasks until {@code pool.isQuiescent()}.
+     */
+    final void helpQuiescePool() {
+        for (;;) {
+            ForkJoinTask<?> t = pollTask();
+            if (t != null)
+                t.quietlyExec();
+            else if (tryInactivate() && pool.isQuiescent())
+                break;
+        }
+        do {} while (!tryActivate()); // re-activate on exit
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long spOffset =
+        objectFieldOffset("sp", ForkJoinWorkerThread.class);
+    private static final long runStateOffset =
+        objectFieldOffset("runState", ForkJoinWorkerThread.class);
+    private static final long qBase;
+    private static final int qShift;
+
+    static {
+        qBase = UNSAFE.arrayBaseOffset(ForkJoinTask[].class);
+        int s = UNSAFE.arrayIndexScale(ForkJoinTask[].class);
+        if ((s & (s-1)) != 0)
+            throw new Error("data type scale not a power of two");
+        qShift = 31 - Integer.numberOfLeadingZeros(s);
+    }
+
+    private static long objectFieldOffset(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;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/concurrent/LinkedTransferQueue.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,1270 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.concurrent.locks.LockSupport;
+/**
+ * An unbounded {@link TransferQueue} based on linked nodes.
+ * This queue orders elements FIFO (first-in-first-out) with respect
+ * to any given producer.  The <em>head</em> of the queue is that
+ * element that has been on the queue the longest time for some
+ * producer.  The <em>tail</em> of the queue is that element that has
+ * been on the queue the shortest time for some producer.
+ *
+ * <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>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code LinkedTransferQueue}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code LinkedTransferQueue} 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
+ * @param <E> the type of elements held in this collection
+ */
+public class LinkedTransferQueue<E> extends AbstractQueue<E>
+    implements TransferQueue<E>, java.io.Serializable {
+    private static final long serialVersionUID = -3223113410248163686L;
+
+    /*
+     * *** Overview of Dual Queues with Slack ***
+     *
+     * Dual Queues, introduced by Scherer and Scott
+     * (http://www.cs.rice.edu/~wns1/papers/2004-DISC-DDS.pdf) are
+     * (linked) queues in which nodes may represent either data or
+     * requests.  When a thread tries to enqueue a data node, but
+     * encounters a request node, it instead "matches" and removes it;
+     * and vice versa for enqueuing requests. Blocking Dual Queues
+     * arrange that threads enqueuing unmatched requests block until
+     * other threads provide the match. Dual Synchronous Queues (see
+     * Scherer, Lea, & Scott
+     * http://www.cs.rochester.edu/u/scott/papers/2009_Scherer_CACM_SSQ.pdf)
+     * additionally arrange that threads enqueuing unmatched data also
+     * block.  Dual Transfer Queues support all of these modes, as
+     * dictated by callers.
+     *
+     * A FIFO dual queue may be implemented using a variation of the
+     * Michael & Scott (M&S) lock-free queue algorithm
+     * (http://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf).
+     * It maintains two pointer fields, "head", pointing to a
+     * (matched) node that in turn points to the first actual
+     * (unmatched) queue node (or null if empty); and "tail" that
+     * points to the last node on the queue (or again null if
+     * empty). For example, here is a possible queue with four data
+     * elements:
+     *
+     *  head                tail
+     *    |                   |
+     *    v                   v
+     *    M -> U -> U -> U -> U
+     *
+     * The M&S queue algorithm is known to be prone to scalability and
+     * overhead limitations when maintaining (via CAS) these head and
+     * tail pointers. This has led to the development of
+     * contention-reducing variants such as elimination arrays (see
+     * Moir et al http://portal.acm.org/citation.cfm?id=1074013) and
+     * optimistic back pointers (see Ladan-Mozes & Shavit
+     * http://people.csail.mit.edu/edya/publications/OptimisticFIFOQueue-journal.pdf).
+     * However, the nature of dual queues enables a simpler tactic for
+     * improving M&S-style implementations when dual-ness is needed.
+     *
+     * In a dual queue, each node must atomically maintain its match
+     * status. While there are other possible variants, we implement
+     * this here as: for a data-mode node, matching entails CASing an
+     * "item" field from a non-null data value to null upon match, and
+     * vice-versa for request nodes, CASing from null to a data
+     * value. (Note that the linearization properties of this style of
+     * queue are easy to verify -- elements are made available by
+     * linking, and unavailable by matching.) Compared to plain M&S
+     * queues, this property of dual queues requires one additional
+     * successful atomic operation per enq/deq pair. But it also
+     * enables lower cost variants of queue maintenance mechanics. (A
+     * variation of this idea applies even for non-dual queues that
+     * support deletion of interior elements, such as
+     * j.u.c.ConcurrentLinkedQueue.)
+     *
+     * Once a node is matched, its match status can never again
+     * change.  We may thus arrange that the linked list of them
+     * contain a prefix of zero or more matched nodes, followed by a
+     * suffix of zero or more unmatched nodes. (Note that we allow
+     * both the prefix and suffix to be zero length, which in turn
+     * means that we do not use a dummy header.)  If we were not
+     * concerned with either time or space efficiency, we could
+     * correctly perform enqueue and dequeue operations by traversing
+     * from a pointer to the initial node; CASing the item of the
+     * first unmatched node on match and CASing the next field of the
+     * trailing node on appends. (Plus some special-casing when
+     * initially empty).  While this would be a terrible idea in
+     * itself, it does have the benefit of not requiring ANY atomic
+     * updates on head/tail fields.
+     *
+     * We introduce here an approach that lies between the extremes of
+     * never versus always updating queue (head and tail) pointers.
+     * This offers a tradeoff between sometimes requiring extra
+     * traversal steps to locate the first and/or last unmatched
+     * nodes, versus the reduced overhead and contention of fewer
+     * updates to queue pointers. For example, a possible snapshot of
+     * a queue is:
+     *
+     *  head           tail
+     *    |              |
+     *    v              v
+     *    M -> M -> U -> U -> U -> U
+     *
+     * The best value for this "slack" (the targeted maximum distance
+     * between the value of "head" and the first unmatched node, and
+     * similarly for "tail") is an empirical matter. We have found
+     * that using very small constants in the range of 1-3 work best
+     * over a range of platforms. Larger values introduce increasing
+     * costs of cache misses and risks of long traversal chains, while
+     * smaller values increase CAS contention and overhead.
+     *
+     * Dual queues with slack differ from plain M&S dual queues by
+     * virtue of only sometimes updating head or tail pointers when
+     * matching, appending, or even traversing nodes; in order to
+     * maintain a targeted slack.  The idea of "sometimes" may be
+     * operationalized in several ways. The simplest is to use a
+     * per-operation counter incremented on each traversal step, and
+     * to try (via CAS) to update the associated queue pointer
+     * whenever the count exceeds a threshold. Another, that requires
+     * more overhead, is to use random number generators to update
+     * with a given probability per traversal step.
+     *
+     * In any strategy along these lines, because CASes updating
+     * fields may fail, the actual slack may exceed targeted
+     * slack. However, they may be retried at any time to maintain
+     * targets.  Even when using very small slack values, this
+     * approach works well for dual queues because it allows all
+     * operations up to the point of matching or appending an item
+     * (hence potentially allowing progress by another thread) to be
+     * read-only, thus not introducing any further contention. As
+     * described below, we implement this by performing slack
+     * maintenance retries only after these points.
+     *
+     * As an accompaniment to such techniques, traversal overhead can
+     * be further reduced without increasing contention of head
+     * pointer updates: Threads may sometimes shortcut the "next" link
+     * path from the current "head" node to be closer to the currently
+     * known first unmatched node, and similarly for tail. Again, this
+     * may be triggered with using thresholds or randomization.
+     *
+     * These ideas must be further extended to avoid unbounded amounts
+     * of costly-to-reclaim garbage caused by the sequential "next"
+     * links of nodes starting at old forgotten head nodes: As first
+     * described in detail by Boehm
+     * (http://portal.acm.org/citation.cfm?doid=503272.503282) if a GC
+     * delays noticing that any arbitrarily old node has become
+     * garbage, all newer dead nodes will also be unreclaimed.
+     * (Similar issues arise in non-GC environments.)  To cope with
+     * this in our implementation, upon CASing to advance the head
+     * pointer, we set the "next" link of the previous head to point
+     * only to itself; thus limiting the length of connected dead lists.
+     * (We also take similar care to wipe out possibly garbage
+     * retaining values held in other Node fields.)  However, doing so
+     * adds some further complexity to traversal: If any "next"
+     * pointer links to itself, it indicates that the current thread
+     * has lagged behind a head-update, and so the traversal must
+     * continue from the "head".  Traversals trying to find the
+     * current tail starting from "tail" may also encounter
+     * self-links, in which case they also continue at "head".
+     *
+     * It is tempting in slack-based scheme to not even use CAS for
+     * updates (similarly to Ladan-Mozes & Shavit). However, this
+     * cannot be done for head updates under the above link-forgetting
+     * mechanics because an update may leave head at a detached node.
+     * And while direct writes are possible for tail updates, they
+     * increase the risk of long retraversals, and hence long garbage
+     * chains, which can be much more costly than is worthwhile
+     * considering that the cost difference of performing a CAS vs
+     * write is smaller when they are not triggered on each operation
+     * (especially considering that writes and CASes equally require
+     * additional GC bookkeeping ("write barriers") that are sometimes
+     * more costly than the writes themselves because of contention).
+     *
+     * Removal of interior nodes (due to timed out or interrupted
+     * waits, or calls to remove(x) or Iterator.remove) can use a
+     * scheme roughly similar to that described in Scherer, Lea, and
+     * Scott's SynchronousQueue. Given a predecessor, we can unsplice
+     * any node except the (actual) tail of the queue. To avoid
+     * build-up of cancelled trailing nodes, upon a request to remove
+     * a trailing node, it is placed in field "cleanMe" to be
+     * unspliced upon the next call to unsplice any other node.
+     * Situations needing such mechanics are not common but do occur
+     * in practice; for example when an unbounded series of short
+     * timed calls to poll repeatedly time out but never otherwise
+     * fall off the list because of an untimed call to take at the
+     * front of the queue. Note that maintaining field cleanMe does
+     * not otherwise much impact garbage retention even if never
+     * cleared by some other call because the held node will
+     * eventually either directly or indirectly lead to a self-link
+     * once off the list.
+     *
+     * *** Overview of implementation ***
+     *
+     * We use a threshold-based approach to updates, with 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. The slack value is hard-wired: a path greater
+     * than one is naturally implemented by checking equality of
+     * traversal pointers except when the list has only one element,
+     * in which case we keep slack threshold at one. Avoiding tracking
+     * explicit counts across method calls slightly simplifies an
+     * already-messy implementation. Using randomization would
+     * probably work better if there were a low-quality dirt-cheap
+     * per-thread one available, but even ThreadLocalRandom is too
+     * heavy for these purposes.
+     *
+     * With such a small slack threshold value, it is rarely
+     * worthwhile to augment this with path short-circuiting; i.e.,
+     * unsplicing nodes between head and the first unmatched node, or
+     * similarly for tail, rather than advancing head or tail
+     * proper. However, it is used (in awaitMatch) immediately before
+     * a waiting thread starts to block, as a final bit of helping at
+     * a point when contention with others is extremely unlikely
+     * (since if other threads that could release it are operating,
+     * then the current thread wouldn't be blocking).
+     *
+     * We allow both the head and tail fields to be null before any
+     * nodes are enqueued; initializing upon first append.  This
+     * simplifies some other logic, as well as providing more
+     * efficient explicit control paths instead of letting JVMs insert
+     * implicit NullPointerExceptions when they are null.  While not
+     * currently fully implemented, we also leave open the possibility
+     * of re-nulling these fields when empty (which is complicated to
+     * arrange, for little benefit.)
+     *
+     * All enqueue/dequeue operations are handled by the single method
+     * "xfer" with parameters indicating whether to act as some form
+     * of offer, put, poll, take, or transfer (each possibly with
+     * timeout). The relative complexity of using one monolithic
+     * method outweighs the code bulk and maintenance problems of
+     * using separate methods for each case.
+     *
+     * Operation consists of up to three phases. The first is
+     * implemented within method xfer, the second in tryAppend, and
+     * the third in method awaitMatch.
+     *
+     * 1. Try to match an existing node
+     *
+     *    Starting at head, skip already-matched nodes until finding
+     *    an unmatched node of opposite mode, if one exists, in which
+     *    case matching it and returning, also if necessary updating
+     *    head to one past the matched node (or the node itself if the
+     *    list has no other unmatched nodes). If the CAS misses, then
+     *    a loop retries advancing head by two steps until either
+     *    success or the slack is at most two. By requiring that each
+     *    attempt advances head by two (if applicable), we ensure that
+     *    the slack does not grow without bound. Traversals also check
+     *    if the initial head is now off-list, in which case they
+     *    start at the new head.
+     *
+     *    If no candidates are found and the call was untimed
+     *    poll/offer, (argument "how" is NOW) return.
+     *
+     * 2. Try to append a new node (method tryAppend)
+     *
+     *    Starting at current tail pointer, find the actual last node
+     *    and try to append a new node (or if head was null, establish
+     *    the first node). Nodes can be appended only if their
+     *    predecessors are either already matched or are of the same
+     *    mode. If we detect otherwise, then a new node with opposite
+     *    mode must have been appended during traversal, so we must
+     *    restart at phase 1. The traversal and update steps are
+     *    otherwise similar to phase 1: Retrying upon CAS misses and
+     *    checking for staleness.  In particular, if a self-link is
+     *    encountered, then we can safely jump to a node on the list
+     *    by continuing the traversal at current head.
+     *
+     *    On successful append, if the call was ASYNC, return.
+     *
+     * 3. Await match or cancellation (method awaitMatch)
+     *
+     *    Wait for another thread to match node; instead cancelling if
+     *    the current thread was interrupted or the wait timed out. On
+     *    multiprocessors, we use front-of-queue spinning: If a node
+     *    appears to be the first unmatched node in the queue, it
+     *    spins a bit before blocking. In either case, before blocking
+     *    it tries to unsplice any nodes between the current "head"
+     *    and the first unmatched node.
+     *
+     *    Front-of-queue spinning vastly improves performance of
+     *    heavily contended queues. And so long as it is relatively
+     *    brief and "quiet", spinning does not much impact performance
+     *    of less-contended queues.  During spins threads check their
+     *    interrupt status and generate a thread-local random number
+     *    to decide to occasionally perform a Thread.yield. While
+     *    yield has underdefined specs, we assume that might it help,
+     *    and will not hurt in limiting impact of spinning on busy
+     *    systems.  We also use smaller (1/2) spins for nodes that are
+     *    not known to be front but whose predecessors have not
+     *    blocked -- these "chained" spins avoid artifacts of
+     *    front-of-queue rules which otherwise lead to alternating
+     *    nodes spinning vs blocking. Further, front threads that
+     *    represent phase changes (from data to request node or vice
+     *    versa) compared to their predecessors receive additional
+     *    chained spins, reflecting longer paths typically required to
+     *    unblock threads during phase changes.
+     */
+
+    /** True if on multiprocessor */
+    private static final boolean MP =
+        Runtime.getRuntime().availableProcessors() > 1;
+
+    /**
+     * The number of times to spin (with randomly interspersed calls
+     * to Thread.yield) on multiprocessor before blocking when a node
+     * is apparently the first waiter in the queue.  See above for
+     * explanation. Must be a power of two. The value is empirically
+     * derived -- it works pretty well across a variety of processors,
+     * numbers of CPUs, and OSes.
+     */
+    private static final int FRONT_SPINS   = 1 << 7;
+
+    /**
+     * The number of times to spin before blocking when a node is
+     * preceded by another node that is apparently spinning.  Also
+     * serves as an increment to FRONT_SPINS on phase changes, and as
+     * base average frequency for yielding during spins. Must be a
+     * power of two.
+     */
+    private static final int CHAINED_SPINS = FRONT_SPINS >>> 1;
+
+    /**
+     * Queue nodes. Uses Object, not E, for items to allow forgetting
+     * them after use.  Relies heavily on Unsafe mechanics to minimize
+     * unnecessary ordering constraints: Writes that intrinsically
+     * precede or follow CASes use simple relaxed forms.  Other
+     * cleanups use releasing/lazy writes.
+     */
+    static final class Node {
+        final boolean isData;   // false if this is a request node
+        volatile Object item;   // initially non-null if isData; CASed to match
+        volatile Node next;
+        volatile Thread waiter; // null until waiting
+
+        // CAS methods for fields
+        final boolean casNext(Node cmp, Node val) {
+            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+        }
+
+        final boolean casItem(Object cmp, Object val) {
+            // assert cmp == null || cmp.getClass() != Node.class;
+            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+        }
+
+        /**
+         * Creates a new node. Uses relaxed write because item can only
+         * be seen if followed by CAS.
+         */
+        Node(Object item, boolean isData) {
+            UNSAFE.putObject(this, itemOffset, item); // relaxed write
+            this.isData = isData;
+        }
+
+        /**
+         * Links node to itself to avoid garbage retention.  Called
+         * only after CASing head field, so uses relaxed write.
+         */
+        final void forgetNext() {
+            UNSAFE.putObject(this, nextOffset, this);
+        }
+
+        /**
+         * Sets item to self (using a releasing/lazy write) and waiter
+         * to null, to avoid garbage retention after extracting or
+         * cancelling.
+         */
+        final void forgetContents() {
+            UNSAFE.putOrderedObject(this, itemOffset, this);
+            UNSAFE.putOrderedObject(this, waiterOffset, null);
+        }
+
+        /**
+         * Returns true if this node has been matched, including the
+         * case of artificial matches due to cancellation.
+         */
+        final boolean isMatched() {
+            Object x = item;
+            return (x == this) || ((x == null) == isData);
+        }
+
+        /**
+         * Returns true if this is an unmatched request node.
+         */
+        final boolean isUnmatchedRequest() {
+            return !isData && item == null;
+        }
+
+        /**
+         * Returns true if a node with the given mode cannot be
+         * appended to this node because this node is unmatched and
+         * has opposite data mode.
+         */
+        final boolean cannotPrecede(boolean haveData) {
+            boolean d = isData;
+            Object x;
+            return d != haveData && (x = item) != this && (x != null) == d;
+        }
+
+        /**
+         * Tries to artificially match a data node -- used by remove.
+         */
+        final boolean tryMatchData() {
+            // assert isData;
+            Object x = item;
+            if (x != null && x != this && casItem(x, null)) {
+                LockSupport.unpark(waiter);
+                return true;
+            }
+            return false;
+        }
+
+        // Unsafe mechanics
+        private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+        private static final long nextOffset =
+            objectFieldOffset(UNSAFE, "next", Node.class);
+        private static final long itemOffset =
+            objectFieldOffset(UNSAFE, "item", Node.class);
+        private static final long waiterOffset =
+            objectFieldOffset(UNSAFE, "waiter", Node.class);
+
+        private static final long serialVersionUID = -3375979862319811754L;
+    }
+
+    /** head of the queue; null until first enqueue */
+    transient volatile Node head;
+
+    /** predecessor of dangling unspliceable node */
+    private transient volatile Node cleanMe; // decl here reduces contention
+
+    /** tail of the queue; null until first append */
+    private transient volatile Node tail;
+
+    // CAS methods for fields
+    private boolean casTail(Node cmp, Node val) {
+        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+    }
+
+    private boolean casHead(Node cmp, Node val) {
+        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+    }
+
+    private boolean casCleanMe(Node cmp, Node val) {
+        return UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val);
+    }
+
+    /*
+     * Possible values for "how" argument in xfer method.
+     */
+    private static final int NOW   = 0; // for untimed poll, tryTransfer
+    private static final int ASYNC = 1; // for offer, put, add
+    private static final int SYNC  = 2; // for transfer, take
+    private static final int TIMED = 3; // for timed poll, tryTransfer
+
+    @SuppressWarnings("unchecked")
+    static <E> E cast(Object item) {
+        // assert item == null || item.getClass() != Node.class;
+        return (E) item;
+    }
+
+    /**
+     * Implements all queuing methods. See above for explanation.
+     *
+     * @param e the item or null for take
+     * @param haveData true if this is a put, else a take
+     * @param how NOW, ASYNC, SYNC, or TIMED
+     * @param nanos timeout in nanosecs, used only if mode is TIMED
+     * @return an item if matched, else e
+     * @throws NullPointerException if haveData mode but e is null
+     */
+    private E xfer(E e, boolean haveData, int how, long nanos) {
+        if (haveData && (e == null))
+            throw new NullPointerException();
+        Node s = null;                        // the node to append, if needed
+
+        retry: for (;;) {                     // restart on append race
+
+            for (Node h = head, p = h; p != null;) { // find & match first node
+                boolean isData = p.isData;
+                Object item = p.item;
+                if (item != p && (item != null) == isData) { // unmatched
+                    if (isData == haveData)   // can't match
+                        break;
+                    if (p.casItem(item, e)) { // match
+                        for (Node q = p; q != h;) {
+                            Node n = q.next;  // update head by 2
+                            if (n != null)    // unless singleton
+                                q = n;
+                            if (head == h && casHead(h, q)) {
+                                h.forgetNext();
+                                break;
+                            }                 // advance and retry
+                            if ((h = head)   == null ||
+                                (q = h.next) == null || !q.isMatched())
+                                break;        // unless slack < 2
+                        }
+                        LockSupport.unpark(p.waiter);
+                        return this.<E>cast(item);
+                    }
+                }
+                Node n = p.next;
+                p = (p != n) ? n : (h = head); // Use head if p offlist
+            }
+
+            if (how != NOW) {                 // No matches available
+                if (s == null)
+                    s = new Node(e, haveData);
+                Node pred = tryAppend(s, haveData);
+                if (pred == null)
+                    continue retry;           // lost race vs opposite mode
+                if (how != ASYNC)
+                    return awaitMatch(s, pred, e, (how == TIMED), nanos);
+            }
+            return e; // not waiting
+        }
+    }
+
+    /**
+     * Tries to append node s as tail.
+     *
+     * @param s the node to append
+     * @param haveData true if appending in data mode
+     * @return null on failure due to losing race with append in
+     * different mode, else s's predecessor, or s itself if no
+     * predecessor
+     */
+    private Node tryAppend(Node s, boolean haveData) {
+        for (Node t = tail, p = t;;) {        // move p to last node and append
+            Node n, u;                        // temps for reads of next & tail
+            if (p == null && (p = head) == null) {
+                if (casHead(null, s))
+                    return s;                 // initialize
+            }
+            else if (p.cannotPrecede(haveData))
+                return null;                  // lost race vs opposite mode
+            else if ((n = p.next) != null)    // not last; keep traversing
+                p = p != t && t != (u = tail) ? (t = u) : // stale tail
+                    (p != n) ? n : null;      // restart if off list
+            else if (!p.casNext(null, s))
+                p = p.next;                   // re-read on CAS failure
+            else {
+                if (p != t) {                 // update if slack now >= 2
+                    while ((tail != t || !casTail(t, s)) &&
+                           (t = tail)   != null &&
+                           (s = t.next) != null && // advance and retry
+                           (s = s.next) != null && s != t);
+                }
+                return p;
+            }
+        }
+    }
+
+    /**
+     * Spins/yields/blocks until node s is matched or caller gives up.
+     *
+     * @param s the waiting node
+     * @param pred the predecessor of s, or s itself if it has no
+     * predecessor, or null if unknown (the null case does not occur
+     * in any current calls but may in possible future extensions)
+     * @param e the comparison value for checking match
+     * @param timed if true, wait only until timeout elapses
+     * @param nanos timeout in nanosecs, used only if timed is true
+     * @return matched item, or e if unmatched on interrupt or timeout
+     */
+    private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) {
+        long lastTime = timed ? System.nanoTime() : 0L;
+        Thread w = Thread.currentThread();
+        int spins = -1; // initialized after first item and cancel checks
+        ThreadLocalRandom randomYields = null; // bound if needed
+
+        for (;;) {
+            Object item = s.item;
+            if (item != e) {                  // matched
+                // assert item != s;
+                s.forgetContents();           // avoid garbage
+                return this.<E>cast(item);
+            }
+            if ((w.isInterrupted() || (timed && nanos <= 0)) &&
+                    s.casItem(e, s)) {       // cancel
+                unsplice(pred, s);
+                return e;
+            }
+
+            if (spins < 0) {                  // establish spins at/near front
+                if ((spins = spinsFor(pred, s.isData)) > 0)
+                    randomYields = ThreadLocalRandom.current();
+            }
+            else if (spins > 0) {             // spin
+                if (--spins == 0)
+                    shortenHeadPath();        // reduce slack before blocking
+                else if (randomYields.nextInt(CHAINED_SPINS) == 0)
+                    Thread.yield();           // occasionally yield
+            }
+            else if (s.waiter == null) {
+                s.waiter = w;                 // request unpark then recheck
+            }
+            else if (timed) {
+                long now = System.nanoTime();
+                if ((nanos -= now - lastTime) > 0)
+                    LockSupport.parkNanos(this, nanos);
+                lastTime = now;
+            }
+            else {
+                LockSupport.park(this);
+                s.waiter = null;
+                spins = -1;                   // spin if front upon wakeup
+            }
+        }
+    }
+
+    /**
+     * Returns spin/yield value for a node with given predecessor and
+     * data mode. See above for explanation.
+     */
+    private static int spinsFor(Node pred, boolean haveData) {
+        if (MP && pred != null) {
+            if (pred.isData != haveData)      // phase change
+                return FRONT_SPINS + CHAINED_SPINS;
+            if (pred.isMatched())             // probably at front
+                return FRONT_SPINS;
+            if (pred.waiter == null)          // pred apparently spinning
+                return CHAINED_SPINS;
+        }
+        return 0;
+    }
+
+    /**
+     * Tries (once) to unsplice nodes between head and first unmatched
+     * or trailing node; failing on contention.
+     */
+    private void shortenHeadPath() {
+        Node h, hn, p, q;
+        if ((p = h = head) != null && h.isMatched() &&
+            (q = hn = h.next) != null) {
+            Node n;
+            while ((n = q.next) != q) {
+                if (n == null || !q.isMatched()) {
+                    if (hn != q && h.next == hn)
+                        h.casNext(hn, q);
+                    break;
+                }
+                p = q;
+                q = n;
+            }
+        }
+    }
+
+    /* -------------- Traversal methods -------------- */
+
+    /**
+     * Returns the successor of p, or the head 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 succ(Node p) {
+        Node next = p.next;
+        return (p == next) ? head : next;
+    }
+
+    /**
+     * Returns the first unmatched node of the given mode, or null if
+     * none.  Used by methods isEmpty, hasWaitingConsumer.
+     */
+    private Node firstOfMode(boolean isData) {
+        for (Node p = head; p != null; p = succ(p)) {
+            if (!p.isMatched())
+                return (p.isData == isData) ? p : null;
+        }
+        return null;
+    }
+
+    /**
+     * Returns the item in the first unmatched node with isData; or
+     * null if none.  Used by peek.
+     */
+    private E firstDataItem() {
+        for (Node p = head; p != null; p = succ(p)) {
+            Object item = p.item;
+            if (p.isData) {
+                if (item != null && item != p)
+                    return this.<E>cast(item);
+            }
+            else if (item == null)
+                return null;
+        }
+        return null;
+    }
+
+    /**
+     * Traverses and counts unmatched nodes of the given mode.
+     * Used by methods size and getWaitingConsumerCount.
+     */
+    private int countOfMode(boolean data) {
+        int count = 0;
+        for (Node p = head; p != null; ) {
+            if (!p.isMatched()) {
+                if (p.isData != data)
+                    return 0;
+                if (++count == Integer.MAX_VALUE) // saturated
+                    break;
+            }
+            Node n = p.next;
+            if (n != p)
+                p = n;
+            else {
+                count = 0;
+                p = head;
+            }
+        }
+        return count;
+    }
+
+    final class Itr implements Iterator<E> {
+        private Node nextNode;   // next node to return item for
+        private E nextItem;      // the corresponding item
+        private Node lastRet;    // last returned node, to support remove
+        private Node lastPred;   // predecessor to unlink lastRet
+
+        /**
+         * Moves to next node after prev, or first node if prev null.
+         */
+        private void advance(Node prev) {
+            lastPred = lastRet;
+            lastRet = prev;
+            for (Node p = (prev == null) ? head : succ(prev);
+                 p != null; p = succ(p)) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p) {
+                        nextItem = LinkedTransferQueue.this.<E>cast(item);
+                        nextNode = p;
+                        return;
+                    }
+                }
+                else if (item == null)
+                    break;
+            }
+            nextNode = null;
+        }
+
+        Itr() {
+            advance(null);
+        }
+
+        public final boolean hasNext() {
+            return nextNode != null;
+        }
+
+        public final E next() {
+            Node p = nextNode;
+            if (p == null) throw new NoSuchElementException();
+            E e = nextItem;
+            advance(p);
+            return e;
+        }
+
+        public final void remove() {
+            Node p = lastRet;
+            if (p == null) throw new IllegalStateException();
+            findAndRemoveDataNode(lastPred, p);
+        }
+    }
+
+    /* -------------- Removal methods -------------- */
+
+    /**
+     * Unsplices (now or later) the given deleted/cancelled node with
+     * the given predecessor.
+     *
+     * @param pred predecessor of node to be unspliced
+     * @param s the node to be unspliced
+     */
+    private void unsplice(Node pred, Node s) {
+        s.forgetContents(); // clear unneeded fields
+        /*
+         * At any given time, exactly one node on list cannot be
+         * unlinked -- the last inserted node. To accommodate this, if
+         * we cannot unlink s, we save its predecessor as "cleanMe",
+         * processing the previously saved version first. Because only
+         * one node in the list can have a null next, at least one of
+         * node s or the node previously saved can always be
+         * processed, so this always terminates.
+         */
+        if (pred != null && pred != s) {
+            while (pred.next == s) {
+                Node oldpred = (cleanMe == null) ? null : reclean();
+                Node n = s.next;
+                if (n != null) {
+                    if (n != s)
+                        pred.casNext(s, n);
+                    break;
+                }
+                if (oldpred == pred ||      // Already saved
+                    ((oldpred == null || oldpred.next == s) &&
+                     casCleanMe(oldpred, pred))) {
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Tries to unsplice the deleted/cancelled node held in cleanMe
+     * that was previously uncleanable because it was at tail.
+     *
+     * @return current cleanMe node (or null)
+     */
+    private Node reclean() {
+        /*
+         * cleanMe is, or at one time was, predecessor of a cancelled
+         * node s that was the tail so could not be unspliced.  If it
+         * is no longer the tail, try to unsplice if necessary and
+         * make cleanMe slot available.  This differs from similar
+         * code in unsplice() because we must check that pred still
+         * points to a matched node that can be unspliced -- if not,
+         * we can (must) clear cleanMe without unsplicing.  This can
+         * loop only due to contention.
+         */
+        Node pred;
+        while ((pred = cleanMe) != null) {
+            Node s = pred.next;
+            Node n;
+            if (s == null || s == pred || !s.isMatched())
+                casCleanMe(pred, null); // already gone
+            else if ((n = s.next) != null) {
+                if (n != s)
+                    pred.casNext(s, n);
+                casCleanMe(pred, null);
+            }
+            else
+                break;
+        }
+        return pred;
+    }
+
+    /**
+     * Main implementation of Iterator.remove(). Finds
+     * and unsplices the given data node.
+     *
+     * @param possiblePred possible predecessor of s
+     * @param s the node to remove
+     */
+    final void findAndRemoveDataNode(Node possiblePred, Node s) {
+        // assert s.isData;
+        if (s.tryMatchData()) {
+            if (possiblePred != null && possiblePred.next == s)
+                unsplice(possiblePred, s); // was actual predecessor
+            else {
+                for (Node pred = null, p = head; p != null; ) {
+                    if (p == s) {
+                        unsplice(pred, p);
+                        break;
+                    }
+                    if (p.isUnmatchedRequest())
+                        break;
+                    pred = p;
+                    if ((p = p.next) == pred) { // stale
+                        pred = null;
+                        p = head;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Main implementation of remove(Object)
+     */
+    private boolean findAndRemove(Object e) {
+        if (e != null) {
+            for (Node pred = null, p = head; p != null; ) {
+                Object item = p.item;
+                if (p.isData) {
+                    if (item != null && item != p && e.equals(item) &&
+                        p.tryMatchData()) {
+                        unsplice(pred, p);
+                        return true;
+                    }
+                }
+                else if (item == null)
+                    break;
+                pred = p;
+                if ((p = p.next) == pred) { // stale
+                    pred = null;
+                    p = head;
+                }
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * Creates an initially empty {@code LinkedTransferQueue}.
+     */
+    public LinkedTransferQueue() {
+    }
+
+    /**
+     * Creates a {@code LinkedTransferQueue}
+     * 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 LinkedTransferQueue(Collection<? extends E> c) {
+        this();
+        addAll(c);
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue.
+     * As the queue is unbounded, this method will never block.
+     *
+     * @throws NullPointerException if the specified element is null
+     */
+    public void put(E e) {
+        xfer(e, true, ASYNC, 0);
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue.
+     * As the queue is unbounded, this method will never block or
+     * return {@code false}.
+     *
+     * @return {@code true} (as specified by
+     *  {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer})
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean offer(E e, long timeout, TimeUnit unit) {
+        xfer(e, true, ASYNC, 0);
+        return true;
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue.
+     * As the queue is unbounded, this method will never return {@code false}.
+     *
+     * @return {@code true} (as specified by
+     *         {@link BlockingQueue#offer(Object) BlockingQueue.offer})
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean offer(E e) {
+        xfer(e, true, ASYNC, 0);
+        return true;
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue.
+     * As the queue is unbounded, this method will never throw
+     * {@link IllegalStateException} or return {@code false}.
+     *
+     * @return {@code true} (as specified by {@link Collection#add})
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean add(E e) {
+        xfer(e, true, ASYNC, 0);
+        return true;
+    }
+
+    /**
+     * Transfers the element to a waiting consumer immediately, if possible.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * otherwise returning {@code false} without enqueuing the element.
+     *
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean tryTransfer(E e) {
+        return xfer(e, true, NOW, 0) == null;
+    }
+
+    /**
+     * Transfers the element to a consumer, waiting if necessary to do so.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * else inserts the specified element at the tail of this queue
+     * and waits until the element is received by a consumer.
+     *
+     * @throws NullPointerException if the specified element is null
+     */
+    public void transfer(E e) throws InterruptedException {
+        if (xfer(e, true, SYNC, 0) != null) {
+            Thread.interrupted(); // failure possible only due to interrupt
+            throw new InterruptedException();
+        }
+    }
+
+    /**
+     * Transfers the element to a consumer if it is possible to do so
+     * before the timeout elapses.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * else inserts the specified element at the tail of this queue
+     * and waits until the element is received by a consumer,
+     * returning {@code false} if the specified wait time elapses
+     * before the element can be transferred.
+     *
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean tryTransfer(E e, long timeout, TimeUnit unit)
+        throws InterruptedException {
+        if (xfer(e, true, TIMED, unit.toNanos(timeout)) == null)
+            return true;
+        if (!Thread.interrupted())
+            return false;
+        throw new InterruptedException();
+    }
+
+    public E take() throws InterruptedException {
+        E e = xfer(null, false, SYNC, 0);
+        if (e != null)
+            return e;
+        Thread.interrupted();
+        throw new InterruptedException();
+    }
+
+    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+        E e = xfer(null, false, TIMED, unit.toNanos(timeout));
+        if (e != null || !Thread.interrupted())
+            return e;
+        throw new InterruptedException();
+    }
+
+    public E poll() {
+        return xfer(null, false, NOW, 0);
+    }
+
+    /**
+     * @throws NullPointerException     {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
+     */
+    public int drainTo(Collection<? super E> c) {
+        if (c == null)
+            throw new NullPointerException();
+        if (c == this)
+            throw new IllegalArgumentException();
+        int n = 0;
+        E e;
+        while ( (e = poll()) != null) {
+            c.add(e);
+            ++n;
+        }
+        return n;
+    }
+
+    /**
+     * @throws NullPointerException     {@inheritDoc}
+     * @throws IllegalArgumentException {@inheritDoc}
+     */
+    public int drainTo(Collection<? super E> c, int maxElements) {
+        if (c == null)
+            throw new NullPointerException();
+        if (c == this)
+            throw new IllegalArgumentException();
+        int n = 0;
+        E e;
+        while (n < maxElements && (e = poll()) != null) {
+            c.add(e);
+            ++n;
+        }
+        return n;
+    }
+
+    /**
+     * Returns an iterator over the elements in this queue in proper
+     * sequence, from head to tail.
+     *
+     * <p>The returned iterator is a "weakly consistent" iterator that
+     * will never throw
+     * {@link 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 queue in proper sequence
+     */
+    public Iterator<E> iterator() {
+        return new Itr();
+    }
+
+    public E peek() {
+        return firstDataItem();
+    }
+
+    /**
+     * Returns {@code true} if this queue contains no elements.
+     *
+     * @return {@code true} if this queue contains no elements
+     */
+    public boolean isEmpty() {
+        return firstOfMode(true) == null;
+    }
+
+    public boolean hasWaitingConsumer() {
+        return firstOfMode(false) != null;
+    }
+
+    /**
+     * Returns the number of elements in this queue.  If this queue
+     * contains more than {@code Integer.MAX_VALUE} elements, 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 queues, determining the current
+     * number of elements requires an O(n) traversal.
+     *
+     * @return the number of elements in this queue
+     */
+    public int size() {
+        return countOfMode(true);
+    }
+
+    public int getWaitingConsumerCount() {
+        return countOfMode(false);
+    }
+
+    /**
+     * Removes a single instance of the specified element from this queue,
+     * if it is present.  More formally, removes an element {@code e} such
+     * that {@code o.equals(e)}, if this queue contains one or more such
+     * elements.
+     * Returns {@code true} if this queue contained the specified element
+     * (or equivalently, if this queue changed as a result of the call).
+     *
+     * @param o element to be removed from this queue, if present
+     * @return {@code true} if this queue changed as a result of the call
+     */
+    public boolean remove(Object o) {
+        return findAndRemove(o);
+    }
+
+    /**
+     * Always returns {@code Integer.MAX_VALUE} because a
+     * {@code LinkedTransferQueue} is not capacity constrained.
+     *
+     * @return {@code Integer.MAX_VALUE} (as specified by
+     *         {@link BlockingQueue#remainingCapacity()})
+     */
+    public int remainingCapacity() {
+        return Integer.MAX_VALUE;
+    }
+
+    /**
+     * 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 {
+        s.defaultWriteObject();
+        for (E e : this)
+            s.writeObject(e);
+        // Use trailing null as sentinel
+        s.writeObject(null);
+    }
+
+    /**
+     * Reconstitutes the Queue 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();
+        for (;;) {
+            @SuppressWarnings("unchecked") E item = (E) s.readObject();
+            if (item == null)
+                break;
+            else
+                offer(item);
+        }
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long headOffset =
+        objectFieldOffset(UNSAFE, "head", LinkedTransferQueue.class);
+    private static final long tailOffset =
+        objectFieldOffset(UNSAFE, "tail", LinkedTransferQueue.class);
+    private static final long cleanMeOffset =
+        objectFieldOffset(UNSAFE, "cleanMe", LinkedTransferQueue.class);
+
+    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;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/concurrent/Phaser.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,1042 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.LockSupport;
+
+/**
+ * A reusable synchronization barrier, similar in functionality to
+ * {@link java.util.concurrent.CyclicBarrier CyclicBarrier} and
+ * {@link java.util.concurrent.CountDownLatch CountDownLatch}
+ * but supporting more flexible usage.
+ *
+ * <p> <b>Registration.</b> Unlike the case for other barriers, the
+ * number of parties <em>registered</em> to synchronize on a phaser
+ * may vary over time.  Tasks may be registered at any time (using
+ * methods {@link #register}, {@link #bulkRegister}, or forms of
+ * constructors establishing initial numbers of parties), and
+ * optionally deregistered upon any arrival (using {@link
+ * #arriveAndDeregister}).  As is the case with most basic
+ * synchronization constructs, registration and deregistration affect
+ * only internal counts; they do not establish any further internal
+ * bookkeeping, so tasks cannot query whether they are registered.
+ * (However, you can introduce such bookkeeping by subclassing this
+ * class.)
+ *
+ * <p> <b>Synchronization.</b> Like a {@code CyclicBarrier}, a {@code
+ * Phaser} may be repeatedly awaited.  Method {@link
+ * #arriveAndAwaitAdvance} has effect analogous to {@link
+ * java.util.concurrent.CyclicBarrier#await CyclicBarrier.await}. Each
+ * generation of a {@code Phaser} has an associated phase number. The
+ * phase number starts at zero, and advances when all parties arrive
+ * at the barrier, wrapping around to zero after reaching {@code
+ * Integer.MAX_VALUE}. The use of phase numbers enables independent
+ * control of actions upon arrival at a barrier and upon awaiting
+ * others, via two kinds of methods that may be invoked by any
+ * registered party:
+ *
+ * <ul>
+ *
+ *   <li> <b>Arrival.</b> Methods {@link #arrive} and
+ *       {@link #arriveAndDeregister} record arrival at a
+ *       barrier. These methods do not block, but return an associated
+ *       <em>arrival phase number</em>; that is, the phase number of
+ *       the barrier to which the arrival applied. When the final
+ *       party for a given phase arrives, an optional barrier action
+ *       is performed and the phase advances.  Barrier actions,
+ *       performed by the party triggering a phase advance, are
+ *       arranged by overriding method {@link #onAdvance(int, int)},
+ *       which also controls termination. Overriding this method is
+ *       similar to, but more flexible than, providing a barrier
+ *       action to a {@code CyclicBarrier}.
+ *
+ *   <li> <b>Waiting.</b> Method {@link #awaitAdvance} requires an
+ *       argument indicating an arrival phase number, and returns when
+ *       the barrier advances to (or is already at) a different phase.
+ *       Unlike similar constructions using {@code CyclicBarrier},
+ *       method {@code awaitAdvance} continues to wait even if the
+ *       waiting thread is interrupted. Interruptible and timeout
+ *       versions are also available, but exceptions encountered while
+ *       tasks wait interruptibly or with timeout do not change the
+ *       state of the barrier. If necessary, you can perform any
+ *       associated recovery within handlers of those exceptions,
+ *       often after invoking {@code forceTermination}.  Phasers may
+ *       also be used by tasks executing in a {@link ForkJoinPool},
+ *       which will ensure sufficient parallelism to execute tasks
+ *       when others are blocked waiting for a phase to advance.
+ *
+ * </ul>
+ *
+ * <p> <b>Termination.</b> A {@code Phaser} may enter a
+ * <em>termination</em> state in which all synchronization methods
+ * immediately return without updating phaser state or waiting for
+ * advance, and indicating (via a negative phase value) that execution
+ * is complete.  Termination is triggered when an invocation of {@code
+ * onAdvance} returns {@code true}.  As illustrated below, when
+ * phasers control actions with a fixed number of iterations, it is
+ * often convenient to override this method to cause termination when
+ * the current phase number reaches a threshold. Method {@link
+ * #forceTermination} is also available to abruptly release waiting
+ * threads and allow them to terminate.
+ *
+ * <p> <b>Tiering.</b> Phasers may be <em>tiered</em> (i.e., arranged
+ * in tree structures) to reduce contention. Phasers with large
+ * numbers of parties that would otherwise experience heavy
+ * synchronization contention costs may instead be set up so that
+ * groups of sub-phasers share a common parent.  This may greatly
+ * increase throughput even though it incurs greater per-operation
+ * overhead.
+ *
+ * <p><b>Monitoring.</b> While synchronization methods may be invoked
+ * only by registered parties, the current state of a phaser may be
+ * monitored by any caller.  At any given moment there are {@link
+ * #getRegisteredParties} parties in total, of which {@link
+ * #getArrivedParties} have arrived at the current phase ({@link
+ * #getPhase}).  When the remaining ({@link #getUnarrivedParties})
+ * parties arrive, the phase advances.  The values returned by these
+ * methods may reflect transient states and so are not in general
+ * useful for synchronization control.  Method {@link #toString}
+ * returns snapshots of these state queries in a form convenient for
+ * informal monitoring.
+ *
+ * <p><b>Sample usages:</b>
+ *
+ * <p>A {@code Phaser} may be used instead of a {@code CountDownLatch}
+ * to control a one-shot action serving a variable number of
+ * parties. The typical idiom is for the method setting this up to
+ * first register, then start the actions, then deregister, as in:
+ *
+ *  <pre> {@code
+ * void runTasks(List<Runnable> tasks) {
+ *   final Phaser phaser = new Phaser(1); // "1" to register self
+ *   // create and start threads
+ *   for (Runnable task : tasks) {
+ *     phaser.register();
+ *     new Thread() {
+ *       public void run() {
+ *         phaser.arriveAndAwaitAdvance(); // await all creation
+ *         task.run();
+ *       }
+ *     }.start();
+ *   }
+ *
+ *   // allow threads to start and deregister self
+ *   phaser.arriveAndDeregister();
+ * }}</pre>
+ *
+ * <p>One way to cause a set of threads to repeatedly perform actions
+ * for a given number of iterations is to override {@code onAdvance}:
+ *
+ *  <pre> {@code
+ * void startTasks(List<Runnable> tasks, final int iterations) {
+ *   final Phaser phaser = new Phaser() {
+ *     protected boolean onAdvance(int phase, int registeredParties) {
+ *       return phase >= iterations || registeredParties == 0;
+ *     }
+ *   };
+ *   phaser.register();
+ *   for (final Runnable task : tasks) {
+ *     phaser.register();
+ *     new Thread() {
+ *       public void run() {
+ *         do {
+ *           task.run();
+ *           phaser.arriveAndAwaitAdvance();
+ *         } while (!phaser.isTerminated());
+ *       }
+ *     }.start();
+ *   }
+ *   phaser.arriveAndDeregister(); // deregister self, don't wait
+ * }}</pre>
+ *
+ * If the main task must later await termination, it
+ * may re-register and then execute a similar loop:
+ *  <pre> {@code
+ *   // ...
+ *   phaser.register();
+ *   while (!phaser.isTerminated())
+ *     phaser.arriveAndAwaitAdvance();}</pre>
+ *
+ * <p>Related constructions may be used to await particular phase numbers
+ * in contexts where you are sure that the phase will never wrap around
+ * {@code Integer.MAX_VALUE}. For example:
+ *
+ *  <pre> {@code
+ * void awaitPhase(Phaser phaser, int phase) {
+ *   int p = phaser.register(); // assumes caller not already registered
+ *   while (p < phase) {
+ *     if (phaser.isTerminated())
+ *       // ... deal with unexpected termination
+ *     else
+ *       p = phaser.arriveAndAwaitAdvance();
+ *   }
+ *   phaser.arriveAndDeregister();
+ * }}</pre>
+ *
+ *
+ * <p>To create a set of tasks using a tree of phasers,
+ * you could use code of the following form, assuming a
+ * Task class with a constructor accepting a phaser that
+ * it registers for upon construction:
+ *
+ *  <pre> {@code
+ * void build(Task[] actions, int lo, int hi, Phaser ph) {
+ *   if (hi - lo > TASKS_PER_PHASER) {
+ *     for (int i = lo; i < hi; i += TASKS_PER_PHASER) {
+ *       int j = Math.min(i + TASKS_PER_PHASER, hi);
+ *       build(actions, i, j, new Phaser(ph));
+ *     }
+ *   } else {
+ *     for (int i = lo; i < hi; ++i)
+ *       actions[i] = new Task(ph);
+ *       // assumes new Task(ph) performs ph.register()
+ *   }
+ * }
+ * // .. initially called, for n tasks via
+ * build(new Task[n], 0, n, new Phaser());}</pre>
+ *
+ * The best value of {@code TASKS_PER_PHASER} depends mainly on
+ * expected barrier synchronization rates. A value as low as four may
+ * be appropriate for extremely small per-barrier task bodies (thus
+ * high rates), or up to hundreds for extremely large ones.
+ *
+ * </pre>
+ *
+ * <p><b>Implementation notes</b>: This implementation restricts the
+ * maximum number of parties to 65535. Attempts to register additional
+ * parties result in {@code IllegalStateException}. However, you can and
+ * should create tiered phasers to accommodate arbitrarily large sets
+ * of participants.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public class Phaser {
+    /*
+     * This class implements an extension of X10 "clocks".  Thanks to
+     * Vijay Saraswat for the idea, and to Vivek Sarkar for
+     * enhancements to extend functionality.
+     */
+
+    /**
+     * Barrier state representation. Conceptually, a barrier contains
+     * four values:
+     *
+     * * parties -- the number of parties to wait (16 bits)
+     * * unarrived -- the number of parties yet to hit barrier (16 bits)
+     * * phase -- the generation of the barrier (31 bits)
+     * * terminated -- set if barrier is terminated (1 bit)
+     *
+     * However, to efficiently maintain atomicity, these values are
+     * packed into a single (atomic) long. Termination uses the sign
+     * bit of 32 bit representation of phase, so phase is set to -1 on
+     * termination. Good performance relies on keeping state decoding
+     * and encoding simple, and keeping race windows short.
+     *
+     * Note: there are some cheats in arrive() that rely on unarrived
+     * count being lowest 16 bits.
+     */
+    private volatile long state;
+
+    private static final int ushortMask = 0xffff;
+    private static final int phaseMask  = 0x7fffffff;
+
+    private static int unarrivedOf(long s) {
+        return (int) (s & ushortMask);
+    }
+
+    private static int partiesOf(long s) {
+        return ((int) s) >>> 16;
+    }
+
+    private static int phaseOf(long s) {
+        return (int) (s >>> 32);
+    }
+
+    private static int arrivedOf(long s) {
+        return partiesOf(s) - unarrivedOf(s);
+    }
+
+    private static long stateFor(int phase, int parties, int unarrived) {
+        return ((((long) phase) << 32) | (((long) parties) << 16) |
+                (long) unarrived);
+    }
+
+    private static long trippedStateFor(int phase, int parties) {
+        long lp = (long) parties;
+        return (((long) phase) << 32) | (lp << 16) | lp;
+    }
+
+    /**
+     * Returns message string for bad bounds exceptions.
+     */
+    private static String badBounds(int parties, int unarrived) {
+        return ("Attempt to set " + unarrived +
+                " unarrived of " + parties + " parties");
+    }
+
+    /**
+     * The parent of this phaser, or null if none
+     */
+    private final Phaser parent;
+
+    /**
+     * The root of phaser tree. Equals this if not in a tree.  Used to
+     * support faster state push-down.
+     */
+    private final Phaser root;
+
+    // Wait queues
+
+    /**
+     * Heads of Treiber stacks for waiting threads. To eliminate
+     * contention while releasing some threads while adding others, we
+     * use two of them, alternating across even and odd phases.
+     */
+    private final AtomicReference<QNode> evenQ = new AtomicReference<QNode>();
+    private final AtomicReference<QNode> oddQ  = new AtomicReference<QNode>();
+
+    private AtomicReference<QNode> queueFor(int phase) {
+        return ((phase & 1) == 0) ? evenQ : oddQ;
+    }
+
+    /**
+     * Returns current state, first resolving lagged propagation from
+     * root if necessary.
+     */
+    private long getReconciledState() {
+        return (parent == null) ? state : reconcileState();
+    }
+
+    /**
+     * Recursively resolves state.
+     */
+    private long reconcileState() {
+        Phaser p = parent;
+        long s = state;
+        if (p != null) {
+            while (unarrivedOf(s) == 0 && phaseOf(s) != phaseOf(root.state)) {
+                long parentState = p.getReconciledState();
+                int parentPhase = phaseOf(parentState);
+                int phase = phaseOf(s = state);
+                if (phase != parentPhase) {
+                    long next = trippedStateFor(parentPhase, partiesOf(s));
+                    if (casState(s, next)) {
+                        releaseWaiters(phase);
+                        s = next;
+                    }
+                }
+            }
+        }
+        return s;
+    }
+
+    /**
+     * Creates a new phaser without any initially registered parties,
+     * initial phase number 0, and no parent. Any thread using this
+     * phaser will need to first register for it.
+     */
+    public Phaser() {
+        this(null);
+    }
+
+    /**
+     * Creates a new phaser with the given numbers of registered
+     * unarrived parties, initial phase number 0, and no parent.
+     *
+     * @param parties the number of parties required to trip barrier
+     * @throws IllegalArgumentException if parties less than zero
+     * or greater than the maximum number of parties supported
+     */
+    public Phaser(int parties) {
+        this(null, parties);
+    }
+
+    /**
+     * Creates a new phaser with the given parent, without any
+     * initially registered parties. If parent is non-null this phaser
+     * is registered with the parent and its initial phase number is
+     * the same as that of parent phaser.
+     *
+     * @param parent the parent phaser
+     */
+    public Phaser(Phaser parent) {
+        int phase = 0;
+        this.parent = parent;
+        if (parent != null) {
+            this.root = parent.root;
+            phase = parent.register();
+        }
+        else
+            this.root = this;
+        this.state = trippedStateFor(phase, 0);
+    }
+
+    /**
+     * Creates a new phaser with the given parent and numbers of
+     * registered unarrived parties. If parent is non-null, this phaser
+     * is registered with the parent and its initial phase number is
+     * the same as that of parent phaser.
+     *
+     * @param parent the parent phaser
+     * @param parties the number of parties required to trip barrier
+     * @throws IllegalArgumentException if parties less than zero
+     * or greater than the maximum number of parties supported
+     */
+    public Phaser(Phaser parent, int parties) {
+        if (parties < 0 || parties > ushortMask)
+            throw new IllegalArgumentException("Illegal number of parties");
+        int phase = 0;
+        this.parent = parent;
+        if (parent != null) {
+            this.root = parent.root;
+            phase = parent.register();
+        }
+        else
+            this.root = this;
+        this.state = trippedStateFor(phase, parties);
+    }
+
+    /**
+     * Adds a new unarrived party to this phaser.
+     *
+     * @return the arrival phase number to which this registration applied
+     * @throws IllegalStateException if attempting to register more
+     * than the maximum supported number of parties
+     */
+    public int register() {
+        return doRegister(1);
+    }
+
+    /**
+     * Adds the given number of new unarrived parties to this phaser.
+     *
+     * @param parties the number of parties required to trip barrier
+     * @return the arrival phase number to which this registration applied
+     * @throws IllegalStateException if attempting to register more
+     * than the maximum supported number of parties
+     */
+    public int bulkRegister(int parties) {
+        if (parties < 0)
+            throw new IllegalArgumentException();
+        if (parties == 0)
+            return getPhase();
+        return doRegister(parties);
+    }
+
+    /**
+     * Shared code for register, bulkRegister
+     */
+    private int doRegister(int registrations) {
+        int phase;
+        for (;;) {
+            long s = getReconciledState();
+            phase = phaseOf(s);
+            int unarrived = unarrivedOf(s) + registrations;
+            int parties = partiesOf(s) + registrations;
+            if (phase < 0)
+                break;
+            if (parties > ushortMask || unarrived > ushortMask)
+                throw new IllegalStateException(badBounds(parties, unarrived));
+            if (phase == phaseOf(root.state) &&
+                casState(s, stateFor(phase, parties, unarrived)))
+                break;
+        }
+        return phase;
+    }
+
+    /**
+     * Arrives at the barrier, but does not wait for others.  (You can
+     * in turn wait for others via {@link #awaitAdvance}).  It is an
+     * unenforced usage error for an unregistered party to invoke this
+     * method.
+     *
+     * @return the arrival phase number, or a negative value if terminated
+     * @throws IllegalStateException if not terminated and the number
+     * of unarrived parties would become negative
+     */
+    public int arrive() {
+        int phase;
+        for (;;) {
+            long s = state;
+            phase = phaseOf(s);
+            if (phase < 0)
+                break;
+            int parties = partiesOf(s);
+            int unarrived = unarrivedOf(s) - 1;
+            if (unarrived > 0) {        // Not the last arrival
+                if (casState(s, s - 1)) // s-1 adds one arrival
+                    break;
+            }
+            else if (unarrived == 0) {  // the last arrival
+                Phaser par = parent;
+                if (par == null) {      // directly trip
+                    if (casState
+                        (s,
+                         trippedStateFor(onAdvance(phase, parties) ? -1 :
+                                         ((phase + 1) & phaseMask), parties))) {
+                        releaseWaiters(phase);
+                        break;
+                    }
+                }
+                else {                  // cascade to parent
+                    if (casState(s, s - 1)) { // zeroes unarrived
+                        par.arrive();
+                        reconcileState();
+                        break;
+                    }
+                }
+            }
+            else if (phase != phaseOf(root.state)) // or if unreconciled
+                reconcileState();
+            else
+                throw new IllegalStateException(badBounds(parties, unarrived));
+        }
+        return phase;
+    }
+
+    /**
+     * Arrives at the barrier and deregisters from it without waiting
+     * for others. Deregistration reduces the number of parties
+     * required to trip the barrier in future phases.  If this phaser
+     * has a parent, and deregistration causes this phaser to have
+     * zero parties, this phaser also arrives at and is deregistered
+     * from its parent.  It is an unenforced usage error for an
+     * unregistered party to invoke this method.
+     *
+     * @return the arrival phase number, or a negative value if terminated
+     * @throws IllegalStateException if not terminated and the number
+     * of registered or unarrived parties would become negative
+     */
+    public int arriveAndDeregister() {
+        // similar code to arrive, but too different to merge
+        Phaser par = parent;
+        int phase;
+        for (;;) {
+            long s = state;
+            phase = phaseOf(s);
+            if (phase < 0)
+                break;
+            int parties = partiesOf(s) - 1;
+            int unarrived = unarrivedOf(s) - 1;
+            if (parties >= 0) {
+                if (unarrived > 0 || (unarrived == 0 && par != null)) {
+                    if (casState
+                        (s,
+                         stateFor(phase, parties, unarrived))) {
+                        if (unarrived == 0) {
+                            par.arriveAndDeregister();
+                            reconcileState();
+                        }
+                        break;
+                    }
+                    continue;
+                }
+                if (unarrived == 0) {
+                    if (casState
+                        (s,
+                         trippedStateFor(onAdvance(phase, parties) ? -1 :
+                                         ((phase + 1) & phaseMask), parties))) {
+                        releaseWaiters(phase);
+                        break;
+                    }
+                    continue;
+                }
+                if (par != null && phase != phaseOf(root.state)) {
+                    reconcileState();
+                    continue;
+                }
+            }
+            throw new IllegalStateException(badBounds(parties, unarrived));
+        }
+        return phase;
+    }
+
+    /**
+     * Arrives at the barrier and awaits others. Equivalent in effect
+     * to {@code awaitAdvance(arrive())}.  If you need to await with
+     * interruption or timeout, you can arrange this with an analogous
+     * construction using one of the other forms of the awaitAdvance
+     * method.  If instead you need to deregister upon arrival use
+     * {@code arriveAndDeregister}. It is an unenforced usage error
+     * for an unregistered party to invoke this method.
+     *
+     * @return the arrival phase number, or a negative number if terminated
+     * @throws IllegalStateException if not terminated and the number
+     * of unarrived parties would become negative
+     */
+    public int arriveAndAwaitAdvance() {
+        return awaitAdvance(arrive());
+    }
+
+    /**
+     * Awaits the phase of the barrier to advance from the given phase
+     * value, returning immediately if the current phase of the
+     * barrier is not equal to the given phase value or this barrier
+     * is terminated.  It is an unenforced usage error for an
+     * unregistered party to invoke this method.
+     *
+     * @param phase an arrival phase number, or negative value if
+     * terminated; this argument is normally the value returned by a
+     * previous call to {@code arrive} or its variants
+     * @return the next arrival phase number, or a negative value
+     * if terminated or argument is negative
+     */
+    public int awaitAdvance(int phase) {
+        if (phase < 0)
+            return phase;
+        long s = getReconciledState();
+        int p = phaseOf(s);
+        if (p != phase)
+            return p;
+        if (unarrivedOf(s) == 0 && parent != null)
+            parent.awaitAdvance(phase);
+        // Fall here even if parent waited, to reconcile and help release
+        return untimedWait(phase);
+    }
+
+    /**
+     * Awaits the phase of the barrier to advance from the given phase
+     * value, throwing {@code InterruptedException} if interrupted
+     * while waiting, or returning immediately if the current phase of
+     * the barrier is not equal to the given phase value or this
+     * barrier is terminated. It is an unenforced usage error for an
+     * unregistered party to invoke this method.
+     *
+     * @param phase an arrival phase number, or negative value if
+     * terminated; this argument is normally the value returned by a
+     * previous call to {@code arrive} or its variants
+     * @return the next arrival phase number, or a negative value
+     * if terminated or argument is negative
+     * @throws InterruptedException if thread interrupted while waiting
+     */
+    public int awaitAdvanceInterruptibly(int phase)
+        throws InterruptedException {
+        if (phase < 0)
+            return phase;
+        long s = getReconciledState();
+        int p = phaseOf(s);
+        if (p != phase)
+            return p;
+        if (unarrivedOf(s) == 0 && parent != null)
+            parent.awaitAdvanceInterruptibly(phase);
+        return interruptibleWait(phase);
+    }
+
+    /**
+     * Awaits the phase of the barrier to advance from the given phase
+     * value or the given timeout to elapse, throwing {@code
+     * InterruptedException} if interrupted while waiting, or
+     * returning immediately if the current phase of the barrier is
+     * not equal to the given phase value or this barrier is
+     * terminated.  It is an unenforced usage error for an
+     * unregistered party to invoke this method.
+     *
+     * @param phase an arrival phase number, or negative value if
+     * terminated; this argument is normally the value returned by a
+     * previous call to {@code arrive} or its variants
+     * @param timeout how long to wait before giving up, in units of
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return the next arrival phase number, or a negative value
+     * if terminated or argument is negative
+     * @throws InterruptedException if thread interrupted while waiting
+     * @throws TimeoutException if timed out while waiting
+     */
+    public int awaitAdvanceInterruptibly(int phase,
+                                         long timeout, TimeUnit unit)
+        throws InterruptedException, TimeoutException {
+        if (phase < 0)
+            return phase;
+        long s = getReconciledState();
+        int p = phaseOf(s);
+        if (p != phase)
+            return p;
+        if (unarrivedOf(s) == 0 && parent != null)
+            parent.awaitAdvanceInterruptibly(phase, timeout, unit);
+        return timedWait(phase, unit.toNanos(timeout));
+    }
+
+    /**
+     * Forces this barrier to enter termination state. Counts of
+     * arrived and registered parties are unaffected. If this phaser
+     * has a parent, it too is terminated. This method may be useful
+     * for coordinating recovery after one or more tasks encounter
+     * unexpected exceptions.
+     */
+    public void forceTermination() {
+        for (;;) {
+            long s = getReconciledState();
+            int phase = phaseOf(s);
+            int parties = partiesOf(s);
+            int unarrived = unarrivedOf(s);
+            if (phase < 0 ||
+                casState(s, stateFor(-1, parties, unarrived))) {
+                releaseWaiters(0);
+                releaseWaiters(1);
+                if (parent != null)
+                    parent.forceTermination();
+                return;
+            }
+        }
+    }
+
+    /**
+     * Returns the current phase number. The maximum phase number is
+     * {@code Integer.MAX_VALUE}, after which it restarts at
+     * zero. Upon termination, the phase number is negative.
+     *
+     * @return the phase number, or a negative value if terminated
+     */
+    public final int getPhase() {
+        return phaseOf(getReconciledState());
+    }
+
+    /**
+     * Returns the number of parties registered at this barrier.
+     *
+     * @return the number of parties
+     */
+    public int getRegisteredParties() {
+        return partiesOf(state);
+    }
+
+    /**
+     * Returns the number of registered parties that have arrived at
+     * the current phase of this barrier.
+     *
+     * @return the number of arrived parties
+     */
+    public int getArrivedParties() {
+        return arrivedOf(state);
+    }
+
+    /**
+     * Returns the number of registered parties that have not yet
+     * arrived at the current phase of this barrier.
+     *
+     * @return the number of unarrived parties
+     */
+    public int getUnarrivedParties() {
+        return unarrivedOf(state);
+    }
+
+    /**
+     * Returns the parent of this phaser, or {@code null} if none.
+     *
+     * @return the parent of this phaser, or {@code null} if none
+     */
+    public Phaser getParent() {
+        return parent;
+    }
+
+    /**
+     * Returns the root ancestor of this phaser, which is the same as
+     * this phaser if it has no parent.
+     *
+     * @return the root ancestor of this phaser
+     */
+    public Phaser getRoot() {
+        return root;
+    }
+
+    /**
+     * Returns {@code true} if this barrier has been terminated.
+     *
+     * @return {@code true} if this barrier has been terminated
+     */
+    public boolean isTerminated() {
+        return getPhase() < 0;
+    }
+
+    /**
+     * Overridable method to perform an action upon impending phase
+     * advance, and to control termination. This method is invoked
+     * upon arrival of the party tripping the barrier (when all other
+     * waiting parties are dormant).  If this method returns {@code
+     * true}, then, rather than advance the phase number, this barrier
+     * will be set to a final termination state, and subsequent calls
+     * to {@link #isTerminated} will return true. Any (unchecked)
+     * Exception or Error thrown by an invocation of this method is
+     * propagated to the party attempting to trip the barrier, in
+     * which case no advance occurs.
+     *
+     * <p>The arguments to this method provide the state of the phaser
+     * prevailing for the current transition. (When called from within
+     * an implementation of {@code onAdvance} the values returned by
+     * methods such as {@code getPhase} may or may not reliably
+     * indicate the state to which this transition applies.)
+     *
+     * <p>The default version returns {@code true} when the number of
+     * registered parties is zero. Normally, overrides that arrange
+     * termination for other reasons should also preserve this
+     * property.
+     *
+     * <p>You may override this method to perform an action with side
+     * effects visible to participating tasks, but it is only sensible
+     * to do so in designs where all parties register before any
+     * arrive, and all {@link #awaitAdvance} at each phase.
+     * Otherwise, you cannot ensure lack of interference from other
+     * parties during the invocation of this method. Additionally,
+     * method {@code onAdvance} may be invoked more than once per
+     * transition if registrations are intermixed with arrivals.
+     *
+     * @param phase the phase number on entering the barrier
+     * @param registeredParties the current number of registered parties
+     * @return {@code true} if this barrier should terminate
+     */
+    protected boolean onAdvance(int phase, int registeredParties) {
+        return registeredParties <= 0;
+    }
+
+    /**
+     * Returns a string identifying this phaser, as well as its
+     * state.  The state, in brackets, includes the String {@code
+     * "phase = "} followed by the phase number, {@code "parties = "}
+     * followed by the number of registered parties, and {@code
+     * "arrived = "} followed by the number of arrived parties.
+     *
+     * @return a string identifying this barrier, as well as its state
+     */
+    public String toString() {
+        long s = getReconciledState();
+        return super.toString() +
+            "[phase = " + phaseOf(s) +
+            " parties = " + partiesOf(s) +
+            " arrived = " + arrivedOf(s) + "]";
+    }
+
+    // methods for waiting
+
+    /**
+     * Wait nodes for Treiber stack representing wait queue
+     */
+    static final class QNode implements ForkJoinPool.ManagedBlocker {
+        final Phaser phaser;
+        final int phase;
+        final long startTime;
+        final long nanos;
+        final boolean timed;
+        final boolean interruptible;
+        volatile boolean wasInterrupted = false;
+        volatile Thread thread; // nulled to cancel wait
+        QNode next;
+        QNode(Phaser phaser, int phase, boolean interruptible,
+              boolean timed, long startTime, long nanos) {
+            this.phaser = phaser;
+            this.phase = phase;
+            this.timed = timed;
+            this.interruptible = interruptible;
+            this.startTime = startTime;
+            this.nanos = nanos;
+            thread = Thread.currentThread();
+        }
+        public boolean isReleasable() {
+            return (thread == null ||
+                    phaser.getPhase() != phase ||
+                    (interruptible && wasInterrupted) ||
+                    (timed && (nanos - (System.nanoTime() - startTime)) <= 0));
+        }
+        public boolean block() {
+            if (Thread.interrupted()) {
+                wasInterrupted = true;
+                if (interruptible)
+                    return true;
+            }
+            if (!timed)
+                LockSupport.park(this);
+            else {
+                long waitTime = nanos - (System.nanoTime() - startTime);
+                if (waitTime <= 0)
+                    return true;
+                LockSupport.parkNanos(this, waitTime);
+            }
+            return isReleasable();
+        }
+        void signal() {
+            Thread t = thread;
+            if (t != null) {
+                thread = null;
+                LockSupport.unpark(t);
+            }
+        }
+        boolean doWait() {
+            if (thread != null) {
+                try {
+                    ForkJoinPool.managedBlock(this, false);
+                } catch (InterruptedException ie) {
+                }
+            }
+            return wasInterrupted;
+        }
+
+    }
+
+    /**
+     * Removes and signals waiting threads from wait queue.
+     */
+    private void releaseWaiters(int phase) {
+        AtomicReference<QNode> head = queueFor(phase);
+        QNode q;
+        while ((q = head.get()) != null) {
+            if (head.compareAndSet(q, q.next))
+                q.signal();
+        }
+    }
+
+    /**
+     * Tries to enqueue given node in the appropriate wait queue.
+     *
+     * @return true if successful
+     */
+    private boolean tryEnqueue(QNode node) {
+        AtomicReference<QNode> head = queueFor(node.phase);
+        return head.compareAndSet(node.next = head.get(), node);
+    }
+
+    /**
+     * Enqueues node and waits unless aborted or signalled.
+     *
+     * @return current phase
+     */
+    private int untimedWait(int phase) {
+        QNode node = null;
+        boolean queued = false;
+        boolean interrupted = false;
+        int p;
+        while ((p = getPhase()) == phase) {
+            if (Thread.interrupted())
+                interrupted = true;
+            else if (node == null)
+                node = new QNode(this, phase, false, false, 0, 0);
+            else if (!queued)
+                queued = tryEnqueue(node);
+            else
+                interrupted = node.doWait();
+        }
+        if (node != null)
+            node.thread = null;
+        releaseWaiters(phase);
+        if (interrupted)
+            Thread.currentThread().interrupt();
+        return p;
+    }
+
+    /**
+     * Interruptible version
+     * @return current phase
+     */
+    private int interruptibleWait(int phase) throws InterruptedException {
+        QNode node = null;
+        boolean queued = false;
+        boolean interrupted = false;
+        int p;
+        while ((p = getPhase()) == phase && !interrupted) {
+            if (Thread.interrupted())
+                interrupted = true;
+            else if (node == null)
+                node = new QNode(this, phase, true, false, 0, 0);
+            else if (!queued)
+                queued = tryEnqueue(node);
+            else
+                interrupted = node.doWait();
+        }
+        if (node != null)
+            node.thread = null;
+        if (p != phase || (p = getPhase()) != phase)
+            releaseWaiters(phase);
+        if (interrupted)
+            throw new InterruptedException();
+        return p;
+    }
+
+    /**
+     * Timeout version.
+     * @return current phase
+     */
+    private int timedWait(int phase, long nanos)
+        throws InterruptedException, TimeoutException {
+        long startTime = System.nanoTime();
+        QNode node = null;
+        boolean queued = false;
+        boolean interrupted = false;
+        int p;
+        while ((p = getPhase()) == phase && !interrupted) {
+            if (Thread.interrupted())
+                interrupted = true;
+            else if (nanos - (System.nanoTime() - startTime) <= 0)
+                break;
+            else if (node == null)
+                node = new QNode(this, phase, true, true, startTime, nanos);
+            else if (!queued)
+                queued = tryEnqueue(node);
+            else
+                interrupted = node.doWait();
+        }
+        if (node != null)
+            node.thread = null;
+        if (p != phase || (p = getPhase()) != phase)
+            releaseWaiters(phase);
+        if (interrupted)
+            throw new InterruptedException();
+        if (p == phase)
+            throw new TimeoutException();
+        return p;
+    }
+
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long stateOffset =
+        objectFieldOffset("state", Phaser.class);
+
+    private final boolean casState(long cmp, long val) {
+        return UNSAFE.compareAndSwapLong(this, stateOffset, cmp, val);
+    }
+
+    private static long objectFieldOffset(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;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/concurrent/RecursiveAction.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,179 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A recursive resultless {@link ForkJoinTask}.  This class
+ * establishes conventions to parameterize resultless actions as
+ * {@code Void} {@code ForkJoinTask}s. Because {@code null} is the
+ * only valid value of type {@code Void}, methods such as join always
+ * return {@code null} upon completion.
+ *
+ * <p><b>Sample Usages.</b> Here is a sketch of a ForkJoin sort that
+ * sorts a given {@code long[]} array:
+ *
+ *  <pre> {@code
+ * class SortTask extends RecursiveAction {
+ *   final long[] array; final int lo; final int hi;
+ *   SortTask(long[] array, int lo, int hi) {
+ *     this.array = array; this.lo = lo; this.hi = hi;
+ *   }
+ *   protected void compute() {
+ *     if (hi - lo < THRESHOLD)
+ *       sequentiallySort(array, lo, hi);
+ *     else {
+ *       int mid = (lo + hi) >>> 1;
+ *       invokeAll(new SortTask(array, lo, mid),
+ *                 new SortTask(array, mid, hi));
+ *       merge(array, lo, hi);
+ *     }
+ *   }
+ * }}</pre>
+ *
+ * You could then sort {@code anArray} by creating {@code new
+ * SortTask(anArray, 0, anArray.length-1) } and invoking it in a
+ * ForkJoinPool.  As a more concrete simple example, the following
+ * task increments each element of an array:
+ *  <pre> {@code
+ * class IncrementTask extends RecursiveAction {
+ *   final long[] array; final int lo; final int hi;
+ *   IncrementTask(long[] array, int lo, int hi) {
+ *     this.array = array; this.lo = lo; this.hi = hi;
+ *   }
+ *   protected void compute() {
+ *     if (hi - lo < THRESHOLD) {
+ *       for (int i = lo; i < hi; ++i)
+ *         array[i]++;
+ *     }
+ *     else {
+ *       int mid = (lo + hi) >>> 1;
+ *       invokeAll(new IncrementTask(array, lo, mid),
+ *                 new IncrementTask(array, mid, hi));
+ *     }
+ *   }
+ * }}</pre>
+ *
+ * <p>The following example illustrates some refinements and idioms
+ * that may lead to better performance: RecursiveActions need not be
+ * fully recursive, so long as they maintain the basic
+ * divide-and-conquer approach. Here is a class that sums the squares
+ * of each element of a double array, by subdividing out only the
+ * right-hand-sides of repeated divisions by two, and keeping track of
+ * them with a chain of {@code next} references. It uses a dynamic
+ * threshold based on method {@code getSurplusQueuedTaskCount}, but
+ * counterbalances potential excess partitioning by directly
+ * performing leaf actions on unstolen tasks rather than further
+ * subdividing.
+ *
+ *  <pre> {@code
+ * double sumOfSquares(ForkJoinPool pool, double[] array) {
+ *   int n = array.length;
+ *   Applyer a = new Applyer(array, 0, n, null);
+ *   pool.invoke(a);
+ *   return a.result;
+ * }
+ *
+ * class Applyer extends RecursiveAction {
+ *   final double[] array;
+ *   final int lo, hi;
+ *   double result;
+ *   Applyer next; // keeps track of right-hand-side tasks
+ *   Applyer(double[] array, int lo, int hi, Applyer next) {
+ *     this.array = array; this.lo = lo; this.hi = hi;
+ *     this.next = next;
+ *   }
+ *
+ *   double atLeaf(int l, int h) {
+ *     double sum = 0;
+ *     for (int i = l; i < h; ++i) // perform leftmost base step
+ *       sum += array[i] * array[i];
+ *     return sum;
+ *   }
+ *
+ *   protected void compute() {
+ *     int l = lo;
+ *     int h = hi;
+ *     Applyer right = null;
+ *     while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
+ *        int mid = (l + h) >>> 1;
+ *        right = new Applyer(array, mid, h, right);
+ *        right.fork();
+ *        h = mid;
+ *     }
+ *     double sum = atLeaf(l, h);
+ *     while (right != null) {
+ *        if (right.tryUnfork()) // directly calculate if not stolen
+ *          sum += right.atLeaf(right.lo, right.hi);
+ *       else {
+ *          right.helpJoin();
+ *          sum += right.result;
+ *        }
+ *        right = right.next;
+ *      }
+ *     result = sum;
+ *   }
+ * }}</pre>
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public abstract class RecursiveAction extends ForkJoinTask<Void> {
+    private static final long serialVersionUID = 5232453952276485070L;
+
+    /**
+     * The main computation performed by this task.
+     */
+    protected abstract void compute();
+
+    /**
+     * Always returns null.
+     */
+    public final Void getRawResult() { return null; }
+
+    /**
+     * Requires null completion value.
+     */
+    protected final void setRawResult(Void mustBeNull) { }
+
+    /**
+     * Implements execution conventions for RecursiveActions.
+     */
+    protected final boolean exec() {
+        compute();
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/concurrent/RecursiveTask.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,97 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A recursive result-bearing {@link ForkJoinTask}.
+ *
+ * <p>For a classic example, here is a task computing Fibonacci numbers:
+ *
+ *  <pre> {@code
+ * class Fibonacci extends RecursiveTask<Integer> {
+ *   final int n;
+ *   Fibonacci(int n) { this.n = n; }
+ *   Integer compute() {
+ *     if (n <= 1)
+ *        return n;
+ *     Fibonacci f1 = new Fibonacci(n - 1);
+ *     f1.fork();
+ *     Fibonacci f2 = new Fibonacci(n - 2);
+ *     return f2.compute() + f1.join();
+ *   }
+ * }}</pre>
+ *
+ * However, besides being a dumb way to compute Fibonacci functions
+ * (there is a simple fast linear algorithm that you'd use in
+ * practice), this is likely to perform poorly because the smallest
+ * subtasks are too small to be worthwhile splitting up. Instead, as
+ * is the case for nearly all fork/join applications, you'd pick some
+ * minimum granularity size (for example 10 here) for which you always
+ * sequentially solve rather than subdividing.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public abstract class RecursiveTask<V> extends ForkJoinTask<V> {
+    private static final long serialVersionUID = 5232453952276485270L;
+
+    /**
+     * The result of the computation.
+     */
+    V result;
+
+    /**
+     * The main computation performed by this task.
+     */
+    protected abstract V compute();
+
+    public final V getRawResult() {
+        return result;
+    }
+
+    protected final void setRawResult(V value) {
+        result = value;
+    }
+
+    /**
+     * Implements execution conventions for RecursiveTask.
+     */
+    protected final boolean exec() {
+        result = compute();
+        return true;
+    }
+
+}
--- a/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java	Thu Nov 12 23:04:42 2009 +0000
@@ -61,6 +61,14 @@
  * causes tasks to be immediately removed from the work queue at
  * time of cancellation.
  *
+ * <p>Successive executions of a task scheduled via
+ * <code>scheduleAtFixedRate</code> or
+ * <code>scheduleWithFixedDelay</code> do not overlap. While different
+ * executions may be performed by different threads, the effects of
+ * prior executions <a
+ * href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * those of subsequent ones.
+ *
  * <p>While this class inherits from {@link ThreadPoolExecutor}, a few
  * of the inherited tuning methods are not useful for it. In
  * particular, because it acts as a fixed-sized pool using
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/concurrent/ThreadLocalRandom.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,228 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.Random;
+
+/**
+ * A random number generator isolated to the current thread.  Like the
+ * global {@link java.util.Random} generator used by the {@link
+ * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
+ * with an internally generated seed that may not otherwise be
+ * modified. When applicable, use of {@code ThreadLocalRandom} rather
+ * than shared {@code Random} objects in concurrent programs will
+ * typically encounter much less overhead and contention.  Use of
+ * {@code ThreadLocalRandom} is particularly appropriate when multiple
+ * tasks (for example, each a {@link ForkJoinTask}) use random numbers
+ * in parallel in thread pools.
+ *
+ * <p>Usages of this class should typically be of the form:
+ * {@code ThreadLocalRandom.current().nextX(...)} (where
+ * {@code X} is {@code Int}, {@code Long}, etc).
+ * When all usages are of this form, it is never possible to
+ * accidently share a {@code ThreadLocalRandom} across multiple threads.
+ *
+ * <p>This class also provides additional commonly used bounded random
+ * generation methods.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ */
+public class ThreadLocalRandom extends Random {
+    // same constants as Random, but must be redeclared because private
+    private final static long multiplier = 0x5DEECE66DL;
+    private final static long addend = 0xBL;
+    private final static long mask = (1L << 48) - 1;
+
+    /**
+     * The random seed. We can't use super.seed.
+     */
+    private long rnd;
+
+    /**
+     * Initialization flag to permit the first and only allowed call
+     * to setSeed (inside Random constructor) to succeed.  We can't
+     * allow others since it would cause setting seed in one part of a
+     * program to unintentionally impact other usages by the thread.
+     */
+    boolean initialized;
+
+    // Padding to help avoid memory contention among seed updates in
+    // different TLRs in the common case that they are located near
+    // each other.
+    private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
+
+    /**
+     * The actual ThreadLocal
+     */
+    private static final ThreadLocal<ThreadLocalRandom> localRandom =
+        new ThreadLocal<ThreadLocalRandom>() {
+            protected ThreadLocalRandom initialValue() {
+                return new ThreadLocalRandom();
+            }
+    };
+
+
+    /**
+     * Constructor called only by localRandom.initialValue.
+     * We rely on the fact that the superclass no-arg constructor
+     * invokes setSeed exactly once to initialize.
+     */
+    ThreadLocalRandom() {
+        super();
+    }
+
+    /**
+     * Returns the current thread's {@code ThreadLocalRandom}.
+     *
+     * @return the current thread's {@code ThreadLocalRandom}
+     */
+    public static ThreadLocalRandom current() {
+        return localRandom.get();
+    }
+
+    /**
+     * Throws {@code UnsupportedOperationException}.  Setting seeds in
+     * this generator is not supported.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    public void setSeed(long seed) {
+        if (initialized)
+            throw new UnsupportedOperationException();
+        initialized = true;
+        rnd = (seed ^ multiplier) & mask;
+    }
+
+    protected int next(int bits) {
+        rnd = (rnd * multiplier + addend) & mask;
+        return (int) (rnd >>> (48-bits));
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed value between the
+     * given least value (inclusive) and bound (exclusive).
+     *
+     * @param least the least value returned
+     * @param bound the upper bound (exclusive)
+     * @throws IllegalArgumentException if least greater than or equal
+     * to bound
+     * @return the next value
+     */
+    public int nextInt(int least, int bound) {
+        if (least >= bound)
+            throw new IllegalArgumentException();
+        return nextInt(bound - least) + least;
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed value
+     * between 0 (inclusive) and the specified value (exclusive).
+     *
+     * @param n the bound on the random number to be returned.  Must be
+     *        positive.
+     * @return the next value
+     * @throws IllegalArgumentException if n is not positive
+     */
+    public long nextLong(long n) {
+        if (n <= 0)
+            throw new IllegalArgumentException("n must be positive");
+        // Divide n by two until small enough for nextInt. On each
+        // iteration (at most 31 of them but usually much less),
+        // randomly choose both whether to include high bit in result
+        // (offset) and whether to continue with the lower vs upper
+        // half (which makes a difference only if odd).
+        long offset = 0;
+        while (n >= Integer.MAX_VALUE) {
+            int bits = next(2);
+            long half = n >>> 1;
+            long nextn = ((bits & 2) == 0) ? half : n - half;
+            if ((bits & 1) == 0)
+                offset += n - nextn;
+            n = nextn;
+        }
+        return offset + nextInt((int) n);
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed value between the
+     * given least value (inclusive) and bound (exclusive).
+     *
+     * @param least the least value returned
+     * @param bound the upper bound (exclusive)
+     * @return the next value
+     * @throws IllegalArgumentException if least greater than or equal
+     * to bound
+     */
+    public long nextLong(long least, long bound) {
+        if (least >= bound)
+            throw new IllegalArgumentException();
+        return nextLong(bound - least) + least;
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed {@code double} value
+     * between 0 (inclusive) and the specified value (exclusive).
+     *
+     * @param n the bound on the random number to be returned.  Must be
+     *        positive.
+     * @return the next value
+     * @throws IllegalArgumentException if n is not positive
+     */
+    public double nextDouble(double n) {
+        if (n <= 0)
+            throw new IllegalArgumentException("n must be positive");
+        return nextDouble() * n;
+    }
+
+    /**
+     * Returns a pseudorandom, uniformly distributed value between the
+     * given least value (inclusive) and bound (exclusive).
+     *
+     * @param least the least value returned
+     * @param bound the upper bound (exclusive)
+     * @return the next value
+     * @throws IllegalArgumentException if least greater than or equal
+     * to bound
+     */
+    public double nextDouble(double least, double bound) {
+        if (least >= bound)
+            throw new IllegalArgumentException();
+        return nextDouble() * (bound - least) + least;
+    }
+
+    private static final long serialVersionUID = -5851777807851030925L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/util/concurrent/TransferQueue.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,161 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A {@link BlockingQueue} in which producers may wait for consumers
+ * to receive elements.  A {@code TransferQueue} may be useful for
+ * example in message passing applications in which producers
+ * sometimes (using method {@link #transfer}) await receipt of
+ * elements by consumers invoking {@code take} or {@code poll}, while
+ * at other times enqueue elements (via method {@code put}) without
+ * waiting for receipt.
+ * {@linkplain #tryTransfer(Object) Non-blocking} and
+ * {@linkplain #tryTransfer(Object,long,TimeUnit) time-out} versions of
+ * {@code tryTransfer} are also available.
+ * A {@code TransferQueue} may also be queried, via {@link
+ * #hasWaitingConsumer}, whether there are any threads waiting for
+ * items, which is a converse analogy to a {@code peek} operation.
+ *
+ * <p>Like other blocking queues, a {@code TransferQueue} may be
+ * capacity bounded.  If so, an attempted transfer operation may
+ * initially block waiting for available space, and/or subsequently
+ * block waiting for reception by a consumer.  Note that in a queue
+ * with zero capacity, such as {@link SynchronousQueue}, {@code put}
+ * and {@code transfer} are effectively synonymous.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.7
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public interface TransferQueue<E> extends BlockingQueue<E> {
+    /**
+     * Transfers the element to a waiting consumer immediately, if possible.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * otherwise returning {@code false} without enqueuing the element.
+     *
+     * @param e the element to transfer
+     * @return {@code true} if the element was transferred, else
+     *         {@code false}
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
+     */
+    boolean tryTransfer(E e);
+
+    /**
+     * Transfers the element to a consumer, waiting if necessary to do so.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * else waits until the element is received by a consumer.
+     *
+     * @param e the element to transfer
+     * @throws InterruptedException if interrupted while waiting,
+     *         in which case the element is not left enqueued
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
+     */
+    void transfer(E e) throws InterruptedException;
+
+    /**
+     * Transfers the element to a consumer if it is possible to do so
+     * before the timeout elapses.
+     *
+     * <p>More precisely, transfers the specified element immediately
+     * if there exists a consumer already waiting to receive it (in
+     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
+     * else waits until the element is received by a consumer,
+     * returning {@code false} if the specified wait time elapses
+     * before the element can be transferred.
+     *
+     * @param e the element to transfer
+     * @param timeout how long to wait before giving up, in units of
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return {@code true} if successful, or {@code false} if
+     *         the specified waiting time elapses before completion,
+     *         in which case the element is not left enqueued
+     * @throws InterruptedException if interrupted while waiting,
+     *         in which case the element is not left enqueued
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
+     */
+    boolean tryTransfer(E e, long timeout, TimeUnit unit)
+        throws InterruptedException;
+
+    /**
+     * Returns {@code true} if there is at least one consumer waiting
+     * to receive an element via {@link #take} or
+     * timed {@link #poll(long,TimeUnit) poll}.
+     * The return value represents a momentary state of affairs.
+     *
+     * @return {@code true} if there is at least one waiting consumer
+     */
+    boolean hasWaitingConsumer();
+
+    /**
+     * Returns an estimate of the number of consumers waiting to
+     * receive elements via {@link #take} or timed
+     * {@link #poll(long,TimeUnit) poll}.  The return value is an
+     * approximation of a momentary state of affairs, that may be
+     * inaccurate if consumers have completed or given up waiting.
+     * The value may be useful for monitoring and heuristics, but
+     * not for synchronization control.  Implementations of this
+     * method are likely to be noticeably slower than those for
+     * {@link #hasWaitingConsumer}.
+     *
+     * @return the number of consumers waiting to receive elements
+     */
+    int getWaitingConsumerCount();
+}
--- a/src/share/classes/java/util/concurrent/locks/Condition.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/concurrent/locks/Condition.java	Thu Nov 12 23:04:42 2009 +0000
@@ -170,8 +170,8 @@
  * <p>As interruption generally implies cancellation, and checks for
  * interruption are often infrequent, an implementation can favor responding
  * to an interrupt over normal method return. This is true even if it can be
- * shown that the interrupt occurred after another action may have unblocked
- * the thread. An implementation should document this behavior.
+ * shown that the interrupt occurred after another action that may have
+ * unblocked the thread. An implementation should document this behavior.
  *
  * @since 1.5
  * @author Doug Lea
--- a/src/share/classes/java/util/concurrent/package-info.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/java/util/concurrent/package-info.java	Thu Nov 12 23:04:42 2009 +0000
@@ -92,6 +92,13 @@
  * assists in coordinating the processing of groups of
  * asynchronous tasks.
  *
+ * <p>Class {@link java.util.concurrent.ForkJoinPool} provides an
+ * Executor primarily designed for processing instances of {@link
+ * java.util.concurrent.ForkJoinTask} and its subclasses.  These
+ * classes employ a work-stealing scheduler that attains high
+ * throughput for tasks conforming to restrictions that often hold in
+ * computation-intensive parallel processing.
+ *
  * <h2>Queues</h2>
  *
  * The {@link java.util.concurrent.ConcurrentLinkedQueue} class
@@ -110,6 +117,12 @@
  * for producer-consumer, messaging, parallel tasking, and
  * related concurrent designs.
  *
+ * <p> Extended interface {@link java.util.concurrent.TransferQueue},
+ * and implementation {@link java.util.concurrent.LinkedTransferQueue}
+ * introduce a synchronous {@code transfer} method (along with related
+ * features) in which a producer may optionally block awaiting its
+ * consumer.
+ *
  * <p>The {@link java.util.concurrent.BlockingDeque} interface
  * extends {@code BlockingQueue} to support both FIFO and LIFO
  * (stack-based) operations.
@@ -136,15 +149,28 @@
  *
  * <h2>Synchronizers</h2>
  *
- * Four classes aid common special-purpose synchronization idioms.
- * {@link java.util.concurrent.Semaphore} is a classic concurrency tool.
- * {@link java.util.concurrent.CountDownLatch} is a very simple yet very
- * common utility for blocking until a given number of signals, events,
- * or conditions hold.  A {@link java.util.concurrent.CyclicBarrier} is a
- * resettable multiway synchronization point useful in some styles of
- * parallel programming.  An {@link java.util.concurrent.Exchanger} allows
- * two threads to exchange objects at a rendezvous point, and is useful
- * in several pipeline designs.
+ * Five classes aid common special-purpose synchronization idioms.
+ * <ul>
+ *
+ * <li>{@link java.util.concurrent.Semaphore} is a classic concurrency tool.
+ *
+ * <li>{@link java.util.concurrent.CountDownLatch} is a very simple yet
+ * very common utility for blocking until a given number of signals,
+ * events, or conditions hold.
+ *
+ * <li>A {@link java.util.concurrent.CyclicBarrier} is a resettable
+ * multiway synchronization point useful in some styles of parallel
+ * programming.
+ *
+ * <li>A {@link java.util.concurrent.Phaser} provides
+ * a more flexible form of barrier that may be used to control phased
+ * computation among multiple threads.
+ *
+ * <li>An {@link java.util.concurrent.Exchanger} allows two threads to
+ * exchange objects at a rendezvous point, and is useful in several
+ * pipeline designs.
+ *
+ * </ul>
  *
  * <h2>Concurrent Collections</h2>
  *
@@ -259,7 +285,8 @@
  *   in each thread <i>happen-before</i> those subsequent to the
  *   corresponding {@code exchange()} in another thread.
  *
- *   <li>Actions prior to calling {@code CyclicBarrier.await}
+ *   <li>Actions prior to calling {@code CyclicBarrier.await} and
+ *   {@code Phaser.awaitAdvance} (as well as its variants)
  *   <i>happen-before</i> actions performed by the barrier action, and
  *   actions performed by the barrier action <i>happen-before</i> actions
  *   subsequent to a successful return from the corresponding {@code await}
--- a/src/share/classes/javax/swing/ToolTipManager.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/ToolTipManager.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,10 +27,7 @@
 package javax.swing;
 
 import java.awt.event.*;
-import java.applet.*;
 import java.awt.*;
-import java.io.Serializable;
-import sun.swing.UIAction;
 
 /**
  * Manages all the <code>ToolTips</code> in the system.
@@ -60,7 +57,7 @@
     JComponent insideComponent;
     MouseEvent mouseEvent;
     boolean showImmediately;
-    final static ToolTipManager sharedInstance = new ToolTipManager();
+    private static final Object TOOL_TIP_MANAGER_KEY = new Object();
     transient Popup tipWindow;
     /** The Window tip is being displayed in. This will be non-null if
      * the Window tip is in differs from that of insideComponent's Window.
@@ -345,7 +342,13 @@
      * @return a shared <code>ToolTipManager</code> object
      */
     public static ToolTipManager sharedInstance() {
-        return sharedInstance;
+        Object value = SwingUtilities.appContextGet(TOOL_TIP_MANAGER_KEY);
+        if (value instanceof ToolTipManager) {
+            return (ToolTipManager) value;
+        }
+        ToolTipManager manager = new ToolTipManager();
+        SwingUtilities.appContextPut(TOOL_TIP_MANAGER_KEY, manager);
+        return manager;
     }
 
     // add keylistener here to trigger tip for access
--- a/src/share/classes/javax/swing/UIManager.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/UIManager.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -197,6 +197,8 @@
         Vector<LookAndFeel> auxLookAndFeels = null;
         SwingPropertyChangeSupport changeSupport;
 
+        LookAndFeelInfo[] installedLAFs;
+
         UIDefaults getLookAndFeelDefaults() { return tables[0]; }
         void setLookAndFeelDefaults(UIDefaults x) { tables[0] = x; }
 
@@ -227,18 +229,6 @@
      */
     private static final Object classLock = new Object();
 
-
-    /* Cache the last referenced LAFState to improve performance
-     * when accessing it.  The cache is based on last thread rather
-     * than last AppContext because of the cost of looking up the
-     * AppContext each time.  Since most Swing UI work is on the
-     * EventDispatchThread, this hits often enough to justify the
-     * overhead.  (4193032)
-     */
-    private static Thread currentLAFStateThread = null;
-    private static LAFState currentLAFState = null;
-
-
     /**
      * Return the <code>LAFState</code> object, lazily create one if necessary.
      * All access to the <code>LAFState</code> fields is done via this method,
@@ -248,13 +238,6 @@
      * </pre>
      */
     private static LAFState getLAFState() {
-        // First check whether we're running on the same thread as
-        // the last request.
-        Thread thisThread = Thread.currentThread();
-        if (thisThread == currentLAFStateThread) {
-            return currentLAFState;
-        }
-
         LAFState rv = (LAFState)SwingUtilities.appContextGet(
                 SwingUtilities2.LAF_STATE_KEY);
         if (rv == null) {
@@ -268,10 +251,6 @@
                 }
             }
         }
-
-        currentLAFStateThread = thisThread;
-        currentLAFState = rv;
-
         return rv;
     }
 
@@ -431,7 +410,10 @@
      */
     public static LookAndFeelInfo[] getInstalledLookAndFeels() {
         maybeInitialize();
-        LookAndFeelInfo[] ilafs = installedLAFs;
+        LookAndFeelInfo[] ilafs = getLAFState().installedLAFs;
+        if (ilafs == null) {
+            ilafs = installedLAFs;
+        }
         LookAndFeelInfo[] rv = new LookAndFeelInfo[ilafs.length];
         System.arraycopy(ilafs, 0, rv, 0, ilafs.length);
         return rv;
@@ -453,9 +435,10 @@
     public static void setInstalledLookAndFeels(LookAndFeelInfo[] infos)
         throws SecurityException
     {
+        maybeInitialize();
         LookAndFeelInfo[] newInfos = new LookAndFeelInfo[infos.length];
         System.arraycopy(infos, 0, newInfos, 0, infos.length);
-        installedLAFs = newInfos;
+        getLAFState().installedLAFs = newInfos;
     }
 
 
@@ -1307,10 +1290,11 @@
             }
         }
 
-        installedLAFs = new LookAndFeelInfo[ilafs.size()];
+        LookAndFeelInfo[] installedLAFs = new LookAndFeelInfo[ilafs.size()];
         for(int i = 0; i < ilafs.size(); i++) {
             installedLAFs[i] = ilafs.elementAt(i);
         }
+        getLAFState().installedLAFs = installedLAFs;
     }
 
 
--- a/src/share/classes/javax/swing/plaf/basic/BasicButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/basic/BasicButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,6 +26,8 @@
 package javax.swing.plaf.basic;
 
 import sun.swing.SwingUtilities2;
+import sun.awt.AppContext;
+
 import java.awt.*;
 import java.awt.event.*;
 import java.io.Serializable;
@@ -44,9 +46,6 @@
  * @author Jeff Dinkins
  */
 public class BasicButtonUI extends ButtonUI{
-    // Shared UI object
-    private final static BasicButtonUI buttonUI = new BasicButtonUI();
-
     // Visual constants
     // NOTE: This is not used or set any where. Were we allowed to remove
     // fields, this would be removed.
@@ -61,10 +60,19 @@
 
     private final static String propertyPrefix = "Button" + ".";
 
+    private static final Object BASIC_BUTTON_UI_KEY = new Object();
+
     // ********************************
     //          Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        BasicButtonUI buttonUI =
+                (BasicButtonUI) appContext.get(BASIC_BUTTON_UI_KEY);
+        if (buttonUI == null) {
+            buttonUI = new BasicButtonUI();
+            appContext.put(BASIC_BUTTON_UI_KEY, buttonUI);
+        }
         return buttonUI;
     }
 
--- a/src/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package javax.swing.plaf.basic;
 
+import sun.awt.AppContext;
+
 import javax.swing.*;
 
 import java.awt.*;
@@ -49,7 +51,7 @@
  */
 public class BasicCheckBoxUI extends BasicRadioButtonUI {
 
-    private final static BasicCheckBoxUI checkboxUI = new BasicCheckBoxUI();
+    private static final Object BASIC_CHECK_BOX_UI_KEY = new Object();
 
     private final static String propertyPrefix = "CheckBox" + ".";
 
@@ -57,6 +59,13 @@
     //            Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent b) {
+        AppContext appContext = AppContext.getAppContext();
+        BasicCheckBoxUI checkboxUI =
+                (BasicCheckBoxUI) appContext.get(BASIC_CHECK_BOX_UI_KEY);
+        if (checkboxUI == null) {
+            checkboxUI = new BasicCheckBoxUI();
+            appContext.put(BASIC_CHECK_BOX_UI_KEY, checkboxUI);
+        }
         return checkboxUI;
     }
 
--- a/src/share/classes/javax/swing/plaf/basic/BasicLabelUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/basic/BasicLabelUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -28,6 +28,8 @@
 import sun.swing.SwingUtilities2;
 import sun.swing.DefaultLookup;
 import sun.swing.UIAction;
+import sun.awt.AppContext;
+
 import javax.swing.*;
 import javax.swing.plaf.*;
 import javax.swing.text.View;
@@ -63,7 +65,7 @@
     * name in defaults table under the key "LabelUI".
     */
     protected static BasicLabelUI labelUI = new BasicLabelUI();
-    private final static BasicLabelUI SAFE_BASIC_LABEL_UI = new BasicLabelUI();
+    private static final Object BASIC_LABEL_UI_KEY = new Object();
 
     private Rectangle paintIconR = new Rectangle();
     private Rectangle paintTextR = new Rectangle();
@@ -394,10 +396,16 @@
 
     public static ComponentUI createUI(JComponent c) {
         if (System.getSecurityManager() != null) {
-            return SAFE_BASIC_LABEL_UI;
-        } else {
-            return labelUI;
+            AppContext appContext = AppContext.getAppContext();
+            BasicLabelUI safeBasicLabelUI =
+                    (BasicLabelUI) appContext.get(BASIC_LABEL_UI_KEY);
+            if (safeBasicLabelUI == null) {
+                safeBasicLabelUI = new BasicLabelUI();
+                appContext.put(BASIC_LABEL_UI_KEY, safeBasicLabelUI);
+            }
+            return safeBasicLabelUI;
         }
+        return labelUI;
     }
 
     public void propertyChange(PropertyChangeEvent e) {
--- a/src/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -32,6 +32,7 @@
 import javax.swing.plaf.*;
 import javax.swing.text.View;
 import sun.swing.SwingUtilities2;
+import sun.awt.AppContext;
 
 
 /**
@@ -41,7 +42,7 @@
  */
 public class BasicRadioButtonUI extends BasicToggleButtonUI
 {
-    private final static BasicRadioButtonUI radioButtonUI = new BasicRadioButtonUI();
+    private static final Object BASIC_RADIO_BUTTON_UI_KEY = new Object();
 
     protected Icon icon;
 
@@ -53,6 +54,13 @@
     //        Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent b) {
+        AppContext appContext = AppContext.getAppContext();
+        BasicRadioButtonUI radioButtonUI =
+                (BasicRadioButtonUI) appContext.get(BASIC_RADIO_BUTTON_UI_KEY);
+        if (radioButtonUI == null) {
+            radioButtonUI = new BasicRadioButtonUI();
+            appContext.put(BASIC_RADIO_BUTTON_UI_KEY, radioButtonUI);
+        }
         return radioButtonUI;
     }
 
--- a/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,14 +31,12 @@
 import sun.swing.UIAction;
 import javax.swing.*;
 import javax.swing.border.Border;
-import javax.swing.event.*;
 import java.awt.*;
 import java.awt.event.*;
 import java.awt.peer.ComponentPeer;
 import java.awt.peer.LightweightPeer;
 import java.beans.*;
 import java.util.*;
-import javax.swing.plaf.ActionMapUIResource;
 import javax.swing.plaf.SplitPaneUI;
 import javax.swing.plaf.ComponentUI;
 import javax.swing.plaf.UIResource;
@@ -106,13 +104,13 @@
      * Keys to use for forward focus traversal when the JComponent is
      * managing focus.
      */
-    private static Set<KeyStroke> managingFocusForwardTraversalKeys;
+    private Set<KeyStroke> managingFocusForwardTraversalKeys;
 
     /**
      * Keys to use for backward focus traversal when the JComponent is
      * managing focus.
      */
-    private static Set<KeyStroke> managingFocusBackwardTraversalKeys;
+    private Set<KeyStroke> managingFocusBackwardTraversalKeys;
 
 
     /**
@@ -675,7 +673,7 @@
      * @return increment via keyboard methods.
      */
     int getKeyboardMoveIncrement() {
-        return KEYBOARD_DIVIDER_MOVE_OFFSET;
+        return 3;
     }
 
     /**
--- a/src/share/classes/javax/swing/plaf/basic/BasicToggleButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/basic/BasicToggleButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package javax.swing.plaf.basic;
 
+import sun.awt.AppContext;
+
 import java.awt.*;
 import java.awt.event.*;
 
@@ -43,7 +45,7 @@
  */
 public class BasicToggleButtonUI extends BasicButtonUI {
 
-    private final static BasicToggleButtonUI toggleButtonUI = new BasicToggleButtonUI();
+    private static final Object BASIC_TOGGLE_BUTTON_UI_KEY = new Object();
 
     private final static String propertyPrefix = "ToggleButton" + ".";
 
@@ -51,6 +53,13 @@
     //          Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent b) {
+        AppContext appContext = AppContext.getAppContext();
+        BasicToggleButtonUI toggleButtonUI =
+                (BasicToggleButtonUI) appContext.get(BASIC_TOGGLE_BUTTON_UI_KEY);
+        if (toggleButtonUI == null) {
+            toggleButtonUI = new BasicToggleButtonUI();
+            appContext.put(BASIC_TOGGLE_BUTTON_UI_KEY, toggleButtonUI);
+        }
         return toggleButtonUI;
     }
 
--- a/src/share/classes/javax/swing/plaf/metal/MetalBumps.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/metal/MetalBumps.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,9 @@
 import java.awt.*;
 import java.awt.image.*;
 import javax.swing.*;
-import java.io.*;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import sun.awt.AppContext;
 
 /**
  * Implements the bumps used throughout the Metal Look and Feel.
@@ -49,19 +50,9 @@
     protected Color shadowColor;
     protected Color backColor;
 
-    protected static Vector<BumpBuffer> buffers = new Vector<BumpBuffer>();
+    private static final Object METAL_BUMPS = new Object();
     protected BumpBuffer buffer;
 
-    public MetalBumps( Dimension bumpArea ) {
-        this( bumpArea.width, bumpArea.height );
-    }
-
-    public MetalBumps( int width, int height ) {
-        this(width, height, MetalLookAndFeel.getPrimaryControlHighlight(),
-             MetalLookAndFeel.getPrimaryControlDarkShadow(),
-             MetalLookAndFeel.getPrimaryControlShadow());
-    }
-
     /**
      * Creates MetalBumps of the specified size with the specified colors.
      * If <code>newBackColor</code> is null, the background will be
@@ -73,26 +64,22 @@
         setBumpColors( newTopColor, newShadowColor, newBackColor );
     }
 
-    private BumpBuffer getBuffer(GraphicsConfiguration gc, Color aTopColor,
-                                 Color aShadowColor, Color aBackColor) {
-        if (buffer != null && buffer.hasSameConfiguration(
-                              gc, aTopColor, aShadowColor, aBackColor)) {
-            return buffer;
+    private static BumpBuffer createBuffer(GraphicsConfiguration gc,
+                                           Color topColor, Color shadowColor, Color backColor) {
+        AppContext context = AppContext.getAppContext();
+        List<BumpBuffer> buffers = (List<BumpBuffer>) context.get(METAL_BUMPS);
+        if (buffers == null) {
+            buffers = new ArrayList<BumpBuffer>();
+            context.put(METAL_BUMPS, buffers);
         }
-        BumpBuffer result = null;
-
-        for (BumpBuffer aBuffer : buffers) {
-            if ( aBuffer.hasSameConfiguration(gc, aTopColor, aShadowColor,
-                                              aBackColor)) {
-                result = aBuffer;
-                break;
+        for (BumpBuffer buffer : buffers) {
+            if (buffer.hasSameConfiguration(gc, topColor, shadowColor, backColor)) {
+                return buffer;
             }
         }
-        if (result == null) {
-            result = new BumpBuffer(gc, topColor, shadowColor, backColor);
-            buffers.addElement(result);
-        }
-        return result;
+        BumpBuffer buffer = new BumpBuffer(gc, topColor, shadowColor, backColor);
+        buffers.add(buffer);
+        return buffer;
     }
 
     public void setBumpArea( Dimension bumpArea ) {
@@ -119,10 +106,12 @@
         GraphicsConfiguration gc = (g instanceof Graphics2D) ?
                 ((Graphics2D) g).getDeviceConfiguration() : null;
 
-        buffer = getBuffer(gc, topColor, shadowColor, backColor);
+        if ((buffer == null) || !buffer.hasSameConfiguration(gc, topColor, shadowColor, backColor)) {
+            buffer = createBuffer(gc, topColor, shadowColor, backColor);
+        }
 
-        int bufferWidth = buffer.getImageSize().width;
-        int bufferHeight = buffer.getImageSize().height;
+        int bufferWidth = BumpBuffer.IMAGE_SIZE;
+        int bufferHeight = BumpBuffer.IMAGE_SIZE;
         int iconWidth = getIconWidth();
         int iconHeight = getIconHeight();
         int x2 = x + iconWidth;
@@ -155,7 +144,6 @@
 class BumpBuffer {
 
     static final int IMAGE_SIZE = 64;
-    static Dimension imageSize = new Dimension( IMAGE_SIZE, IMAGE_SIZE );
 
     transient Image image;
     Color topColor;
@@ -197,10 +185,6 @@
         return image;
     }
 
-    public Dimension getImageSize() {
-        return imageSize;
-    }
-
     /**
      * Paints the bumps into the current image.
      */
--- a/src/share/classes/javax/swing/plaf/metal/MetalButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/metal/MetalButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,6 +26,8 @@
 package javax.swing.plaf.metal;
 
 import sun.swing.SwingUtilities2;
+import sun.awt.AppContext;
+
 import javax.swing.*;
 import javax.swing.border.*;
 import javax.swing.plaf.basic.*;
@@ -49,19 +51,25 @@
  * @author Tom Santos
  */
 public class MetalButtonUI extends BasicButtonUI {
-
-    private final static MetalButtonUI metalButtonUI = new MetalButtonUI();
-
     // NOTE: These are not really needed, but at this point we can't pull
     // them. Their values are updated purely for historical reasons.
     protected Color focusColor;
     protected Color selectColor;
     protected Color disabledTextColor;
 
+    private static final Object METAL_BUTTON_UI_KEY = new Object();
+
     // ********************************
     //          Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        MetalButtonUI metalButtonUI =
+                (MetalButtonUI) appContext.get(METAL_BUTTON_UI_KEY);
+        if (metalButtonUI == null) {
+            metalButtonUI = new MetalButtonUI();
+            appContext.put(METAL_BUTTON_UI_KEY, metalButtonUI);
+        }
         return metalButtonUI;
     }
 
--- a/src/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
 
 package javax.swing.plaf.metal;
 
+import sun.awt.AppContext;
+
 import javax.swing.*;
 import javax.swing.plaf.basic.BasicCheckBoxUI;
 
@@ -55,7 +57,7 @@
     // of BasicCheckBoxUI because we want to pick up all the
     // painting changes made in MetalRadioButtonUI.
 
-    private final static MetalCheckBoxUI checkboxUI = new MetalCheckBoxUI();
+    private static final Object METAL_CHECK_BOX_UI_KEY = new Object();
 
     private final static String propertyPrefix = "CheckBox" + ".";
 
@@ -65,6 +67,13 @@
     //         Create PlAF
     // ********************************
     public static ComponentUI createUI(JComponent b) {
+        AppContext appContext = AppContext.getAppContext();
+        MetalCheckBoxUI checkboxUI =
+                (MetalCheckBoxUI) appContext.get(METAL_CHECK_BOX_UI_KEY);
+        if (checkboxUI == null) {
+            checkboxUI = new MetalCheckBoxUI();
+            appContext.put(METAL_CHECK_BOX_UI_KEY, checkboxUI);
+        }
         return checkboxUI;
     }
 
--- a/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,10 +31,8 @@
 import javax.swing.event.*;
 import javax.swing.border.*;
 import javax.swing.plaf.basic.*;
-import java.util.EventListener;
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeEvent;
-import java.beans.PropertyVetoException;
 import javax.swing.plaf.*;
 
 /**
@@ -51,7 +49,7 @@
   private static final Border handyEmptyBorder = new EmptyBorder(0,0,0,0);
 
   protected static String IS_PALETTE   = "JInternalFrame.isPalette";
-
+  private static String IS_PALETTE_KEY = "JInternalFrame.isPalette";
   private static String FRAME_TYPE     = "JInternalFrame.frameType";
   private static String NORMAL_FRAME   = "normal";
   private static String PALETTE_FRAME  = "palette";
@@ -68,7 +66,7 @@
   public void installUI(JComponent c) {
     super.installUI(c);
 
-    Object paletteProp = c.getClientProperty( IS_PALETTE );
+    Object paletteProp = c.getClientProperty(IS_PALETTE_KEY);
     if ( paletteProp != null ) {
         setPalette( ((Boolean)paletteProp).booleanValue() );
     }
@@ -187,7 +185,7 @@
                   ui.setFrameType( (String) e.getNewValue() );
               }
           }
-          else if ( name.equals( IS_PALETTE ) )
+          else if ( name.equals(IS_PALETTE_KEY) )
           {
               if ( e.getNewValue() != null )
               {
--- a/src/share/classes/javax/swing/plaf/metal/MetalLabelUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/metal/MetalLabelUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,6 +26,8 @@
 package javax.swing.plaf.metal;
 
 import sun.swing.SwingUtilities2;
+import sun.awt.AppContext;
+
 import javax.swing.*;
 import javax.swing.plaf.*;
 import javax.swing.plaf.basic.*;
@@ -51,15 +53,21 @@
     * name in defaults table under the key "LabelUI".
     */
     protected static MetalLabelUI metalLabelUI = new MetalLabelUI();
-    private final static MetalLabelUI SAFE_METAL_LABEL_UI = new MetalLabelUI();
 
+    private static final Object METAL_LABEL_UI_KEY = new Object();
 
     public static ComponentUI createUI(JComponent c) {
         if (System.getSecurityManager() != null) {
-            return SAFE_METAL_LABEL_UI;
-        } else {
-            return metalLabelUI;
+            AppContext appContext = AppContext.getAppContext();
+            MetalLabelUI safeMetalLabelUI =
+                    (MetalLabelUI) appContext.get(METAL_LABEL_UI_KEY);
+            if (safeMetalLabelUI == null) {
+                safeMetalLabelUI = new MetalLabelUI();
+                appContext.put(METAL_LABEL_UI_KEY, safeMetalLabelUI);
+            }
+            return safeMetalLabelUI;
         }
+        return metalLabelUI;
     }
 
     /**
--- a/src/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,6 +26,8 @@
 package javax.swing.plaf.metal;
 
 import sun.swing.SwingUtilities2;
+import sun.awt.AppContext;
+
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
@@ -53,7 +55,7 @@
  */
 public class MetalRadioButtonUI extends BasicRadioButtonUI {
 
-    private static final MetalRadioButtonUI metalRadioButtonUI = new MetalRadioButtonUI();
+    private static final Object METAL_RADIO_BUTTON_UI_KEY = new Object();
 
     protected Color focusColor;
     protected Color selectColor;
@@ -65,6 +67,13 @@
     //        Create PlAF
     // ********************************
     public static ComponentUI createUI(JComponent c) {
+        AppContext appContext = AppContext.getAppContext();
+        MetalRadioButtonUI metalRadioButtonUI =
+                (MetalRadioButtonUI) appContext.get(METAL_RADIO_BUTTON_UI_KEY);
+        if (metalRadioButtonUI == null) {
+            metalRadioButtonUI = new MetalRadioButtonUI();
+            appContext.put(METAL_RADIO_BUTTON_UI_KEY, metalRadioButtonUI);
+        }
         return metalRadioButtonUI;
     }
 
--- a/src/share/classes/javax/swing/plaf/metal/MetalSliderUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/metal/MetalSliderUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,12 +54,13 @@
 
     protected final int TICK_BUFFER = 4;
     protected boolean filledSlider = false;
-    // NOTE: these next three variables are currently unused.
+    // NOTE: these next five variables are currently unused.
     protected static Color thumbColor;
     protected static Color highlightColor;
     protected static Color darkShadowColor;
     protected static int trackWidth;
     protected static int tickLength;
+    private int safeLength;
 
    /**
     * A default horizontal thumb <code>Icon</code>. This field might not be
@@ -107,7 +108,7 @@
 
     public void installUI( JComponent c ) {
         trackWidth = ((Integer)UIManager.get( "Slider.trackWidth" )).intValue();
-        tickLength = ((Integer)UIManager.get( "Slider.majorTickLength" )).intValue();
+        tickLength = safeLength = ((Integer)UIManager.get( "Slider.majorTickLength" )).intValue();
         horizThumbIcon = SAFE_HORIZ_THUMB_ICON =
                 UIManager.getIcon( "Slider.horizontalThumbIcon" );
         vertThumbIcon = SAFE_VERT_THUMB_ICON =
@@ -477,8 +478,8 @@
      * determine the tick area rectangle.
      */
     public int getTickLength() {
-        return slider.getOrientation() == JSlider.HORIZONTAL ? tickLength + TICK_BUFFER + 1 :
-        tickLength + TICK_BUFFER + 3;
+        return slider.getOrientation() == JSlider.HORIZONTAL ? safeLength + TICK_BUFFER + 1 :
+        safeLength + TICK_BUFFER + 3;
     }
 
     /**
@@ -523,22 +524,22 @@
 
     protected void paintMinorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
         g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
-        g.drawLine( x, TICK_BUFFER, x, TICK_BUFFER + (tickLength / 2) );
+        g.drawLine( x, TICK_BUFFER, x, TICK_BUFFER + (safeLength / 2) );
     }
 
     protected void paintMajorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
         g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
-        g.drawLine( x, TICK_BUFFER , x, TICK_BUFFER + (tickLength - 1) );
+        g.drawLine( x, TICK_BUFFER , x, TICK_BUFFER + (safeLength - 1) );
     }
 
     protected void paintMinorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) {
         g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
 
         if (MetalUtils.isLeftToRight(slider)) {
-            g.drawLine( TICK_BUFFER, y, TICK_BUFFER + (tickLength / 2), y );
+            g.drawLine( TICK_BUFFER, y, TICK_BUFFER + (safeLength / 2), y );
         }
         else {
-            g.drawLine( 0, y, tickLength/2, y );
+            g.drawLine( 0, y, safeLength/2, y );
         }
     }
 
@@ -546,10 +547,10 @@
         g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
 
         if (MetalUtils.isLeftToRight(slider)) {
-            g.drawLine( TICK_BUFFER, y, TICK_BUFFER + tickLength, y );
+            g.drawLine( TICK_BUFFER, y, TICK_BUFFER + safeLength, y );
         }
         else {
-            g.drawLine( 0, y, tickLength, y );
+            g.drawLine( 0, y, safeLength, y );
         }
     }
 }
--- a/src/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,6 +26,8 @@
 package javax.swing.plaf.metal;
 
 import sun.swing.SwingUtilities2;
+import sun.awt.AppContext;
+
 import java.awt.*;
 import java.awt.event.*;
 import java.lang.ref.*;
@@ -55,7 +57,7 @@
  */
 public class MetalToggleButtonUI extends BasicToggleButtonUI {
 
-    private static final MetalToggleButtonUI metalToggleButtonUI = new MetalToggleButtonUI();
+    private static final Object METAL_TOGGLE_BUTTON_UI_KEY = new Object();
 
     protected Color focusColor;
     protected Color selectColor;
@@ -67,6 +69,13 @@
     //        Create PLAF
     // ********************************
     public static ComponentUI createUI(JComponent b) {
+        AppContext appContext = AppContext.getAppContext();
+        MetalToggleButtonUI metalToggleButtonUI =
+                (MetalToggleButtonUI) appContext.get(METAL_TOGGLE_BUTTON_UI_KEY);
+        if (metalToggleButtonUI == null) {
+            metalToggleButtonUI = new MetalToggleButtonUI();
+            appContext.put(METAL_TOGGLE_BUTTON_UI_KEY, metalToggleButtonUI);
+        }
         return metalToggleButtonUI;
     }
 
--- a/src/share/classes/sun/applet/AppletClassLoader.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/applet/AppletClassLoader.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1995-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,6 +51,7 @@
 import java.security.PermissionCollection;
 import sun.awt.AppContext;
 import sun.awt.SunToolkit;
+import sun.misc.IOUtils;
 import sun.net.www.ParseUtil;
 import sun.security.util.SecurityConstants;
 
@@ -331,36 +332,7 @@
 
         byte[] b;
         try {
-            if (len != -1) {
-                // Read exactly len bytes from the input stream
-                b = new byte[len];
-                while (len > 0) {
-                    int n = in.read(b, b.length - len, len);
-                    if (n == -1) {
-                        throw new IOException("unexpected EOF");
-                    }
-                    len -= n;
-                }
-            } else {
-                // Read until end of stream is reached - use 8K buffer
-                // to speed up performance [stanleyh]
-                b = new byte[8192];
-                int total = 0;
-                while ((len = in.read(b, total, b.length - total)) != -1) {
-                    total += len;
-                    if (total >= b.length) {
-                        byte[] tmp = new byte[total * 2];
-                        System.arraycopy(b, 0, tmp, 0, total);
-                        b = tmp;
-                    }
-                }
-                // Trim array to correct size, if necessary
-                if (total != b.length) {
-                    byte[] tmp = new byte[total];
-                    System.arraycopy(b, 0, tmp, 0, total);
-                    b = tmp;
-                }
-            }
+            b = IOUtils.readFully(in, len, true);
         } finally {
             in.close();
         }
--- a/src/share/classes/sun/awt/image/ImageRepresentation.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/awt/image/ImageRepresentation.java	Thu Nov 12 23:04:42 2009 +0000
@@ -336,10 +336,6 @@
     public native void setICMpixels(int x, int y, int w, int h, int[] lut,
                                     byte[] pix, int off, int scansize,
                                     IntegerComponentRaster ict);
-
-    public native void setBytePixels(int x, int y, int w, int h, byte[] pix,
-                                     int off, int scansize,
-                                     ByteComponentRaster bct, int chanOff);
     public native int setDiffICM(int x, int y, int w, int h, int[] lut,
                                  int transPix, int numLut, IndexColorModel icm,
                                  byte[] pix, int off, int scansize,
@@ -450,27 +446,17 @@
                      (biRaster instanceof ByteComponentRaster) &&
                      (biRaster.getNumDataElements() == 1)){
                 ByteComponentRaster bt = (ByteComponentRaster) biRaster;
-                if (w*h > 200) {
-                    if (off == 0 && scansize == w) {
-                        bt.putByteData(x, y, w, h, pix);
-                    }
-                    else {
-                        byte[] bpix = new byte[w];
-                        poff = off;
-                        for (int yoff=y; yoff < y+h; yoff++) {
-                            System.arraycopy(pix, poff, bpix, 0, w);
-                            bt.putByteData(x, yoff, w, 1, bpix);
-                            poff += scansize;
-                        }
-                    }
+                if (off == 0 && scansize == w) {
+                    bt.putByteData(x, y, w, h, pix);
                 }
                 else {
-                    // Only is faster if #pixels
-                    // Note that setBytePixels modifies the raster directly
-                    // so we must mark it as changed afterwards
-                    setBytePixels(x, y, w, h, pix, off, scansize, bt,
-                                  bt.getDataOffset(0));
-                    bt.markDirty();
+                    byte[] bpix = new byte[w];
+                    poff = off;
+                    for (int yoff=y; yoff < y+h; yoff++) {
+                        System.arraycopy(pix, poff, bpix, 0, w);
+                        bt.putByteData(x, yoff, w, 1, bpix);
+                        poff += scansize;
+                    }
                 }
             }
             else {
--- a/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,9 +26,9 @@
 package sun.dyn.anon;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import sun.misc.IOUtils;
 
 /**
  * Anonymous class loader.  Will load any valid classfile, producing
@@ -285,13 +285,6 @@
         if (contentLength < 0)
             throw new IOException("invalid content length "+contentLength);
 
-        byte[] classFile = new byte[contentLength];
-        InputStream tcs = connection.getInputStream();
-        for (int fill = 0, nr; fill < classFile.length; fill += nr) {
-            nr = tcs.read(classFile, fill, classFile.length - fill);
-            if (nr < 0)
-                throw new IOException("premature end of file");
-        }
-        return classFile;
+        return IOUtils.readFully(connection.getInputStream(), contentLength, true);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/IOUtils.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * IOUtils: A collection of IO-related public static methods.
+ */
+
+package sun.misc;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+public class IOUtils {
+
+    /**
+     * Read up to <code>length</code> of bytes from <code>in</code>
+     * until EOF is detected.
+     * @param in input stream, must not be null
+     * @param length number of bytes to read, -1 or Integer.MAX_VALUE means
+     *        read as much as possible
+     * @param readAll if true, an EOFException will be thrown if not enough
+     *        bytes are read. Ignored when length is -1 or Integer.MAX_VALUE
+     * @return bytes read
+     * @throws IOException Any IO error or a premature EOF is detected
+     */
+    public static byte[] readFully(InputStream is, int length, boolean readAll)
+            throws IOException {
+        byte[] output = {};
+        if (length == -1) length = Integer.MAX_VALUE;
+        int pos = 0;
+        while (pos < length) {
+            int bytesToRead;
+            if (pos >= output.length) { // Only expand when there's no room
+                bytesToRead = Math.min(length - pos, output.length + 1024);
+                if (output.length < pos + bytesToRead) {
+                    output = Arrays.copyOf(output, pos + bytesToRead);
+                }
+            } else {
+                bytesToRead = output.length - pos;
+            }
+            int cc = is.read(output, pos, bytesToRead);
+            if (cc < 0) {
+                if (readAll && length != Integer.MAX_VALUE) {
+                    throw new EOFException("Detect premature EOF");
+                } else {
+                    if (output.length != pos) {
+                        output = Arrays.copyOf(output, pos);
+                    }
+                    break;
+                }
+            }
+            pos += cc;
+        }
+        return output;
+    }
+}
--- a/src/share/classes/sun/misc/Resource.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/misc/Resource.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,14 +25,15 @@
 
 package sun.misc;
 
+import java.io.EOFException;
 import java.net.URL;
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.io.InputStream;
 import java.security.CodeSigner;
 import java.util.jar.Manifest;
-import java.util.jar.Attributes;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 import sun.nio.ByteBuffered;
 
 /**
@@ -105,49 +106,37 @@
         }
 
         try {
-            if (len != -1) {
-                // Read exactly len bytes from the input stream
-                b = new byte[len];
-                while (len > 0) {
-                    int n = 0;
-                    try {
-                        n = in.read(b, b.length - len, len);
-                    } catch (InterruptedIOException iioe) {
-                        Thread.interrupted();
-                        isInterrupted = true;
+            b = new byte[0];
+            if (len == -1) len = Integer.MAX_VALUE;
+            int pos = 0;
+            while (pos < len) {
+                int bytesToRead;
+                if (pos >= b.length) { // Only expand when there's no room
+                    bytesToRead = Math.min(len - pos, b.length + 1024);
+                    if (b.length < pos + bytesToRead) {
+                        b = Arrays.copyOf(b, pos + bytesToRead);
                     }
-                    if (n == -1) {
-                        throw new IOException("unexpected EOF");
-                    }
-                    len -= n;
+                } else {
+                    bytesToRead = b.length - pos;
                 }
-            } else {
-                // Read until end of stream is reached
-                b = new byte[1024];
-                int total = 0;
-                for (;;) {
-                    len = 0;
-                    try {
-                        len = in.read(b, total, b.length - total);
-                        if (len == -1)
-                            break;
-                    } catch (InterruptedIOException iioe) {
-                        Thread.interrupted();
-                        isInterrupted = true;
-                    }
-                    total += len;
-                    if (total >= b.length) {
-                        byte[] tmp = new byte[total * 2];
-                        System.arraycopy(b, 0, tmp, 0, total);
-                        b = tmp;
+                int cc = 0;
+                try {
+                    cc = in.read(b, pos, bytesToRead);
+                } catch (InterruptedIOException iioe) {
+                    Thread.interrupted();
+                    isInterrupted = true;
+                }
+                if (cc < 0) {
+                    if (len != Integer.MAX_VALUE) {
+                        throw new EOFException("Detect premature EOF");
+                    } else {
+                        if (b.length != pos) {
+                            b = Arrays.copyOf(b, pos);
+                        }
+                        break;
                     }
                 }
-                // Trim array to correct size, if necessary
-                if (total != b.length) {
-                    byte[] tmp = new byte[total];
-                    System.arraycopy(b, 0, tmp, 0, total);
-                    b = tmp;
-                }
+                pos += cc;
             }
         } finally {
             try {
--- a/src/share/classes/sun/misc/Version-template.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,327 +0,0 @@
-/*
- * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.misc;
-import java.io.PrintStream;
-
-public class Version {
-
-
-    private static final String launcher_name =
-        "@@launcher_name@@";
-
-    private static final String java_version =
-        "@@java_version@@";
-
-    private static final String java_runtime_name =
-        "@@java_runtime_name@@";
-
-    private static final String java_runtime_version =
-        "@@java_runtime_version@@";
-
-    static {
-        init();
-    }
-
-    public static void init() {
-        System.setProperty("java.version", java_version);
-        System.setProperty("java.runtime.version", java_runtime_version);
-        System.setProperty("java.runtime.name", java_runtime_name);
-    }
-
-    private static boolean versionsInitialized = false;
-    private static int jvm_major_version = 0;
-    private static int jvm_minor_version = 0;
-    private static int jvm_micro_version = 0;
-    private static int jvm_update_version = 0;
-    private static int jvm_build_number = 0;
-    private static String jvm_special_version = null;
-    private static int jdk_major_version = 0;
-    private static int jdk_minor_version = 0;
-    private static int jdk_micro_version = 0;
-    private static int jdk_update_version = 0;
-    private static int jdk_build_number = 0;
-    private static String jdk_special_version = null;
-
-    /**
-     * In case you were wondering this method is called by java -version.
-     * Sad that it prints to stderr; would be nicer if default printed on
-     * stdout.
-     */
-    public static void print() {
-        print(System.err);
-    }
-
-    /**
-     * This is the same as print except that it adds an extra line-feed
-     * at the end, typically used by the -showversion in the launcher
-     */
-    public static void println() {
-        print(System.err);
-        System.err.println();
-    }
-
-    /**
-     * Give a stream, it will print version info on it.
-     */
-    public static void print(PrintStream ps) {
-        /* First line: platform version. */
-        ps.println(launcher_name + " version \"" + java_version + "\"");
-
-        /* Second line: runtime version (ie, libraries). */
-        ps.println(java_runtime_name + " (build " +
-                           java_runtime_version + ")");
-
-        /* Third line: JVM information. */
-        String java_vm_name    = System.getProperty("java.vm.name");
-        String java_vm_version = System.getProperty("java.vm.version");
-        String java_vm_info    = System.getProperty("java.vm.info");
-        ps.println(java_vm_name + " (build " + java_vm_version + ", " +
-                   java_vm_info + ")");
-    }
-
-
-    /**
-     * Returns the major version of the running JVM if it's 1.6 or newer
-     * or any RE VM build. It will return 0 if it's an internal 1.5 or
-     * 1.4.x build.
-     *
-     * @since 1.6
-     */
-    public static synchronized int jvmMajorVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_major_version;
-    }
-
-    /**
-     * Returns the minor version of the running JVM if it's 1.6 or newer
-     * or any RE VM build. It will return 0 if it's an internal 1.5 or
-     * 1.4.x build.
-     * @since 1.6
-     */
-    public static synchronized int jvmMinorVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_minor_version;
-    }
-
-
-    /**
-     * Returns the micro version of the running JVM if it's 1.6 or newer
-     * or any RE VM build. It will return 0 if it's an internal 1.5 or
-     * 1.4.x build.
-     * @since 1.6
-     */
-    public static synchronized int jvmMicroVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_micro_version;
-    }
-
-    /**
-     * Returns the update release version of the running JVM if it's
-     * a RE build. It will return 0 if it's an internal build.
-     * @since 1.6
-     */
-    public static synchronized int jvmUpdateVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_update_version;
-    }
-
-    public static synchronized String jvmSpecialVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        if (jvm_special_version == null) {
-            jvm_special_version = getJvmSpecialVersion();
-        }
-        return jvm_special_version;
-    }
-    public static native String getJvmSpecialVersion();
-
-    /**
-     * Returns the build number of the running JVM if it's a RE build
-     * It will return 0 if it's an internal build.
-     * @since 1.6
-     */
-    public static synchronized int jvmBuildNumber() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jvm_build_number;
-    }
-
-    /**
-     * Returns the major version of the running JDK.
-     *
-     * @since 1.6
-     */
-    public static synchronized int jdkMajorVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_major_version;
-    }
-
-    /**
-     * Returns the minor version of the running JDK.
-     * @since 1.6
-     */
-    public static synchronized int jdkMinorVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_minor_version;
-    }
-
-    /**
-     * Returns the micro version of the running JDK.
-     * @since 1.6
-     */
-    public static synchronized int jdkMicroVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_micro_version;
-    }
-
-    /**
-     * Returns the update release version of the running JDK if it's
-     * a RE build. It will return 0 if it's an internal build.
-     * @since 1.6
-     */
-    public static synchronized int jdkUpdateVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_update_version;
-    }
-
-    public static synchronized String jdkSpecialVersion() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        if (jdk_special_version == null) {
-            jdk_special_version = getJdkSpecialVersion();
-        }
-        return jdk_special_version;
-    }
-    public static native String getJdkSpecialVersion();
-
-    /**
-     * Returns the build number of the running JDK if it's a RE build
-     * It will return 0 if it's an internal build.
-     * @since 1.6
-     */
-    public static synchronized int jdkBuildNumber() {
-        if (!versionsInitialized) {
-            initVersions();
-        }
-        return jdk_build_number;
-    }
-
-    // true if JVM exports the version info including the capabilities
-    private static boolean jvmVersionInfoAvailable;
-    private static synchronized void initVersions() {
-        if (versionsInitialized) {
-            return;
-        }
-        jvmVersionInfoAvailable = getJvmVersionInfo();
-        if (!jvmVersionInfoAvailable) {
-            // parse java.vm.version for older JVM before the
-            // new JVM_GetVersionInfo is added.
-            // valid format of the version string is:
-            // n.n.n[_uu[c]][-<identifer>]-bxx
-            CharSequence cs = System.getProperty("java.vm.version");
-            if (cs.length() >= 5 &&
-                Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' &&
-                Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' &&
-                Character.isDigit(cs.charAt(4))) {
-                jvm_major_version = Character.digit(cs.charAt(0), 10);
-                jvm_minor_version = Character.digit(cs.charAt(2), 10);
-                jvm_micro_version = Character.digit(cs.charAt(4), 10);
-                cs = cs.subSequence(5, cs.length());
-                if (cs.charAt(0) == '_' && cs.length() >= 3 &&
-                    Character.isDigit(cs.charAt(1)) &&
-                    Character.isDigit(cs.charAt(2))) {
-                    int nextChar = 3;
-                    try {
-                        String uu = cs.subSequence(1, 3).toString();
-                        jvm_update_version = Integer.valueOf(uu).intValue();
-                        if (cs.length() >= 4) {
-                            char c = cs.charAt(3);
-                            if (c >= 'a' && c <= 'z') {
-                                jvm_special_version = Character.toString(c);
-                                nextChar++;
-                            }
-                        }
-                    } catch (NumberFormatException e) {
-                        // not conforming to the naming convention
-                        return;
-                    }
-                    cs = cs.subSequence(nextChar, cs.length());
-                }
-                if (cs.charAt(0) == '-') {
-                    // skip the first character
-                    // valid format: <identifier>-bxx or bxx
-                    // non-product VM will have -debug|-release appended
-                    cs = cs.subSequence(1, cs.length());
-                    String[] res = cs.toString().split("-");
-                    for (String s : res) {
-                        if (s.charAt(0) == 'b' && s.length() == 3 &&
-                            Character.isDigit(s.charAt(1)) &&
-                            Character.isDigit(s.charAt(2))) {
-                            jvm_build_number =
-                                Integer.valueOf(s.substring(1, 3)).intValue();
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-        getJdkVersionInfo();
-        versionsInitialized = true;
-    }
-
-    // Gets the JVM version info if available and sets the jvm_*_version fields
-    // and its capabilities.
-    //
-    // Return false if not available which implies an old VM (Tiger or before).
-    private static native boolean getJvmVersionInfo();
-    private static native void getJdkVersionInfo();
-
-}
-
-// Help Emacs a little because this file doesn't end in .java.
-//
-// Local Variables: ***
-// mode: java ***
-// End: ***
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/Version.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,327 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+import java.io.PrintStream;
+
+public class Version {
+
+
+    private static final String launcher_name =
+        "@@launcher_name@@";
+
+    private static final String java_version =
+        "@@java_version@@";
+
+    private static final String java_runtime_name =
+        "@@java_runtime_name@@";
+
+    private static final String java_runtime_version =
+        "@@java_runtime_version@@";
+
+    static {
+        init();
+    }
+
+    public static void init() {
+        System.setProperty("java.version", java_version);
+        System.setProperty("java.runtime.version", java_runtime_version);
+        System.setProperty("java.runtime.name", java_runtime_name);
+    }
+
+    private static boolean versionsInitialized = false;
+    private static int jvm_major_version = 0;
+    private static int jvm_minor_version = 0;
+    private static int jvm_micro_version = 0;
+    private static int jvm_update_version = 0;
+    private static int jvm_build_number = 0;
+    private static String jvm_special_version = null;
+    private static int jdk_major_version = 0;
+    private static int jdk_minor_version = 0;
+    private static int jdk_micro_version = 0;
+    private static int jdk_update_version = 0;
+    private static int jdk_build_number = 0;
+    private static String jdk_special_version = null;
+
+    /**
+     * In case you were wondering this method is called by java -version.
+     * Sad that it prints to stderr; would be nicer if default printed on
+     * stdout.
+     */
+    public static void print() {
+        print(System.err);
+    }
+
+    /**
+     * This is the same as print except that it adds an extra line-feed
+     * at the end, typically used by the -showversion in the launcher
+     */
+    public static void println() {
+        print(System.err);
+        System.err.println();
+    }
+
+    /**
+     * Give a stream, it will print version info on it.
+     */
+    public static void print(PrintStream ps) {
+        /* First line: platform version. */
+        ps.println(launcher_name + " version \"" + java_version + "\"");
+
+        /* Second line: runtime version (ie, libraries). */
+        ps.println(java_runtime_name + " (build " +
+                           java_runtime_version + ")");
+
+        /* Third line: JVM information. */
+        String java_vm_name    = System.getProperty("java.vm.name");
+        String java_vm_version = System.getProperty("java.vm.version");
+        String java_vm_info    = System.getProperty("java.vm.info");
+        ps.println(java_vm_name + " (build " + java_vm_version + ", " +
+                   java_vm_info + ")");
+    }
+
+
+    /**
+     * Returns the major version of the running JVM if it's 1.6 or newer
+     * or any RE VM build. It will return 0 if it's an internal 1.5 or
+     * 1.4.x build.
+     *
+     * @since 1.6
+     */
+    public static synchronized int jvmMajorVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_major_version;
+    }
+
+    /**
+     * Returns the minor version of the running JVM if it's 1.6 or newer
+     * or any RE VM build. It will return 0 if it's an internal 1.5 or
+     * 1.4.x build.
+     * @since 1.6
+     */
+    public static synchronized int jvmMinorVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_minor_version;
+    }
+
+
+    /**
+     * Returns the micro version of the running JVM if it's 1.6 or newer
+     * or any RE VM build. It will return 0 if it's an internal 1.5 or
+     * 1.4.x build.
+     * @since 1.6
+     */
+    public static synchronized int jvmMicroVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_micro_version;
+    }
+
+    /**
+     * Returns the update release version of the running JVM if it's
+     * a RE build. It will return 0 if it's an internal build.
+     * @since 1.6
+     */
+    public static synchronized int jvmUpdateVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_update_version;
+    }
+
+    public static synchronized String jvmSpecialVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        if (jvm_special_version == null) {
+            jvm_special_version = getJvmSpecialVersion();
+        }
+        return jvm_special_version;
+    }
+    public static native String getJvmSpecialVersion();
+
+    /**
+     * Returns the build number of the running JVM if it's a RE build
+     * It will return 0 if it's an internal build.
+     * @since 1.6
+     */
+    public static synchronized int jvmBuildNumber() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jvm_build_number;
+    }
+
+    /**
+     * Returns the major version of the running JDK.
+     *
+     * @since 1.6
+     */
+    public static synchronized int jdkMajorVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_major_version;
+    }
+
+    /**
+     * Returns the minor version of the running JDK.
+     * @since 1.6
+     */
+    public static synchronized int jdkMinorVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_minor_version;
+    }
+
+    /**
+     * Returns the micro version of the running JDK.
+     * @since 1.6
+     */
+    public static synchronized int jdkMicroVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_micro_version;
+    }
+
+    /**
+     * Returns the update release version of the running JDK if it's
+     * a RE build. It will return 0 if it's an internal build.
+     * @since 1.6
+     */
+    public static synchronized int jdkUpdateVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_update_version;
+    }
+
+    public static synchronized String jdkSpecialVersion() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        if (jdk_special_version == null) {
+            jdk_special_version = getJdkSpecialVersion();
+        }
+        return jdk_special_version;
+    }
+    public static native String getJdkSpecialVersion();
+
+    /**
+     * Returns the build number of the running JDK if it's a RE build
+     * It will return 0 if it's an internal build.
+     * @since 1.6
+     */
+    public static synchronized int jdkBuildNumber() {
+        if (!versionsInitialized) {
+            initVersions();
+        }
+        return jdk_build_number;
+    }
+
+    // true if JVM exports the version info including the capabilities
+    private static boolean jvmVersionInfoAvailable;
+    private static synchronized void initVersions() {
+        if (versionsInitialized) {
+            return;
+        }
+        jvmVersionInfoAvailable = getJvmVersionInfo();
+        if (!jvmVersionInfoAvailable) {
+            // parse java.vm.version for older JVM before the
+            // new JVM_GetVersionInfo is added.
+            // valid format of the version string is:
+            // n.n.n[_uu[c]][-<identifer>]-bxx
+            CharSequence cs = System.getProperty("java.vm.version");
+            if (cs.length() >= 5 &&
+                Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' &&
+                Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' &&
+                Character.isDigit(cs.charAt(4))) {
+                jvm_major_version = Character.digit(cs.charAt(0), 10);
+                jvm_minor_version = Character.digit(cs.charAt(2), 10);
+                jvm_micro_version = Character.digit(cs.charAt(4), 10);
+                cs = cs.subSequence(5, cs.length());
+                if (cs.charAt(0) == '_' && cs.length() >= 3 &&
+                    Character.isDigit(cs.charAt(1)) &&
+                    Character.isDigit(cs.charAt(2))) {
+                    int nextChar = 3;
+                    try {
+                        String uu = cs.subSequence(1, 3).toString();
+                        jvm_update_version = Integer.valueOf(uu).intValue();
+                        if (cs.length() >= 4) {
+                            char c = cs.charAt(3);
+                            if (c >= 'a' && c <= 'z') {
+                                jvm_special_version = Character.toString(c);
+                                nextChar++;
+                            }
+                        }
+                    } catch (NumberFormatException e) {
+                        // not conforming to the naming convention
+                        return;
+                    }
+                    cs = cs.subSequence(nextChar, cs.length());
+                }
+                if (cs.charAt(0) == '-') {
+                    // skip the first character
+                    // valid format: <identifier>-bxx or bxx
+                    // non-product VM will have -debug|-release appended
+                    cs = cs.subSequence(1, cs.length());
+                    String[] res = cs.toString().split("-");
+                    for (String s : res) {
+                        if (s.charAt(0) == 'b' && s.length() == 3 &&
+                            Character.isDigit(s.charAt(1)) &&
+                            Character.isDigit(s.charAt(2))) {
+                            jvm_build_number =
+                                Integer.valueOf(s.substring(1, 3)).intValue();
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        getJdkVersionInfo();
+        versionsInitialized = true;
+    }
+
+    // Gets the JVM version info if available and sets the jvm_*_version fields
+    // and its capabilities.
+    //
+    // Return false if not available which implies an old VM (Tiger or before).
+    private static native boolean getJvmVersionInfo();
+    private static native void getJdkVersionInfo();
+
+}
+
+// Help Emacs a little because this file doesn't end in .java.
+//
+// Local Variables: ***
+// mode: java ***
+// End: ***
--- a/src/share/classes/sun/reflect/misc/MethodUtil.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/reflect/misc/MethodUtil.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import sun.misc.IOUtils;
 import sun.net.www.ParseUtil;
 import sun.security.util.SecurityConstants;
 
@@ -373,34 +374,7 @@
 
         byte[] b;
         try {
-            if (len != -1) {
-                // Read exactly len bytes from the input stream
-                b = new byte[len];
-                while (len > 0) {
-                    int n = in.read(b, b.length - len, len);
-                    if (n == -1) {
-                        throw new IOException("unexpected EOF");
-                    }
-                    len -= n;
-                }
-            } else {
-                b = new byte[8192];
-                int total = 0;
-                while ((len = in.read(b, total, b.length - total)) != -1) {
-                    total += len;
-                    if (total >= b.length) {
-                        byte[] tmp = new byte[total * 2];
-                        System.arraycopy(b, 0, tmp, 0, total);
-                        b = tmp;
-                    }
-                }
-                // Trim array to correct size, if necessary
-                if (total != b.length) {
-                    byte[] tmp = new byte[total];
-                    System.arraycopy(b, 0, tmp, 0, total);
-                    b = tmp;
-                }
-            }
+            b = IOUtils.readFully(in, len, true);
         } finally {
             in.close();
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.provider.certpath;
+
+import java.util.Set;
+import java.util.Collection;
+import java.util.Locale;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.cert.X509CRL;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.PKIXCertPathChecker;
+
+import sun.security.x509.AlgorithmId;
+
+/**
+ * AlgorithmChecker is a <code>PKIXCertPathChecker</code> that checks that
+ * the signature algorithm of the specified certificate is not disabled.
+ *
+ * @author      Xuelei Fan
+ */
+final public class AlgorithmChecker extends PKIXCertPathChecker {
+
+    // the disabled algorithms
+    private static final String[] disabledAlgorithms = new String[] {"md2"};
+
+    // singleton instance
+    static final AlgorithmChecker INSTANCE = new AlgorithmChecker();
+
+    /**
+     * Default Constructor
+     */
+    private AlgorithmChecker() {
+        // do nothing
+    }
+
+    /**
+     * Return a AlgorithmChecker instance.
+     */
+    static AlgorithmChecker getInstance() {
+        return INSTANCE;
+    }
+
+    /**
+     * Initializes the internal state of the checker from parameters
+     * specified in the constructor.
+     */
+    public void init(boolean forward) throws CertPathValidatorException {
+        // do nothing
+    }
+
+    public boolean isForwardCheckingSupported() {
+        return false;
+    }
+
+    public Set<String> getSupportedExtensions() {
+        return null;
+    }
+
+    /**
+     * Checks the signature algorithm of the specified certificate.
+     */
+    public void check(Certificate cert, Collection<String> unresolvedCritExts)
+            throws CertPathValidatorException {
+        check(cert);
+    }
+
+    public static void check(Certificate cert)
+            throws CertPathValidatorException {
+        X509Certificate xcert = (X509Certificate)cert;
+        check(xcert.getSigAlgName());
+    }
+
+    static void check(AlgorithmId aid) throws CertPathValidatorException {
+        check(aid.getName());
+    }
+
+    static void check(X509CRL crl) throws CertPathValidatorException {
+        check(crl.getSigAlgName());
+    }
+
+    private static void check(String algName)
+            throws CertPathValidatorException {
+
+        String lowerCaseAlgName = algName.toLowerCase(Locale.ENGLISH);
+
+        for (String disabled : disabledAlgorithms) {
+            // checking the signature algorithm name
+            if (lowerCaseAlgName.indexOf(disabled) != -1) {
+                throw new CertPathValidatorException(
+                    "algorithm check failed: " + algName + " is disabled");
+            }
+        }
+    }
+
+}
--- a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Thu Nov 12 23:04:42 2009 +0000
@@ -289,6 +289,16 @@
         X500Name certIssuer = (X500Name) certImpl.getIssuerDN();
         X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();
 
+        // check the crl signature algorithm
+        try {
+            AlgorithmChecker.check(crl);
+        } catch (CertPathValidatorException cpve) {
+            if (debug != null) {
+                debug.println("CRL signature algorithm check failed: " + cpve);
+            }
+            return false;
+        }
+
         // if crlIssuer is set, verify that it matches the issuer of the
         // CRL and the CRL contains an IDP extension with the indirectCRL
         // boolean asserted. Otherwise, verify that the CRL issuer matches the
--- a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Thu Nov 12 23:04:42 2009 +0000
@@ -719,6 +719,11 @@
         /* we don't perform any validation of the trusted cert */
         if (!isTrustedCert) {
             /*
+             * check that the signature algorithm is not disabled.
+             */
+            AlgorithmChecker.check(cert);
+
+            /*
              * Check CRITICAL private extensions for user checkers that
              * support forward checking (forwardCheckers) and remove
              * ones we know how to check.
--- a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Thu Nov 12 23:04:42 2009 +0000
@@ -275,6 +275,7 @@
         int certPathLen = certList.size();
 
         basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
+        AlgorithmChecker algorithmChecker= AlgorithmChecker.getInstance();
         KeyChecker keyChecker = new KeyChecker(certPathLen,
             pkixParam.getTargetCertConstraints());
         ConstraintsChecker constraintsChecker =
@@ -291,6 +292,7 @@
         ArrayList<PKIXCertPathChecker> certPathCheckers =
             new ArrayList<PKIXCertPathChecker>();
         // add standard checkers that we will be using
+        certPathCheckers.add(algorithmChecker);
         certPathCheckers.add(keyChecker);
         certPathCheckers.add(constraintsChecker);
         certPathCheckers.add(policyChecker);
--- a/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -347,6 +347,9 @@
             return;
         }
 
+        /* check that the signature algorithm is not disabled. */
+        AlgorithmChecker.check(cert);
+
         /*
          * check for looping - abort a loop if
          * ((we encounter the same certificate twice) AND
--- a/src/share/classes/sun/security/timestamp/HttpTimestamper.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/security/timestamp/HttpTimestamper.java	Thu Nov 12 23:04:42 2009 +0000
@@ -34,6 +34,7 @@
 import java.util.Set;
 import java.util.Arrays;
 
+import sun.misc.IOUtils;
 import sun.security.pkcs.*;
 
 /**
@@ -142,25 +143,7 @@
 
             int total = 0;
             int contentLength = connection.getContentLength();
-            if (contentLength != -1) {
-                replyBuffer = new byte[contentLength];
-            } else {
-                replyBuffer = new byte[2048];
-                contentLength = Integer.MAX_VALUE;
-            }
-
-            while (total < contentLength) {
-                int count = input.read(replyBuffer, total,
-                                        replyBuffer.length - total);
-                if (count < 0)
-                    break;
-
-                total += count;
-                if (total >= replyBuffer.length && total < contentLength) {
-                    replyBuffer = Arrays.copyOf(replyBuffer, total * 2);
-                }
-            }
-            replyBuffer = Arrays.copyOf(replyBuffer, total);
+            replyBuffer = IOUtils.readFully(input, contentLength, false);
 
             if (DEBUG) {
                 System.out.println("received timestamp response (length=" +
--- a/src/share/classes/sun/security/util/DerValue.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/security/util/DerValue.java	Thu Nov 12 23:04:42 2009 +0000
@@ -28,6 +28,7 @@
 import java.io.*;
 import java.math.BigInteger;
 import java.util.Date;
+import sun.misc.IOUtils;
 
 /**
  * Represents a single DER-encoded value.  DER encoding rules are a subset
@@ -382,12 +383,8 @@
         if (fullyBuffered && in.available() != length)
             throw new IOException("extra data given to DerValue constructor");
 
-        byte[] bytes = new byte[length];
+        byte[] bytes = IOUtils.readFully(in, length, true);
 
-        // n.b. readFully not needed in normal fullyBuffered case
-        DataInputStream dis = new DataInputStream(in);
-
-        dis.readFully(bytes);
         buffer = new DerInputBuffer(bytes);
         return new DerInputStream(buffer);
     }
--- a/src/share/classes/sun/security/validator/SimpleValidator.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/security/validator/SimpleValidator.java	Thu Nov 12 23:04:42 2009 +0000
@@ -40,6 +40,8 @@
 import sun.security.util.DerOutputStream;
 import sun.security.util.ObjectIdentifier;
 
+import sun.security.provider.certpath.AlgorithmChecker;
+
 /**
  * A simple validator implementation. It is based on code from the JSSE
  * X509TrustManagerImpl. This implementation is designed for compatibility with
@@ -134,6 +136,13 @@
             X509Certificate issuerCert = chain[i + 1];
             X509Certificate cert = chain[i];
 
+            // check certificate algorithm
+            try {
+                AlgorithmChecker.check(cert);
+            } catch (CertPathValidatorException cpve) {
+                throw new ValidatorException
+                        (ValidatorException.T_ALGORITHM_DISABLED, cert, cpve);
+            }
 
             // no validity check for code signing certs
             if ((variant.equals(VAR_CODE_SIGNING) == false)
--- a/src/share/classes/sun/security/validator/ValidatorException.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/security/validator/ValidatorException.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,6 +55,9 @@
     public final static Object T_NAME_CHAINING =
         "Certificate chaining error";
 
+    public final static Object T_ALGORITHM_DISABLED =
+        "Certificate signature algorithm disabled";
+
     private Object type;
     private X509Certificate cert;
 
--- a/src/share/classes/sun/text/bidi/BidiBase.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/text/bidi/BidiBase.java	Thu Nov 12 23:04:42 2009 +0000
@@ -52,10 +52,11 @@
 
 package sun.text.bidi;
 
-import java.awt.font.TextAttribute;
-import java.awt.font.NumericShaper;
 import java.io.IOException;
 import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
 import java.text.AttributedCharacterIterator;
 import java.text.Bidi;
 import java.util.Arrays;
@@ -2689,12 +2690,13 @@
     public void setPara(AttributedCharacterIterator paragraph)
     {
         byte paraLvl;
-        Boolean runDirection = (Boolean) paragraph.getAttribute(TextAttribute.RUN_DIRECTION);
-        NumericShaper shaper = (NumericShaper) paragraph.getAttribute(TextAttribute.NUMERIC_SHAPING);
+        Boolean runDirection =
+            (Boolean) paragraph.getAttribute(TextAttributeConstants.RUN_DIRECTION);
+        Object shaper = paragraph.getAttribute(TextAttributeConstants.NUMERIC_SHAPING);
         if (runDirection == null) {
             paraLvl = INTERNAL_LEVEL_DEFAULT_LTR;
         } else {
-            paraLvl = (runDirection.equals(TextAttribute.RUN_DIRECTION_LTR)) ?
+            paraLvl = (runDirection.equals(TextAttributeConstants.RUN_DIRECTION_LTR)) ?
                         (byte)Bidi.DIRECTION_LEFT_TO_RIGHT : (byte)Bidi.DIRECTION_RIGHT_TO_LEFT;
         }
 
@@ -2706,7 +2708,8 @@
         char ch = paragraph.first();
         while (ch != AttributedCharacterIterator.DONE) {
             txt[i] = ch;
-            Integer embedding = (Integer) paragraph.getAttribute(TextAttribute.BIDI_EMBEDDING);
+            Integer embedding =
+                (Integer) paragraph.getAttribute(TextAttributeConstants.BIDI_EMBEDDING);
             if (embedding != null) {
                 byte level = embedding.byteValue();
                 if (level == 0) {
@@ -2724,7 +2727,7 @@
         }
 
         if (shaper != null) {
-            shaper.shape(txt, 0, len);
+            NumericShapings.shape(shaper, txt, 0, len);
         }
         setPara(txt, paraLvl, lvls);
     }
@@ -3441,4 +3444,106 @@
         return buf.toString();
     }
 
+    /**
+     * A class that provides access to constants defined by
+     * java.awt.font.TextAttribute without creating a static dependency.
+     */
+    private static class TextAttributeConstants {
+        private static final Class<?> clazz = getClass("java.awt.font.TextAttribute");
+
+        /**
+         * TextAttribute instances (or a fake Attribute type if
+         * java.awt.font.TextAttribute is not present)
+         */
+        static final AttributedCharacterIterator.Attribute RUN_DIRECTION =
+            getTextAttribute("RUN_DIRECTION");
+        static final Boolean RUN_DIRECTION_LTR =
+            (Boolean)getStaticField(clazz, "RUN_DIRECTION_LTR");
+        static final AttributedCharacterIterator.Attribute NUMERIC_SHAPING =
+            getTextAttribute("NUMERIC_SHAPING");
+        static final AttributedCharacterIterator.Attribute BIDI_EMBEDDING =
+            getTextAttribute("BIDI_EMBEDDING");
+
+        private static Class<?> getClass(String name) {
+            try {
+                return Class.forName(name, true, null);
+            } catch (ClassNotFoundException e) {
+                return null;
+            }
+        }
+
+        private static Object getStaticField(Class<?> clazz, String name) {
+            if (clazz == null) {
+                // fake attribute
+                return new AttributedCharacterIterator.Attribute(name) { };
+            } else {
+                try {
+                    Field f = clazz.getField(name);
+                    return f.get(null);
+                } catch (NoSuchFieldException x) {
+                    throw new AssertionError(x);
+                } catch (IllegalAccessException x) {
+                    throw new AssertionError(x);
+                }
+            }
+        }
+
+        private static AttributedCharacterIterator.Attribute
+            getTextAttribute(String name)
+        {
+            return (AttributedCharacterIterator.Attribute)getStaticField(clazz, name);
+        }
+    }
+
+    /**
+     * A class that provides access to java.awt.font.NumericShaping without
+     * creating a static dependency.
+     */
+    private static class NumericShapings {
+        private static final Class<?> clazz =
+            getClass("java.awt.font.NumericShaper");
+        private static final Method shapeMethod =
+            getMethod(clazz, "shape", char[].class, int.class, int.class);
+
+        private static Class<?> getClass(String name) {
+            try {
+                return Class.forName(name, true, null);
+            } catch (ClassNotFoundException e) {
+                return null;
+            }
+        }
+
+        private static Method getMethod(Class<?> clazz,
+                                        String name,
+                                        Class<?>... paramTypes)
+        {
+            if (clazz != null) {
+                try {
+                    return clazz.getMethod(name, paramTypes);
+                } catch (NoSuchMethodException e) {
+                    throw new AssertionError(e);
+                }
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Invokes NumericShaping shape(text,start,count) method.
+         */
+        static void shape(Object shaper, char[] text, int start, int count) {
+            if (shapeMethod == null)
+                throw new AssertionError("Should not get here");
+            try {
+                shapeMethod.invoke(shaper, text, start, count);
+            } catch (InvocationTargetException e) {
+                Throwable cause = e.getCause();
+                if (cause instanceof RuntimeException)
+                    throw (RuntimeException)cause;
+                throw new AssertionError(e);
+            } catch (IllegalAccessException iae) {
+                throw new AssertionError(iae);
+            }
+        }
+    }
 }
--- a/src/share/classes/sun/tools/jconsole/Version-template.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright 2004-2006 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.tools.jconsole;
-
-import java.io.PrintStream;
-
-public class Version {
-    private static final String jconsole_version =
-        "@@jconsole_version@@";
-
-    public static void print(PrintStream ps) {
-        printFullVersion(ps);
-
-        ps.println(Resources.getText("Name and Build",
-                                     System.getProperty("java.runtime.name"),
-                                     System.getProperty("java.runtime.version")));
-
-        ps.println(Resources.getText("Name Build and Mode",
-                                     System.getProperty("java.vm.name"),
-                                     System.getProperty("java.vm.version"),
-                                     System.getProperty("java.vm.info")));
-
-    }
-
-    public static void printFullVersion(PrintStream ps) {
-        ps.println(Resources.getText("JConsole version", jconsole_version));
-    }
-
-    static String getVersion() {
-        return jconsole_version;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/tools/jconsole/Version.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.tools.jconsole;
+
+import java.io.PrintStream;
+
+public class Version {
+    private static final String jconsole_version =
+        "@@jconsole_version@@";
+
+    public static void print(PrintStream ps) {
+        printFullVersion(ps);
+
+        ps.println(Resources.getText("Name and Build",
+                                     System.getProperty("java.runtime.name"),
+                                     System.getProperty("java.runtime.version")));
+
+        ps.println(Resources.getText("Name Build and Mode",
+                                     System.getProperty("java.vm.name"),
+                                     System.getProperty("java.vm.version"),
+                                     System.getProperty("java.vm.info")));
+
+    }
+
+    public static void printFullVersion(PrintStream ps) {
+        ps.println(Resources.getText("JConsole version", jconsole_version));
+    }
+
+    static String getVersion() {
+        return jconsole_version;
+    }
+}
--- a/src/share/classes/sun/util/calendar/ZoneInfoFile.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/classes/sun/util/calendar/ZoneInfoFile.java	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -472,6 +472,18 @@
 
     private static Map<String, ZoneInfo> zoneInfoObjects = null;
 
+    private static final String ziDir;
+    static {
+        String zi = (String) AccessController.doPrivileged(
+                         new sun.security.action.GetPropertyAction("java.home"))
+                    + File.separator + "lib" + File.separator + "zi";
+        try {
+            zi = new File(zi).getCanonicalPath();
+        } catch (Exception e) {
+        }
+        ziDir = zi;
+    }
+
     /**
      * Converts the given time zone ID to a platform dependent path
      * name. For example, "America/Los_Angeles" is converted to
@@ -576,20 +588,7 @@
             return null;
         }
 
-        int index;
-        for (index = 0; index < JAVAZI_LABEL.length; index++) {
-            if (buf[index] != JAVAZI_LABEL[index]) {
-                System.err.println("ZoneInfo: wrong magic number: " + id);
-                return null;
-            }
-        }
-
-        if (buf[index++] > JAVAZI_VERSION) {
-            System.err.println("ZoneInfo: incompatible version ("
-                               + buf[index - 1] + "): " + id);
-            return null;
-        }
-
+        int index = 0;
         int filesize = buf.length;
         int rawOffset = 0;
         int dstSavings = 0;
@@ -600,6 +599,18 @@
         int[] simpleTimeZoneParams = null;
 
         try {
+            for (index = 0; index < JAVAZI_LABEL.length; index++) {
+                if (buf[index] != JAVAZI_LABEL[index]) {
+                    System.err.println("ZoneInfo: wrong magic number: " + id);
+                    return null;
+                }
+            }
+            if (buf[index++] > JAVAZI_VERSION) {
+                System.err.println("ZoneInfo: incompatible version ("
+                                   + buf[index - 1] + "): " + id);
+                return null;
+            }
+
             while (index < filesize) {
                 byte tag = buf[index++];
                 int  len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF);
@@ -1017,30 +1028,33 @@
      * Reads the specified file under &lt;java.home&gt;/lib/zi into a buffer.
      * @return the buffer, or null if any I/O error occurred.
      */
-    private static byte[] readZoneInfoFile(String fileName) {
+    private static byte[] readZoneInfoFile(final String fileName) {
         byte[] buffer = null;
 
         try {
-            String homeDir = AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction("java.home"));
-            final String fname = homeDir + File.separator + "lib" + File.separator
-                                 + "zi" + File.separator + fileName;
             buffer = (byte[]) AccessController.doPrivileged(new PrivilegedExceptionAction() {
                 public Object run() throws IOException {
-                    File file = new File(fname);
-                    if (!file.canRead()) {
+                    File file = new File(ziDir, fileName);
+                    if (!file.exists() || !file.isFile()) {
                         return null;
                     }
-                    int filesize = (int)file.length();
-                    byte[] buf = new byte[filesize];
-
-                    FileInputStream fis = new FileInputStream(file);
-
-                    if (fis.read(buf) != filesize) {
-                        fis.close();
-                        throw new IOException("read error on " + fname);
+                    file = file.getCanonicalFile();
+                    String path = file.getCanonicalPath();
+                    byte[] buf = null;
+                    if (path != null && path.startsWith(ziDir)) {
+                        int filesize = (int)file.length();
+                        if (filesize > 0) {
+                            FileInputStream fis = new FileInputStream(file);
+                            buf = new byte[filesize];
+                            try {
+                                if (fis.read(buf) != filesize) {
+                                    throw new IOException("read error on " + fileName);
+                                }
+                            } finally {
+                                fis.close();
+                            }
+                        }
                     }
-                    fis.close();
                     return buf;
                 }
             });
--- a/src/share/native/com/sun/media/sound/SoundDefs.h	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/native/com/sun/media/sound/SoundDefs.h	Thu Nov 12 23:04:42 2009 +0000
@@ -38,6 +38,7 @@
 #define X_SPARCV9       3
 #define X_IA64          4
 #define X_AMD64         5
+#define X_ZERO          6
 
 // **********************************
 // Make sure you set X_PLATFORM and X_ARCH defines correctly.
--- a/src/share/native/sun/awt/image/awt_ImageRep.c	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/native/sun/awt/image/awt_ImageRep.c	Thu Nov 12 23:04:42 2009 +0000
@@ -142,84 +142,6 @@
 
 }
 
-JNIEXPORT void JNICALL
-Java_sun_awt_image_ImageRepresentation_setBytePixels(JNIEnv *env, jclass cls,
-                                                     jint x, jint y, jint w,
-                                                     jint h, jbyteArray jpix,
-                                                     jint off, jint scansize,
-                                                     jobject jbct,
-                                                     jint chanOffs)
-{
-    int sStride;
-    int pixelStride;
-    jobject jdata;
-    unsigned char *srcData;
-    unsigned char *dstData;
-    unsigned char *dataP;
-    unsigned char *pixP;
-    int i;
-    int j;
-
-
-    if (JNU_IsNull(env, jpix)) {
-        JNU_ThrowNullPointerException(env, "NullPointerException");
-        return;
-    }
-
-    sStride = (*env)->GetIntField(env, jbct, g_BCRscanstrID);
-    pixelStride = (*env)->GetIntField(env, jbct, g_BCRpixstrID);
-    jdata = (*env)->GetObjectField(env, jbct, g_BCRdataID);
-
-    srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix,
-                                                                  NULL);
-    if (srcData == NULL) {
-        /* out of memory error already thrown */
-        return;
-    }
-
-    dstData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jdata,
-                                                                  NULL);
-    if (dstData == NULL) {
-        /* out of memory error already thrown */
-        (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
-        return;
-    }
-
-    dataP = dstData + chanOffs + y*sStride + x*pixelStride;
-    pixP  = srcData + off;
-    if (pixelStride == 1) {
-        if (sStride == scansize && scansize == w) {
-            memcpy(dataP, pixP, w*h);
-        }
-        else {
-            for (i=0; i < h; i++) {
-                memcpy(dataP, pixP, w);
-                dataP += sStride;
-                pixP  += scansize;
-            }
-        }
-    }
-    else {
-        unsigned char *ydataP = dataP;
-        unsigned char *ypixP  = pixP;
-
-        for (i=0; i < h; i++) {
-            dataP = ydataP;
-            pixP = ypixP;
-            for (j=0; j < w; j++) {
-                *dataP = *pixP++;
-                dataP += pixelStride;
-            }
-            ydataP += sStride;
-            ypixP  += scansize;
-        }
-    }
-
-    (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
-    (*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
-
-}
-
 JNIEXPORT jint JNICALL
 Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
                                                   jint x, jint y, jint w,
@@ -266,6 +188,13 @@
     jnewlut = (*env)->GetObjectField(env, jicm, g_ICMrgbID);
     mapSize = (*env)->GetIntField(env, jicm, g_ICMmapSizeID);
 
+    if (numLut < 0 || numLut > 256 || mapSize < 0 || mapSize > 256) {
+        /* Ether old or new ICM has a palette that exceeds capacity
+           of byte data type, so we have to convert the image data
+           to default representation.
+        */
+        return 0;
+    }
     srcLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jlut,
                                                                 NULL);
     if (srcLUT == NULL) {
--- a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Thu Nov 12 23:04:42 2009 +0000
@@ -676,6 +676,10 @@
 #ifdef DEBUG_IIO_JPEG
     printf("in setQTables, qlen = %d, write is %d\n", qlen, write);
 #endif
+    if (qlen > NUM_QUANT_TBLS) {
+        /* Ignore extra qunterization tables. */
+        qlen = NUM_QUANT_TBLS;
+    }
     for (i = 0; i < qlen; i++) {
         table = (*env)->GetObjectArrayElement(env, qtables, i);
         qdata = (*env)->GetObjectField(env, table, JPEGQTable_tableID);
@@ -727,6 +731,11 @@
     hlensBody = (*env)->GetShortArrayElements(env,
                                               huffLens,
                                               NULL);
+    if (hlensLen > 16) {
+        /* Ignore extra elements of bits array. Only 16 elements can be
+           stored. 0-th element is not used. (see jpeglib.h, line 107)  */
+        hlensLen = 16;
+    }
     for (i = 1; i <= hlensLen; i++) {
         huff_ptr->bits[i] = (UINT8)hlensBody[i-1];
     }
@@ -743,6 +752,11 @@
                                               huffValues,
                                               NULL);
 
+    if (hvalsLen > 256) {
+        /* Ignore extra elements of hufval array. Only 256 elements
+           can be stored. (see jpeglib.h, line 109)                  */
+        hlensLen = 256;
+    }
     for (i = 0; i < hvalsLen; i++) {
         huff_ptr->huffval[i] = (UINT8)hvalsBody[i];
     }
@@ -763,6 +777,11 @@
     j_compress_ptr comp;
     j_decompress_ptr decomp;
     jsize hlen = (*env)->GetArrayLength(env, DCHuffmanTables);
+
+    if (hlen > NUM_HUFF_TBLS) {
+        /* Ignore extra DC huffman tables. */
+        hlen = NUM_HUFF_TBLS;
+    }
     for (i = 0; i < hlen; i++) {
         if (cinfo->is_decompressor) {
             decomp = (j_decompress_ptr) cinfo;
@@ -784,6 +803,10 @@
         huff_ptr->sent_table = !write;
     }
     hlen = (*env)->GetArrayLength(env, ACHuffmanTables);
+    if (hlen > NUM_HUFF_TBLS) {
+        /* Ignore extra AC huffman tables. */
+        hlen = NUM_HUFF_TBLS;
+    }
     for (i = 0; i < hlen; i++) {
         if (cinfo->is_decompressor) {
             decomp = (j_decompress_ptr) cinfo;
@@ -1833,6 +1856,13 @@
         return JNI_FALSE;
     }
 
+    if (stepX > cinfo->image_width) {
+        stepX = cinfo->image_width;
+    }
+    if (stepY > cinfo->image_height) {
+        stepY = cinfo->image_height;
+    }
+
     /*
      * First get the source bands array and copy it to our local array
      * so we don't have to worry about pinning and unpinning it again.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/bin/ergo_zero.c	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+#include "ergo.h"
+
+
+/* Methods for solaris-sparc and linux-sparc: these are easy. */
+
+/* Ask the OS how many processors there are. */
+static unsigned long
+physical_processors(void) {
+  const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF);
+
+  JLI_TraceLauncher("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors);
+  return sys_processors;
+}
+
+/* The sparc version of the "server-class" predicate. */
+jboolean
+ServerClassMachineImpl(void) {
+  jboolean            result            = JNI_FALSE;
+  /* How big is a server class machine? */
+  const unsigned long server_processors = 2UL;
+  const uint64_t      server_memory     = 2UL * GB;
+  const uint64_t      actual_memory     = physical_memory();
+
+  /* Is this a server class machine? */
+  if (actual_memory >= server_memory) {
+    const unsigned long actual_processors = physical_processors();
+    if (actual_processors >= server_processors) {
+      result = JNI_TRUE;
+    }
+  }
+  JLI_TraceLauncher("unix_" LIBARCHNAME "_ServerClassMachine: %s\n",
+           (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/bin/zero/jvm.cfg	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,39 @@
+# Copyright 2003 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+# 
+# List of JVMs that can be used as an option to java, javac, etc.
+# Order is important -- first in this list is the default JVM.
+# NOTE that this both this file and its format are UNSUPPORTED and
+# WILL GO AWAY in a future release.
+#
+# You may also select a JVM in an arbitrary location with the
+# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
+# and may not be available in a future release.
+#
+-server KNOWN
+-client IGNORE
+-hotspot ERROR
+-classic WARN
+-native ERROR
+-green ERROR
--- a/src/solaris/classes/java/util/prefs/FileSystemPreferences.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/solaris/classes/java/util/prefs/FileSystemPreferences.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,12 +26,12 @@
 package java.util.prefs;
 import java.util.*;
 import java.io.*;
-import java.util.logging.Logger;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
 
+import sun.util.logging.PlatformLogger;
 
 /**
  * Preferences implementation for Unix.  Preferences are stored in the file
@@ -61,8 +61,8 @@
      * Returns logger for error messages. Backing store exceptions are logged at
      * WARNING level.
      */
-    private static Logger getLogger() {
-        return Logger.getLogger("java.util.prefs");
+    private static PlatformLogger getLogger() {
+        return PlatformLogger.getLogger("java.util.prefs");
     }
 
     /**
--- a/src/solaris/classes/sun/awt/X11GraphicsDevice.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/solaris/classes/sun/awt/X11GraphicsDevice.java	Thu Nov 12 23:04:42 2009 +0000
@@ -134,7 +134,7 @@
                 makeConfigurations();
             }
         }
-        return configs;
+        return configs.clone();
     }
 
     private void makeConfigurations() {
--- a/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java	Thu Nov 12 23:04:42 2009 +0000
@@ -28,6 +28,7 @@
 import java.io.IOException;
 import java.util.LinkedList;
 import java.util.HashSet;
+import java.util.Iterator;
 
 /**
  * Manipulates a native array of epoll_event structs on Linux:
@@ -200,12 +201,9 @@
     void release(SelChImpl channel) {
         synchronized (updateList) {
             // flush any pending updates
-            int i = 0;
-            while (i < updateList.size()) {
-                if (updateList.get(i).channel == channel) {
-                    updateList.remove(i);
-                } else {
-                    i++;
+            for (Iterator<Updator> it = updateList.iterator(); it.hasNext();) {
+                if (it.next().channel == channel) {
+                    it.remove();
                 }
             }
 
--- a/src/windows/classes/sun/awt/Win32GraphicsDevice.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/windows/classes/sun/awt/Win32GraphicsDevice.java	Thu Nov 12 23:04:42 2009 +0000
@@ -165,7 +165,7 @@
                 if (defaultConfig != null) {
                     configs = new GraphicsConfiguration[1];
                     configs[0] = defaultConfig;
-                    return configs;
+                    return configs.clone();
                 }
             }
 
@@ -196,7 +196,7 @@
             configs = new GraphicsConfiguration[v.size()];
             v.copyInto(configs);
         }
-        return configs;
+        return configs.clone();
     }
 
     /**
--- a/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java	Thu Nov 12 23:04:42 2009 +0000
@@ -429,7 +429,7 @@
                 if (defaultConfig != null) {
                     configs = new GraphicsConfiguration[1];
                     configs[0] = defaultConfig;
-                    return configs;
+                    return configs.clone();
                 }
             }
         }
--- a/test/Makefile	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/Makefile	Thu Nov 12 23:04:42 2009 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1995-2009 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -27,83 +27,141 @@
 # Makefile to run various jdk tests
 #
 
-# Get OS/ARCH specifics
-OSNAME = $(shell uname -s)
+# Empty these to get rid of some default rules
+.SUFFIXES:
+.SUFFIXES: .java
+CO=
+GET=
+
+# Utilities used
+AWK       = awk
+CAT       = cat
+CD        = cd
+CHMOD     = chmod
+CP        = cp
+CUT       = cut
+ECHO      = echo
+EGREP     = egrep
+EXPAND    = expand
+EXPR      = expr
+KILL      = /usr/bin/kill
+MKDIR     = mkdir
+NOHUP     = nohup
+PWD       = pwd
+SED       = sed
+SLEEP     = sleep
+SORT      = sort
+TEE       = tee
+UNAME     = uname
+UNIQ      = uniq
+WC        = wc
+XHOST     = xhost
+ZIP       = zip
+
+# Get OS name from uname
+UNAME_S := $(shell $(UNAME) -s)
 
 # Commands to run on paths to make mixed paths for java on windows
-GETMIXEDPATH=echo
+GETMIXEDPATH=$(ECHO)
 
 # Location of developer shared files
 SLASH_JAVA = /java
 
 # Platform specific settings
-ifeq ($(OSNAME), SunOS)
-  PLATFORM = solaris
-  ARCH = $(shell uname -p)
-  ifeq ($(ARCH), i386)
-    ARCH=i586
-  endif
+ifeq ($(UNAME_S), SunOS)
+  OS_NAME     = solaris
+  OS_ARCH    := $(shell $(UNAME) -p)
+  OS_VERSION := $(shell $(UNAME) -r)
+endif
+ifeq ($(UNAME_S), Linux)
+  OS_NAME     = linux
+  OS_ARCH    := $(shell $(UNAME) -m)
+  OS_VERSION := $(shell $(UNAME) -r)
 endif
-ifeq ($(OSNAME), Linux)
-  PLATFORM = linux
-  ARCH = $(shell uname -m)
-  ifeq ($(ARCH), i386)
-    ARCH=i586
+ifndef OS_NAME
+  ifneq ($(PROCESSOR_IDENTIFIER), )
+    OS_NAME = windows
+    SLASH_JAVA = J:
+    # A variety of ways to say X64 arch :^(
+    OS_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER))
+    EXESUFFIX = .exe
+    # These need to be different depending on MKS or CYGWIN
+    ifeq ($(findstring cygdrive,$(shell ($(CD) C:/ && $(PWD)))), )
+      GETMIXEDPATH  = dosname -s
+      OS_VERSION   := $(shell $(UNAME) -r)
+    else
+      GETMIXEDPATH  = cygpath -m -s
+      OS_VERSION   := $(shell $(UNAME) -s | $(CUT) -d'-' -f2)
+    endif
   endif
 endif
 
-# Cannot trust uname output
-ifneq ($(PROCESSOR_IDENTIFIER), )
-  PLATFORM = windows
-  SLASH_JAVA = J:
-  # A variety of ways to say X64 arch :^(
-  PROC_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER))
-  PROC_ARCH:=$(subst x86,X86,$(PROC_ARCH))
-  PROC_ARCH:=$(subst x64,X64,$(PROC_ARCH))
-  PROC_ARCH:=$(subst AMD64,X64,$(PROC_ARCH))
-  PROC_ARCH:=$(subst amd64,X64,$(PROC_ARCH))
-  PROC_ARCH:=$(subst EM64T,X64,$(PROC_ARCH))
-  PROC_ARCH:=$(subst em64t,X64,$(PROC_ARCH))
-  PROC_ARCH:=$(subst intel64,X64,$(PROC_ARCH))
-  PROC_ARCH:=$(subst Intel64,X64,$(PROC_ARCH))
-  PROC_ARCH:=$(subst INTEL64,X64,$(PROC_ARCH))
-  PROC_ARCH:=$(subst ia64,IA64,$(PROC_ARCH))
-  ifeq ($(PROC_ARCH),IA64)
-    ARCH = ia64
+# Only want major and minor numbers from os version
+OS_VERSION := $(shell $(ECHO) "$(OS_VERSION)" | $(CUT) -d'.' -f1,2)
+
+# Try and use names i586, x64, and ia64 consistently  
+OS_ARCH:=$(subst X64,x64,$(OS_ARCH))
+OS_ARCH:=$(subst AMD64,x64,$(OS_ARCH))
+OS_ARCH:=$(subst amd64,x64,$(OS_ARCH))
+OS_ARCH:=$(subst x86_64,x64,$(OS_ARCH))
+OS_ARCH:=$(subst EM64T,x64,$(OS_ARCH))
+OS_ARCH:=$(subst em64t,x64,$(OS_ARCH))
+OS_ARCH:=$(subst intel64,x64,$(OS_ARCH))
+OS_ARCH:=$(subst Intel64,x64,$(OS_ARCH))
+OS_ARCH:=$(subst INTEL64,x64,$(OS_ARCH))
+OS_ARCH:=$(subst IA64,ia64,$(OS_ARCH))
+OS_ARCH:=$(subst X86,i586,$(OS_ARCH))
+OS_ARCH:=$(subst x86,i586,$(OS_ARCH))
+OS_ARCH:=$(subst i386,i586,$(OS_ARCH))
+OS_ARCH:=$(subst i486,i586,$(OS_ARCH))
+OS_ARCH:=$(subst i686,i586,$(OS_ARCH))
+
+# Check for ARCH_DATA_MODEL, adjust OS_ARCH accordingly
+ifndef ARCH_DATA_MODEL
+  ARCH_DATA_MODEL=32
+endif
+ARCH_DATA_MODEL_ERROR= \
+  ARCH_DATA_MODEL=$(ARCH_DATA_MODEL) cannot be used with $(OS_NAME)-$(ARCH)
+ifeq ($(ARCH_DATA_MODEL),64)
+  ifeq ($(OS_NAME)-$(OS_ARCH),solaris-i586)
+    OS_ARCH=x64
+  endif
+  ifeq ($(OS_NAME)-$(OS_ARCH),solaris-sparc)
+    OS_ARCH=sparcv9
+  endif
+  ifeq ($(OS_ARCH),i586)
+    x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
+  endif
+  ifeq ($(OS_ARCH),sparc)
+    x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
+  endif
+else
+  ifeq ($(ARCH_DATA_MODEL),32)
+    ifeq ($(OS_ARCH),x64)
+      x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
+    endif
+    ifeq ($(OS_ARCH),ia64)
+      x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
+    endif
+    ifeq ($(OS_ARCH),sparcv9)
+      x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
+    endif
   else
-    ifeq ($(PROC_ARCH),X64)
-      ARCH = x64
-    else
-      ARCH = i586
-    endif
-  endif
-  EXESUFFIX = .exe
-  # These need to be different depending on MKS or CYGWIN
-  ifeq ($(findstring cygdrive,$(shell (cd C:/ && pwd))), )
-    GETMIXEDPATH=dosname -s
-  else
-    GETMIXEDPATH=cygpath -m -s
+    x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
   endif
 endif
 
-# Utilities used
-CD    = cd
-CP    = cp
-ECHO  = echo
-MKDIR = mkdir
-ZIP   = zip
-
 # Root of this test area (important to use full paths in some places)
-TEST_ROOT := $(shell pwd)
+TEST_ROOT := $(shell $(PWD))
 
 # Root of all test results
 ifdef ALT_OUTPUTDIR
   ABS_OUTPUTDIR = $(ALT_OUTPUTDIR)
 else
-  ABS_OUTPUTDIR = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
+  ABS_OUTPUTDIR = $(TEST_ROOT)/../build/$(OS_NAME)-$(OS_ARCH)
 endif
 ABS_BUILD_ROOT = $(ABS_OUTPUTDIR)
-ABS_TEST_OUTPUT_DIR := $(ABS_BUILD_ROOT)/testoutput
+ABS_TEST_OUTPUT_DIR := $(ABS_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
 
 # Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
 ifndef PRODUCT_HOME
@@ -114,13 +172,14 @@
       if [ -d $(ABS_JDK_IMAGE) ] ; then \
          $(ECHO) "$(ABS_JDK_IMAGE)";    \
        else                             \
-         $(ECHO) "$(ABS_BUILD_ROOT)" ;  \
+         $(ECHO) "$(ABS_BUILD_ROOT)";   \
        fi)
   PRODUCT_HOME := $(PRODUCT_HOME)
 endif
 
 # Expect JPRT to set JPRT_PRODUCT_ARGS (e.g. -server etc.)
 #   Should be passed into 'java' only.
+#   Could include: -d64 -server -client OR any java option
 ifdef JPRT_PRODUCT_ARGS
   JAVA_ARGS = $(JPRT_PRODUCT_ARGS)
 endif
@@ -131,18 +190,131 @@
   JAVA_VM_ARGS = $(JPRT_PRODUCT_VM_ARGS)
 endif
 
+# Check JAVA_ARGS arguments based on ARCH_DATA_MODEL etc.
+ifeq ($(OS_NAME),solaris)
+  D64_ERROR_MESSAGE=Mismatch between ARCH_DATA_MODEL=$(ARCH_DATA_MODEL) and use of -d64 in JAVA_ARGS=$(JAVA_ARGS)
+  ifeq ($(ARCH_DATA_MODEL),32)
+    ifneq ($(findstring -d64,$(JAVA_ARGS)),)
+      x:=$(warning "WARNING: $(D64_ERROR_MESSAGE)")
+    endif
+  endif
+  ifeq ($(ARCH_DATA_MODEL),64)
+    ifeq ($(findstring -d64,$(JAVA_ARGS)),)
+      x:=$(warning "WARNING: $(D64_ERROR_MESSAGE)")
+    endif
+  endif
+endif
+
 # Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results)
 ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip
 ifdef JPRT_ARCHIVE_BUNDLE
   ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE)
 endif
 
+# DISPLAY settings for virtual frame buffer
+START_XVFB = start-Xvfb.sh
+NOHUP_OUTPUT = $(ABS_TEST_OUTPUT_DIR)/start-Xvfb.nohup-output.txt
+DISPLAY_PID_FILE=$(ABS_TEST_OUTPUT_DIR)/xvfb-display-number.txt
+DISPLAY_SLEEP_TIME=10
+DISPLAY_MAX_SLEEPS=10
+ifeq ($(OS_NAME),solaris)
+  VIRTUAL_FRAME_BUFFER = true
+endif
+ifeq ($(OS_NAME),linux)
+  VIRTUAL_FRAME_BUFFER = true
+endif
+
+# Does not work yet, display dies as soon as it gets used. :^(
+VIRTUAL_FRAME_BUFFER = false
+
+# Are we using a VIRTUAL_FRAME_BUFFER (Xvfb)
+ifeq ($(VIRTUAL_FRAME_BUFFER),true)
+  
+  PREP_DISPLAY = \
+    $(CP) $(START_XVFB) $(ABS_TEST_OUTPUT_DIR); \
+    $(CHMOD) a+x $(ABS_TEST_OUTPUT_DIR)/$(START_XVFB); \
+    ( $(CD) $(ABS_TEST_OUTPUT_DIR) && \
+      $(NOHUP) $(ABS_TEST_OUTPUT_DIR)/$(START_XVFB) $(DISPLAY_PID_FILE) > $(NOHUP_OUTPUT) 2>&1 && \
+      $(SLEEP) $(DISPLAY_SLEEP_TIME) ) & \
+    count=1; \
+    while [ ! -s $(DISPLAY_PID_FILE) ] ; do \
+      $(ECHO) "Sleeping $(DISPLAY_SLEEP_TIME) more seconds, DISPLAY not ready"; \
+      $(SLEEP) $(DISPLAY_SLEEP_TIME); \
+      count=`$(EXPR) $${count} '+' 1`; \
+      if [ $${count} -gt $(DISPLAY_MAX_SLEEPS) ] ; then \
+        $(ECHO) "ERROR: DISPLAY not ready, giving up on DISPLAY"; \
+        exit 9; \
+      fi; \
+    done ; \
+    DISPLAY=":`$(CAT) $(DISPLAY_PID_FILE)`"; \
+    export DISPLAY; \
+    $(CAT) $(NOHUP_OUTPUT); \
+    $(ECHO) "Prepared DISPLAY=$${DISPLAY}"; \
+    $(XHOST) || \
+    ( $(ECHO) "ERROR: No display" ; exit 8)
+
+  KILL_DISPLAY = \
+    ( \
+      DISPLAY=":`$(CAT) $(DISPLAY_PID_FILE)`"; \
+      export DISPLAY; \
+      if [ -s "$(DISPLAY_PID_FILE)" ] ; then \
+        $(KILL) `$(CAT) $(DISPLAY_PID_FILE)` > /dev/null 2>&1; \
+        $(KILL) -9 `$(CAT) $(DISPLAY_PID_FILE)` > /dev/null 2>&1; \
+      fi; \
+      $(ECHO) "Killed DISPLAY=$${DISPLAY}"; \
+    )
+
+else
+  
+  PREP_DISPLAY = $(ECHO) "VIRTUAL_FRAME_BUFFER=$(VIRTUAL_FRAME_BUFFER)"
+  KILL_DISPLAY = $(ECHO) "VIRTUAL_FRAME_BUFFER=$(VIRTUAL_FRAME_BUFFER)"
+
+endif
+
 # How to create the test bundle (pass or fail, we want to create this)
 #   Follow command with ";$(BUNDLE_UP_AND_EXIT)", so it always gets executed.
 ZIP_UP_RESULTS = ( $(MKDIR) -p `dirname $(ARCHIVE_BUNDLE)`     \
 	           && $(CD) $(ABS_TEST_OUTPUT_DIR)             \
 	           && $(ZIP) -q -r $(ARCHIVE_BUNDLE) . )
-BUNDLE_UP_AND_EXIT = ( exitCode=$$? && $(ZIP_UP_RESULTS) && exit $${exitCode} )
+SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport/text/summary.txt
+STATS_TXT_NAME = Stats.txt
+STATS_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/$(STATS_TXT_NAME)
+RUNLIST   = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/runlist.txt
+PASSLIST  = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/passlist.txt
+FAILLIST  = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/faillist.txt
+BUNDLE_UP_AND_EXIT = \
+( \
+  exitCode=$$? && \
+  _summary="$(SUMMARY_TXT)"; \
+  $(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST); \
+  if [ -r "$${_summary}" ] ; then \
+    $(ECHO) "Summary: $${_summary}" > $(STATS_TXT); \
+    $(EXPAND) $${_summary} | $(EGREP) -v ' Not run\.' > $(RUNLIST); \
+    $(EGREP) ' Passed\.' $(RUNLIST) \
+      | $(EGREP) -v ' Error\.' \
+      | $(EGREP) -v ' Failed\.' > $(PASSLIST); \
+    ( $(EGREP) ' Failed\.' $(RUNLIST); \
+      $(EGREP) ' Error\.' $(RUNLIST); \
+      $(EGREP) -v ' Passed\.' $(RUNLIST) ) \
+      | $(SORT) | $(UNIQ) > $(FAILLIST); \
+    if [ $${exitCode} != 0 -o -s $(FAILLIST) ] ; then \
+      $(EXPAND) $(FAILLIST) \
+        | $(CUT) -d' ' -f1 \
+        | $(SED) -e 's@^@FAILED: @' >> $(STATS_TXT); \
+    fi; \
+    runc="`$(CAT) $(RUNLIST)      | $(WC) -l | $(AWK) '{print $$1;}'`"; \
+    passc="`$(CAT) $(PASSLIST)    | $(WC) -l | $(AWK) '{print $$1;}'`"; \
+    failc="`$(CAT) $(FAILLIST)    | $(WC) -l | $(AWK) '{print $$1;}'`"; \
+    exclc="`$(CAT) $(EXCLUDELIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
+    $(ECHO) "TEST STATS: run=$${runc}  pass=$${passc}  fail=$${failc}  excluded=$${exclc}" \
+      >> $(STATS_TXT); \
+  else \
+    $(ECHO) "Missing file: $${_summary}" >> $(STATS_TXT); \
+  fi; \
+  $(CAT) $(STATS_TXT); \
+  $(ZIP_UP_RESULTS) && $(KILL_DISPLAY) && \
+  exit $${exitCode} \
+)
 
 ################################################################
 
@@ -172,32 +344,239 @@
 
 # Expect JPRT to set TESTDIRS to the jtreg test dirs
 ifndef TESTDIRS
-  TESTDIRS = demo/jvmti/gctest demo/jvmti/hprof
+  TESTDIRS = demo
+endif
+
+# Samevm settings (default is false)
+ifndef USE_JTREG_SAMEVM
+  USE_JTREG_SAMEVM=false
+endif
+# With samevm, you cannot use -javaoptions?
+ifeq ($(USE_JTREG_SAMEVM),true)
+  EXTRA_JTREG_OPTIONS += -samevm $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%)
+  JTREG_TEST_OPTIONS = $(JAVA_VM_ARGS:%=-vmoption:%)
+else
+  JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%)
+endif
+
+# Some tests annoy me and fail frequently
+PROBLEM_LIST=ProblemList.txt
+EXCLUDELIST=$(ABS_TEST_OUTPUT_DIR)/excludelist.txt
+
+# Create exclude list for this platform and arch
+ifdef NO_EXCLUDES
+$(EXCLUDELIST): $(PROBLEM_LIST) $(TESTDIRS)
+	@$(ECHO) "NOTHING_EXCLUDED" > $@
+else
+$(EXCLUDELIST): $(PROBLEM_LIST) $(TESTDIRS)
+	@$(RM) $@ $@.temp1 $@.temp2
+	@( ( $(EGREP) -- '$(OS_NAME)-all'           $< ) ;\
+	   ( $(EGREP) -- '$(OS_NAME)-$(OS_ARCH)'    $< ) ;\
+	   ( $(EGREP) -- '$(OS_NAME)-$(OS_VERSION)' $< ) ;\
+	   ( $(EGREP) -- 'generic-$(OS_ARCH)'       $< ) ;\
+           ( $(EGREP) -- 'generic-all'              $< ) ;\
+           ( $(ECHO) "#") ;\
+        ) | $(SED) -e 's@^[\ ]*@@' \
+          | $(EGREP) -v '^#' > $@.temp1
+	@for tdir in $(TESTDIRS) ; do \
+          ( ( $(CAT) $@.temp1 | $(EGREP) "^$${tdir}" ) ; $(ECHO) "#" ) >> $@.temp2 ; \
+        done
+	@$(ECHO) "# at least one line" >> $@.temp2
+	@( $(EGREP) -v '^#' $@.temp2 ; true ) > $@
+	@$(ECHO) "Excluding list contains `$(EXPAND) $@ | $(WC) -l` items"
 endif
 
+# Running batches of tests with or without samevm
+define RunSamevmBatch
+$(ECHO) "Running tests in samevm mode: $?"
+$(MAKE) TESTDIRS="$?" USE_JTREG_SAMEVM=true  UNIQUE_DIR=$@ jtreg_tests
+endef
+define RunOthervmBatch
+$(ECHO) "Running tests in othervm mode: $?"
+$(MAKE) TESTDIRS="$?" USE_JTREG_SAMEVM=false UNIQUE_DIR=$@ jtreg_tests
+endef
+define SummaryInfo
+$(ECHO) "Summary for: $?"
+$(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME))
+endef
+
+# ------------------------------------------------------------------
+
+# Batches of tests (somewhat arbitrary assigments to jdk_* targets)
+JDK_ALL_TARGETS =
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has problems, and doesn't help performance as much as others.
+JDK_ALL_TARGETS += jdk_awt
+jdk_awt: com/sun/awt java/awt sun/awt
+	$(call RunOthervmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_beans1
+jdk_beans1: java/beans/beancontext java/beans/PropertyChangeSupport \
+            java/beans/Introspector java/beans/Performance \
+            java/beans/VetoableChangeSupport java/beans/Statement
+	$(call RunSamevmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
+JDK_ALL_TARGETS += jdk_beans2
+jdk_beans2: java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \
+            java/beans/PropertyEditor
+	$(call RunOthervmBatch)
+JDK_ALL_TARGETS += jdk_beans3
+jdk_beans3: java/beans/XMLEncoder
+	$(call RunOthervmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_io
+jdk_io: java/io
+	$(call RunSamevmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_lang
+jdk_lang: java/lang
+	$(call RunSamevmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
+JDK_ALL_TARGETS += jdk_management1
+jdk_management1: javax/management
+	$(call RunOthervmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
+JDK_ALL_TARGETS += jdk_management2
+jdk_management2: com/sun/jmx com/sun/management sun/management
+	$(call RunOthervmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_math
+jdk_math: java/math
+	$(call RunSamevmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_misc
+jdk_misc: demo javax/imageio javax/naming javax/print javax/script \
+          javax/smartcardio javax/sound com/sun/java com/sun/jndi \
+	  com/sun/org sun/misc sun/pisces
+	$(call RunSamevmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_net
+jdk_net: com/sun/net java/net sun/net
+	$(call RunSamevmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_nio1
+jdk_nio1: java/nio/file
+	$(call RunSamevmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
+JDK_ALL_TARGETS += jdk_nio2
+jdk_nio2: java/nio/Buffer java/nio/ByteOrder \
+          java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer
+	$(call RunOthervmBatch)
+JDK_ALL_TARGETS += jdk_nio3
+jdk_nio3: com/sun/nio sun/nio
+	$(call RunOthervmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
+JDK_ALL_TARGETS += jdk_rmi
+jdk_rmi: java/rmi javax/rmi sun/rmi
+	$(call RunOthervmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_security1
+jdk_security1: java/security
+	$(call RunSamevmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
+JDK_ALL_TARGETS += jdk_security2
+jdk_security2: javax/crypto com/sun/crypto
+	$(call RunOthervmBatch)
+JDK_ALL_TARGETS += jdk_security3
+jdk_security3: com/sun/security lib/security javax/security sun/security
+	$(call RunOthervmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has problems, and doesn't help performance as much as others.
+JDK_ALL_TARGETS += jdk_swing
+jdk_swing: javax/swing sun/java2d
+	$(call RunOthervmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_text
+jdk_text: java/text sun/text
+	$(call RunSamevmBatch)
+
+# Stable othervm testruns (minus items from PROBLEM_LIST)
+#   Using samevm has serious problems with these tests
+JDK_ALL_TARGETS += jdk_tools1
+jdk_tools1: com/sun/jdi
+	$(call RunOthervmBatch)
+JDK_ALL_TARGETS += jdk_tools2
+jdk_tools2: com/sun/tools sun/jvmstat sun/tools tools vm com/sun/servicetag com/sun/tracing
+	$(call RunOthervmBatch)
+
+# Stable samevm testruns (minus items from PROBLEM_LIST)
+JDK_ALL_TARGETS += jdk_util
+jdk_util: java/util sun/util
+	$(call RunSamevmBatch)
+
+# ------------------------------------------------------------------
+
+# Run all tests
+jdk_all: $(filter-out jdk_awt jdk_rmi jdk_swing, $(JDK_ALL_TARGETS))
+	@$(SummaryInfo)
+
+# These are all phony targets
+PHONY_LIST += $(JDK_ALL_TARGETS)
+
+# ------------------------------------------------------------------
+
 # Default JTREG to run (win32 script works for everybody)
 JTREG = $(JT_HOME)/win32/bin/jtreg
+# Add any extra options (samevm etc.)
+JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS)
+# Only run automatic tests
+JTREG_BASIC_OPTIONS += -a
+# Report details on all failed or error tests, times too
+JTREG_BASIC_OPTIONS += -v:fail,error,time
+# Retain all files for failing tests
+JTREG_BASIC_OPTIONS += -retain:fail,error
+# Ignore tests are not run and completely silent about it
+JTREG_BASIC_OPTIONS += -ignore:quiet
+# Multiple by 2 the timeout numbers
+JTREG_BASIC_OPTIONS += -timeoutFactor:2
+# Boost the max memory for jtreg to avoid gc thrashing
+JTREG_BASIC_OPTIONS += -J-Xmx512m
 
-jtreg_tests: prep $(JT_HOME) $(PRODUCT_HOME) $(JTREG)
-	$(RM) $(JTREG).orig
-	cp $(JTREG) $(JTREG).orig
-	$(RM) $(JTREG)
-	sed -e 's@-J\*@-J-*@' $(JTREG).orig > $(JTREG)
-	chmod a+x $(JTREG)
-	( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)");                     \
-          export JT_HOME;                                                    \
-          $(shell $(GETMIXEDPATH) "$(JTREG)")                                \
-            -a -v:fail,error                                                 \
-	    -ignore:quiet                                                    \
-	    -timeoutFactor:2                                                 \
-            $(EXTRA_JTREG_OPTIONS)                                           \
-            -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport    \
-            -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork      \
-            -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)")                  \
-            $(JAVA_ARGS:%=-javaoptions:%)                                     \
-            $(JAVA_VM_ARGS:%=-vmoption:%)                                    \
-            $(TESTDIRS)                                                      \
-	) ; $(BUNDLE_UP_AND_EXIT)
+# Make sure jtreg exists
+$(JTREG): $(JT_HOME)
+
+# Run jtreg
+jtreg_tests: prep $(PRODUCT_HOME) $(JTREG) $(EXCLUDELIST)
+	@$(EXPAND) $(EXCLUDELIST) \
+            | $(CUT) -d' ' -f1 \
+            | $(SED) -e 's@^@Excluding: @'
+	(                                                                    \
+	  ( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)");                   \
+            export JT_HOME;                                                  \
+	    $(PREP_DISPLAY) &&                                               \
+            $(shell $(GETMIXEDPATH) "$(JTREG)")                              \
+              $(JTREG_BASIC_OPTIONS)                                         \
+              -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport  \
+              -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork    \
+              -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)")                \
+              -exclude:$(shell $(GETMIXEDPATH) "$(EXCLUDELIST)")             \
+              $(JTREG_TEST_OPTIONS)                                          \
+              $(TESTDIRS)                                                    \
+	  ) ; $(BUNDLE_UP_AND_EXIT)                                          \
+	) 2>&1 | $(TEE) $(ABS_TEST_OUTPUT_DIR)/output.txt
 
 PHONY_LIST += jtreg_tests
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/ProblemList.txt	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,1211 @@
+###########################################################################
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+###########################################################################
+#
+# List of tests that should not be run by test/Makefile, for various reasons:
+#   1. Does not run with jtreg -samevm mode
+#   2. Causes problems in jtreg -samevm mode for jtreg or tests that follow it
+#   3. The test is too slow or consumes too many system resources
+#   4. The test fails when run on any official build systems
+#
+# It is possible that a test being on this list is a mistake, and that some
+#   other test in samevm mode caused tests to fail, mistakes happen.
+#
+# Tests marked @ignore are not run by test/Makefile, but harmless to be listed.
+#
+# Tests that explicitly state "@run main/othervm ...", and are not listed here,
+#   will be run in the same batch as the samevm tests.
+#
+# Shell tests are othervm by default.
+#
+# List items  are testnames followed by labels, all MUST BE commented 
+#   as to why they are here and use a label:
+#     generic-all	Problems on all platforms
+#     generic-ARCH	Where ARCH is one of: sparc, sparcv9, x64, i586, etc.
+#     OSNAME-all	Where OSNAME is one of: solaris, linux, windows
+#     OSNAME-ARCH	Specific on to one OSNAME and ARCH, e.g. solaris-x64
+#     OSNAME-REV	Specific on to one OSNAME and REV, e.g. solaris-5.8
+#	 
+# More than one label is allowed but must be on the same line.
+#
+#############################################################################
+#
+# Running the tests:
+#    cd test && make JT_HOME=jtreg_home PRODUCT_HOME=jdk_home jdk_all
+#  Or instead of jdk_all, use any of the jdk_* targets.
+#
+# Samevm Notes:
+#  * Although some tests may have only been seen to fail on some platforms,
+#    they might be flagged as 'generic-all' because the problem they have
+#    could cause hidden slowdowns on other platforms.
+#    Most samevm problems will be generic-all, but windows usually dislikes
+#    them the most.
+#    Address already in use or connection errors indicate a generic port issue.
+#    (this is not necessarily a samevm issue, but an issue for running the tests
+#     on shared machines, two people or two test runs will collide).
+#  * Samevm problem (windows in particular) is not closing all input/output
+#  * Samevm problem when a test calls setSecurityManager()
+#  * Samevm problem with setHttps*() is used? (not exactly sure here)
+#  * Samevm problem when stuffing system properties with non Strings or anything
+#  * Samevm problem when changing vm settings, or registering any vm actions
+#  * Samevm problems with deleteOnExit(), if it must happen at end of test
+#  * Samevm problems with URLClassLoader? (no details here)
+#  * Samevm problems with dependence on predictable GC or finalizations
+#
+# Any of the above problems may mean the test needs to be flagged as "othervm".
+#
+#############################################################################
+#
+# Fixing the tests:
+#
+# Some tests just may need to be run with "othervm", and that can easily be
+#   done my adding a @run line (or modifying any existing @run):
+#      @run main/othervm NameOfMainClass
+#   Make sure this @run follows any use of @library.
+#   Otherwise, if the test is a samevm possibility, make sure the test is
+#     cleaning up after itself, closing all streams, deleting temp files, etc.
+#
+# Keep in mind that the bug could be in many places, and even different per
+#   platform, it could be a bug in any one of:
+#      - the testcase
+#      - the jdk (jdk classes, native code, or hotspot)
+#      - the native compiler
+#      - the javac compiler
+#      - the OS (depends on what the testcase does)
+#
+# If you managed to really fix one of these tests, here is how you can
+#    remove tests from this list:
+#  1. Make sure test passes on all platforms with samevm, or mark it othervm
+#  2. Make sure test passes on all platforms when run with it's entire group
+#  3. Make sure both VMs are tested, -server and -client, if possible
+#  4. Make sure you try the -d64 option on Solaris
+#  5. Use a tool like JPRT or something to verify these results
+#  6. Delete lines in this file, include the changes with your test changes
+#
+# You may need to repeat your testing 2 or even 3 times to verify good
+#   results, some of these samevm failures are not very predictable.
+#
+#############################################################################
+
+############################################################################
+
+# jdk_awt
+
+# None of the awt tests are using samevm, might not be worth the effort due
+#  to the vm overhead not being enough to make a difference.
+# In general, the awt tests are problematic with or without samevm, and there
+#  are issues with using a Xvfb display.
+
+# Fails on solaris sparc, timedout? in othervm mode
+java/awt/event/MouseEvent/AcceptExtraButton/AcceptExtraButton.java generic-all
+
+# Causes hang in samevm mode??? Solaris 11 i586
+java/awt/FullScreen/SetFSWindow/FSFrame.java			generic-all
+
+# Fails on solaris 11 i586, -client, in othervm mode not sure why
+java/awt/Component/PrintAllXcheckJNI/PrintAllXcheckJNI.java	generic-all
+java/awt/Focus/CloseDialogActivateOwnerTest/CloseDialogActivateOwnerTest.java generic-all
+java/awt/FontClass/FontAccess.java				generic-all
+java/awt/Mixing/HWDisappear.java				generic-all
+java/awt/Mixing/MixingInHwPanel.java				generic-all
+java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.html	generic-all
+java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java generic-all
+java/awt/Toolkit/SecurityTest/SecurityTest2.java		generic-all
+java/awt/image/mlib/MlibOpsTest.java				generic-all
+
+# Fails on windows, othervm mode, various errors
+java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java	generic-all
+java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java	generic-all
+java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java	generic-all
+java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java	generic-all
+java/awt/event/KeyEvent/KeyTyped/CtrlASCII.html			generic-all
+java/awt/font/Threads/FontThread.java				generic-all
+java/awt/print/PrinterJob/PrtException.java			generic-all
+
+# Fails with windows X64, othervm, -server
+com/sun/awt/Translucency/WindowOpacity.java			generic-all
+java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java		generic-all
+java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html	generic-all
+java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.html generic-all
+java/awt/Focus/FocusEmbeddedFrameTest/FocusEmbeddedFrameTest.java generic-all
+java/awt/Frame/LayoutOnMaximizeTest/LayoutOnMaximizeTest.java	generic-all
+java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java	generic-all
+java/awt/Mixing/MixingOnShrinkingHWButton.java			generic-all
+java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java	generic-all
+
+############################################################################
+
+# jdk_beans
+
+# A large set of the beans tests set the security manager, which would seem
+#  to indicate that a large number of them should be "othervm", yet are all
+#  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.
+
+# Linux, some kind of problems with X11 display
+java/beans/PropertyChangeSupport/Test4682386.java		generic-all
+java/beans/PropertyChangeSupport/TestSynchronization.java	generic-all
+java/beans/Statement/Test4653179.java				generic-all
+
+# Runs REALLY slow on Solaris sparc for some reason, both -client and -server
+java/beans/XMLEncoder/Test4625418.java				solaris-sparc
+
+# Problems with samevm and setting security manager (speculation partially)
+java/beans/Beans/Test4080522.java				generic-all
+java/beans/EventHandler/Test6277246.java			generic-all
+java/beans/EventHandler/Test6277266.java			generic-all
+java/beans/Introspector/Test6277246.java			generic-all
+java/beans/Introspector/4168475/Test4168475.java		generic-all
+java/beans/Introspector/4520754/Test4520754.java		generic-all
+java/beans/Introspector/6380849/TestBeanInfo.java		generic-all
+java/beans/Introspector/Test4144543.java			generic-all
+
+# Failed to call method solaris-sparc???
+java/beans/EventHandler/Test6788531.java		 	generic-all
+
+# Jar or class not found???
+java/beans/XMLEncoder/6329581/Test6329581.java		 	generic-all
+
+############################################################################
+
+# jdk_io
+
+# Many of these tests have a tendency to leave input streams open, which
+#  will cause following tests to be failures when used in samevm mode.
+
+# Should be othervm, or corrected for samevm, fails with samevm:
+java/io/BufferedReader/BigMark.java			 	generic-all
+java/io/BufferedReader/ReadLineSync.java		 	generic-all
+
+# One of these is leaving "a.ser" file open, windows samevm
+java/io/Serializable/duplicateSerialFields/Setup.java		generic-all
+java/io/Serializable/duplicateSerialFields/Test.java		generic-all
+
+# One of these leaving foo.ser open, windows samevm problem
+java/io/Serializable/enum/constantSubclasses/Read.java		generic-all
+java/io/Serializable/enum/constantSubclasses/Write.java		generic-all
+java/io/Serializable/enum/missingConstant/Read.java		generic-all
+java/io/Serializable/enum/missingConstant/Write.java		generic-all
+
+# This is leaving subtest1.tmp open, windows samevm problem
+java/io/Serializable/oldTests/AnnotateClass.java		generic-all
+
+# One or more of these leave a piotest* file open, windows samevm
+java/io/Serializable/oldTests/ArrayFields.java			generic-all
+java/io/Serializable/oldTests/ArraysOfArrays.java		generic-all
+java/io/Serializable/oldTests/BinaryTree.java			generic-all
+java/io/Serializable/oldTests/CircularList.java			generic-all
+java/io/Serializable/oldTests/SerializeWithException.java	generic-all
+java/io/Serializable/oldTests/SimpleArrays.java			generic-all
+java/io/Serializable/oldTests/WritePrimitive.java		generic-all
+
+# Missing close on file 0.ser, windows samevm
+java/io/Serializable/enum/badResolve/Read.java			generic-all
+java/io/Serializable/enum/badResolve/Write.java			generic-all
+
+# One of these tests is leaving parents.ser open, windows samevm
+java/io/Serializable/parents/EvolvedClass.java			generic-all
+java/io/Serializable/parents/OriginalClass.java			generic-all
+
+# One of these tests is leaving file foo.ser and/or bar.ser open, windows samevm
+java/io/Serializable/fieldTypeString/Read.java			generic-all
+java/io/Serializable/fieldTypeString/Write.java			generic-all
+
+# One of these tests is leaving tmp.ser file open, windows samevm
+java/io/Serializable/ClassCastExceptionDetail/Read.java		generic-all
+java/io/Serializable/ClassCastExceptionDetail/Write.java	generic-all
+java/io/Serializable/GetField/Read.java				generic-all
+java/io/Serializable/GetField/Read2.java			generic-all
+java/io/Serializable/GetField/Write.java			generic-all
+java/io/Serializable/PutField/Read.java				generic-all
+java/io/Serializable/PutField/Read2.java			generic-all
+java/io/Serializable/PutField/Write.java			generic-all
+java/io/Serializable/PutField/Write2.java			generic-all
+java/io/Serializable/arraySuidConflict/Read.java		generic-all
+java/io/Serializable/arraySuidConflict/Write.java		generic-all
+java/io/Serializable/backRefCNFException/Read.java		generic-all
+java/io/Serializable/backRefCNFException/Write.java		generic-all
+java/io/Serializable/class/Test.java				generic-all
+java/io/Serializable/evolution/AddedExternField/ReadAddedField.java generic-all
+java/io/Serializable/evolution/AddedExternField/WriteAddedField.java generic-all
+java/io/Serializable/evolution/AddedExternField/run.sh		generic-all
+java/io/Serializable/evolution/AddedField/ReadAddedField.java	generic-all
+java/io/Serializable/evolution/AddedField/WriteAddedField.java	generic-all
+java/io/Serializable/evolution/AddedSuperClass/ReadAddedSuperClass.java	generic-all
+java/io/Serializable/evolution/AddedSuperClass/ReadAddedSuperClass2.java generic-all
+java/io/Serializable/evolution/AddedSuperClass/WriteAddedSuperClass.java generic-all
+java/io/Serializable/proxy/skipMissing/Read.java		generic-all
+java/io/Serializable/proxy/skipMissing/Write.java		generic-all
+java/io/Serializable/readObjectNoData/Read.java			generic-all
+java/io/Serializable/readObjectNoData/Write.java		generic-all
+java/io/Serializable/skipWriteObject/Read.java			generic-all
+java/io/Serializable/skipWriteObject/Write.java			generic-all
+java/io/Serializable/skippedObjCNFException/Read.java		generic-all
+java/io/Serializable/skippedObjCNFException/Write.java		generic-all
+java/io/Serializable/stopCustomDeserialization/Read.java	generic-all
+java/io/Serializable/stopCustomDeserialization/Write.java	generic-all
+java/io/Serializable/unresolvedClassDesc/Read.java		generic-all
+java/io/Serializable/unresolvedClassDesc/Write.java		generic-all
+java/io/Serializable/unshared/Read.java				generic-all
+java/io/Serializable/unshared/Write.java			generic-all
+java/io/Serializable/wrongReturnTypes/Read.java			generic-all
+java/io/Serializable/wrongReturnTypes/Write.java		generic-all
+
+# Windows samevm issues? triggers other tests to fail, missing close() on f.txt?
+java/io/DataInputStream/OpsAfterClose.java		 	generic-all
+
+# Windows 32bit samevm failure: RuntimeException: File.getFreeSpace() failed
+java/io/File/MaxPathLength.java					generic-all
+
+# Should be othervm, or corrected for samevm, fails with samevm:
+java/io/File/DeleteOnExit.java				 	generic-all
+java/io/File/DeleteOnExitLong.java			 	generic-all
+java/io/File/DeleteOnExitNPE.java			 	generic-all
+java/io/File/IsHidden.java				 	generic-all
+java/io/FileDescriptor/FileChannelFDTest.java		 	generic-all
+java/io/FileDescriptor/Finalize.java			 	generic-all
+java/io/FileInputStream/FinalizeShdCallClose.java	 	generic-all
+
+# Known to cause samevm issues on windows, other tests fail, missing close()?
+java/io/FileInputStream/OpsAfterClose.java		 	generic-all
+
+# Should be othervm, or corrected for samevm, fails with samevm:
+java/io/FileOutputStream/FinalizeShdCallClose.java	 	generic-all
+
+# Known to cause samevm issues on windows, other tests fail, missing close()?
+java/io/FileOutputStream/OpsAfterClose.java		 	generic-all
+
+# Windows samevm issues? triggers other tests to fail, missing close() on f.txt?
+java/io/InputStream/OpsAfterClose.java			 	generic-all
+
+# Missing close() on x.ReadBounds file? Windows samevm issues
+java/io/InputStream/ReadParams.java			 	generic-all
+
+# Known to cause samevm issues on windows, other tests fail, missing close()?
+java/io/InputStreamReader/GrowAfterEOF.java		 	generic-all
+
+# Should be othervm, or corrected for samevm, fails with samevm:
+java/io/ObjectInputStream/ResolveProxyClass.java	 	generic-all
+
+# Not doing a close() on x.ParameterCheck file? windows samevm cascade error
+java/io/RandomAccessFile/ParameterCheck.java                    generic-all
+
+# Not doing a close on x.ReadLine file? windows cascade samevm problems
+java/io/RandomAccessFile/ReadLine.java				generic-all
+
+# Not doing close on file input x.WriteByteChars, windows samevm problems
+java/io/RandomAccessFile/WriteBytesChars.java			generic-all
+
+# Not doing close on file input x.WriteUTF, windows samevm problems
+java/io/RandomAccessFile/WriteUTF.java                          generic-all
+
+# Possibly, not doing a close() on input.txt, windows samevm issues.
+java/io/RandomAccessFile/skipBytes/SkipBytes.java	 	generic-all
+java/io/readBytes/MemoryLeak.java			 	generic-all
+java/io/readBytes/ReadBytesBounds.java			 	generic-all 
+
+# Missing close on fields.ser, windows samevm
+java/io/Serializable/checkModifiers/CheckModifiers.java		generic-all
+
+# Should be othervm, or corrected for samevm, fails with samevm:
+java/io/Serializable/auditStreamSubclass/AuditStreamSubclass.java generic-all
+java/io/Serializable/proxy/Basic.java			 	generic-all
+
+# Possibly not doing a close() on input.txt, windows samevm issues.
+java/io/StreamTokenizer/Comment.java			 	generic-all
+
+############################################################################
+
+# jdk_lang
+
+# Some of these tests (like java/lang/management) may just need to be marked
+#   othervm, but that is partially speculation.
+
+# Times out on solaris 10 sparc
+java/lang/ClassLoader/Assert.java				generic-all
+
+# Fedora 9 X64, RuntimeException: MyThread expected to be blocked on lock, but got null
+java/lang/management/ThreadMXBean/ThreadStateTest.java 		generic-all
+
+# RuntimeException: Uptime of the JVM is more than 30 minutes (32 minutes).
+java/lang/management/RuntimeMXBean/UpTime.java			generic-all
+
+# Times out on solaris sparc occasionally, in samevm mode
+java/lang/Runtime/exec/ExecWithDir.java				generic-all
+java/lang/ProcessBuilder/Basic.java				generic-all
+
+# Solaris sparc, samevm, java.lang.Exception: Read from closed pipe hangs
+java/lang/Runtime/exec/SleepyCat.java				generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/lang/annotation/ParameterAnnotations.java			generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/lang/ClassLoader/defineClass/DefineClassByteBuffer.java	generic-all
+java/lang/ClassLoader/findSystemClass/Loader.java		generic-all
+
+# Fedora 9 32bit, -client, samevm, Error while cleaning up threads after test
+java/lang/management/ThreadMXBean/Locks.java			generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/lang/management/ClassLoadingMXBean/LoadCounts.java		generic-all
+java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java generic-all
+java/lang/management/ManagementFactory/MXBeanProxyTest.java	generic-all
+java/lang/management/ManagementFactory/ThreadMXBeanProxy.java	generic-all
+java/lang/management/MemoryMXBean/CollectionUsageThreshold.java	generic-all
+java/lang/management/MemoryMXBean/GetMBeanInfo.java		generic-all
+java/lang/management/MemoryMXBean/LowMemoryTest.java		generic-all
+java/lang/management/MemoryMXBean/MemoryManagement.java		generic-all
+java/lang/management/MemoryMXBean/MemoryTest.java		generic-all
+java/lang/management/MemoryMXBean/Pending.java			generic-all
+
+# Problematic on all platforms (even as othervm)
+java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java 	generic-all
+
+# Causes jtreg exit samevm issues due to non-String object in system properties
+java/lang/management/RuntimeMXBean/GetSystemProperties.java 	generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/lang/management/RuntimeMXBean/PropertiesTest.java		generic-all
+java/lang/management/ThreadMXBean/AllThreadIds.java		generic-all
+java/lang/management/ThreadMXBean/EnableTest.java		generic-all
+java/lang/management/ThreadMXBean/FindMonitorDeadlock.java	generic-all
+java/lang/management/ThreadMXBean/LockingThread.java		generic-all
+java/lang/management/ThreadMXBean/MonitorDeadlock.java		generic-all
+java/lang/management/ThreadMXBean/MyOwnSynchronizer.java	generic-all
+java/lang/management/ThreadMXBean/SharedSynchronizer.java	generic-all
+java/lang/management/ThreadMXBean/SynchronizerLockingThread.java generic-all
+java/lang/management/ThreadMXBean/ThreadCounts.java		generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/lang/reflect/Proxy/Boxing.java				generic-all
+java/lang/reflect/Proxy/ClassRestrictions.java			generic-all
+java/lang/reflect/Proxy/returnTypes/Test.java			generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/lang/Runtime/exec/LotsOfOutput.java			generic-all
+java/lang/System/ExitFinalizersAndJIT.java			generic-all
+java/lang/System/finalization/FinThreads.java			generic-all
+java/lang/System/IgnoreNullSecurityManager.java			generic-all
+java/lang/Thread/GenerifyStackTraces.java			generic-all
+java/lang/Thread/StackTraces.java				generic-all
+java/lang/ThreadGroup/Daemon.java				generic-all
+java/lang/ThreadGroup/NullThreadName.java			generic-all
+
+# Times out on solaris sparc -server
+java/lang/ThreadLocal/MemoryLeak.java			 	solaris-all
+
+# Windows X64, RuntimeException: MyThread expected to have RUNNABLE but got WAITING
+java/lang/Thread/ThreadStateTest.java				generic-all
+
+# Timeout on windows 64bit 
+java/lang/ClassLoader/deadlock/TestCrossDelegate.sh		generic-all
+
+############################################################################
+
+# jdk_management
+
+# Solaris 10 sparc, NPE from org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke
+javax/management/remote/mandatory/threads/ExecutorTest.java 	generic-all
+
+# Linux 32bit Fedora 9, IllegalStateException
+javax/management/monitor/RuntimeExceptionTest.java		generic-all
+
+# Problems with rmi connection, othervm  
+javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java generic-all
+
+# Fails with port already in use
+sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh generic-all
+
+# Fails with port already in use
+sun/management/jmxremote/bootstrap/RmiRegistrySslTest.sh	generic-all
+
+# Windows, connection can't last that long
+javax/management/eventService/LeaseTest.java			generic-all
+
+# Linux othervm, X64, java.lang.Exception: Failed: ratio=102.4027795593753
+javax/management/remote/mandatory/notif/ListenerScaleTest.java	generic-all
+
+# Windows run seems to have triggered a hotspot gc error (see 6801625)
+com/sun/management/HotSpotDiagnosticMXBean/DumpHeap.sh		generic-all
+
+# rmi problem? othervm, java.lang.reflect.UndeclaredThrowableException
+javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java generic-all
+
+# Linux Fedora 9 32bit NPE in rmi server somehere??? othervm
+javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java generic-all
+
+# Times out on solaris sparc, with othervm
+javax/management/eventService/AddRemoveListenerTest.java	generic-all
+
+# Linux i586 and x64 -server, timed out waiting for threads to expire? othervm
+javax/management/eventService/EventClientThreadTest.java	generic-all
+
+# Linux i586 -server, Expected to receive 20, but got 21, othervm
+#   Fails on Linux X64 -server 20!=21
+javax/management/eventService/FetchingTest.java			generic-all
+
+# NPE on windows 2000 i586 -client and -server
+javax/management/eventService/CustomForwarderTest.java	 	windows-all
+
+# Windows i586 failure, callback did not complete
+javax/management/eventService/LeaseManagerDeadlockTest.java 	windows-all
+
+# Port already in use
+sun/management/jmxremote/bootstrap/LocalManagementTest.sh 	generic-all
+
+# Failed to initialize connector (also overflowing jtreg io buffers)
+sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh	 	generic-all
+sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh 	generic-all
+
+# Windows X64, java.lang.IllegalStateException
+javax/management/monitor/AttributeArbitraryDataTypeTest.java	generic-all
+
+############################################################################
+
+# jdk_math
+
+# Problems with rounding add failures on solaris-sparcv9 and -server
+java/math/BigDecimal/AddTests.java			 	solaris-sparcv9
+
+# Problems on windows with samevm, missing inputstream close()?
+# Also times out on solaris-sparcv9 -server
+java/math/BigInteger/BigIntegerTest.java		 	generic-all
+
+# Should be samevm? But seems problematic with samevm on windows
+java/math/BigInteger/ModPow65537.java			 	generic-all
+
+############################################################################
+
+# jdk_misc
+
+# On Windows com.sun.java.swing.plaf.gtk does not exist, always fails there
+com/sun/java/swing/plaf/gtk/Test6635110.java		 	windows-all
+
+# Need to be marked othervm, or changed to be samevm safe
+com/sun/jndi/ldap/ReadTimeoutTest.java				generic-all
+com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java	generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+com/sun/org/apache/xml/internal/security/transforms/ClassLoaderTest.java generic-all
+
+# Solaris sparc and others, exception in initializer
+javax/imageio/CachePremissionsTest/CachePermissionsTest.java 	generic-all
+
+# Leaves file rgba_* open, fails with windows samevm
+javax/imageio/plugins/png/PngOutputTypeTest.java		generic-all
+
+# Suspect test.png file is left open, windows samevm problems
+javax/imageio/plugins/png/ITXtTest.java				generic-all
+
+# Solaris sparc and others, failed to compile testcase
+javax/imageio/metadata/DOML3Node.java			 	generic-all
+
+# One of these tests is leaving file IMGP1001.JPG open, windows samevm
+javax/imageio/plugins/jpeg/ConcurrentReadingTest.java		generic-all
+javax/imageio/plugins/jpeg/ReadingInterruptionTest.java		generic-all
+
+# One of these files is missing a close on writer_* files, windows samevm
+javax/imageio/plugins/jpeg/ConcurrentWritingTest.java		generic-all
+javax/imageio/plugins/jpeg/WritingInterruptionTest.java		generic-all
+
+# Leaving file test.jpg open, windows samevm
+javax/imageio/plugins/jpeg/ReadAsGrayTest.java			generic-all
+
+# Missing close on file wbmp*, windows samevm
+javax/imageio/plugins/wbmp/CanDecodeTest.java			generic-all
+
+# Exclude all javax/print tests, even if they passed, they may need samevm work
+
+# Times out on solaris-sparc, sparcv9, x64 -server, some on i586 -client
+javax/print/attribute/autosense/PrintAutoSenseData.java 	generic-all
+javax/print/attribute/Chroma.java			 	generic-all
+javax/print/attribute/CollateAttr.java			 	generic-all
+javax/print/attribute/PSCopiesFlavorTest.java		 	generic-all
+javax/print/LookupServices.java 			 	generic-all
+javax/print/TestRaceCond.java				 	generic-all
+
+# These tests really require a printer (might all be windows only tests?)
+javax/print/CheckDupFlavor.java					generic-all
+javax/print/PrintSE/PrintSE.sh					generic-all
+javax/print/attribute/ChromaticityValues.java			generic-all
+javax/print/attribute/GetCopiesSupported.java			generic-all
+javax/print/attribute/SidesPageRangesTest.java			generic-all
+javax/print/attribute/SupportedPrintableAreas.java		generic-all
+
+# Only print test left, excluding just because all print tests have been
+javax/print/attribute/MediaMappingsTest.java 			generic-all
+
+############################################################################
+
+# jdk_net
+
+# Suspect many of these tests auffer from using fixed ports, no concrete 
+#   evidence.
+
+# Fails on OpenSolaris, BindException unexpected 
+java/net/BindException/Test.java				generic-all
+
+# Fails on OpenSolaris, times out
+java/net/MulticastSocket/SetOutgoingIf.java			generic-all
+
+# Timed out on Solaris 10 X86.
+com/sun/net/httpserver/Test3.java				generic-all
+
+# Exception in test on windows
+com/sun/net/httpserver/bugs/B6373555.java		 	windows-all
+
+# One of these pollutes the samevm on Linux, too many open files, kills jtreg
+com/sun/net/httpserver/bugs/B6339483.java			generic-all
+com/sun/net/httpserver/bugs/B6341616.java			generic-all
+
+# Suspects in cascading samevm problem, solaris 11 i586 (needs othervm?)
+#   Suspect use of setHttps*()?
+com/sun/net/httpserver/SelCacheTest.java			generic-all
+com/sun/net/httpserver/Test1.java				generic-all
+com/sun/net/httpserver/Test12.java				generic-all
+com/sun/net/httpserver/Test13.java				generic-all
+com/sun/net/httpserver/Test6a.java				generic-all
+com/sun/net/httpserver/Test7a.java				generic-all
+com/sun/net/httpserver/Test8a.java				generic-all
+com/sun/net/httpserver/Test9.java				generic-all
+com/sun/net/httpserver/Test9a.java				generic-all
+
+# 10,000 connections, fails on Linux and makes tests&jtreg fail with samevm
+com/sun/net/httpserver/bugs/B6361557.java			generic-all
+
+# Address already in use with samevm? Always? Solaris sparc, probably ports
+java/net/Authenticator/B4933582.sh				generic-all
+java/net/DatagramSocket/SendSize.java				generic-all
+
+# Solaris 11: exception wrong address???
+java/net/Inet6Address/B6558853.java				generic-all
+
+# Not closing stream on file i6a1, windows samevm problem
+java/net/Inet6Address/serialize/Serialize.java			generic-all
+
+# Linux x64 fails "network unreachable"?
+java/net/ipv6tests/TcpTest.java 			 	generic-all
+
+# Linux i586, fails with unexpected output
+java/net/MulticastSocket/NoLoopbackPackets.java 	 	linux-i586
+
+# Times out on windows x64, fails with samevm on solaris 11 i586
+java/net/ServerSocket/AcceptCauseFileDescriptorLeak.java 	generic-all
+
+# Address already in use
+java/net/DatagramSocket/DatagramTimeout.java			generic-all
+
+# Fails on windows, takes too long and fails
+#   Solaris 10 sparcv9, samevm, java.lang.Exception: Takes too long. Dead lock
+java/net/Socket/DeadlockTest.java				generic-all
+
+# Linux i586 address already in use or connection error, samevm issues
+java/net/Socket/AccurateTimeout.java			 	generic-all
+java/net/Socket/asyncClose/BrokenPipe.java		 	generic-all
+java/net/Socket/CloseAvailable.java			 	generic-all
+java/net/Socket/FDClose.java				 	generic-all
+
+# Linux X64 address already in use, samevm issues
+java/net/Socket/LingerTest.java 			 	generic-all
+java/net/Socket/LinkLocal.java				 	generic-all
+java/net/Socket/NullHost.java				 	generic-all
+java/net/Socket/ProxyCons.java				 	generic-all
+java/net/Socket/ReadTimeout.java			 	generic-all
+
+# Linux X64 address already in use, samevm issues
+java/net/Socket/SetReceiveBufferSize.java		 	generic-all
+
+# Linux i586 address already in use or connection error, samevm issues
+java/net/Socket/setReuseAddress/Basic.java		 	generic-all
+java/net/Socket/setReuseAddress/Restart.java		 	generic-all
+
+# Linux X64 address already in use, samevm issues
+java/net/Socket/SetSoLinger.java			 	generic-all
+
+# Address already in use, windows samevm
+java/net/Socket/Timeout.java					generic-all
+
+# Linux X64 address already in use, samevm issues
+java/net/Socket/ShutdownBoth.java			 	generic-all
+java/net/Socket/SoTimeout.java				 	generic-all
+java/net/Socket/TestClose.java				 	generic-all
+java/net/Socket/UrgentDataTest.java			 	generic-all
+java/net/SocketInputStream/SocketClosedException.java	 	generic-all
+java/net/SocketInputStream/SocketTimeout.java		 	generic-all
+
+# Linux i586, address already in use or timeout, samevm issues
+java/net/URLConnection/B5052093.java			 	generic-all
+java/net/URLConnection/contentHandler/UserContentHandler.java 	generic-all
+java/net/URLConnection/DisconnectAfterEOF.java		 	generic-all
+java/net/URLConnection/HandleContentTypeWithAttrs.java	 	generic-all
+java/net/URLConnection/Responses.java			 	generic-all
+java/net/URLConnection/TimeoutTest.java 		 	generic-all
+java/net/URLConnection/ZeroContentLength.java		 	generic-all
+
+# Solaris 11 i586 fails with samevm, not sure why
+java/net/Authenticator/B4769350.java				generic-all
+java/net/HttpURLConnection/HttpResponseCode.java		generic-all
+java/net/ResponseCache/B6181108.java				generic-all
+java/net/ResponseCache/ResponseCacheTest.java			generic-all
+java/net/URL/GetContent.java					generic-all
+java/net/URL/TestIPv6Addresses.java				generic-all
+java/net/URLClassLoader/HttpTest.java				generic-all
+java/net/URLConnection/HttpContinueStackOverflow.java		generic-all
+java/net/URLConnection/Redirect307Test.java			generic-all
+java/net/URLConnection/RedirectLimit.java			generic-all
+java/net/URLConnection/ResendPostBody.java			generic-all
+java/net/URL/OpenStream.java					generic-all
+java/net/URLClassLoader/ClassLoad.java				generic-all
+java/net/URLConnection/SetIfModifiedSince.java			generic-all
+java/net/URLConnection/URLConnectionHeaders.java		generic-all
+
+# Linux i586 Connection refused or address already in use, samevm issues
+sun/net/ftp/B6427768.java				 	generic-all
+sun/net/ftp/FtpGetContent.java				 	generic-all
+sun/net/ftp/FtpURL.java 				 	generic-all
+
+# Failed on solaris 10 i586, Exception: should have gotten HttpRetryException?
+sun/net/www/http/ChunkedOutputStream/Test.java			generic-all
+
+# Trouble cleaning up threads in samevm mode on solaris 11 i586
+sun/net/www/http/HttpClient/ProxyTest.java			generic-all
+sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java	generic-all
+sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java	generic-all
+sun/net/www/http/HttpClient/B6726695.java			generic-all
+sun/net/www/http/HttpClient/MultiThreadTest.java		generic-all
+sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java	generic-all
+
+# Connection refused, windows samevm
+sun/net/www/protocol/http/DigestTest.java			generic-all
+
+############################################################################
+
+# jdk_nio
+
+# Suspect many of these tests auffer from using fixed ports, no concrete 
+#   evidence.
+
+# Fails on OpenSolaris, IllegalStateException: Cannot add or remove addresses 
+#    from a channel that is bound to the wildcard address
+com/sun/nio/sctp/SctpChannel/Bind.java				generic-all
+
+# Failed on OpenSolaris, java.lang.AssertionError: Unknown event type
+com/sun/nio/sctp/SctpChannel/Receive.java			generic-all
+
+# Triggers a hotspot crash on Fedora 9 32bit -server and Windows X64  samevm
+sun/nio/cs/TestUTF8.java					generic-all
+
+# Solaris sparc, socket timeout
+java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh generic-all
+
+# Runtime exception on windows X64, samevm mode
+java/nio/channels/Selector/WakeupNow.java			generic-all
+
+# Occasional errors, solarix x86, address already in use, othervm mode
+java/nio/channels/Selector/SelectorTest.java			generic-all
+
+# Fails on Linux Fedora 9 X64
+sun/nio/cs/FindDecoderBugs.java					generic-all
+
+# Solaris 11 gave assert error and "connection refused", samevm issues?
+com/sun/nio/sctp/SctpServerChannel/NonBlockingAccept.java 	generic-all
+
+# Fails with othervm on solaris 11 i586
+com/sun/nio/sctp/SctpChannel/CommUp.java			generic-all
+com/sun/nio/sctp/SctpChannel/Connect.java			generic-all
+com/sun/nio/sctp/SctpMultiChannel/Branch.java			generic-all
+com/sun/nio/sctp/SctpMultiChannel/Send.java			generic-all
+com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java	generic-all
+
+# Linux 64bit failures. too many files open
+java/nio/channels/Selector/HelperSlowToDie.java			generic-all
+
+# Timeouts etc. on Window
+java/nio/channels/AsyncCloseAndInterrupt.java		 	windows-all
+
+# Gets java.lang.ExceptionInInitializerError on windows: (Windows 2000 only?)
+java/nio/channels/AsynchronousChannelGroup/Basic.java	 	windows-5.0
+java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java 	windows-5.0
+java/nio/channels/AsynchronousChannelGroup/Identity.java 	windows-5.0
+java/nio/channels/AsynchronousChannelGroup/Restart.java 	windows-5.0
+java/nio/channels/AsynchronousDatagramChannel/Basic.java 	windows-5.0
+java/nio/channels/AsynchronousFileChannel/Lock.java	 	windows-5.0
+java/nio/channels/AsynchronousServerSocketChannel/Basic.java 	windows-5.0
+java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java windows-5.0
+java/nio/channels/AsynchronousSocketChannel/Basic.java	 	windows-5.0
+java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java windows-5.0
+java/nio/channels/AsynchronousSocketChannel/Leaky.java	 	windows-5.0
+java/nio/channels/AsynchronousSocketChannel/StressLoopback.java windows-5.0
+java/nio/channels/Channels/Basic2.java			 	windows-5.0
+
+# Solaris sparc timeout
+java/nio/channels/DatagramChannel/Connect.java		 	generic-all
+
+# Solaris i586 timeouts
+java/nio/channels/DatagramChannel/EmptyBuffer.java	 	solaris-all
+
+# Failed loopback connection? On windows 32bit? 
+#   Considered a stress test, can consume all resources.
+java/nio/channels/Selector/LotsOfChannels.java		 	generic-all
+
+# Solaris sparcv9, just fails with exception
+java/nio/channels/Selector/OpRead.java			 	solaris-sparc
+
+# Windows i586 client, crashed hotspot? Unpredictable
+#   Considered a stress test, can consume all resources.
+java/nio/channels/Selector/RegAfterPreClose.java	 	generic-all
+
+# Solaris i586, cannot assign address, samevm issues
+java/nio/channels/Selector/SelectorLimit.java		 	generic-all
+
+# Socket timeout windows X64
+java/nio/channels/ServerSocketChannel/AdaptServerSocket.java 	windows-all
+
+# Timeouts etc. on Window
+java/nio/channels/SocketChannel/ConnectState.java	 	windows-all
+java/nio/channels/SocketChannel/FinishConnect.java	 	windows-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/nio/channels/SocketChannel/OpenLeak.java			generic-all
+
+# Gets java.net.BindException alot (static port number?)
+java/nio/channels/SocketChannel/VectorIO.java		 	generic-all
+
+# Solaris i586 java.net.BindExceptions
+java/nio/channels/SocketChannel/VectorParams.java	 	solaris-all
+
+# Linux i586 address already in use, samevm issues
+java/nio/channels/SocketChannel/Write.java		 	generic-all
+
+# Fails on all platforms due to overlap of JDK jar file contents:
+sun/nio/cs/Test4200310.sh				 	generic-all
+
+# Depends on motif packages that do not exist all the time:
+sun/nio/cs/TestX11CNS.java				 	generic-all
+
+############################################################################
+
+# jdk_rmi
+
+# Port already in use, fails on sparc, othervm
+java/rmi/reliability/benchmark/runRmiBench.sh			generic-all
+
+# Already in use port issues? othervm solaris
+java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java generic-all
+java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java generic-all
+
+# Address already in use, othervm mode, solaris
+java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java	generic-all
+java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java	generic-all
+
+# Registry already running on port, solaris
+java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java	generic-all
+
+# Fails on Linux 32 and 64bit -server?, impl not garbage collected???
+java/rmi/transport/pinLastArguments/PinLastArguments.java	generic-all
+
+# Times out on solaris sparc
+java/rmi/server/RemoteServer/AddrInUse.java			generic-all
+
+# Connection error on Windows i586 -server
+#  Also connection errors in othervm on Solaris 10 sparc, same port??? 
+sun/rmi/transport/tcp/DeadCachedConnection.java 	 	generic-all
+
+# Connection errors in othervm on Solaris 10 sparc, same port??? 
+java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java generic-all
+java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java generic-all
+java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java generic-all
+java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java generic-all
+java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java generic-all
+java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java generic-all
+java/rmi/activation/Activatable/extLoadedImpl/ext.sh generic-all
+java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java generic-all
+java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java generic-all
+java/rmi/activation/Activatable/nestedActivate/NestedActivate.java generic-all
+java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java generic-all
+java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java generic-all
+java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java generic-all
+java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java generic-all
+java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java generic-all
+java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java generic-all
+java/rmi/activation/ActivationSystem/activeGroup/IdempotentActiveGroup.java generic-all
+java/rmi/reliability/juicer/AppleUserImpl.java generic-all
+java/rmi/server/RMISocketFactory/useSocketFactory/unicast/UseCustomSocketFactory.java generic-all
+java/rmi/server/UnicastRemoteObject/keepAliveDuringCall/KeepAliveDuringCall.java generic-all
+java/rmi/transport/handshakeTimeout/HandshakeTimeout.java generic-all
+java/rmi/activation/Activatable/restartService/RestartService.java generic-all
+java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java generic-all
+java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java generic-all
+java/rmi/activation/ActivationSystem/unregisterGroup/UnregisterGroup.java generic-all
+java/rmi/activation/CommandEnvironment/SetChildEnv.java generic-all
+java/rmi/registry/classPathCodebase/ClassPathCodebase.java generic-all
+java/rmi/registry/reexport/Reexport.java generic-all
+java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java generic-all
+java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java generic-all
+java/rmi/server/Unreferenced/unreferencedContext/UnreferencedContext.java generic-all
+java/rmi/server/useCustomRef/UseCustomRef.java generic-all
+java/rmi/transport/checkFQDN/CheckFQDN.java generic-all
+java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java generic-all
+java/rmi/server/RMISocketFactory/useSocketFactory/activatable/UseCustomSocketFactory.java generic-all
+java/rmi/server/RMISocketFactory/useSocketFactory/registry/UseCustomSocketFactory.java generic-all
+java/rmi/server/UnicastRemoteObject/unexportObject/UnexportLeak.java generic-all
+
+############################################################################
+
+# jdk_security
+
+# Run too slow on Solaris 10 sparc
+sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/SSLSocketTimeoutNulls.java solaris-sparc
+sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientTimeout.java solaris-sparc
+sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ServerTimeout.java solaris-sparc
+sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java solaris-sparc
+sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh solaris-sparc
+sun/security/tools/keytool/AltProviderPath.sh 			solaris-sparc
+
+# Solaris 10 sparc, passed/failed confusion? java.security.ProviderException: update() failed
+sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java generic-all
+
+# Seem really slow on Solaris sparc, being excluded just for timing reasons
+sun/security/tools/jarsigner/AlgOptions.sh			solaris-sparc
+sun/security/tools/jarsigner/nameclash.sh			solaris-sparc
+sun/security/krb5/auto/basic.sh					solaris-sparc
+sun/security/provider/PolicyFile/getinstance/getinstance.sh	solaris-sparc
+sun/security/tools/jarsigner/samename.sh			solaris-sparc
+
+# Timed out, Solaris 10 64bit sparcv9
+com/sun/crypto/provider/Cipher/DES/PaddingTest.java		generic-all
+
+# Othervm, sparc, NoRouteToHostException: Cannot assign requested address
+sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java generic-all
+
+# ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DEVICE_ERROR
+#    Does not seem to run on windows machines? dll missing? 
+sun/security/pkcs11/rsa/TestKeyPairGenerator.java		generic-all
+
+# Times out on windows X64, othervm mode
+#    Solaris sparc and sparcv9 -server, timeout
+sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java	generic-all
+
+# Failed on solaris 10 sparc, othervm mode,  "js.jks: No such file or directory"
+#  Also, cannot verify signature on solaris i586 -server
+sun/security/tools/jarsigner/concise_jarsigner.sh		generic-all
+
+# Various failures on Linux Fedora 9 X64, othervm mode
+lib/security/cacerts/VerifyCACerts.java				generic-all
+sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java generic-all
+sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java	generic-all
+sun/security/tools/jarsigner/oldsig.sh				generic-all
+
+# Various failures on Linux Fedora 9 X64, othervm mode
+#   Does not seem to run on windows machines? dll missing? 
+sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java	generic-all
+
+# Linux i586 -server, buffer too short to hold shared secret?
+com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java	generic-all
+
+# Solaris sparcv9: Failed to parse input emptysubject.jks: No such file or directory
+sun/security/tools/keytool/emptysubject.sh			generic-all
+
+# Timeout on solaris-sparcv9 or exception thrown
+com/sun/crypto/provider/Cipher/RSA/TestOAEP_KAT.java	 	solaris-all
+
+# File 6535697.test input stream left open? windows samevm
+java/security/cert/CertificateFactory/openssl/OpenSSLCert.java	generic-all
+
+# Leaving file open: SerialVersion.current, windows samevm
+java/security/BasicPermission/SerialVersion.java		generic-all
+
+# Solaris 11 i586, these all fail with samevm, need to be othervm???
+java/security/BasicPermission/NullOrEmptyName.java		generic-all
+
+# Suspect missing close() on file PermClass.current, windows samevm cascade
+java/security/BasicPermission/PermClass.java			generic-all
+
+# Solaris 11 i586, these all fail with samevm, need to be othervm???
+java/security/KeyPairGenerator/Failover.java			generic-all
+java/security/Provider/DefaultPKCS11.java			generic-all
+java/security/SecureClassLoader/DefineClassByteBuffer.java	generic-all
+java/security/SecureRandom/GetAlgorithm.java			generic-all
+java/security/Security/removing/RemoveProviders.java		generic-all
+java/security/Signature/ByteBuffers.java			generic-all
+java/security/Signature/NONEwithRSA.java			generic-all
+java/security/Signature/SignWithOutputBuffer.java		generic-all
+java/security/Signature/TestInitSignWithMyOwnRandom.java	generic-all
+java/security/UnresolvedPermission/AccessorMethods.java		generic-all
+java/security/UnresolvedPermission/Equals.java			generic-all
+
+# Do not seem to run on windows machines? dll missing? 
+sun/security/krb5/auto/IgnoreChannelBinding.java	 	windows-all
+
+# Fails on OpenSolaris, missing classes, slow on Solaris sparc
+sun/security/ec/TestEC.java					generic-all
+
+# Problems with windows x64
+sun/security/mscapi/IsSunMSCAPIAvailable.sh		 	windows-x64
+sun/security/mscapi/RSAEncryptDecrypt.sh		 	windows-x64
+
+# Do not seem to run on windows machines? dll missing? 
+sun/security/pkcs11/Cipher/ReinitCipher.java		 	windows-all
+sun/security/pkcs11/Cipher/TestRSACipher.java		 	windows-all
+sun/security/pkcs11/Cipher/TestRSACipherWrap.java	 	windows-all
+sun/security/pkcs11/Cipher/TestSymmCiphers.java 	 	windows-all
+sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java	 	windows-all
+
+# Do not seem to run on windows machines? dll missing? 
+sun/security/pkcs11/ec/ReadCertificates.java		 	windows-all
+sun/security/pkcs11/ec/ReadPKCS12.java			 	windows-all
+sun/security/pkcs11/ec/TestCurves.java			 	windows-all
+sun/security/pkcs11/ec/TestECDH.java			 	windows-all
+sun/security/pkcs11/ec/TestECDSA.java			 	windows-all
+sun/security/pkcs11/ec/TestECGenSpec.java		 	windows-all
+sun/security/pkcs11/ec/TestKeyFactory.java		 	windows-all
+sun/security/pkcs11/fips/TrustManagerTest.java		 	windows-all
+
+# Do not seem to run on windows machines? dll missing? 
+sun/security/pkcs11/KeyAgreement/TestShort.java 	 	windows-all
+sun/security/pkcs11/KeyGenerator/DESParity.java 	 	windows-all
+
+# Exception in test solaris-sparc -client -server, no windows
+sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java	windows-all solaris-all
+
+# Do not seem to run on windows machines? dll missing? 
+sun/security/pkcs11/KeyStore/Basic.sh			 	windows-all
+sun/security/pkcs11/KeyStore/ClientAuth.sh		 	windows-all
+
+# Solaris sparc client, fails to compile?
+sun/security/pkcs11/KeyStore/SecretKeysBasic.sh 	 	solaris-all
+
+# Do not seem to run on windows machines? dll missing? 
+sun/security/pkcs11/Mac/ReinitMac.java			 	windows-all
+sun/security/pkcs11/MessageDigest/ByteBuffers.java	 	windows-all
+sun/security/pkcs11/MessageDigest/DigestKAT.java	 	windows-all
+sun/security/pkcs11/MessageDigest/ReinitDigest.java	 	windows-all
+sun/security/pkcs11/Provider/ConfigQuotedString.sh	 	windows-all
+sun/security/pkcs11/Provider/Login.sh			 	windows-all
+sun/security/pkcs11/rsa/KeyWrap.java			 	windows-all
+sun/security/pkcs11/rsa/TestCACerts.java		 	windows-all
+sun/security/pkcs11/rsa/TestKeyFactory.java		 	windows-all
+sun/security/pkcs11/rsa/TestSignatures.java		 	windows-all
+sun/security/pkcs11/SampleTest.java			 	windows-all
+sun/security/pkcs11/Secmod/AddPrivateKey.java		 	windows-all
+sun/security/pkcs11/Secmod/AddTrustedCert.java		 	windows-all
+sun/security/pkcs11/Secmod/Crypto.java			 	windows-all
+sun/security/pkcs11/Secmod/GetPrivateKey.java		 	windows-all
+sun/security/pkcs11/Secmod/JksSetPrivateKey.java	 	windows-all
+sun/security/pkcs11/Secmod/TrustAnchors.java		 	windows-all
+sun/security/pkcs11/SecureRandom/Basic.java		 	windows-all
+sun/security/pkcs11/Serialize/SerializeProvider.java	 	windows-all
+sun/security/pkcs11/Signature/ByteBuffers.java		 	windows-all
+sun/security/pkcs11/Signature/ReinitSignature.java	 	windows-all
+sun/security/pkcs11/Signature/TestDSA.java		 	windows-all
+sun/security/pkcs11/tls/TestKeyMaterial.java		 	windows-all
+sun/security/pkcs11/tls/TestMasterSecret.java		 	windows-all
+sun/security/pkcs11/tls/TestPremaster.java		 	windows-all
+sun/security/pkcs11/tls/TestPRF.java			 	windows-all
+
+# Fails on OpenSolaris java.net.BindException: Address already in use
+sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java		generic-all
+
+# Timeout on solaris-sparcv9 or ArrayIndexOutOfBoundsException?
+sun/security/rsa/TestKeyPairGeneratorLength.java	 	solaris-all
+sun/security/rsa/TestSignatures.java			 	solaris-all
+
+# Timeout on solaris-sparc and i586 and x64, -client and -server
+sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/InterruptedIO.java solaris-all
+
+# Do not seem to run on windows machines? dll missing? 
+sun/security/tools/jarsigner/emptymanifest.sh		 	windows-all
+
+# Files does not exist or no encoding? solaris-sparcv9
+sun/security/tools/keytool/importreadall.sh		 	solaris-all
+sun/security/tools/keytool/selfissued.sh		 	solaris-all
+
+############################################################################
+
+# jdk_swing (not using samevm)
+
+# Fails on solaris 10 sparc, throws RuntimeException that just says "failed"
+javax/swing/JLabel/6501991/bug6501991.java			generic-all
+
+# Fails on solaris 11 i586, with othervm
+javax/swing/JFileChooser/6570445/bug6570445.java		generic-all
+javax/swing/JFileChooser/6738668/bug6738668.java		generic-all
+javax/swing/JPopupMenu/6675802/bug6675802.java			generic-all
+javax/swing/system/6799345/TestShutdown.java			generic-all
+
+############################################################################
+
+# jdk_text
+
+# Linux x64 occasional errors, no details
+java/text/Bidi/Bug6665028.java				 	linux-x64
+
+############################################################################
+
+# jdk_tools
+
+# Some of the tools tests kind of require "othervm" or if they don't will
+#  always be firing up another VM anyway due to the nature of tools testing.
+#  So most if not all tools tests are now being run with "othervm" mode.
+#  Some of these tools tests have a tendency to use fixed ports, bad idea.
+
+# Solaris 10 client x86, java.lang.IndexOutOfBoundsException resumer Interrupted
+com/sun/jdi/SimulResumerTest.java				generic-all
+
+# Output of jps differs from expected output.
+#   Invalid argument count on solaris-sparc and x64
+sun/tools/jstatd/jstatdPort.sh					generic-all
+
+# othervm mode, Could not synchronize with target
+sun/tools/jps/jps-l_1.sh					generic-all
+sun/tools/jps/jps-l_2.sh					generic-all
+sun/tools/jps/jps-lm.sh						generic-all
+sun/tools/jps/jps-Vvml_2.sh					generic-all
+sun/tools/jps/jps-m_2.sh					generic-all
+
+# Server name error, port 2098 problem?
+sun/tools/jstatd/jstatdServerName.sh				generic-all
+
+# Solaris, handshake failed, othervm mode
+com/sun/jdi/RedefineException.sh				generic-all
+
+# These tests fail on solaris sparc, all the time
+com/sun/servicetag/DeleteServiceTag.java			generic-all
+com/sun/servicetag/DuplicateNotFound.java			generic-all
+com/sun/servicetag/FindServiceTags.java				generic-all
+com/sun/servicetag/InstanceUrnCheck.java			generic-all
+com/sun/servicetag/InvalidRegistrationData.java			generic-all
+com/sun/servicetag/InvalidServiceTag.java			generic-all
+com/sun/servicetag/JavaServiceTagTest.java			generic-all
+com/sun/servicetag/JavaServiceTagTest1.java			generic-all
+com/sun/servicetag/NewRegistrationData.java			generic-all
+com/sun/servicetag/SystemRegistryTest.java			generic-all
+com/sun/servicetag/TestLoadFromXML.java				generic-all
+com/sun/servicetag/UpdateServiceTagTest.java			generic-all
+com/sun/servicetag/ValidRegistrationData.java			generic-all
+
+# Problems on windows, jmap.exe hangs?
+com/sun/tools/attach/BasicTests.sh				windows-all
+
+# Fails on Solaris 10 sparc, in othervm mode, throws unexpected exception
+sun/jvmstat/monitor/MonitoredVm/CR6672135.java			generic-all
+
+# Unexpected Monitor Exception, solaris sparc -client
+sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh	generic-all
+
+# Probably should be samevm, but seem to cause errors even in othervm at times
+sun/tools/jhat/HatHeapDump1Test.java			 	generic-all
+
+# Problems on windows, jmap.exe hangs? (these run jmap)
+sun/tools/jmap/Basic.sh						windows-all
+
+# Invalid argument count on solaris-sparc and x64
+sun/tools/jstatd/jstatdDefaults.sh			 	solaris-all
+
+# Solaris sparcv9, jps output does not match, x64 different
+sun/tools/jstatd/jstatdExternalRegistry.sh		 	solaris-all
+
+# Probably should be samevm, but seem to cause errors even in othervm at times
+sun/tools/native2ascii/NativeErrors.java		 	generic-all
+
+# Solaris 10 sparc 32bit -client, java.lang.AssertionError: Some tests failed
+tools/jar/JarEntryTime.java					generic-all
+
+# Times out on sparc?
+tools/launcher/VersionCheck.java				generic-all
+
+# These tests fail on solaris sparc, all the time
+tools/jar/ChangeDir.java					generic-all
+
+# Cannot write jar
+#  Also, possible problems on windows, jmap.exe hangs? 
+tools/jar/index/MetaInf.java				 	windows-all
+
+############################################################################
+
+# jdk_util
+
+# Assert error, failures, on Linux Fedora 9 -server
+#   Windows samevm failure, assert error "Passed = 134, failed = 2"
+java/util/Arrays/ArrayObjectMethods.java			generic-all
+
+# Windows 2000, -client, samevm, java.lang.Error: Completed != 2
+java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java generic-all
+
+# Windows X64, Executor Stuck samevm mode:
+java/util/concurrent/FutureTask/BlockingTaskExecutor.java	generic-all
+
+# Problems on windows, jmap.exe hangs? (these run jmap), fails on Solaris 10 x86
+java/util/concurrent/locks/Lock/TimedAcquireLeak.java		generic-all
+
+# Solaris sparc client, some failures, "1 not equal to 3"?
+#   also Linux problems with samevm mode, -server linux i586? 1 not equal to 3?
+java/util/concurrent/Executors/AutoShutdown.java		generic-all
+
+# Fails on solaris-sparc -server (Set not equal to copy. 1)
+java/util/EnumSet/EnumSetBash.java			 	solaris-sparc
+
+# Failing to close an input stream? "foo", triggers samevm windows failures
+java/util/Formatter/Constructors.java				generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/util/Locale/Bug4175998Test.java				generic-all
+java/util/Locale/Bug4184873Test.java				generic-all
+java/util/Locale/LocaleTest.java				generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/util/logging/GetGlobalTest.java				generic-all
+java/util/logging/LoggerSubclass.java				generic-all
+java/util/logging/LoggingDeadlock.java				generic-all
+java/util/logging/LoggingDeadlock2.java 			generic-all
+java/util/logging/LoggingMXBeanTest.java			generic-all
+java/util/logging/LoggingMXBeanTest2.java			generic-all
+java/util/logging/LoggingNIOChange.java 			generic-all
+java/util/logging/ParentLoggersTest.java			generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/util/ResourceBundle/Bug4168625Test.java			generic-all
+java/util/ResourceBundle/Bug6359330.java			generic-all
+java/util/ResourceBundle/TestBug4179766.java			generic-all
+
+# Need to be marked othervm, or changed to be samevm safe
+java/util/WeakHashMap/GCDuringIteration.java			generic-all
+
+# Possible missing input stream close()? Causes samevm issues on windows
+java/util/zip/InfoZip.java				 	generic-all
+
+# Missing a close() on file Test0.zip? windows samevm cascade problem
+java/util/zip/ZipFile/Comment.java                              generic-all
+
+# Suspect missing close() on bad*.zip files, windows cascade errors with samevm
+java/util/zip/ZipFile/CorruptedZipFiles.java			generic-all
+
+# Should be samevm but causes problems with samevm, no details:
+java/util/zip/ZipFile/ManyEntries.java			 	generic-all
+
+############################################################################
+
--- a/test/demo/jvmti/DemoRun.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/demo/jvmti/DemoRun.java	Thu Nov 12 23:04:42 2009 +0000
@@ -145,7 +145,7 @@
          */
         int nvm_options = 0;
         if ( vm_options != null ) nvm_options = vm_options.length;
-        String cmd[]     = new String[1 + (d64?1:0) + 5 + nvm_options];
+        String cmd[]     = new String[1 + (d64?1:0) + 7 + nvm_options];
         String cmdLine;
         int exitStatus;
         int i,j;
@@ -154,6 +154,10 @@
         cmdLine = "";
         cmdLine += (cmd[i++] = java);
         cmdLine += " ";
+        cmdLine += (cmd[i++] = "-cp");
+        cmdLine += " ";
+        cmdLine += (cmd[i++] = cdir);
+        cmdLine += " ";
         cmdLine += (cmd[i++] = "-Dtest.classes=" + cdir);
         if ( d64 ) {
             cmdLine += " ";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/GraphicsDevice/CloneConfigsTest.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug     6822057
+ *
+ * @summary Test verifies that list of supported graphics configurations
+ *          can not be changed via modification of elements of an array
+ *          returned by getConfiguration() method.
+ *
+ * @run     main CloneConfigsTest
+ * @run     main/othervm -Dsun.java2d.opengl=True CloneConfigsTest
+ * @run     main/othervm -Dsun.java2d.d3d=true CloneConfigsTest
+ * @run     main/othervm -Dsun.java2d.noddraw=true CloneConfigsTest
+ */
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+
+public class CloneConfigsTest {
+
+    public static void main(String[] args) {
+        GraphicsEnvironment env =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+
+        GraphicsDevice[] devices = env.getScreenDevices();
+
+        GraphicsConfiguration c = new TestConfig();
+
+        for (GraphicsDevice gd : devices) {
+            System.out.println("Device: " + gd);
+
+            GraphicsConfiguration[] configs = gd.getConfigurations();
+
+            for (int i = 0; i < configs.length; i++) {
+                GraphicsConfiguration gc  = configs[i];
+                System.out.println("\tConfig: " + gc);
+
+                configs[i] = c;
+            }
+
+            // verify whether array of configs was modified
+            configs = gd.getConfigurations();
+            for (GraphicsConfiguration gc : configs) {
+                if (gc == c) {
+                    throw new RuntimeException("Test failed.");
+                }
+            }
+            System.out.println("Test passed.");
+        }
+    }
+
+    private static class TestConfig extends GraphicsConfiguration {
+
+        @Override
+        public GraphicsDevice getDevice() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public BufferedImage createCompatibleImage(int width, int height) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public ColorModel getColorModel() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public ColorModel getColorModel(int transparency) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public AffineTransform getDefaultTransform() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public AffineTransform getNormalizingTransform() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        @Override
+        public Rectangle getBounds() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/ClassLoader/UninitializedParent.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6636650
+ * @summary Uninitialized class loaders should not be a parent of other
+ *          class loaders.
+ */
+
+
+import java.net.*;
+
+public class UninitializedParent {
+    private static ClassLoader loader;
+    public static void main(String[] args) throws Exception {
+        System.setSecurityManager(new SecurityManager());
+
+        // Create an uninitialized class loader
+        try {
+            new ClassLoader(null) {
+                @Override
+                protected void finalize() {
+                    loader = this;
+                }
+            };
+        } catch (SecurityException exc) {
+            // Expected
+        }
+        System.gc();
+        System.runFinalization();
+
+        // if 'loader' isn't null, need to ensure that it can't be used as
+        // parent
+        if (loader != null) {
+            try {
+                // Create a class loader with 'loader' being the parent
+                URLClassLoader child = URLClassLoader.newInstance
+                    (new URL[0], loader);
+                throw new RuntimeException("Test Failed!");
+            } catch (SecurityException se) {
+                System.out.println("Test Passed: Exception thrown");
+            }
+        } else {
+            System.out.println("Test Passed: Loader is null");
+        }
+    }
+}
--- a/test/java/nio/Buffer/Basic-X.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,869 +0,0 @@
-/*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/* Type-specific source code for unit test
- *
- * Regenerate the BasicX classes via genBasic.sh whenever this file changes.
- * We check in the generated source files so that the test tree can be used
- * independently of the rest of the source tree.
- */
-
-#warn This file is preprocessed before being compiled
-
-import java.nio.*;
-import java.lang.reflect.Method;
-
-
-public class Basic$Type$
-    extends Basic
-{
-
-    private static void relGet($Type$Buffer b) {
-        int n = b.capacity();
-        $type$ v;
-        for (int i = 0; i < n; i++)
-            ck(b, (long)b.get(), (long)(($type$)ic(i)));
-        b.rewind();
-    }
-
-    private static void relGet($Type$Buffer b, int start) {
-        int n = b.remaining();
-        $type$ v;
-        for (int i = start; i < n; i++)
-            ck(b, (long)b.get(), (long)(($type$)ic(i)));
-        b.rewind();
-    }
-
-    private static void absGet($Type$Buffer b) {
-        int n = b.capacity();
-        $type$ v;
-        for (int i = 0; i < n; i++)
-            ck(b, (long)b.get(), (long)(($type$)ic(i)));
-        b.rewind();
-    }
-
-    private static void bulkGet($Type$Buffer b) {
-        int n = b.capacity();
-        $type$[] a = new $type$[n + 7];
-        b.get(a, 7, n);
-        for (int i = 0; i < n; i++)
-            ck(b, (long)a[i + 7], (long)(($type$)ic(i)));
-    }
-
-    private static void relPut($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        for (int i = 0; i < n; i++)
-            b.put(($type$)ic(i));
-        b.flip();
-    }
-
-    private static void absPut($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        for (int i = 0; i < n; i++)
-            b.put(i, ($type$)ic(i));
-        b.limit(n);
-        b.position(0);
-    }
-
-    private static void bulkPutArray($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        $type$[] a = new $type$[n + 7];
-        for (int i = 0; i < n; i++)
-            a[i + 7] = ($type$)ic(i);
-        b.put(a, 7, n);
-        b.flip();
-    }
-
-    private static void bulkPutBuffer($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        $Type$Buffer c = $Type$Buffer.allocate(n + 7);
-        c.position(7);
-        for (int i = 0; i < n; i++)
-            c.put(($type$)ic(i));
-        c.flip();
-        c.position(7);
-        b.put(c);
-        b.flip();
-    }
-
-    //6231529
-    private static void callReset($Type$Buffer b) {
-        b.position(0);
-        b.mark();
-
-        b.duplicate().reset();
-        b.asReadOnlyBuffer().reset();
-    }
-
-#if[byte]
-#else[byte]
-    // 6221101-6234263
-
-    private static void putBuffer() {
-        final int cap = 10;
-
-        $Type$Buffer direct1 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
-        $Type$Buffer nondirect1 = ByteBuffer.allocate(cap).as$Type$Buffer();
-        direct1.put(nondirect1);
-
-        $Type$Buffer direct2 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
-        $Type$Buffer nondirect2 = ByteBuffer.allocate(cap).as$Type$Buffer();
-        nondirect2.put(direct2);
-
-        $Type$Buffer direct3 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
-        $Type$Buffer direct4 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
-        direct3.put(direct4);
-
-        $Type$Buffer nondirect3 = ByteBuffer.allocate(cap).as$Type$Buffer();
-        $Type$Buffer nondirect4 = ByteBuffer.allocate(cap).as$Type$Buffer();
-        nondirect3.put(nondirect4);
-    }
-#end[byte]
-
-#if[char]
-
-    private static void bulkPutString($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        StringBuffer sb = new StringBuffer(n + 7);
-        sb.append("1234567");
-        for (int i = 0; i < n; i++)
-            sb.append((char)ic(i));
-        b.put(sb.toString(), 7, 7 + n);
-        b.flip();
-    }
-
-#end[char]
-
-    private static void checkSlice($Type$Buffer b, $Type$Buffer slice) {
-        ck(slice, 0, slice.position());
-        ck(slice, b.remaining(), slice.limit());
-        ck(slice, b.remaining(), slice.capacity());
-        if (b.isDirect() != slice.isDirect())
-            fail("Lost direction", slice);
-        if (b.isReadOnly() != slice.isReadOnly())
-            fail("Lost read-only", slice);
-    }
-
-#if[byte]
-
-    private static void checkBytes(ByteBuffer b, byte[] bs) {
-        int n = bs.length;
-        int p = b.position();
-        byte v;
-        if (b.order() == ByteOrder.BIG_ENDIAN) {
-            for (int i = 0; i < n; i++)
-                ck(b, b.get(), bs[i]);
-        } else {
-            for (int i = n - 1; i >= 0; i--)
-                ck(b, b.get(), bs[i]);
-        }
-        b.position(p);
-    }
-
-    private static void compact(Buffer b) {
-        try {
-            Class<?> cl = b.getClass();
-            Method m = cl.getDeclaredMethod("compact");
-            m.setAccessible(true);
-            m.invoke(b);
-        } catch (Exception e) {
-            fail(e.getMessage(), b);
-        }
-    }
-
-    private static void checkInvalidMarkException(final Buffer b) {
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-            public void run() {
-                b.mark();
-                compact(b);
-                b.reset();
-            }});
-    }
-
-    private static void testViews(int level, ByteBuffer b, boolean direct) {
-
-        ShortBuffer sb = b.asShortBuffer();
-        BasicShort.test(level, sb, direct);
-        checkBytes(b, new byte[] { 0, (byte)ic(0) });
-        checkInvalidMarkException(sb);
-
-        CharBuffer cb = b.asCharBuffer();
-        BasicChar.test(level, cb, direct);
-        checkBytes(b, new byte[] { 0, (byte)ic(0) });
-        checkInvalidMarkException(cb);
-
-        IntBuffer ib = b.asIntBuffer();
-        BasicInt.test(level, ib, direct);
-        checkBytes(b, new byte[] { 0, 0, 0, (byte)ic(0) });
-        checkInvalidMarkException(ib);
-
-        LongBuffer lb = b.asLongBuffer();
-        BasicLong.test(level, lb, direct);
-        checkBytes(b, new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)ic(0) });
-        checkInvalidMarkException(lb);
-
-        FloatBuffer fb = b.asFloatBuffer();
-        BasicFloat.test(level, fb, direct);
-        checkBytes(b, new byte[] { 0x42, (byte)0xc2, 0, 0 });
-        checkInvalidMarkException(fb);
-
-        DoubleBuffer db = b.asDoubleBuffer();
-        BasicDouble.test(level, db, direct);
-        checkBytes(b, new byte[] { 0x40, 0x58, 0x40, 0, 0, 0, 0, 0 });
-        checkInvalidMarkException(db);
-    }
-
-    private static void testHet(int level, ByteBuffer b) {
-
-        int p = b.position();
-        b.limit(b.capacity());
-        show(level, b);
-        out.print("    put:");
-
-        b.putChar((char)1);
-        b.putChar((char)Character.MAX_VALUE);
-        out.print(" char");
-
-        b.putShort((short)1);
-        b.putShort((short)Short.MAX_VALUE);
-        out.print(" short");
-
-        b.putInt(1);
-        b.putInt(Integer.MAX_VALUE);
-        out.print(" int");
-
-        b.putLong((long)1);
-        b.putLong((long)Long.MAX_VALUE);
-        out.print(" long");
-
-        b.putFloat((float)1);
-        b.putFloat((float)Float.MIN_VALUE);
-        b.putFloat((float)Float.MAX_VALUE);
-        out.print(" float");
-
-        b.putDouble((double)1);
-        b.putDouble((double)Double.MIN_VALUE);
-        b.putDouble((double)Double.MAX_VALUE);
-        out.print(" double");
-
-        out.println();
-        b.limit(b.position());
-        b.position(p);
-        show(level, b);
-        out.print("    get:");
-
-        ck(b, b.getChar(), 1);
-        ck(b, b.getChar(), Character.MAX_VALUE);
-        out.print(" char");
-
-        ck(b, b.getShort(), 1);
-        ck(b, b.getShort(), Short.MAX_VALUE);
-        out.print(" short");
-
-        ck(b, b.getInt(), 1);
-        ck(b, b.getInt(), Integer.MAX_VALUE);
-        out.print(" int");
-
-        ck(b, b.getLong(), 1);
-        ck(b, b.getLong(), Long.MAX_VALUE);
-        out.print(" long");
-
-        ck(b, (long)b.getFloat(), 1);
-        ck(b, (long)b.getFloat(), (long)Float.MIN_VALUE);
-        ck(b, (long)b.getFloat(), (long)Float.MAX_VALUE);
-        out.print(" float");
-
-        ck(b, (long)b.getDouble(), 1);
-        ck(b, (long)b.getDouble(), (long)Double.MIN_VALUE);
-        ck(b, (long)b.getDouble(), (long)Double.MAX_VALUE);
-        out.print(" double");
-
-        out.println();
-
-    }
-
-#end[byte]
-
-    private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
-        boolean caught = false;
-        try {
-            thunk.run();
-        } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass())) {
-                caught = true;
-            } else {
-                fail(x.getMessage() + " not expected");
-            }
-        }
-        if (!caught)
-            fail(ex.getName() + " not thrown", b);
-    }
-
-    private static void tryCatch($type$ [] t, Class ex, Runnable thunk) {
-        tryCatch($Type$Buffer.wrap(t), ex, thunk);
-    }
-
-    public static void test(int level, final $Type$Buffer b, boolean direct) {
-
-        show(level, b);
-
-        if (direct != b.isDirect())
-            fail("Wrong direction", b);
-
-        // Gets and puts
-
-        relPut(b);
-        relGet(b);
-        absGet(b);
-        bulkGet(b);
-
-        absPut(b);
-        relGet(b);
-        absGet(b);
-        bulkGet(b);
-
-        bulkPutArray(b);
-        relGet(b);
-
-        bulkPutBuffer(b);
-        relGet(b);
-
-#if[char]
-
-        bulkPutString(b);
-        relGet(b);
-        b.position(1);
-        b.limit(7);
-        ck(b, b.toString().equals("bcdefg"));
-
-        // CharSequence ops
-
-        b.position(2);
-        ck(b, b.charAt(1), 'd');
-        CharBuffer c = b.subSequence(1, 4);
-        ck(c, c.capacity(), b.capacity());
-        ck(c, c.position(), b.position()+1);
-        ck(c, c.limit(), b.position()+4);
-        ck(c, b.subSequence(1, 4).toString().equals("def"));
-
-        // 4938424
-        b.position(4);
-        ck(b, b.charAt(1), 'f');
-        ck(b, b.subSequence(1, 3).toString().equals("fg"));
-
-#end[char]
-
-        // Compact
-
-        relPut(b);
-        b.position(13);
-        b.compact();
-        b.flip();
-        relGet(b, 13);
-
-        // Exceptions
-
-        relPut(b);
-        b.limit(b.capacity() / 2);
-        b.position(b.limit());
-
-        tryCatch(b, BufferUnderflowException.class, new Runnable() {
-                public void run() {
-                    b.get();
-                }});
-
-        tryCatch(b, BufferOverflowException.class, new Runnable() {
-                public void run() {
-                    b.put(($type$)42);
-                }});
-
-        // The index must be non-negative and lesss than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.put(b.limit(), ($type$)42);
-                }});
-
-        tryCatch(b, InvalidMarkException.class, new Runnable() {
-                public void run() {
-                    b.position(0);
-                    b.mark();
-                    b.compact();
-                    b.reset();
-                }});
-
-        // Values
-
-        b.clear();
-        b.put(($type$)0);
-        b.put(($type$)-1);
-        b.put(($type$)1);
-        b.put($Fulltype$.MAX_VALUE);
-        b.put($Fulltype$.MIN_VALUE);
-#if[float]
-        b.put(-Float.MAX_VALUE);
-        b.put(-Float.MIN_VALUE);
-        b.put(Float.NEGATIVE_INFINITY);
-        b.put(Float.POSITIVE_INFINITY);
-        b.put(Float.NaN);
-        b.put(0.91697687f);             // Changes value if incorrectly swapped
-#end[float]
-#if[double]
-        b.put(-Double.MAX_VALUE);
-        b.put(-Double.MIN_VALUE);
-        b.put(Double.NEGATIVE_INFINITY);
-        b.put(Double.POSITIVE_INFINITY);
-        b.put(Double.NaN);
-        b.put(0.5121609353879392);      // Changes value if incorrectly swapped
-#end[double]
-
-        $type$ v;
-        b.flip();
-        ck(b, b.get(), 0);
-        ck(b, b.get(), ($type$)-1);
-        ck(b, b.get(), 1);
-        ck(b, b.get(), $Fulltype$.MAX_VALUE);
-        ck(b, b.get(), $Fulltype$.MIN_VALUE);
-
-#if[float]
-        ck(b, b.get(), -Float.MAX_VALUE);
-        ck(b, b.get(), -Float.MIN_VALUE);
-        ck(b, b.get(), Float.NEGATIVE_INFINITY);
-        ck(b, b.get(), Float.POSITIVE_INFINITY);
-        if (Float.floatToRawIntBits(v = b.get()) != Float.floatToRawIntBits(Float.NaN))
-            fail(b, (long)Float.NaN, (long)v);
-        ck(b, b.get(), 0.91697687f);
-#end[float]
-#if[double]
-        ck(b, b.get(), -Double.MAX_VALUE);
-        ck(b, b.get(), -Double.MIN_VALUE);
-        ck(b, b.get(), Double.NEGATIVE_INFINITY);
-        ck(b, b.get(), Double.POSITIVE_INFINITY);
-        if (Double.doubleToRawLongBits(v = b.get())
-            != Double.doubleToRawLongBits(Double.NaN))
-            fail(b, (long)Double.NaN, (long)v);
-        ck(b, b.get(), 0.5121609353879392);
-#end[double]
-
-
-        // Comparison
-        b.rewind();
-        $Type$Buffer b2 = $Type$Buffer.allocate(b.capacity());
-        b2.put(b);
-        b2.flip();
-        b.position(2);
-        b2.position(2);
-        if (!b.equals(b2)) {
-            for (int i = 2; i < b.limit(); i++) {
-                $type$ x = b.get(i);
-                $type$ y = b2.get(i);
-                if (x != y
-#if[double]
-                    || Double.compare(x, y) != 0
-#end[double]
-#if[float]
-                    || Float.compare(x, y) != 0
-#end[float]
-                    )
-                    out.println("[" + i + "] " + x + " != " + y);
-            }
-            fail("Identical buffers not equal", b, b2);
-        }
-        if (b.compareTo(b2) != 0)
-            fail("Comparison to identical buffer != 0", b, b2);
-
-        b.limit(b.limit() + 1);
-        b.position(b.limit() - 1);
-        b.put(($type$)99);
-        b.rewind();
-        b2.rewind();
-        if (b.equals(b2))
-            fail("Non-identical buffers equal", b, b2);
-        if (b.compareTo(b2) <= 0)
-            fail("Comparison to shorter buffer <= 0", b, b2);
-        b.limit(b.limit() - 1);
-
-        b.put(2, ($type$)42);
-        if (b.equals(b2))
-            fail("Non-identical buffers equal", b, b2);
-        if (b.compareTo(b2) <= 0)
-            fail("Comparison to lesser buffer <= 0", b, b2);
-
-        // Sub, dup
-
-        relPut(b);
-        relGet(b.duplicate());
-        b.position(13);
-        relGet(b.duplicate(), 13);
-        relGet(b.duplicate().slice(), 13);
-        relGet(b.slice(), 13);
-        relGet(b.slice().duplicate(), 13);
-
-        // Slice
-
-        b.position(5);
-        $Type$Buffer sb = b.slice();
-        checkSlice(b, sb);
-        b.position(0);
-        $Type$Buffer sb2 = sb.slice();
-        checkSlice(sb, sb2);
-
-        if (!sb.equals(sb2))
-            fail("Sliced slices do not match", sb, sb2);
-        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
-            fail("Array offsets do not match: "
-                 + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
-
-#if[byte]
-
-        // Views
-
-        b.clear();
-        b.order(ByteOrder.BIG_ENDIAN);
-        testViews(level + 1, b, direct);
-
-        for (int i = 1; i <= 9; i++) {
-            b.position(i);
-            show(level + 1, b);
-            testViews(level + 2, b, direct);
-        }
-
-        b.position(0);
-        b.order(ByteOrder.LITTLE_ENDIAN);
-        testViews(level + 1, b, direct);
-
-        // Heterogeneous accessors
-
-        b.order(ByteOrder.BIG_ENDIAN);
-        for (int i = 0; i <= 9; i++) {
-            b.position(i);
-            testHet(level + 1, b);
-        }
-        b.order(ByteOrder.LITTLE_ENDIAN);
-        b.position(3);
-        testHet(level + 1, b);
-
-#end[byte]
-
-        // Read-only views
-
-        b.rewind();
-        final $Type$Buffer rb = b.asReadOnlyBuffer();
-        if (!b.equals(rb))
-            fail("Buffer not equal to read-only view", b, rb);
-        show(level + 1, rb);
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    relPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    absPut(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutArray(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    bulkPutBuffer(rb);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.compact();
-                }});
-
-#if[byte]
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putChar((char)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putChar(0, (char)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putShort((short)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putShort(0, (short)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putInt(1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putInt(0, 1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putLong((long)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putLong(0, (long)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putFloat((float)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putFloat(0, (float)1);
-                }});
-
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putDouble((double)1);
-                }});
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    rb.putDouble(0, (double)1);
-                }});
-
-#end[byte]
-
-        if (rb.getClass().getName().startsWith("java.nio.Heap")) {
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.array();
-                    }});
-
-            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                    public void run() {
-                        rb.arrayOffset();
-                    }});
-
-            if (rb.hasArray())
-                fail("Read-only heap buffer's backing array is accessible",
-                     rb);
-
-        }
-
-        // Bulk puts from read-only buffers
-
-        b.clear();
-        rb.rewind();
-        b.put(rb);
-
-#if[byte]
-        // For byte buffers, test both the direct and non-direct cases
-        $Type$Buffer ob
-            = (b.isDirect()
-               ? $Type$Buffer.allocate(rb.capacity())
-               : $Type$Buffer.allocateDirect(rb.capacity()));
-        rb.rewind();
-        ob.put(rb);
-#end[byte]
-
-        relPut(b);                       // Required by testViews
-
-    }
-
-#if[char]
-
-    private static void testStr() {
-        final String s = "abcdefghijklm";
-        int start = 3;
-        int end = 9;
-        final CharBuffer b = CharBuffer.wrap(s, start, end);
-        show(0, b);
-        ck(b, b.toString().equals(s.substring(start, end)));
-        ck(b, b.toString().equals("defghi"));
-        ck(b, b.isReadOnly());
-        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
-                public void run() {
-                    b.put('x');
-                }});
-        ck(b, start, b.position());
-        ck(b, end, b.limit());
-        ck(b, s.length(), b.capacity());
-        b.position(6);
-        ck(b, b.subSequence(0,3).toString().equals("ghi"));
-
-        // The index, relative to the position, must be non-negative and
-        // smaller than remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.charAt(-1);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.charAt(b.remaining());
-                }});
-
-        // The index must be non-negative and less than the buffer's limit.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(b.limit());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.get(-1);
-                }});
-
-        // The start must be non-negative and no larger than remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(-1, b.remaining());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(b.remaining() + 1, b.remaining());
-                }});
-
-        // The end must be no smaller than start and no larger than
-        // remaining().
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(2, 1);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    b.subSequence(0, b.remaining() + 1);
-                }});
-
-        // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, -1, s.length());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, s.length() + 1, s.length());
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, 1, 0);
-                }});
-        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(s, 0, s.length() + 1);
-                }});
-    }
-
-#end[char]
-
-    public static void test(final $type$ [] ba) {
-        int offset = 47;
-        int length = 900;
-        final $Type$Buffer b = $Type$Buffer.wrap(ba, offset, length);
-        show(0, b);
-        ck(b, b.capacity(), ba.length);
-        ck(b, b.position(), offset);
-        ck(b, b.limit(), offset + length);
-
-        // The offset must be non-negative and no larger than <array.length>.
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, -1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, ba.length + 1, ba.length);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, 0, -1);
-                }});
-        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(ba, 0, ba.length + 1);
-                }});
-
-        // A NullPointerException will be thrown if the array is null.
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(($type$ []) null, 0, 5);
-                }});
-        tryCatch(ba, NullPointerException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.wrap(($type$ []) null);
-                }});
-    }
-
-    private static void testAllocate() {
-        // An IllegalArgumentException will be thrown for negative capacities.
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.allocate(-1);
-                }});
-#if[byte]
-        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
-                public void run() {
-                    $Type$Buffer.allocateDirect(-1);
-                }});
-#end[byte]
-    }
-
-    public static void test() {
-        testAllocate();
-        test(0, $Type$Buffer.allocate(7 * 1024), false);
-        test(0, $Type$Buffer.wrap(new $type$[7 * 1024], 0, 7 * 1024), false);
-        test(new $type$[1024]);
-#if[byte]
-        $Type$Buffer b = $Type$Buffer.allocateDirect(7 * 1024);
-        for (b.position(0); b.position() < b.limit(); )
-            ck(b, b.get(), 0);
-        test(0, b, true);
-#end[byte]
-#if[char]
-        testStr();
-#end[char]
-
-        callReset($Type$Buffer.allocate(10));
-
-#if[byte]
-#else[byte]
-        putBuffer();
-#end[byte]
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/nio/Buffer/Basic-X.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,869 @@
+/*
+ * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* Type-specific source code for unit test
+ *
+ * Regenerate the BasicX classes via genBasic.sh whenever this file changes.
+ * We check in the generated source files so that the test tree can be used
+ * independently of the rest of the source tree.
+ */
+
+#warn This file is preprocessed before being compiled
+
+import java.nio.*;
+import java.lang.reflect.Method;
+
+
+public class Basic$Type$
+    extends Basic
+{
+
+    private static void relGet($Type$Buffer b) {
+        int n = b.capacity();
+        $type$ v;
+        for (int i = 0; i < n; i++)
+            ck(b, (long)b.get(), (long)(($type$)ic(i)));
+        b.rewind();
+    }
+
+    private static void relGet($Type$Buffer b, int start) {
+        int n = b.remaining();
+        $type$ v;
+        for (int i = start; i < n; i++)
+            ck(b, (long)b.get(), (long)(($type$)ic(i)));
+        b.rewind();
+    }
+
+    private static void absGet($Type$Buffer b) {
+        int n = b.capacity();
+        $type$ v;
+        for (int i = 0; i < n; i++)
+            ck(b, (long)b.get(), (long)(($type$)ic(i)));
+        b.rewind();
+    }
+
+    private static void bulkGet($Type$Buffer b) {
+        int n = b.capacity();
+        $type$[] a = new $type$[n + 7];
+        b.get(a, 7, n);
+        for (int i = 0; i < n; i++)
+            ck(b, (long)a[i + 7], (long)(($type$)ic(i)));
+    }
+
+    private static void relPut($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        for (int i = 0; i < n; i++)
+            b.put(($type$)ic(i));
+        b.flip();
+    }
+
+    private static void absPut($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        for (int i = 0; i < n; i++)
+            b.put(i, ($type$)ic(i));
+        b.limit(n);
+        b.position(0);
+    }
+
+    private static void bulkPutArray($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        $type$[] a = new $type$[n + 7];
+        for (int i = 0; i < n; i++)
+            a[i + 7] = ($type$)ic(i);
+        b.put(a, 7, n);
+        b.flip();
+    }
+
+    private static void bulkPutBuffer($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        $Type$Buffer c = $Type$Buffer.allocate(n + 7);
+        c.position(7);
+        for (int i = 0; i < n; i++)
+            c.put(($type$)ic(i));
+        c.flip();
+        c.position(7);
+        b.put(c);
+        b.flip();
+    }
+
+    //6231529
+    private static void callReset($Type$Buffer b) {
+        b.position(0);
+        b.mark();
+
+        b.duplicate().reset();
+        b.asReadOnlyBuffer().reset();
+    }
+
+#if[byte]
+#else[byte]
+    // 6221101-6234263
+
+    private static void putBuffer() {
+        final int cap = 10;
+
+        $Type$Buffer direct1 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
+        $Type$Buffer nondirect1 = ByteBuffer.allocate(cap).as$Type$Buffer();
+        direct1.put(nondirect1);
+
+        $Type$Buffer direct2 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
+        $Type$Buffer nondirect2 = ByteBuffer.allocate(cap).as$Type$Buffer();
+        nondirect2.put(direct2);
+
+        $Type$Buffer direct3 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
+        $Type$Buffer direct4 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
+        direct3.put(direct4);
+
+        $Type$Buffer nondirect3 = ByteBuffer.allocate(cap).as$Type$Buffer();
+        $Type$Buffer nondirect4 = ByteBuffer.allocate(cap).as$Type$Buffer();
+        nondirect3.put(nondirect4);
+    }
+#end[byte]
+
+#if[char]
+
+    private static void bulkPutString($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        StringBuffer sb = new StringBuffer(n + 7);
+        sb.append("1234567");
+        for (int i = 0; i < n; i++)
+            sb.append((char)ic(i));
+        b.put(sb.toString(), 7, 7 + n);
+        b.flip();
+    }
+
+#end[char]
+
+    private static void checkSlice($Type$Buffer b, $Type$Buffer slice) {
+        ck(slice, 0, slice.position());
+        ck(slice, b.remaining(), slice.limit());
+        ck(slice, b.remaining(), slice.capacity());
+        if (b.isDirect() != slice.isDirect())
+            fail("Lost direction", slice);
+        if (b.isReadOnly() != slice.isReadOnly())
+            fail("Lost read-only", slice);
+    }
+
+#if[byte]
+
+    private static void checkBytes(ByteBuffer b, byte[] bs) {
+        int n = bs.length;
+        int p = b.position();
+        byte v;
+        if (b.order() == ByteOrder.BIG_ENDIAN) {
+            for (int i = 0; i < n; i++)
+                ck(b, b.get(), bs[i]);
+        } else {
+            for (int i = n - 1; i >= 0; i--)
+                ck(b, b.get(), bs[i]);
+        }
+        b.position(p);
+    }
+
+    private static void compact(Buffer b) {
+        try {
+            Class<?> cl = b.getClass();
+            Method m = cl.getDeclaredMethod("compact");
+            m.setAccessible(true);
+            m.invoke(b);
+        } catch (Exception e) {
+            fail(e.getMessage(), b);
+        }
+    }
+
+    private static void checkInvalidMarkException(final Buffer b) {
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+            public void run() {
+                b.mark();
+                compact(b);
+                b.reset();
+            }});
+    }
+
+    private static void testViews(int level, ByteBuffer b, boolean direct) {
+
+        ShortBuffer sb = b.asShortBuffer();
+        BasicShort.test(level, sb, direct);
+        checkBytes(b, new byte[] { 0, (byte)ic(0) });
+        checkInvalidMarkException(sb);
+
+        CharBuffer cb = b.asCharBuffer();
+        BasicChar.test(level, cb, direct);
+        checkBytes(b, new byte[] { 0, (byte)ic(0) });
+        checkInvalidMarkException(cb);
+
+        IntBuffer ib = b.asIntBuffer();
+        BasicInt.test(level, ib, direct);
+        checkBytes(b, new byte[] { 0, 0, 0, (byte)ic(0) });
+        checkInvalidMarkException(ib);
+
+        LongBuffer lb = b.asLongBuffer();
+        BasicLong.test(level, lb, direct);
+        checkBytes(b, new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)ic(0) });
+        checkInvalidMarkException(lb);
+
+        FloatBuffer fb = b.asFloatBuffer();
+        BasicFloat.test(level, fb, direct);
+        checkBytes(b, new byte[] { 0x42, (byte)0xc2, 0, 0 });
+        checkInvalidMarkException(fb);
+
+        DoubleBuffer db = b.asDoubleBuffer();
+        BasicDouble.test(level, db, direct);
+        checkBytes(b, new byte[] { 0x40, 0x58, 0x40, 0, 0, 0, 0, 0 });
+        checkInvalidMarkException(db);
+    }
+
+    private static void testHet(int level, ByteBuffer b) {
+
+        int p = b.position();
+        b.limit(b.capacity());
+        show(level, b);
+        out.print("    put:");
+
+        b.putChar((char)1);
+        b.putChar((char)Character.MAX_VALUE);
+        out.print(" char");
+
+        b.putShort((short)1);
+        b.putShort((short)Short.MAX_VALUE);
+        out.print(" short");
+
+        b.putInt(1);
+        b.putInt(Integer.MAX_VALUE);
+        out.print(" int");
+
+        b.putLong((long)1);
+        b.putLong((long)Long.MAX_VALUE);
+        out.print(" long");
+
+        b.putFloat((float)1);
+        b.putFloat((float)Float.MIN_VALUE);
+        b.putFloat((float)Float.MAX_VALUE);
+        out.print(" float");
+
+        b.putDouble((double)1);
+        b.putDouble((double)Double.MIN_VALUE);
+        b.putDouble((double)Double.MAX_VALUE);
+        out.print(" double");
+
+        out.println();
+        b.limit(b.position());
+        b.position(p);
+        show(level, b);
+        out.print("    get:");
+
+        ck(b, b.getChar(), 1);
+        ck(b, b.getChar(), Character.MAX_VALUE);
+        out.print(" char");
+
+        ck(b, b.getShort(), 1);
+        ck(b, b.getShort(), Short.MAX_VALUE);
+        out.print(" short");
+
+        ck(b, b.getInt(), 1);
+        ck(b, b.getInt(), Integer.MAX_VALUE);
+        out.print(" int");
+
+        ck(b, b.getLong(), 1);
+        ck(b, b.getLong(), Long.MAX_VALUE);
+        out.print(" long");
+
+        ck(b, (long)b.getFloat(), 1);
+        ck(b, (long)b.getFloat(), (long)Float.MIN_VALUE);
+        ck(b, (long)b.getFloat(), (long)Float.MAX_VALUE);
+        out.print(" float");
+
+        ck(b, (long)b.getDouble(), 1);
+        ck(b, (long)b.getDouble(), (long)Double.MIN_VALUE);
+        ck(b, (long)b.getDouble(), (long)Double.MAX_VALUE);
+        out.print(" double");
+
+        out.println();
+
+    }
+
+#end[byte]
+
+    private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
+        boolean caught = false;
+        try {
+            thunk.run();
+        } catch (Throwable x) {
+            if (ex.isAssignableFrom(x.getClass())) {
+                caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
+        }
+        if (!caught)
+            fail(ex.getName() + " not thrown", b);
+    }
+
+    private static void tryCatch($type$ [] t, Class ex, Runnable thunk) {
+        tryCatch($Type$Buffer.wrap(t), ex, thunk);
+    }
+
+    public static void test(int level, final $Type$Buffer b, boolean direct) {
+
+        show(level, b);
+
+        if (direct != b.isDirect())
+            fail("Wrong direction", b);
+
+        // Gets and puts
+
+        relPut(b);
+        relGet(b);
+        absGet(b);
+        bulkGet(b);
+
+        absPut(b);
+        relGet(b);
+        absGet(b);
+        bulkGet(b);
+
+        bulkPutArray(b);
+        relGet(b);
+
+        bulkPutBuffer(b);
+        relGet(b);
+
+#if[char]
+
+        bulkPutString(b);
+        relGet(b);
+        b.position(1);
+        b.limit(7);
+        ck(b, b.toString().equals("bcdefg"));
+
+        // CharSequence ops
+
+        b.position(2);
+        ck(b, b.charAt(1), 'd');
+        CharBuffer c = b.subSequence(1, 4);
+        ck(c, c.capacity(), b.capacity());
+        ck(c, c.position(), b.position()+1);
+        ck(c, c.limit(), b.position()+4);
+        ck(c, b.subSequence(1, 4).toString().equals("def"));
+
+        // 4938424
+        b.position(4);
+        ck(b, b.charAt(1), 'f');
+        ck(b, b.subSequence(1, 3).toString().equals("fg"));
+
+#end[char]
+
+        // Compact
+
+        relPut(b);
+        b.position(13);
+        b.compact();
+        b.flip();
+        relGet(b, 13);
+
+        // Exceptions
+
+        relPut(b);
+        b.limit(b.capacity() / 2);
+        b.position(b.limit());
+
+        tryCatch(b, BufferUnderflowException.class, new Runnable() {
+                public void run() {
+                    b.get();
+                }});
+
+        tryCatch(b, BufferOverflowException.class, new Runnable() {
+                public void run() {
+                    b.put(($type$)42);
+                }});
+
+        // The index must be non-negative and lesss than the buffer's limit.
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.get(b.limit());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.get(-1);
+                }});
+
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.put(b.limit(), ($type$)42);
+                }});
+
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
+        // Values
+
+        b.clear();
+        b.put(($type$)0);
+        b.put(($type$)-1);
+        b.put(($type$)1);
+        b.put($Fulltype$.MAX_VALUE);
+        b.put($Fulltype$.MIN_VALUE);
+#if[float]
+        b.put(-Float.MAX_VALUE);
+        b.put(-Float.MIN_VALUE);
+        b.put(Float.NEGATIVE_INFINITY);
+        b.put(Float.POSITIVE_INFINITY);
+        b.put(Float.NaN);
+        b.put(0.91697687f);             // Changes value if incorrectly swapped
+#end[float]
+#if[double]
+        b.put(-Double.MAX_VALUE);
+        b.put(-Double.MIN_VALUE);
+        b.put(Double.NEGATIVE_INFINITY);
+        b.put(Double.POSITIVE_INFINITY);
+        b.put(Double.NaN);
+        b.put(0.5121609353879392);      // Changes value if incorrectly swapped
+#end[double]
+
+        $type$ v;
+        b.flip();
+        ck(b, b.get(), 0);
+        ck(b, b.get(), ($type$)-1);
+        ck(b, b.get(), 1);
+        ck(b, b.get(), $Fulltype$.MAX_VALUE);
+        ck(b, b.get(), $Fulltype$.MIN_VALUE);
+
+#if[float]
+        ck(b, b.get(), -Float.MAX_VALUE);
+        ck(b, b.get(), -Float.MIN_VALUE);
+        ck(b, b.get(), Float.NEGATIVE_INFINITY);
+        ck(b, b.get(), Float.POSITIVE_INFINITY);
+        if (Float.floatToRawIntBits(v = b.get()) != Float.floatToRawIntBits(Float.NaN))
+            fail(b, (long)Float.NaN, (long)v);
+        ck(b, b.get(), 0.91697687f);
+#end[float]
+#if[double]
+        ck(b, b.get(), -Double.MAX_VALUE);
+        ck(b, b.get(), -Double.MIN_VALUE);
+        ck(b, b.get(), Double.NEGATIVE_INFINITY);
+        ck(b, b.get(), Double.POSITIVE_INFINITY);
+        if (Double.doubleToRawLongBits(v = b.get())
+            != Double.doubleToRawLongBits(Double.NaN))
+            fail(b, (long)Double.NaN, (long)v);
+        ck(b, b.get(), 0.5121609353879392);
+#end[double]
+
+
+        // Comparison
+        b.rewind();
+        $Type$Buffer b2 = $Type$Buffer.allocate(b.capacity());
+        b2.put(b);
+        b2.flip();
+        b.position(2);
+        b2.position(2);
+        if (!b.equals(b2)) {
+            for (int i = 2; i < b.limit(); i++) {
+                $type$ x = b.get(i);
+                $type$ y = b2.get(i);
+                if (x != y
+#if[double]
+                    || Double.compare(x, y) != 0
+#end[double]
+#if[float]
+                    || Float.compare(x, y) != 0
+#end[float]
+                    )
+                    out.println("[" + i + "] " + x + " != " + y);
+            }
+            fail("Identical buffers not equal", b, b2);
+        }
+        if (b.compareTo(b2) != 0)
+            fail("Comparison to identical buffer != 0", b, b2);
+
+        b.limit(b.limit() + 1);
+        b.position(b.limit() - 1);
+        b.put(($type$)99);
+        b.rewind();
+        b2.rewind();
+        if (b.equals(b2))
+            fail("Non-identical buffers equal", b, b2);
+        if (b.compareTo(b2) <= 0)
+            fail("Comparison to shorter buffer <= 0", b, b2);
+        b.limit(b.limit() - 1);
+
+        b.put(2, ($type$)42);
+        if (b.equals(b2))
+            fail("Non-identical buffers equal", b, b2);
+        if (b.compareTo(b2) <= 0)
+            fail("Comparison to lesser buffer <= 0", b, b2);
+
+        // Sub, dup
+
+        relPut(b);
+        relGet(b.duplicate());
+        b.position(13);
+        relGet(b.duplicate(), 13);
+        relGet(b.duplicate().slice(), 13);
+        relGet(b.slice(), 13);
+        relGet(b.slice().duplicate(), 13);
+
+        // Slice
+
+        b.position(5);
+        $Type$Buffer sb = b.slice();
+        checkSlice(b, sb);
+        b.position(0);
+        $Type$Buffer sb2 = sb.slice();
+        checkSlice(sb, sb2);
+
+        if (!sb.equals(sb2))
+            fail("Sliced slices do not match", sb, sb2);
+        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset()))
+            fail("Array offsets do not match: "
+                 + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
+
+#if[byte]
+
+        // Views
+
+        b.clear();
+        b.order(ByteOrder.BIG_ENDIAN);
+        testViews(level + 1, b, direct);
+
+        for (int i = 1; i <= 9; i++) {
+            b.position(i);
+            show(level + 1, b);
+            testViews(level + 2, b, direct);
+        }
+
+        b.position(0);
+        b.order(ByteOrder.LITTLE_ENDIAN);
+        testViews(level + 1, b, direct);
+
+        // Heterogeneous accessors
+
+        b.order(ByteOrder.BIG_ENDIAN);
+        for (int i = 0; i <= 9; i++) {
+            b.position(i);
+            testHet(level + 1, b);
+        }
+        b.order(ByteOrder.LITTLE_ENDIAN);
+        b.position(3);
+        testHet(level + 1, b);
+
+#end[byte]
+
+        // Read-only views
+
+        b.rewind();
+        final $Type$Buffer rb = b.asReadOnlyBuffer();
+        if (!b.equals(rb))
+            fail("Buffer not equal to read-only view", b, rb);
+        show(level + 1, rb);
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    relPut(rb);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    absPut(rb);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    bulkPutArray(rb);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    bulkPutBuffer(rb);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.compact();
+                }});
+
+#if[byte]
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putChar((char)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putChar(0, (char)1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putShort((short)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putShort(0, (short)1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putInt(1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putInt(0, 1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putLong((long)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putLong(0, (long)1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putFloat((float)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putFloat(0, (float)1);
+                }});
+
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putDouble((double)1);
+                }});
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    rb.putDouble(0, (double)1);
+                }});
+
+#end[byte]
+
+        if (rb.getClass().getName().startsWith("java.nio.Heap")) {
+
+            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                    public void run() {
+                        rb.array();
+                    }});
+
+            tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                    public void run() {
+                        rb.arrayOffset();
+                    }});
+
+            if (rb.hasArray())
+                fail("Read-only heap buffer's backing array is accessible",
+                     rb);
+
+        }
+
+        // Bulk puts from read-only buffers
+
+        b.clear();
+        rb.rewind();
+        b.put(rb);
+
+#if[byte]
+        // For byte buffers, test both the direct and non-direct cases
+        $Type$Buffer ob
+            = (b.isDirect()
+               ? $Type$Buffer.allocate(rb.capacity())
+               : $Type$Buffer.allocateDirect(rb.capacity()));
+        rb.rewind();
+        ob.put(rb);
+#end[byte]
+
+        relPut(b);                       // Required by testViews
+
+    }
+
+#if[char]
+
+    private static void testStr() {
+        final String s = "abcdefghijklm";
+        int start = 3;
+        int end = 9;
+        final CharBuffer b = CharBuffer.wrap(s, start, end);
+        show(0, b);
+        ck(b, b.toString().equals(s.substring(start, end)));
+        ck(b, b.toString().equals("defghi"));
+        ck(b, b.isReadOnly());
+        tryCatch(b, ReadOnlyBufferException.class, new Runnable() {
+                public void run() {
+                    b.put('x');
+                }});
+        ck(b, start, b.position());
+        ck(b, end, b.limit());
+        ck(b, s.length(), b.capacity());
+        b.position(6);
+        ck(b, b.subSequence(0,3).toString().equals("ghi"));
+
+        // The index, relative to the position, must be non-negative and
+        // smaller than remaining().
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.charAt(-1);
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.charAt(b.remaining());
+                }});
+
+        // The index must be non-negative and less than the buffer's limit.
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.get(b.limit());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.get(-1);
+                }});
+
+        // The start must be non-negative and no larger than remaining().
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.subSequence(-1, b.remaining());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.subSequence(b.remaining() + 1, b.remaining());
+                }});
+
+        // The end must be no smaller than start and no larger than
+        // remaining().
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.subSequence(2, 1);
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    b.subSequence(0, b.remaining() + 1);
+                }});
+
+        // The offset must be non-negative and no larger than <array.length>.
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(s, -1, s.length());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(s, s.length() + 1, s.length());
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(s, 1, 0);
+                }});
+        tryCatch(b, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(s, 0, s.length() + 1);
+                }});
+    }
+
+#end[char]
+
+    public static void test(final $type$ [] ba) {
+        int offset = 47;
+        int length = 900;
+        final $Type$Buffer b = $Type$Buffer.wrap(ba, offset, length);
+        show(0, b);
+        ck(b, b.capacity(), ba.length);
+        ck(b, b.position(), offset);
+        ck(b, b.limit(), offset + length);
+
+        // The offset must be non-negative and no larger than <array.length>.
+        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(ba, -1, ba.length);
+                }});
+        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(ba, ba.length + 1, ba.length);
+                }});
+        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(ba, 0, -1);
+                }});
+        tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(ba, 0, ba.length + 1);
+                }});
+
+        // A NullPointerException will be thrown if the array is null.
+        tryCatch(ba, NullPointerException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(($type$ []) null, 0, 5);
+                }});
+        tryCatch(ba, NullPointerException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.wrap(($type$ []) null);
+                }});
+    }
+
+    private static void testAllocate() {
+        // An IllegalArgumentException will be thrown for negative capacities.
+        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.allocate(-1);
+                }});
+#if[byte]
+        tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() {
+                public void run() {
+                    $Type$Buffer.allocateDirect(-1);
+                }});
+#end[byte]
+    }
+
+    public static void test() {
+        testAllocate();
+        test(0, $Type$Buffer.allocate(7 * 1024), false);
+        test(0, $Type$Buffer.wrap(new $type$[7 * 1024], 0, 7 * 1024), false);
+        test(new $type$[1024]);
+#if[byte]
+        $Type$Buffer b = $Type$Buffer.allocateDirect(7 * 1024);
+        for (b.position(0); b.position() < b.limit(); )
+            ck(b, b.get(), 0);
+        test(0, b, true);
+#end[byte]
+#if[char]
+        testStr();
+#end[char]
+
+        callReset($Type$Buffer.allocate(10));
+
+#if[byte]
+#else[byte]
+        putBuffer();
+#end[byte]
+    }
+
+}
--- a/test/java/nio/Buffer/CopyDirect-X-Memory.java	Thu Nov 12 23:00:23 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-#warn This file is preprocessed before being compiled
-
-import java.nio.*;
-
-public class CopyDirect$Type$Memory
-    extends CopyDirectMemory
-{
-    private static void init($Type$Buffer b) {
-        int n = b.capacity();
-        b.clear();
-        for (int i = 0; i < n; i++)
-            b.put(i, ($type$)ic(i));
-        b.limit(n);
-        b.position(0);
-    }
-
-    private static void init($type$ [] a) {
-        for (int i = 0; i < a.length; i++)
-            a[i] = ($type$)ic(i + 1);
-    }
-
-    public static void test() {
-#if[byte]
-        ByteBuffer b = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
-#else[byte]
-        ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
-        $Type$Buffer b = bb.as$Type$Buffer();
-#end[byte]
-        init(b);
-        $type$ [] a = new $type$[b.capacity()];
-        init(a);
-
-        // copyFrom$Type$Array (a -> b)
-        b.put(a);
-        for (int i = 0; i < a.length; i++)
-            ck(b, b.get(i), ($type$)ic(i + 1));
-
-        // copyTo$Type$Array (b -> a)
-        init(b);
-        init(a);
-        b.get(a);
-        for (int i = 0; i < a.length; i++)
-            if (a[i] != b.get(i))
-                fail("Copy failed at " + i + ": '"
-                     + a[i] + "' != '" + b.get(i) + "'");
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/nio/Buffer/CopyDirect-X-Memory.java.template	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+import java.nio.*;
+
+public class CopyDirect$Type$Memory
+    extends CopyDirectMemory
+{
+    private static void init($Type$Buffer b) {
+        int n = b.capacity();
+        b.clear();
+        for (int i = 0; i < n; i++)
+            b.put(i, ($type$)ic(i));
+        b.limit(n);
+        b.position(0);
+    }
+
+    private static void init($type$ [] a) {
+        for (int i = 0; i < a.length; i++)
+            a[i] = ($type$)ic(i + 1);
+    }
+
+    public static void test() {
+#if[byte]
+        ByteBuffer b = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
+#else[byte]
+        ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024);
+        $Type$Buffer b = bb.as$Type$Buffer();
+#end[byte]
+        init(b);
+        $type$ [] a = new $type$[b.capacity()];
+        init(a);
+
+        // copyFrom$Type$Array (a -> b)
+        b.put(a);
+        for (int i = 0; i < a.length; i++)
+            ck(b, b.get(i), ($type$)ic(i + 1));
+
+        // copyTo$Type$Array (b -> a)
+        init(b);
+        init(a);
+        b.get(a);
+        for (int i = 0; i < a.length; i++)
+            if (a[i] != b.get(i))
+                fail("Copy failed at " + i + ": '"
+                     + a[i] + "' != '" + b.get(i) + "'");
+    }
+}
--- a/test/java/nio/Buffer/genBasic.sh	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/nio/Buffer/genBasic.sh	Thu Nov 12 23:04:42 2009 +0000
@@ -26,7 +26,7 @@
 javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java
 
 gen() {
-    java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 <Basic-X.java >Basic$2.java
+    java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 <Basic-X.java.template >Basic$2.java
 }
 
 gen byte Byte Byte
--- a/test/java/nio/Buffer/genCopyDirectMemory.sh	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/nio/Buffer/genCopyDirectMemory.sh	Thu Nov 12 23:04:42 2009 +0000
@@ -26,7 +26,7 @@
 javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java > Spp.java
 
 gen() {
-    java  build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3<CopyDirect-X-Memory.java >CopyDirect$2Memory.java
+    java  build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3<CopyDirect-X-Memory.java.template >CopyDirect$2Memory.java
 }
 
 gen byte Byte Byte
--- a/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java	Thu Nov 12 23:04:42 2009 +0000
@@ -34,7 +34,7 @@
 
 public class Unbounded {
     // number of concurrent completion handlers
-    static final int CONCURRENCY_COUNT = 512;
+    static final int CONCURRENCY_COUNT = 256;
 
     public static void main(String[] args) throws Exception {
         // all accepted connections are added to a queue
--- a/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java	Thu Nov 12 23:04:42 2009 +0000
@@ -73,22 +73,22 @@
 
             List<InetAddress> addrs = Collections.list(nif.getInetAddresses());
             for (InetAddress addr: addrs) {
-                if (addr instanceof Inet4Address) {
-                    List<InetAddress> list = ip4Interfaces.get(nif);
-                    if (list == null) {
-                        list = new LinkedList<InetAddress>();
+                if (!addr.isAnyLocalAddress()) {
+                    if (addr instanceof Inet4Address) {
+                        List<InetAddress> list = ip4Interfaces.get(nif);
+                        if (list == null) {
+                            list = new LinkedList<InetAddress>();
+                        }
+                        list.add(addr);
+                        ip4Interfaces.put(nif, list);
+                    } else if (addr instanceof Inet6Address) {
+                        List<InetAddress> list = ip6Interfaces.get(nif);
+                        if (list == null) {
+                            list = new LinkedList<InetAddress>();
+                        }
+                        list.add(addr);
+                        ip6Interfaces.put(nif, list);
                     }
-                    list.add(addr);
-                    ip4Interfaces.put(nif, list);
-                }
-                if (addr instanceof Inet6Address) {
-                    List<InetAddress> list = ip6Interfaces.get(nif);
-                    if (list == null) {
-                        list = new LinkedList<InetAddress>();
-                    }
-                    list.add(addr);
-                    ip6Interfaces.put(nif, list);
-
                 }
             }
         }
--- a/test/java/nio/channels/FileChannel/Transfer.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/nio/channels/FileChannel/Transfer.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,7 @@
  * @bug 4434723 4482726 4559072 4638365 4795550 5081340 5103988 6253145
  * @summary Test FileChannel.transferFrom and transferTo
  * @library ..
+ * @run main/timeout=180 Transfer
  */
 
 import java.io.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/nio/channels/Selector/LotsOfCancels.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2009 Google Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Reproduces O(N^2) behavior of JDK6/7 select() call. This happens when
+ * a selector has many unprocessed updates to its interest set (e.g. adding
+ * OP_READ on a bunch of newly accepted sockets). The O(N^2) is triggered
+ * by cancelling a number of selection keys (or just closing a few sockets).
+ * In this case, select() will first go through the list of cancelled keys
+ * and try to deregister them. That deregistration is O(N^2) over the list
+ * of unprocessed updates to the interest set.
+ *
+ * <p> This O(N^2) behavior is a BUG in JVM and should be fixed.
+ *
+ * <p> The test first creates initCount connections, and adds them
+ * to the server epoll set. It then creates massCount connections,
+ * registers interest (causing updateList to be populated with massCount*2
+ * elements), but does not add them to epoll set (that would've cleared
+ * updateList). The test then closes initCount connections, thus populating
+ * deregistration queue. The subsequent call to selectNow() will first process
+ * deregistration queue, performing O(N^2) over updateList size,
+ * equal to massCount * 2.
+ *
+ * <p> Note that connect rate is artificially slowed down to compensate
+ * for what I believe is a Linux bug, where too high of a connection rate
+ * ends up in SYN's being dropped and then slow retransmits.
+ *
+ * @author Igor Chernyshev
+ */
+public class LotsOfCancels {
+
+    static long testStartTime;
+
+    public static void main(String[] args) throws Exception {
+        // the final select should run in less than 1000ms.
+        runTest(500, 2700, 1000);
+    }
+
+    static void log(String msg) {
+        System.out.println(getLogPrefix() + msg);
+    }
+
+    static String getLogPrefix() {
+        return durationMillis(testStartTime) + ": ";
+    }
+
+    /**
+     * Returns the elapsed time since startNanos, in milliseconds.
+     * @param startNanos the start time; this must be a value returned
+     * by {@link System.nanoTime}
+     */
+    static long durationMillis(long startNanos) {
+        return (System.nanoTime() - startNanos) / (1000L * 1000L);
+    }
+
+    static void runTest(int initCount, int massCount, int maxSelectTime)
+            throws Exception {
+        testStartTime = System.nanoTime();
+
+        InetSocketAddress address = new InetSocketAddress("127.0.0.1", 7359);
+
+        // Create server channel, add it to selector and run epoll_ctl.
+        log("Setting up server");
+        Selector serverSelector = Selector.open();
+        ServerSocketChannel server = ServerSocketChannel.open();
+        server.configureBlocking(false);
+        server.socket().bind(address, 5000);
+        server.register(serverSelector, SelectionKey.OP_ACCEPT);
+        serverSelector.selectNow();
+
+        log("Setting up client");
+        ClientThread client = new ClientThread(address);
+        client.start();
+        Thread.sleep(100);
+
+        // Set up initial set of client sockets.
+        log("Starting initial client connections");
+        client.connectClients(initCount);
+        Thread.sleep(500);  // Wait for client connections to arrive
+
+        // Accept all initial client sockets, add to selector and run
+        // epoll_ctl.
+        log("Accepting initial connections");
+        List<SocketChannel> serverChannels1 =
+            acceptAndAddAll(serverSelector, server, initCount);
+        if (serverChannels1.size() != initCount) {
+            throw new Exception("Accepted " + serverChannels1.size() +
+                                " instead of " + initCount);
+        }
+        serverSelector.selectNow();
+
+        // Set up mass set of client sockets.
+        log("Requesting mass client connections");
+        client.connectClients(massCount);
+        Thread.sleep(500);  // Wait for client connections to arrive
+
+        // Accept all mass client sockets, add to selector and do NOT
+        // run epoll_ctl.
+        log("Accepting mass connections");
+        List<SocketChannel> serverChannels2 =
+            acceptAndAddAll(serverSelector, server, massCount);
+        if (serverChannels2.size() != massCount) {
+            throw new Exception("Accepted " + serverChannels2.size() +
+                                " instead of " + massCount);
+        }
+
+        // Close initial set of sockets.
+        log("Closing initial connections");
+        closeAll(serverChannels1);
+
+        // Now get the timing of select() call.
+        log("Running the final select call");
+        long startTime = System.nanoTime();
+        serverSelector.selectNow();
+        long duration = durationMillis(startTime);
+        log("Init count = " + initCount +
+            ", mass count = " + massCount +
+            ", duration = " + duration + "ms");
+
+        if (duration > maxSelectTime) {
+            System.out.println
+                ("\n\n\n\n\nFAILURE: The final selectNow() took " +
+                 duration + "ms " +
+                 "- seems like O(N^2) bug is still here\n\n");
+            System.exit(1);
+        }
+    }
+
+    static List<SocketChannel> acceptAndAddAll(Selector selector,
+                                               ServerSocketChannel server,
+                                               int expected)
+            throws Exception {
+        int retryCount = 0;
+        int acceptCount = 0;
+        List<SocketChannel> channels = new ArrayList<SocketChannel>();
+        while (channels.size() < expected) {
+            SocketChannel channel = server.accept();
+            if (channel == null) {
+                log("accept() returned null " +
+                    "after accepting " + acceptCount + " more connections");
+                acceptCount = 0;
+                if (retryCount < 10) {
+                    // See if more new sockets got stacked behind.
+                    retryCount++;
+                    Thread.sleep(500);
+                    continue;
+                }
+                break;
+            }
+            retryCount = 0;
+            acceptCount++;
+            channel.configureBlocking(false);
+            channel.register(selector, SelectionKey.OP_READ);
+            channels.add(channel);
+        }
+        // Cause an additional updateList entry per channel.
+        for (SocketChannel channel : channels) {
+            channel.register(selector, SelectionKey.OP_WRITE);
+        }
+        return channels;
+    }
+
+    static void closeAll(List<SocketChannel> channels)
+            throws Exception {
+        for (SocketChannel channel : channels) {
+            channel.close();
+        }
+    }
+
+    static class ClientThread extends Thread {
+        private final SocketAddress address;
+        private final Selector selector;
+        private int connectionsNeeded;
+        private int totalCreated;
+
+        ClientThread(SocketAddress address) throws Exception {
+            this.address = address;
+            selector = Selector.open();
+            setDaemon(true);
+        }
+
+        void connectClients(int count) throws Exception {
+            synchronized (this) {
+                connectionsNeeded += count;
+            }
+            selector.wakeup();
+        }
+
+        @Override
+        public void run() {
+            try {
+                handleClients();
+            } catch (Throwable e) {
+                e.printStackTrace();
+                System.exit(1);
+            }
+        }
+
+        private void handleClients() throws Exception {
+            int selectCount = 0;
+            while (true) {
+                int createdCount = 0;
+                synchronized (this) {
+                    if (connectionsNeeded > 0) {
+
+                        while (connectionsNeeded > 0 && createdCount < 20) {
+                            connectionsNeeded--;
+                            createdCount++;
+                            totalCreated++;
+
+                            SocketChannel channel = SocketChannel.open();
+                            channel.configureBlocking(false);
+                            channel.connect(address);
+                            if (!channel.finishConnect()) {
+                                channel.register(selector,
+                                                 SelectionKey.OP_CONNECT);
+                            }
+                        }
+
+                        log("Started total of " +
+                            totalCreated + " client connections");
+                        Thread.sleep(200);
+                    }
+                }
+
+                if (createdCount > 0) {
+                    selector.selectNow();
+                } else {
+                    selectCount++;
+                    long startTime = System.nanoTime();
+                    selector.select();
+                    long duration = durationMillis(startTime);
+                    log("Exited clientSelector.select(), loop #"
+                        + selectCount + ", duration = " + duration + "ms");
+                }
+
+                int keyCount = -1;
+                Iterator<SelectionKey> keys =
+                    selector.selectedKeys().iterator();
+                while (keys.hasNext()) {
+                    SelectionKey key = keys.next();
+                    synchronized (key) {
+                        keyCount++;
+                        keys.remove();
+                        if (!key.isValid()) {
+                            log("Ignoring client key #" + keyCount);
+                            continue;
+                        }
+                        int readyOps = key.readyOps();
+                        if (readyOps == SelectionKey.OP_CONNECT) {
+                            key.interestOps(0);
+                            ((SocketChannel) key.channel()).finishConnect();
+                        } else {
+                            log("readyOps() on client key #" + keyCount +
+                                " returned " + readyOps);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
--- a/test/java/nio/file/Path/CopyAndMove.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/nio/file/Path/CopyAndMove.java	Thu Nov 12 23:04:42 2009 +0000
@@ -25,6 +25,8 @@
  * @bug 4313887 6838333
  * @summary Unit test for java.nio.file.Path copyTo/moveTo methods
  * @library ..
+ * @build CopyAndMove
+ * @run main/othervm CopyAndMove
  */
 
 import java.nio.ByteBuffer;
--- a/test/java/nio/file/Path/Links.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/nio/file/Path/Links.java	Thu Nov 12 23:04:42 2009 +0000
@@ -26,6 +26,8 @@
  * @summary Unit test for java.nio.file.Path createSymbolicLink,
  *     readSymbolicLink, and createLink methods
  * @library ..
+ * @build Links
+ * @run main/othervm Links
  */
 
 import java.nio.file.*;
--- a/test/java/util/Arrays/Sorting.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/Arrays/Sorting.java	Thu Nov 12 23:04:42 2009 +0000
@@ -23,11 +23,14 @@
 
 /*
  * @test
- * @bug 6880672 6896573
+ * @bug 6880672 6896573 6899694
  * @summary Exercise Arrays.sort
  * @build Sorting
  * @run main Sorting -shortrun
- * @author Vladimir Yaroslavskiy, Josh Bloch, Jon Bentley
+ *
+ * @author Vladimir Yaroslavskiy
+ * @author Jon Bentley
+ * @author Josh Bloch
  */
 
 import java.util.Arrays;
@@ -35,59 +38,300 @@
 import java.io.PrintStream;
 
 public class Sorting {
-    static final PrintStream out = System.out;
-    static final PrintStream err = System.err;
+    private static final PrintStream out = System.out;
+    private static final PrintStream err = System.err;
+
+    // Array lengths used in a long run (default)
+    private static final int[] LONG_RUN_LENGTHS = {
+        1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000};
 
-    // array lengths used in a long run (default)
-    static final int[] LONG_RUN = {
-        0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000};
+    // Array lengths used in a short run
+    private static final int[] SHORT_RUN_LENGTHS = { 1, 2, 3, 21, 55, 1000, 10000 };
 
-    // array lengths used in a short run
-    static final int[] SHORT_RUN = {0, 1, 2, 3, 21, 55, 1000, 10000, 500000};
+    // Random initial values used in a long run (default)
+    private static final long[] LONG_RUN_RANDOMS = {666, 0xC0FFEE, 999};
+
+    // Random initial values used in a short run
+    private static final long[] SHORT_RUN_RANDOMS = {666};
 
     public static void main(String[] args) {
-        boolean shortRun = false;
-        if (args.length > 0 && args[0].equals("-shortrun"))
-            shortRun = true;
+        boolean shortRun = args.length > 0 && args[0].equals("-shortrun");
+        long start = System.currentTimeMillis();
+
+        if (shortRun) {
+            testAndCheck(SHORT_RUN_LENGTHS, SHORT_RUN_RANDOMS);
+        } else {
+            testAndCheck(LONG_RUN_LENGTHS, LONG_RUN_RANDOMS);
+        }
+        long end = System.currentTimeMillis();
+
+        out.format("PASS in %d sec.\n", Math.round((end - start) / 1E3));
+    }
 
-        long start = System.nanoTime();
+    private static void testAndCheck(int[] lengths, long[] randoms) {
+        for (long random : randoms) {
+            reset(random);
+
+            for (int len : lengths) {
+                testAndCheckWithCheckSum(len, random);
+            }
+            reset(random);
+
+            for (int len : lengths) {
+                testAndCheckWithScrambling(len, random);
+            }
+            reset(random);
+
+            for (int len : lengths) {
+                testAndCheckFloat(len, random);
+            }
+            reset(random);
 
-        testAndCheck((shortRun) ? SHORT_RUN : LONG_RUN);
+            for (int len : lengths) {
+                testAndCheckDouble(len, random);
+            }
+            reset(random);
+
+            for (int len : lengths) {
+                testAndCheckRange(len, random);
+            }
+            reset(random);
+
+            for (int len : lengths) {
+                testAndCheckSubArray(len, random);
+            }
+        }
+    }
+
+    private static void testAndCheckSubArray(int len, long random) {
+        int[] golden = new int[len];
 
-        long end = System.nanoTime();
+        for (int m = 1; m < len / 2; m *= 2) {
+            int fromIndex = m;
+            int toIndex = len - m;
+
+            prepareSubArray(golden, fromIndex, toIndex, m);
+            int[] test = golden.clone();
 
+            for (TypeConverter converter : TypeConverter.values()) {
+                out.println("Test #6: " + converter +
+                   " len = " + len + ", m = " + m);
+                Object convertedGolden = converter.convert(golden);
+                Object convertedTest = converter.convert(test);
+
+                // outArr(test);
+                sortSubArray(convertedTest, fromIndex, toIndex);
+                // outArr(test);
+                checkSubArray(convertedTest, fromIndex, toIndex, m);
+            }
+        }
         out.println();
-        out.format("PASS in %ds%n", Math.round((end - start) / 1e9));
     }
 
-    static void testAndCheck(int[] lengths) {
-        for (int len : lengths) {
-            out.println();
-            ArrayBuilder.reset();
-            int[] golden = new int[len];
+    private static void testAndCheckRange(int len, long random) {
+        int[] golden = new int[len];
+
+        for (int m = 1; m < 2 * len; m *= 2) {
+            for (int i = 1; i <= len; i++) {
+                golden[i - 1] = i % m + m % i;
+            }
+            for (TypeConverter converter : TypeConverter.values()) {
+                out.println("Test #5: " + converter +
+                   ", len = " + len + ", m = " + m);
+                Object convertedGolden = converter.convert(golden);
+                sortRange(convertedGolden, m);
+                sortEmpty(convertedGolden);
+            }
+        }
+        out.println();
+    }
+
+    private static void testAndCheckWithCheckSum(int len, long random) {
+        int[] golden = new int[len];
+
+        for (int m = 1; m < 2 * len; m *= 2) {
+            for (UnsortedBuilder builder : UnsortedBuilder.values()) {
+                builder.build(golden, m);
+                int[] test = golden.clone();
+
+                for (TypeConverter converter : TypeConverter.values()) {
+                    out.println("Test #1: " + converter + " " + builder +
+                       "random = " +  random + ", len = " + len +
+                       ", m = " + m);
+                    Object convertedGolden = converter.convert(golden);
+                    Object convertedTest = converter.convert(test);
+                    sort(convertedTest);
+                    checkWithCheckSum(convertedTest, convertedGolden);
+                }
+            }
+        }
+        out.println();
+    }
+
+    private static void testAndCheckWithScrambling(int len, long random) {
+        int[] golden = new int[len];
 
-            for (int m = 1; m < 2 * len; m *= 2) {
-                for (ArrayBuilder builder : ArrayBuilder.values()) {
-                    builder.build(golden, m);
-                    int[] test = golden.clone();
+        for (int m = 1; m <= 7; m++) {
+            if (m > len) {
+                break;
+            }
+            for (SortedBuilder builder : SortedBuilder.values()) {
+                builder.build(golden, m);
+                int[] test = golden.clone();
+                scramble(test);
+
+                for (TypeConverter converter : TypeConverter.values()) {
+                    out.println("Test #2: " + converter + " " + builder +
+                       "random = " +  random + ", len = " + len +
+                       ", m = " + m);
+                    Object convertedGolden = converter.convert(golden);
+                    Object convertedTest = converter.convert(test);
+                    sort(convertedTest);
+                    compare(convertedTest, convertedGolden);
+                }
+            }
+        }
+        out.println();
+    }
 
-                    for (Converter converter : Converter.values()) {
-                        out.println("Test: " + converter + " " + builder +
-                            "len = " + len + ", m = " + m);
-                        Object convertedGolden = converter.convert(golden);
-                        Object convertedTest = converter.convert(test);
-                        sort(convertedTest);
-                        checkWithCheckSum(convertedTest, convertedGolden);
+    private static void testAndCheckFloat(int len, long random) {
+        float[] golden = new float[len];
+        final int MAX = 10;
+        boolean newLine = false;
+
+        for (int a = 0; a <= MAX; a++) {
+            for (int g = 0; g <= MAX; g++) {
+                for (int z = 0; z <= MAX; z++) {
+                    for (int n = 0; n <= MAX; n++) {
+                        for (int p = 0; p <= MAX; p++) {
+                            if (a + g + z + n + p > len) {
+                                continue;
+                            }
+                            if (a + g + z + n + p < len) {
+                                continue;
+                            }
+                            for (FloatBuilder builder : FloatBuilder.values()) {
+                                out.println("Test #3: random = " + random +
+                                   ", len = " + len + ", a = " + a + ", g = " + g +
+                                   ", z = " + z + ", n = " + n + ", p = " + p);
+                                builder.build(golden, a, g, z, n, p);
+                                float[] test = golden.clone();
+                                scramble(test);
+                                // outArr(test);
+                                sort(test);
+                                // outArr(test);
+                                compare(test, golden, a, n, g);
+                            }
+                            newLine = true;
+                        }
                     }
                 }
             }
         }
+        if (newLine) {
+            out.println();
+        }
+    }
+
+    private static void testAndCheckDouble(int len, long random) {
+        double[] golden = new double[len];
+        final int MAX = 10;
+        boolean newLine = false;
+
+        for (int a = 0; a <= MAX; a++) {
+            for (int g = 0; g <= MAX; g++) {
+                for (int z = 0; z <= MAX; z++) {
+                    for (int n = 0; n <= MAX; n++) {
+                        for (int p = 0; p <= MAX; p++) {
+                            if (a + g + z + n + p > len) {
+                                continue;
+                            }
+                            if (a + g + z + n + p < len) {
+                                continue;
+                            }
+                            for (DoubleBuilder builder : DoubleBuilder.values()) {
+                                out.println("Test #4: random = " + random +
+                                   ", len = " + len + ", a = " + a + ", g = " + g +
+                                   ", z = " + z + ", n = " + n + ", p = " + p);
+                                builder.build(golden, a, g, z, n, p);
+                                double[] test = golden.clone();
+                                scramble(test);
+                                // outArr(test);
+                                sort(test);
+                                // outArr(test);
+                                compare(test, golden, a, n, g);
+                            }
+                            newLine = true;
+                        }
+                    }
+                }
+            }
+        }
+        if (newLine) {
+            out.println();
+        }
     }
 
-    static enum Converter {
+    private static void prepareSubArray(int[] a, int fromIndex, int toIndex, int m) {
+        for (int i = 0; i < fromIndex; i++) {
+            a[i] = 0xBABA;
+        }
+
+        for (int i = fromIndex; i < toIndex; i++) {
+            a[i] = -i + m;
+        }
+
+        for (int i = toIndex; i < a.length; i++) {
+            a[i] = 0xDEDA;
+        }
+    }
+
+    private static void scramble(int[] a) {
+        int length = a.length;
+
+        for (int i = 0; i < length * 7; i++) {
+            swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
+        }
+    }
+
+    private static void scramble(float[] a) {
+        int length = a.length;
+
+        for (int i = 0; i < length * 7; i++) {
+            swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
+        }
+    }
+
+    private static void scramble(double[] a) {
+        int length = a.length;
+
+        for (int i = 0; i < length * 7; i++) {
+            swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
+        }
+    }
+
+    private static void swap(int[] a, int i, int j) {
+        int t = a[i];
+        a[i] = a[j];
+        a[j] = t;
+    }
+
+    private static void swap(float[] a, int i, int j) {
+        float t = a[i];
+        a[i] = a[j];
+        a[j] = t;
+    }
+
+    private static void swap(double[] a, int i, int j) {
+        double t = a[i];
+        a[i] = a[j];
+        a[j] = t;
+    }
+
+    private static enum TypeConverter {
         INT {
             Object convert(int[] a) {
-                return a;
+                return a.clone();
             }
         },
         LONG {
@@ -95,7 +339,7 @@
                 long[] b = new long[a.length];
 
                 for (int i = 0; i < a.length; i++) {
-                    b[i] = (int) a[i];
+                    b[i] = (long) a[i];
                 }
                 return b;
             }
@@ -163,7 +407,161 @@
         }
     }
 
-    static enum ArrayBuilder {
+    private static enum FloatBuilder {
+        SIMPLE {
+            void build(float[] x, int a, int g, int z, int n, int p) {
+                int fromIndex = 0;
+                float negativeValue = -ourRandom.nextFloat();
+                float positiveValue =  ourRandom.nextFloat();
+
+                writeValue(x, negativeValue, fromIndex, n);
+                fromIndex += n;
+
+                writeValue(x, -0.0f, fromIndex, g);
+                fromIndex += g;
+
+                writeValue(x, 0.0f, fromIndex, z);
+                fromIndex += z;
+
+                writeValue(x, positiveValue, fromIndex, p);
+                fromIndex += p;
+
+                writeValue(x, Float.NaN, fromIndex, a);
+            }
+        };
+
+        abstract void build(float[] x, int a, int g, int z, int n, int p);
+    }
+
+    private static enum DoubleBuilder {
+        SIMPLE {
+            void build(double[] x, int a, int g, int z, int n, int p) {
+                int fromIndex = 0;
+                double negativeValue = -ourRandom.nextFloat();
+                double positiveValue =  ourRandom.nextFloat();
+
+                writeValue(x, negativeValue, fromIndex, n);
+                fromIndex += n;
+
+                writeValue(x, -0.0d, fromIndex, g);
+                fromIndex += g;
+
+                writeValue(x, 0.0d, fromIndex, z);
+                fromIndex += z;
+
+                writeValue(x, positiveValue, fromIndex, p);
+                fromIndex += p;
+
+                writeValue(x, Double.NaN, fromIndex, a);
+            }
+        };
+
+        abstract void build(double[] x, int a, int g, int z, int n, int p);
+    }
+
+    private static void writeValue(float[] a, float value, int fromIndex, int count) {
+        for (int i = fromIndex; i < fromIndex + count; i++) {
+            a[i] = value;
+        }
+    }
+
+    private static void compare(float[] a, float[] b, int numNaN, int numNeg, int numNegZero) {
+        for (int i = a.length - numNaN; i < a.length; i++) {
+            if (a[i] == a[i]) {
+                failed("On position " + i + " must be NaN instead of " + a[i]);
+            }
+        }
+        final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f);
+
+        for (int i = numNeg; i < numNeg + numNegZero; i++) {
+            if (NEGATIVE_ZERO != Float.floatToIntBits(a[i])) {
+                failed("On position " + i + " must be -0.0f instead of " + a[i]);
+            }
+        }
+        for (int i = 0; i < a.length - numNaN; i++) {
+            if (a[i] != b[i]) {
+                failed(i, "" + a[i], "" + b[i]);
+            }
+        }
+    }
+
+    private static void writeValue(double[] a, double value, int fromIndex, int count) {
+        for (int i = fromIndex; i < fromIndex + count; i++) {
+            a[i] = value;
+        }
+    }
+
+    private static void compare(double[] a, double[] b, int numNaN, int numNeg, int numNegZero) {
+        for (int i = a.length - numNaN; i < a.length; i++) {
+            if (a[i] == a[i]) {
+                failed("On position " + i + " must be NaN instead of " + a[i]);
+            }
+        }
+        final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d);
+
+        for (int i = numNeg; i < numNeg + numNegZero; i++) {
+            if (NEGATIVE_ZERO != Double.doubleToLongBits(a[i])) {
+                failed("On position " + i + " must be -0.0d instead of " + a[i]);
+            }
+        }
+        for (int i = 0; i < a.length - numNaN; i++) {
+            if (a[i] != b[i]) {
+                failed(i, "" + a[i], "" + b[i]);
+            }
+        }
+    }
+
+    private static enum SortedBuilder {
+        REPEATED {
+            void build(int[] a, int m) {
+                int period = a.length / m;
+                int i = 0;
+                int k = 0;
+
+                while (true) {
+                    for (int t = 1; t <= period; t++) {
+                        if (i >= a.length) {
+                            return;
+                        }
+                        a[i++] = k;
+                    }
+                    if (i >= a.length) {
+                        return;
+                    }
+                    k++;
+                }
+            }
+        },
+
+        ORGAN_PIPES {
+            void build(int[] a, int m) {
+                int i = 0;
+                int k = m;
+
+                while (true) {
+                    for (int t = 1; t <= m; t++) {
+                        if (i >= a.length) {
+                            return;
+                        }
+                        a[i++] = k;
+                    }
+                }
+            }
+        };
+
+        abstract void build(int[] a, int m);
+
+        @Override public String toString() {
+            String name = name();
+
+            for (int i = name.length(); i < 12; i++) {
+                name += " ";
+            }
+            return name;
+        }
+    }
+
+    private static enum UnsortedBuilder {
         RANDOM {
             void build(int[] a, int m) {
                 for (int i = 0; i < a.length; i++) {
@@ -268,41 +666,53 @@
 
         abstract void build(int[] a, int m);
 
-        static void reset() {
-            ourRandom = new Random(666);
-            ourFirst = 0;
-            ourSecond = 0;
-        }
-
         @Override public String toString() {
             String name = name();
+
             for (int i = name.length(); i < 12; i++) {
                 name += " ";
             }
             return name;
         }
-
-        private static int ourFirst;
-        private static int ourSecond;
-        private static Random ourRandom = new Random(666);
     }
 
-    static void checkWithCheckSum(Object test, Object golden) {
+    private static void compare(Object test, Object golden) {
+        if (test instanceof int[]) {
+            compare((int[]) test, (int[]) golden);
+        } else if (test instanceof long[]) {
+            compare((long[]) test, (long[]) golden);
+        } else if (test instanceof short[]) {
+            compare((short[]) test, (short[]) golden);
+        } else if (test instanceof byte[]) {
+            compare((byte[]) test, (byte[]) golden);
+        } else if (test instanceof char[]) {
+            compare((char[]) test, (char[]) golden);
+        } else if (test instanceof float[]) {
+            compare((float[]) test, (float[]) golden);
+        } else if (test instanceof double[]) {
+            compare((double[]) test, (double[]) golden);
+        } else {
+            failed("Unknow type of array: " + test + " of class " +
+                test.getClass().getName());
+        }
+    }
+
+    private static void checkWithCheckSum(Object test, Object golden) {
         checkSorted(test);
         checkCheckSum(test, golden);
     }
 
-    static void failed(String message) {
-        err.format("***FAILED: %s%%n", message);
+    private static void failed(String message) {
+        err.format("\n*** FAILED: %s\n\n", message);
         throw new RuntimeException("Test failed - see log file for details");
     }
 
-    static void failed(int index, String value1, String value2) {
+    private static void failed(int index, String value1, String value2) {
         failed("Array is not sorted at " + index + "-th position: " + value1 +
                " and " + value2);
     }
 
-    static void checkSorted(Object object) {
+    private static void checkSorted(Object object) {
         if (object instanceof int[]) {
             checkSorted((int[]) object);
         } else if (object instanceof long[]) {
@@ -323,31 +733,63 @@
         }
     }
 
-    static void checkSorted(int[] a) {
-        for (int i = 0; i < a.length - 1; i++) {
-            if (a[i] > a[i + 1]) {
-                failed(i, "" + a[i], "" + a[i + 1]);
+    private static void compare(int[] a, int[] b) {
+        for (int i = 0; i < a.length; i++) {
+            if (a[i] != b[i]) {
+                failed(i, "" + a[i], "" + b[i]);
+            }
+        }
+    }
+
+    private static void compare(long[] a, long[] b) {
+        for (int i = 0; i < a.length; i++) {
+            if (a[i] != b[i]) {
+                failed(i, "" + a[i], "" + b[i]);
+            }
+        }
+    }
+
+    private static void compare(short[] a, short[] b) {
+        for (int i = 0; i < a.length; i++) {
+            if (a[i] != b[i]) {
+                failed(i, "" + a[i], "" + b[i]);
             }
         }
     }
 
-    static void checkSorted(long[] a) {
-        for (int i = 0; i < a.length - 1; i++) {
-            if (a[i] > a[i + 1]) {
-                failed(i, "" + a[i], "" + a[i + 1]);
+    private static void compare(byte[] a, byte[] b) {
+        for (int i = 0; i < a.length; i++) {
+            if (a[i] != b[i]) {
+                failed(i, "" + a[i], "" + b[i]);
+            }
+        }
+    }
+
+    private static void compare(char[] a, char[] b) {
+        for (int i = 0; i < a.length; i++) {
+            if (a[i] != b[i]) {
+                failed(i, "" + a[i], "" + b[i]);
             }
         }
     }
 
-    static void checkSorted(short[] a) {
-        for (int i = 0; i < a.length - 1; i++) {
-            if (a[i] > a[i + 1]) {
-                failed(i, "" + a[i], "" + a[i + 1]);
+    private static void compare(float[] a, float[] b) {
+        for (int i = 0; i < a.length; i++) {
+            if (a[i] != b[i]) {
+                failed(i, "" + a[i], "" + b[i]);
             }
         }
     }
 
-    static void checkSorted(byte[] a) {
+    private static void compare(double[] a, double[] b) {
+        for (int i = 0; i < a.length; i++) {
+            if (a[i] != b[i]) {
+                failed(i, "" + a[i], "" + b[i]);
+            }
+        }
+    }
+
+    private static void checkSorted(int[] a) {
         for (int i = 0; i < a.length - 1; i++) {
             if (a[i] > a[i + 1]) {
                 failed(i, "" + a[i], "" + a[i + 1]);
@@ -355,7 +797,7 @@
         }
     }
 
-    static void checkSorted(char[] a) {
+    private static void checkSorted(long[] a) {
         for (int i = 0; i < a.length - 1; i++) {
             if (a[i] > a[i + 1]) {
                 failed(i, "" + a[i], "" + a[i + 1]);
@@ -363,7 +805,15 @@
         }
     }
 
-    static void checkSorted(float[] a) {
+    private static void checkSorted(short[] a) {
+        for (int i = 0; i < a.length - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+    }
+
+    private static void checkSorted(byte[] a) {
         for (int i = 0; i < a.length - 1; i++) {
             if (a[i] > a[i + 1]) {
                 failed(i, "" + a[i], "" + a[i + 1]);
@@ -371,7 +821,15 @@
         }
     }
 
-    static void checkSorted(double[] a) {
+    private static void checkSorted(char[] a) {
+        for (int i = 0; i < a.length - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+    }
+
+    private static void checkSorted(float[] a) {
         for (int i = 0; i < a.length - 1; i++) {
             if (a[i] > a[i + 1]) {
                 failed(i, "" + a[i], "" + a[i + 1]);
@@ -379,13 +837,21 @@
         }
     }
 
-    static void checkCheckSum(Object test, Object golden) {
+    private static void checkSorted(double[] a) {
+        for (int i = 0; i < a.length - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+    }
+
+    private static void checkCheckSum(Object test, Object golden) {
         if (checkSum(test) != checkSum(golden)) {
             failed("Original and sorted arrays seems not identical");
         }
     }
 
-    static int checkSum(Object object) {
+    private static int checkSum(Object object) {
         if (object instanceof int[]) {
             return checkSum((int[]) object);
         } else if (object instanceof long[]) {
@@ -407,70 +873,70 @@
         }
     }
 
-    static int checkSum(int[] a) {
-        int checkSum = 0;
+    private static int checkSum(int[] a) {
+        int checkXorSum = 0;
 
         for (int e : a) {
-            checkSum ^= e; // xor
+            checkXorSum ^= e;
         }
-        return checkSum;
+        return checkXorSum;
     }
 
-    static int checkSum(long[] a) {
-        long checkSum = 0;
+    private static int checkSum(long[] a) {
+        long checkXorSum = 0;
 
         for (long e : a) {
-            checkSum ^= e; // xor
+            checkXorSum ^= e;
         }
-        return (int) checkSum;
+        return (int) checkXorSum;
     }
 
-    static int checkSum(short[] a) {
-        short checkSum = 0;
+    private static int checkSum(short[] a) {
+        short checkXorSum = 0;
 
         for (short e : a) {
-            checkSum ^= e; // xor
+            checkXorSum ^= e;
         }
-        return (int) checkSum;
+        return (int) checkXorSum;
     }
 
-    static int checkSum(byte[] a) {
-        byte checkSum = 0;
+    private static int checkSum(byte[] a) {
+        byte checkXorSum = 0;
 
         for (byte e : a) {
-            checkSum ^= e; // xor
+            checkXorSum ^= e;
         }
-        return (int) checkSum;
+        return (int) checkXorSum;
     }
 
-    static int checkSum(char[] a) {
-        char checkSum = 0;
+    private static int checkSum(char[] a) {
+        char checkXorSum = 0;
 
         for (char e : a) {
-            checkSum ^= e; // xor
+            checkXorSum ^= e;
         }
-        return (int) checkSum;
+        return (int) checkXorSum;
     }
 
-    static int checkSum(float[] a) {
-        int checkSum = 0;
+    private static int checkSum(float[] a) {
+        int checkXorSum = 0;
 
         for (float e : a) {
-            checkSum ^= (int) e; // xor
+            checkXorSum ^= (int) e;
         }
-        return checkSum;
+        return checkXorSum;
     }
 
-    static int checkSum(double[] a) {
-        int checkSum = 0;
+    private static int checkSum(double[] a) {
+        int checkXorSum = 0;
 
         for (double e : a) {
-            checkSum ^= (int) e; // xor
+            checkXorSum ^= (int) e;
         }
-        return checkSum;
+        return checkXorSum;
     }
 
-    static void sort(Object object) {
+    private static void sort(Object object) {
         if (object instanceof int[]) {
             Arrays.sort((int[]) object);
         } else if (object instanceof long[]) {
@@ -490,4 +956,485 @@
                 object.getClass().getName());
         }
     }
+
+    private static void sortSubArray(Object object, int fromIndex, int toIndex) {
+        if (object instanceof int[]) {
+            Arrays.sort((int[]) object, fromIndex, toIndex);
+        } else if (object instanceof long[]) {
+            Arrays.sort((long[]) object, fromIndex, toIndex);
+        } else if (object instanceof short[]) {
+            Arrays.sort((short[]) object, fromIndex, toIndex);
+        } else if (object instanceof byte[]) {
+            Arrays.sort((byte[]) object, fromIndex, toIndex);
+        } else if (object instanceof char[]) {
+            Arrays.sort((char[]) object, fromIndex, toIndex);
+        } else if (object instanceof float[]) {
+            Arrays.sort((float[]) object, fromIndex, toIndex);
+        } else if (object instanceof double[]) {
+            Arrays.sort((double[]) object, fromIndex, toIndex);
+        } else {
+            failed("Unknow type of array: " + object + " of class " +
+                object.getClass().getName());
+        }
+    }
+
+    private static void checkSubArray(Object object, int fromIndex, int toIndex, int m) {
+        if (object instanceof int[]) {
+            checkSubArray((int[]) object, fromIndex, toIndex, m);
+        } else if (object instanceof long[]) {
+            checkSubArray((long[]) object, fromIndex, toIndex, m);
+        } else if (object instanceof short[]) {
+            checkSubArray((short[]) object, fromIndex, toIndex, m);
+        } else if (object instanceof byte[]) {
+            checkSubArray((byte[]) object, fromIndex, toIndex, m);
+        } else if (object instanceof char[]) {
+            checkSubArray((char[]) object, fromIndex, toIndex, m);
+        } else if (object instanceof float[]) {
+            checkSubArray((float[]) object, fromIndex, toIndex, m);
+        } else if (object instanceof double[]) {
+            checkSubArray((double[]) object, fromIndex, toIndex, m);
+        } else {
+            failed("Unknow type of array: " + object + " of class " +
+                object.getClass().getName());
+        }
+    }
+
+    private static void checkSubArray(int[] a, int fromIndex, int toIndex, int m) {
+        for (int i = 0; i < fromIndex; i++) {
+            if (a[i] != 0xBABA) {
+                failed("Range sort changes left element on position " + i +
+                    ": " + a[i] + ", must be " + 0xBABA);
+            }
+        }
+
+        for (int i = fromIndex; i < toIndex - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+
+        for (int i = toIndex; i < a.length; i++) {
+            if (a[i] != 0xDEDA) {
+                failed("Range sort changes right element on position " + i +
+                    ": " + a[i] + ", must be " + 0xDEDA);
+            }
+        }
+    }
+
+    private static void checkSubArray(byte[] a, int fromIndex, int toIndex, int m) {
+        for (int i = 0; i < fromIndex; i++) {
+            if (a[i] != (byte) 0xBABA) {
+                failed("Range sort changes left element on position " + i +
+                    ": " + a[i] + ", must be " + 0xBABA);
+            }
+        }
+
+        for (int i = fromIndex; i < toIndex - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+
+        for (int i = toIndex; i < a.length; i++) {
+            if (a[i] != (byte) 0xDEDA) {
+                failed("Range sort changes right element on position " + i +
+                    ": " + a[i] + ", must be " + 0xDEDA);
+            }
+        }
+    }
+
+    private static void checkSubArray(long[] a, int fromIndex, int toIndex, int m) {
+        for (int i = 0; i < fromIndex; i++) {
+            if (a[i] != (long) 0xBABA) {
+                failed("Range sort changes left element on position " + i +
+                    ": " + a[i] + ", must be " + 0xBABA);
+            }
+        }
+
+        for (int i = fromIndex; i < toIndex - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+
+        for (int i = toIndex; i < a.length; i++) {
+            if (a[i] != (long) 0xDEDA) {
+                failed("Range sort changes right element on position " + i +
+                    ": " + a[i] + ", must be " + 0xDEDA);
+            }
+        }
+    }
+
+    private static void checkSubArray(char[] a, int fromIndex, int toIndex, int m) {
+        for (int i = 0; i < fromIndex; i++) {
+            if (a[i] != (char) 0xBABA) {
+                failed("Range sort changes left element on position " + i +
+                    ": " + a[i] + ", must be " + 0xBABA);
+            }
+        }
+
+        for (int i = fromIndex; i < toIndex - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+
+        for (int i = toIndex; i < a.length; i++) {
+            if (a[i] != (char) 0xDEDA) {
+                failed("Range sort changes right element on position " + i +
+                    ": " + a[i] + ", must be " + 0xDEDA);
+            }
+        }
+    }
+
+    private static void checkSubArray(short[] a, int fromIndex, int toIndex, int m) {
+        for (int i = 0; i < fromIndex; i++) {
+            if (a[i] != (short) 0xBABA) {
+                failed("Range sort changes left element on position " + i +
+                    ": " + a[i] + ", must be " + 0xBABA);
+            }
+        }
+
+        for (int i = fromIndex; i < toIndex - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+
+        for (int i = toIndex; i < a.length; i++) {
+            if (a[i] != (short) 0xDEDA) {
+                failed("Range sort changes right element on position " + i +
+                    ": " + a[i] + ", must be " + 0xDEDA);
+            }
+        }
+    }
+
+    private static void checkSubArray(float[] a, int fromIndex, int toIndex, int m) {
+        for (int i = 0; i < fromIndex; i++) {
+            if (a[i] != (float) 0xBABA) {
+                failed("Range sort changes left element on position " + i +
+                    ": " + a[i] + ", must be " + 0xBABA);
+            }
+        }
+
+        for (int i = fromIndex; i < toIndex - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+
+        for (int i = toIndex; i < a.length; i++) {
+            if (a[i] != (float) 0xDEDA) {
+                failed("Range sort changes right element on position " + i +
+                    ": " + a[i] + ", must be " + 0xDEDA);
+            }
+        }
+    }
+
+    private static void checkSubArray(double[] a, int fromIndex, int toIndex, int m) {
+        for (int i = 0; i < fromIndex; i++) {
+            if (a[i] != (double) 0xBABA) {
+                failed("Range sort changes left element on position " + i +
+                    ": " + a[i] + ", must be " + 0xBABA);
+            }
+        }
+
+        for (int i = fromIndex; i < toIndex - 1; i++) {
+            if (a[i] > a[i + 1]) {
+                failed(i, "" + a[i], "" + a[i + 1]);
+            }
+        }
+
+        for (int i = toIndex; i < a.length; i++) {
+            if (a[i] != (double) 0xDEDA) {
+                failed("Range sort changes right element on position " + i +
+                    ": " + a[i] + ", must be " + 0xDEDA);
+            }
+        }
+    }
+
+    private static void sortRange(Object object, int m) {
+        if (object instanceof int[]) {
+            sortRange((int[]) object, m);
+        } else if (object instanceof long[]) {
+            sortRange((long[]) object, m);
+        } else if (object instanceof short[]) {
+            sortRange((short[]) object, m);
+        } else if (object instanceof byte[]) {
+            sortRange((byte[]) object, m);
+        } else if (object instanceof char[]) {
+            sortRange((char[]) object, m);
+        } else if (object instanceof float[]) {
+            sortRange((float[]) object, m);
+        } else if (object instanceof double[]) {
+            sortRange((double[]) object, m);
+        } else {
+            failed("Unknow type of array: " + object + " of class " +
+                object.getClass().getName());
+        }
+    }
+
+    private static void sortEmpty(Object object) {
+        if (object instanceof int[]) {
+            Arrays.sort(new int [] {});
+        } else if (object instanceof long[]) {
+            Arrays.sort(new long [] {});
+        } else if (object instanceof short[]) {
+            Arrays.sort(new short [] {});
+        } else if (object instanceof byte[]) {
+            Arrays.sort(new byte [] {});
+        } else if (object instanceof char[]) {
+            Arrays.sort(new char [] {});
+        } else if (object instanceof float[]) {
+            Arrays.sort(new float [] {});
+        } else if (object instanceof double[]) {
+            Arrays.sort(new double [] {});
+        } else {
+            failed("Unknow type of array: " + object + " of class " +
+                object.getClass().getName());
+        }
+    }
+
+    private static void sortRange(int[] a, int m) {
+        try {
+            Arrays.sort(a, m + 1, m);
+
+            failed("Sort does not throw IllegalArgumentException " +
+                " as expected: fromIndex = " + (m + 1) +
+                " toIndex = " + m);
+        }
+        catch (IllegalArgumentException iae) {
+            try {
+                Arrays.sort(a, -m, a.length);
+
+                failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                    " as expected: fromIndex = " + (-m));
+            }
+            catch (ArrayIndexOutOfBoundsException aoe) {
+                try {
+                    Arrays.sort(a, 0, a.length + m);
+
+                    failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                        " as expected: toIndex = " + (a.length + m));
+                }
+                catch (ArrayIndexOutOfBoundsException aie) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private static void sortRange(long[] a, int m) {
+        try {
+            Arrays.sort(a, m + 1, m);
+
+            failed("Sort does not throw IllegalArgumentException " +
+                " as expected: fromIndex = " + (m + 1) +
+                " toIndex = " + m);
+        }
+        catch (IllegalArgumentException iae) {
+            try {
+                Arrays.sort(a, -m, a.length);
+
+                failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                    " as expected: fromIndex = " + (-m));
+            }
+            catch (ArrayIndexOutOfBoundsException aoe) {
+                try {
+                    Arrays.sort(a, 0, a.length + m);
+
+                    failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                        " as expected: toIndex = " + (a.length + m));
+                }
+                catch (ArrayIndexOutOfBoundsException aie) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private static void sortRange(byte[] a, int m) {
+        try {
+            Arrays.sort(a, m + 1, m);
+
+            failed("Sort does not throw IllegalArgumentException " +
+                " as expected: fromIndex = " + (m + 1) +
+                " toIndex = " + m);
+        }
+        catch (IllegalArgumentException iae) {
+            try {
+                Arrays.sort(a, -m, a.length);
+
+                failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                    " as expected: fromIndex = " + (-m));
+            }
+            catch (ArrayIndexOutOfBoundsException aoe) {
+                try {
+                    Arrays.sort(a, 0, a.length + m);
+
+                    failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                        " as expected: toIndex = " + (a.length + m));
+                }
+                catch (ArrayIndexOutOfBoundsException aie) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private static void sortRange(short[] a, int m) {
+        try {
+            Arrays.sort(a, m + 1, m);
+
+            failed("Sort does not throw IllegalArgumentException " +
+                " as expected: fromIndex = " + (m + 1) +
+                " toIndex = " + m);
+        }
+        catch (IllegalArgumentException iae) {
+            try {
+                Arrays.sort(a, -m, a.length);
+
+                failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                    " as expected: fromIndex = " + (-m));
+            }
+            catch (ArrayIndexOutOfBoundsException aoe) {
+                try {
+                    Arrays.sort(a, 0, a.length + m);
+
+                    failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                        " as expected: toIndex = " + (a.length + m));
+                }
+                catch (ArrayIndexOutOfBoundsException aie) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private static void sortRange(char[] a, int m) {
+        try {
+            Arrays.sort(a, m + 1, m);
+
+            failed("Sort does not throw IllegalArgumentException " +
+                " as expected: fromIndex = " + (m + 1) +
+                " toIndex = " + m);
+        }
+        catch (IllegalArgumentException iae) {
+            try {
+                Arrays.sort(a, -m, a.length);
+
+                failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                    " as expected: fromIndex = " + (-m));
+            }
+            catch (ArrayIndexOutOfBoundsException aoe) {
+                try {
+                    Arrays.sort(a, 0, a.length + m);
+
+                    failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                        " as expected: toIndex = " + (a.length + m));
+                }
+                catch (ArrayIndexOutOfBoundsException aie) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private static void sortRange(float[] a, int m) {
+        try {
+            Arrays.sort(a, m + 1, m);
+
+            failed("Sort does not throw IllegalArgumentException " +
+                " as expected: fromIndex = " + (m + 1) +
+                " toIndex = " + m);
+        }
+        catch (IllegalArgumentException iae) {
+            try {
+                Arrays.sort(a, -m, a.length);
+
+                failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                    " as expected: fromIndex = " + (-m));
+            }
+            catch (ArrayIndexOutOfBoundsException aoe) {
+                try {
+                    Arrays.sort(a, 0, a.length + m);
+
+                    failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                        " as expected: toIndex = " + (a.length + m));
+                }
+                catch (ArrayIndexOutOfBoundsException aie) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private static void sortRange(double[] a, int m) {
+        try {
+            Arrays.sort(a, m + 1, m);
+
+            failed("Sort does not throw IllegalArgumentException " +
+                " as expected: fromIndex = " + (m + 1) +
+                " toIndex = " + m);
+        }
+        catch (IllegalArgumentException iae) {
+            try {
+                Arrays.sort(a, -m, a.length);
+
+                failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                    " as expected: fromIndex = " + (-m));
+            }
+            catch (ArrayIndexOutOfBoundsException aoe) {
+                try {
+                    Arrays.sort(a, 0, a.length + m);
+
+                    failed("Sort does not throw ArrayIndexOutOfBoundsException " +
+                        " as expected: toIndex = " + (a.length + m));
+                }
+                catch (ArrayIndexOutOfBoundsException aie) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private static void prepareRandom(int[] a) {
+        for (int i = 0; i < a.length; i++) {
+            a[i] = ourRandom.nextInt();
+        }
+    }
+
+    private static void reset(long seed) {
+        ourRandom = new Random(seed);
+        ourFirst = 0;
+        ourSecond = 0;
+    }
+
+    private static void outArr(int[] a) {
+        for (int i = 0; i < a.length; i++) {
+            out.print(a[i] + " ");
+        }
+        out.println();
+        out.println();
+    }
+
+    private static void outArr(float[] a) {
+        for (int i = 0; i < a.length; i++) {
+            out.print(a[i] + " ");
+        }
+        out.println();
+        out.println();
+    }
+
+    private static void outArr(double[] a) {
+        for (int i = 0; i < a.length; i++) {
+            out.print(a[i] + " ");
+        }
+        out.println();
+        out.println();
+    }
+
+    private static int ourFirst;
+    private static int ourSecond;
+    private static Random ourRandom;
 }
--- a/test/java/util/Collection/BiggernYours.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/Collection/BiggernYours.java	Thu Nov 12 23:04:42 2009 +0000
@@ -178,10 +178,10 @@
             new ConcurrentLinkedQueue() {
                 public int size() {return randomize(super.size());}});
 
-//         testCollections(
-//             new LinkedTransferQueue(),
-//             new LinkedTransferQueue() {
-//                 public int size() {return randomize(super.size());}});
+        testCollections(
+            new LinkedTransferQueue(),
+            new LinkedTransferQueue() {
+                public int size() {return randomize(super.size());}});
 
         testCollections(
             new LinkedBlockingQueue(),
--- a/test/java/util/Collection/IteratorAtEnd.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/Collection/IteratorAtEnd.java	Thu Nov 12 23:04:42 2009 +0000
@@ -49,7 +49,7 @@
         testCollection(new LinkedBlockingQueue());
         testCollection(new ArrayBlockingQueue(100));
         testCollection(new ConcurrentLinkedQueue());
-//         testCollection(new LinkedTransferQueue());
+        testCollection(new LinkedTransferQueue());
 
         testMap(new HashMap());
         testMap(new Hashtable());
--- a/test/java/util/Collection/MOAT.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/Collection/MOAT.java	Thu Nov 12 23:04:42 2009 +0000
@@ -76,7 +76,7 @@
         testCollection(new LinkedBlockingQueue<Integer>(20));
         testCollection(new LinkedBlockingDeque<Integer>(20));
         testCollection(new ConcurrentLinkedQueue<Integer>());
-//         testCollection(new LinkedTransferQueue<Integer>());
+        testCollection(new LinkedTransferQueue<Integer>());
         testCollection(new ConcurrentSkipListSet<Integer>());
         testCollection(Arrays.asList(new Integer(42)));
         testCollection(Arrays.asList(1,2,3));
@@ -421,8 +421,11 @@
 
     private static void testQueue(Queue<Integer> q) {
         q.clear();
-        for (int i = 0; i < 5; i++)
+        for (int i = 0; i < 5; i++) {
+            testQueueAddRemove(q, null);
+            testQueueAddRemove(q, 537);
             q.add(i);
+        }
         equal(q.size(), 5);
         checkFunctionalInvariants(q);
         q.poll();
@@ -435,6 +438,216 @@
         }
     }
 
+    private static void testQueueAddRemove(final Queue<Integer> q,
+                                           final Integer e) {
+        final List<Integer> originalContents = new ArrayList<Integer>(q);
+        final boolean isEmpty = q.isEmpty();
+        final boolean isList = (q instanceof List);
+        final List asList = isList ? (List) q : null;
+        check(!q.contains(e));
+        try {
+            q.add(e);
+        } catch (NullPointerException npe) {
+            check(e == null);
+            return;                     // Null elements not supported
+        }
+        check(q.contains(e));
+        check(q.remove(e));
+        check(!q.contains(e));
+        equal(new ArrayList<Integer>(q), originalContents);
+
+        if (q instanceof Deque<?>) {
+            final Deque<Integer> deq = (Deque<Integer>) q;
+            final List<Integer> singleton = Collections.singletonList(e);
+
+            // insert, query, remove element at head
+            if (isEmpty) {
+                THROWS(NoSuchElementException.class,
+                       new Fun(){void f(){ deq.getFirst(); }},
+                       new Fun(){void f(){ deq.element(); }},
+                       new Fun(){void f(){ deq.iterator().next(); }});
+                check(deq.peekFirst() == null);
+                check(deq.peek() == null);
+            } else {
+                check(deq.getFirst() != e);
+                check(deq.element() != e);
+                check(deq.iterator().next() != e);
+                check(deq.peekFirst() != e);
+                check(deq.peek() != e);
+            }
+            check(!deq.contains(e));
+            check(!deq.removeFirstOccurrence(e));
+            check(!deq.removeLastOccurrence(e));
+            if (isList) {
+                check(asList.indexOf(e) == -1);
+                check(asList.lastIndexOf(e) == -1);
+            }
+            switch (rnd.nextInt(isList ? 4 : 3)) {
+            case 0: deq.addFirst(e); break;
+            case 1: check(deq.offerFirst(e)); break;
+            case 2: deq.push(e); break;
+            case 3: asList.add(0, e); break;
+            default: throw new AssertionError();
+            }
+            check(deq.peekFirst() == e);
+            check(deq.getFirst() == e);
+            check(deq.element() == e);
+            check(deq.peek() == e);
+            check(deq.iterator().next() == e);
+            check(deq.contains(e));
+            if (isList) {
+                check(asList.get(0) == e);
+                check(asList.indexOf(e) == 0);
+                check(asList.lastIndexOf(e) == 0);
+                check(asList.subList(0, 1).equals(singleton));
+            }
+            switch (rnd.nextInt(isList ? 11 : 9)) {
+            case 0: check(deq.pollFirst() == e); break;
+            case 1: check(deq.removeFirst() == e); break;
+            case 2: check(deq.remove() == e); break;
+            case 3: check(deq.pop() == e); break;
+            case 4: check(deq.removeFirstOccurrence(e)); break;
+            case 5: check(deq.removeLastOccurrence(e)); break;
+            case 6: check(deq.remove(e)); break;
+            case 7: check(deq.removeAll(singleton)); break;
+            case 8: Iterator it = deq.iterator(); it.next(); it.remove(); break;
+            case 9: asList.remove(0); break;
+            case 10: asList.subList(0, 1).clear(); break;
+            default: throw new AssertionError();
+            }
+            if (isEmpty) {
+                THROWS(NoSuchElementException.class,
+                       new Fun(){void f(){ deq.getFirst(); }},
+                       new Fun(){void f(){ deq.element(); }},
+                       new Fun(){void f(){ deq.iterator().next(); }});
+                check(deq.peekFirst() == null);
+                check(deq.peek() == null);
+            } else {
+                check(deq.getFirst() != e);
+                check(deq.element() != e);
+                check(deq.iterator().next() != e);
+                check(deq.peekFirst() != e);
+                check(deq.peek() != e);
+            }
+            check(!deq.contains(e));
+            check(!deq.removeFirstOccurrence(e));
+            check(!deq.removeLastOccurrence(e));
+            if (isList) {
+                check(isEmpty || asList.get(0) != e);
+                check(asList.indexOf(e) == -1);
+                check(asList.lastIndexOf(e) == -1);
+            }
+            equal(new ArrayList<Integer>(deq), originalContents);
+
+            // insert, query, remove element at tail
+            if (isEmpty) {
+                check(deq.peekLast() == null);
+                THROWS(NoSuchElementException.class,
+                       new Fun(){void f(){ deq.getLast(); }});
+            } else {
+                check(deq.peekLast() != e);
+                check(deq.getLast() != e);
+            }
+            switch (rnd.nextInt(isList ? 6 : 4)) {
+            case 0: deq.addLast(e); break;
+            case 1: check(deq.offerLast(e)); break;
+            case 2: check(deq.add(e)); break;
+            case 3: deq.addAll(singleton); break;
+            case 4: asList.addAll(deq.size(), singleton); break;
+            case 5: asList.add(deq.size(), e); break;
+            default: throw new AssertionError();
+            }
+            check(deq.peekLast() == e);
+            check(deq.getLast() == e);
+            check(deq.contains(e));
+            if (isList) {
+                ListIterator it = asList.listIterator(asList.size());
+                check(it.previous() == e);
+                check(asList.get(asList.size() - 1) == e);
+                check(asList.indexOf(e) == asList.size() - 1);
+                check(asList.lastIndexOf(e) == asList.size() - 1);
+                int size = asList.size();
+                check(asList.subList(size - 1, size).equals(singleton));
+            }
+            switch (rnd.nextInt(isList ? 8 : 6)) {
+            case 0: check(deq.pollLast() == e); break;
+            case 1: check(deq.removeLast() == e); break;
+            case 2: check(deq.removeFirstOccurrence(e)); break;
+            case 3: check(deq.removeLastOccurrence(e)); break;
+            case 4: check(deq.remove(e)); break;
+            case 5: check(deq.removeAll(singleton)); break;
+            case 6: asList.remove(asList.size() - 1); break;
+            case 7:
+                ListIterator it = asList.listIterator(asList.size());
+                it.previous();
+                it.remove();
+                break;
+            default: throw new AssertionError();
+            }
+            if (isEmpty) {
+                check(deq.peekLast() == null);
+                THROWS(NoSuchElementException.class,
+                       new Fun(){void f(){ deq.getLast(); }});
+            } else {
+                check(deq.peekLast() != e);
+                check(deq.getLast() != e);
+            }
+            check(!deq.contains(e));
+            equal(new ArrayList<Integer>(deq), originalContents);
+
+            // Test operations on empty deque
+            switch (rnd.nextInt(isList ? 4 : 2)) {
+            case 0: deq.clear(); break;
+            case 1:
+                Iterator it = deq.iterator();
+                while (it.hasNext()) {
+                    it.next();
+                    it.remove();
+                }
+                break;
+            case 2: asList.subList(0, asList.size()).clear(); break;
+            case 3:
+                ListIterator lit = asList.listIterator(asList.size());
+                while (lit.hasPrevious()) {
+                    lit.previous();
+                    lit.remove();
+                }
+                break;
+            default: throw new AssertionError();
+            }
+            testEmptyCollection(deq);
+            check(!deq.iterator().hasNext());
+            if (isList) {
+                check(!asList.listIterator().hasPrevious());
+                THROWS(NoSuchElementException.class,
+                       new Fun(){void f(){ asList.listIterator().previous(); }});
+            }
+            THROWS(NoSuchElementException.class,
+                   new Fun(){void f(){ deq.iterator().next(); }},
+                   new Fun(){void f(){ deq.element(); }},
+                   new Fun(){void f(){ deq.getFirst(); }},
+                   new Fun(){void f(){ deq.getLast(); }},
+                   new Fun(){void f(){ deq.pop(); }},
+                   new Fun(){void f(){ deq.remove(); }},
+                   new Fun(){void f(){ deq.removeFirst(); }},
+                   new Fun(){void f(){ deq.removeLast(); }});
+
+            check(deq.poll() == null);
+            check(deq.pollFirst() == null);
+            check(deq.pollLast() == null);
+            check(deq.peek() == null);
+            check(deq.peekFirst() == null);
+            check(deq.peekLast() == null);
+            check(!deq.removeFirstOccurrence(e));
+            check(!deq.removeLastOccurrence(e));
+
+            check(deq.addAll(originalContents) == !isEmpty);
+            equal(new ArrayList<Integer>(deq), originalContents);
+            check(!deq.addAll(Collections.<Integer>emptyList()));
+            equal(new ArrayList<Integer>(deq), originalContents);
+        }
+    }
+
     private static void testQueueIteratorRemove(Queue<Integer> q) {
         System.err.printf("testQueueIteratorRemove %s%n",
                           q.getClass().getSimpleName());
--- a/test/java/util/Collections/CheckedNull.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/Collections/CheckedNull.java	Thu Nov 12 23:04:42 2009 +0000
@@ -52,7 +52,7 @@
 
         testMap(Collections.checkedMap(
                     new HashMap<String, String>(),
-                    String.class, String.class));;
+                    String.class, String.class));
     }
 
     ClassCastException cce(F f) {
--- a/test/java/util/Collections/RacingCollections.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/Collections/RacingCollections.java	Thu Nov 12 23:04:42 2009 +0000
@@ -234,7 +234,7 @@
         List<Queue<Integer>> list =
             new ArrayList<Queue<Integer>>(newConcurrentDeques());
         list.add(new LinkedBlockingQueue<Integer>(10));
-//         list.add(new LinkedTransferQueue<Integer>());
+        list.add(new LinkedTransferQueue<Integer>());
         return list;
     }
 
--- a/test/java/util/PriorityQueue/RemoveContains.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/PriorityQueue/RemoveContains.java	Thu Nov 12 23:04:42 2009 +0000
@@ -69,7 +69,7 @@
         test(new ArrayBlockingQueue<String>(10));
         test(new LinkedBlockingQueue<String>(10));
         test(new LinkedBlockingDeque<String>(10));
-//         test(new LinkedTransferQueue<String>());
+        test(new LinkedTransferQueue<String>());
         test(new ArrayDeque<String>(10));
 
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
--- a/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java	Thu Nov 12 23:04:42 2009 +0000
@@ -119,12 +119,36 @@
         }
     }
 
+    static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
+        LTQasSQ() { super(); }
+        public void put(T x) {
+            try { super.transfer(x); }
+            catch (InterruptedException ex) { throw new Error(); }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
+    static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
+        HalfSyncLTQ() { super(); }
+        public void put(T x) {
+            if (ThreadLocalRandom.current().nextBoolean())
+                super.put(x);
+            else {
+                try { super.transfer(x); }
+                catch (InterruptedException ex) { throw new Error(); }
+            }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
     static void oneTest(int pairs, int iters) throws Exception {
 
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), pairs, iters);
-//         oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
+        oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
+        oneRun(new LTQasSQ<Integer>(), pairs, iters);
+        oneRun(new HalfSyncLTQ<Integer>(), pairs, iters);
         oneRun(new SynchronousQueue<Integer>(), pairs, iters / 8);
 
         /* PriorityBlockingQueue is unbounded
--- a/test/java/util/concurrent/BlockingQueue/LastElement.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/BlockingQueue/LastElement.java	Thu Nov 12 23:04:42 2009 +0000
@@ -37,7 +37,7 @@
         testQueue(new LinkedBlockingDeque<Integer>());
         testQueue(new ArrayBlockingQueue<Integer>(10, true));
         testQueue(new ArrayBlockingQueue<Integer>(10, false));
-//         testQueue(new LinkedTransferQueue<Integer>());
+        testQueue(new LinkedTransferQueue<Integer>());
 
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
         if (failed > 0) throw new Exception("Some tests failed");
--- a/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java	Thu Nov 12 23:04:42 2009 +0000
@@ -87,11 +87,35 @@
             throw new Error();
    }
 
+    static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
+        LTQasSQ() { super(); }
+        public void put(T x) {
+            try { super.transfer(x); }
+            catch (InterruptedException ex) { throw new Error(); }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
+    static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
+        HalfSyncLTQ() { super(); }
+        public void put(T x) {
+            if (ThreadLocalRandom.current().nextBoolean())
+                super.put(x);
+            else {
+                try { super.transfer(x); }
+                catch (InterruptedException ex) { throw new Error(); }
+            }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
     static void oneTest(int producers, int iters) throws Exception {
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), producers, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), producers, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), producers, iters);
-//         oneRun(new LinkedTransferQueue<Integer>(), producers, iters);
+        oneRun(new LinkedTransferQueue<Integer>(), producers, iters);
+        oneRun(new LTQasSQ<Integer>(), producers, iters);
+        oneRun(new HalfSyncLTQ<Integer>(), producers, iters);
 
         // Don't run PBQ since can legitimately run out of memory
         //        if (print)
--- a/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java	Thu Nov 12 23:04:42 2009 +0000
@@ -63,12 +63,11 @@
         test(new LinkedBlockingDeque());
         test(new LinkedBlockingDeque(2000));
         test(new ArrayBlockingQueue(2000));
-//         test(new LinkedTransferQueue());
+        test(new LinkedTransferQueue());
     }
 
     Random getRandom() {
-        return new Random();
-        // return ThreadLocalRandom.current();
+        return ThreadLocalRandom.current();
     }
 
     void test(final BlockingQueue q) throws Throwable {
--- a/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java	Thu Nov 12 23:04:42 2009 +0000
@@ -46,7 +46,7 @@
     public static void main(String[] args) throws InterruptedException {
         final BlockingQueue[] qs = {
             new LinkedBlockingQueue(10),
-//             new LinkedTransferQueue(),
+            new LinkedTransferQueue(),
             new ArrayBlockingQueue(10),
             new SynchronousQueue(),
             new SynchronousQueue(true),
--- a/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java	Thu Nov 12 23:04:42 2009 +0000
@@ -87,11 +87,35 @@
             throw new Error();
    }
 
+    static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
+        LTQasSQ() { super(); }
+        public void put(T x) {
+            try { super.transfer(x); }
+            catch (InterruptedException ex) { throw new Error(); }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
+    static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
+        HalfSyncLTQ() { super(); }
+        public void put(T x) {
+            if (ThreadLocalRandom.current().nextBoolean())
+                super.put(x);
+            else {
+                try { super.transfer(x); }
+                catch (InterruptedException ex) { throw new Error(); }
+            }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
     static void oneTest(int pairs, int iters) throws Exception {
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), pairs, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), pairs, iters);
-//         oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
+        oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
+        oneRun(new LTQasSQ<Integer>(), pairs, iters);
+        oneRun(new HalfSyncLTQ<Integer>(), pairs, iters);
         oneRun(new PriorityBlockingQueue<Integer>(), pairs, iters);
         oneRun(new SynchronousQueue<Integer>(), pairs, iters);
 
--- a/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java	Thu Nov 12 23:04:42 2009 +0000
@@ -73,11 +73,35 @@
             throw new Error();
    }
 
+    static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
+        LTQasSQ() { super(); }
+        public void put(T x) {
+            try { super.transfer(x); }
+            catch (InterruptedException ex) { throw new Error(); }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
+    static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
+        HalfSyncLTQ() { super(); }
+        public void put(T x) {
+            if (ThreadLocalRandom.current().nextBoolean())
+                super.put(x);
+            else {
+                try { super.transfer(x); }
+                catch (InterruptedException ex) { throw new Error(); }
+            }
+        }
+        private final static long serialVersionUID = 42;
+    }
+
     static void oneTest(int consumers, int iters) throws Exception {
         oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), consumers, iters);
         oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), consumers, iters);
         oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), consumers, iters);
-//         oneRun(new LinkedTransferQueue<Integer>(), consumers, iters);
+        oneRun(new LinkedTransferQueue<Integer>(), consumers, iters);
+        oneRun(new LTQasSQ<Integer>(), consumers, iters);
+        oneRun(new HalfSyncLTQ<Integer>(), consumers, iters);
         oneRun(new PriorityBlockingQueue<Integer>(), consumers, iters);
         oneRun(new SynchronousQueue<Integer>(), consumers, iters);
         if (print)
--- a/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java	Thu Nov 12 23:04:42 2009 +0000
@@ -60,7 +60,7 @@
         //queues.add(new ArrayBlockingQueue<Integer>(count, true));
         queues.add(new LinkedBlockingQueue<Integer>());
         queues.add(new LinkedBlockingDeque<Integer>());
-//         queues.add(new LinkedTransferQueue<Integer>());
+        queues.add(new LinkedTransferQueue<Integer>());
 
         // Following additional implementations are available from:
         // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html
--- a/test/java/util/concurrent/ConcurrentQueues/GCRetention.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/ConcurrentQueues/GCRetention.java	Thu Nov 12 23:04:42 2009 +0000
@@ -43,7 +43,7 @@
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.LinkedBlockingQueue;
-// import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.LinkedTransferQueue;
 import java.util.concurrent.PriorityBlockingQueue;
 import java.util.LinkedList;
 import java.util.PriorityQueue;
@@ -70,7 +70,7 @@
         queues.add(new PriorityBlockingQueue<Boolean>());
         queues.add(new PriorityQueue<Boolean>());
         queues.add(new LinkedList<Boolean>());
-//         queues.add(new LinkedTransferQueue<Boolean>());
+        queues.add(new LinkedTransferQueue<Boolean>());
 
         // Following additional implementations are available from:
         // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html
--- a/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java	Thu Nov 12 23:04:42 2009 +0000
@@ -49,7 +49,7 @@
         test(new LinkedBlockingDeque());
         test(new LinkedBlockingDeque(20));
         test(new ConcurrentLinkedQueue());
-//         test(new LinkedTransferQueue());
+        test(new LinkedTransferQueue());
         // Other concurrent queues (e.g. ArrayBlockingQueue) do not
         // currently have weakly consistent iterators.
         // test(new ArrayBlockingQueue(20));
--- a/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java	Thu Nov 12 23:04:42 2009 +0000
@@ -56,12 +56,11 @@
         testQueue(new ArrayBlockingQueue(10));
         testQueue(new PriorityBlockingQueue(10));
         testQueue(new ConcurrentLinkedQueue());
-//         testQueue(new LinkedTransferQueue());
+        testQueue(new LinkedTransferQueue());
     }
 
     Random getRandom() {
-        return new Random();
-        // return ThreadLocalRandom.current();
+        return ThreadLocalRandom.current();
     }
 
     void testQueue(final Queue q) throws Throwable {
--- a/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java	Thu Nov 12 23:04:42 2009 +0000
@@ -45,7 +45,7 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.LinkedBlockingQueue;
-// import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.LinkedTransferQueue;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -67,7 +67,7 @@
         queues.add(new ArrayBlockingQueue<Boolean>(count, true));
         queues.add(new LinkedBlockingQueue<Boolean>());
         queues.add(new LinkedBlockingDeque<Boolean>());
-//         queues.add(new LinkedTransferQueue<Boolean>());
+        queues.add(new LinkedTransferQueue<Boolean>());
 
         // Following additional implementations are available from:
         // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/Phaser/Arrive.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,94 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6445158
+ * @summary tests for Phaser.arrive()
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class Arrive {
+    void test(String[] args) throws Throwable {
+        final int n = ThreadLocalRandom.current().nextInt(1, 10);
+        final int nthreads = n*3/2;
+        final Phaser startingGate = new Phaser(nthreads);
+        final Phaser phaser = new Phaser(n);
+        final List<Thread> threads = new ArrayList<Thread>();
+        final AtomicInteger count0 = new AtomicInteger(0);
+        final AtomicInteger count1 = new AtomicInteger(0);
+        final Runnable task = new Runnable() { public void run() {
+            equal(startingGate.getPhase(), 0);
+            startingGate.arriveAndAwaitAdvance();
+            equal(startingGate.getPhase(), 1);
+            int phase = phaser.arrive();
+            if (phase == 0)
+                count0.getAndIncrement();
+            else if (phase == 1)
+                count1.getAndIncrement();
+            else
+                fail();
+        }};
+        for (int i = 0; i < nthreads; i++)
+            threads.add(new Thread(task));
+        for (Thread thread : threads)
+            thread.start();
+        for (Thread thread : threads)
+            thread.join();
+        equal(count0.get(), n);
+        equal(count1.get(), nthreads-n);
+        equal(phaser.getPhase(), 1);
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new Arrive().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/Phaser/Basic.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,407 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6445158
+ * @summary Basic tests for Phaser
+ * @author Chris Hegarty
+ */
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+import static java.util.concurrent.TimeUnit.*;
+
+public class Basic {
+
+    private static void checkTerminated(final Phaser phaser) {
+        check(phaser.isTerminated());
+        int unarriverParties = phaser.getUnarrivedParties();
+        int registeredParties = phaser.getRegisteredParties();
+        equal(phaser.arrive(), -1);
+        equal(phaser.arriveAndDeregister(), -1);
+        equal(phaser.arriveAndAwaitAdvance(), -1);
+        equal(phaser.bulkRegister(10), -1);
+        equal(phaser.getPhase(), -1);
+        equal(phaser.register(), -1);
+        try {
+            equal(phaser.awaitAdvanceInterruptibly(0), -1);
+            equal(phaser.awaitAdvanceInterruptibly(0, 10, SECONDS), -1);
+        } catch (Exception ie) {
+            unexpected(ie);
+        }
+        equal(phaser.getUnarrivedParties(), unarriverParties);
+        equal(phaser.getRegisteredParties(), registeredParties);
+    }
+
+    private static void checkResult(Arriver a, Class<? extends Throwable> c) {
+        Throwable t = a.result();
+        if (! ((t == null && c == null) || (c != null && c.isInstance(t)))) {
+            //      t.printStackTrace();
+            fail("Mismatch in thread " +
+                 a.getName() + ": " +
+                 t + ", " +
+                 (c == null ? "<null>" : c.getName()));
+        } else {
+            pass();
+        }
+    }
+
+    //----------------------------------------------------------------
+    // Mechanism to get all test threads into "running" mode.
+    //----------------------------------------------------------------
+    private static Phaser atTheStartingGate = new Phaser(3);
+
+    private static void toTheStartingGate() {
+        try {
+            boolean expectNextPhase = false;
+            if (atTheStartingGate.getUnarrivedParties() == 1) {
+                expectNextPhase = true;
+            }
+            int phase = atTheStartingGate.getPhase();
+            equal(phase, atTheStartingGate.arrive());
+            int AwaitPhase = atTheStartingGate.awaitAdvanceInterruptibly(phase,
+                                                        10,
+                                                        SECONDS);
+            if (expectNextPhase) check(AwaitPhase == (phase + 1));
+
+            pass();
+        } catch (Throwable t) {
+            unexpected(t);
+           // reset(atTheStartingGate);
+            throw new Error(t);
+        }
+    }
+
+    //----------------------------------------------------------------
+    // Convenience methods for creating threads that call arrive,
+    // awaitAdvance, arriveAndAwaitAdvance, awaitAdvanceInterruptibly
+    //----------------------------------------------------------------
+    private static abstract class Arriver extends Thread {
+        static AtomicInteger count = new AtomicInteger(1);
+
+        Arriver() {
+            this("Arriver");
+        }
+
+        Arriver(String name) {
+            this.setName(name + ":" + count.getAndIncrement());
+            this.setDaemon(true);
+        }
+
+        private volatile Throwable result;
+        private volatile int phase;
+        protected void result(Throwable result) { this.result = result; }
+        public Throwable result() { return this.result; }
+        protected void phase(int phase) { this.phase = phase; }
+        public int phase() { return this.phase; }
+    }
+
+    private static abstract class Awaiter extends Arriver {
+        Awaiter() { super("Awaiter"); }
+        Awaiter(String name) { super(name); }
+    }
+
+    private static Arriver arriver(final Phaser phaser) {
+        return new Arriver() { public void run() {
+            toTheStartingGate();
+
+            try { phase(phaser.arrive()); }
+            catch (Throwable result) { result(result); }}};
+    }
+
+    private static AtomicInteger cycleArriveAwaitAdvance = new AtomicInteger(1);
+
+    private static Awaiter awaiter(final Phaser phaser) {
+        return new Awaiter() { public void run() {
+            toTheStartingGate();
+
+            try {
+                if (cycleArriveAwaitAdvance.getAndIncrement() % 2 == 0)
+                    phase(phaser.awaitAdvance(phaser.arrive()));
+                else
+                    phase(phaser.arriveAndAwaitAdvance());
+            } catch (Throwable result) { result(result); }}};
+    }
+
+    private static Awaiter awaiter(final Phaser phaser,
+                                   final long timeout,
+                                   final TimeUnit unit) {
+        return new Awaiter("InterruptibleWaiter") { public void run() {
+            toTheStartingGate();
+
+            try {
+                if (timeout < 0)
+                    phase(phaser.awaitAdvanceInterruptibly(phaser.arrive()));
+                else
+                    phase(phaser.awaitAdvanceInterruptibly(phaser.arrive(),
+                                                     timeout,
+                                                     unit));
+            } catch (Throwable result) { result(result); }}};
+    }
+
+    // Returns an infinite lazy list of all possible arriver/awaiter combinations.
+    private static Iterator<Arriver> arriverIterator(final Phaser phaser) {
+        return new Iterator<Arriver>() {
+            int i = 0;
+            public boolean hasNext() { return true; }
+            public Arriver next() {
+                switch ((i++)&7) {
+                    case 0: case 4:
+                        return arriver(phaser);
+                    case 1: case 5:
+                        return awaiter(phaser);
+                    case 2: case 6: case 7:
+                        return awaiter(phaser, -1, SECONDS);
+                    default:
+                        return awaiter(phaser, 10, SECONDS); }}
+            public void remove() {throw new UnsupportedOperationException();}};
+    }
+
+    // Returns an infinite lazy list of all possible awaiter only combinations.
+    private static Iterator<Awaiter> awaiterIterator(final Phaser phaser) {
+        return new Iterator<Awaiter>() {
+            int i = 0;
+            public boolean hasNext() { return true; }
+            public Awaiter next() {
+                switch ((i++)&7) {
+                    case 1: case 4: case 7:
+                        return awaiter(phaser);
+                    case 2: case 5:
+                        return awaiter(phaser, -1, SECONDS);
+                    default:
+                        return awaiter(phaser, 10, SECONDS); }}
+            public void remove() {throw new UnsupportedOperationException();}};
+    }
+
+    private static void realMain(String[] args) throws Throwable {
+
+        Thread.currentThread().setName("mainThread");
+
+        //----------------------------------------------------------------
+        // Normal use
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(3);
+            equal(phaser.getRegisteredParties(), 3);
+            equal(phaser.getArrivedParties(), 0);
+            equal(phaser.getPhase(), 0);
+            check(phaser.getRoot().equals(phaser));
+            equal(phaser.getParent(), null);
+            check(!phaser.isTerminated());
+
+            Iterator<Arriver> arrivers = arriverIterator(phaser);
+            int phase = 0;
+            for (int i = 0; i < 10; i++) {
+                equal(phaser.getPhase(), phase++);
+                Arriver a1 = arrivers.next(); a1.start();
+                Arriver a2 = arrivers.next(); a2.start();
+                toTheStartingGate();
+                phaser.arriveAndAwaitAdvance();
+                a1.join();
+                a2.join();
+                checkResult(a1, null);
+                checkResult(a2, null);
+                check(!phaser.isTerminated());
+                equal(phaser.getRegisteredParties(), 3);
+                equal(phaser.getArrivedParties(), 0);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // One thread interrupted
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(3);
+            Iterator<Arriver> arrivers = arriverIterator(phaser);
+            int phase = phaser.getPhase();
+            for (int i = 0; i < 4; i++) {
+                check(phaser.getPhase() == phase);
+                Awaiter a1 = awaiter(phaser, 10, SECONDS); a1.start();
+                Arriver a2 = arrivers.next(); a2.start();
+                toTheStartingGate();
+                a1.interrupt();
+                a1.join();
+                phaser.arriveAndAwaitAdvance();
+                a2.join();
+                checkResult(a1, InterruptedException.class);
+                checkResult(a2, null);
+                check(!phaser.isTerminated());
+                equal(phaser.getRegisteredParties(), 3);
+                equal(phaser.getArrivedParties(), 0);
+                phase++;
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Phaser is terminated while threads are waiting
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(3);
+            Iterator<Awaiter> awaiters = awaiterIterator(phaser);
+            for (int i = 0; i < 4; i++) {
+                Arriver a1 = awaiters.next(); a1.start();
+                Arriver a2 = awaiters.next(); a2.start();
+                toTheStartingGate();
+                while (phaser.getArrivedParties() < 2) Thread.yield();
+                phaser.forceTermination();
+                a1.join();
+                a2.join();
+                check(a1.phase == -1);
+                check(a2.phase == -1);
+                int arrivedParties = phaser.getArrivedParties();
+                checkTerminated(phaser);
+                equal(phaser.getArrivedParties(), arrivedParties);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Adds new unarrived parties to this phaser
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(1);
+            Iterator<Arriver> arrivers = arriverIterator(phaser);
+            LinkedList<Arriver> arriverList = new LinkedList<Arriver>();
+            int phase = phaser.getPhase();
+            for (int i = 1; i < 5; i++) {
+                atTheStartingGate = new Phaser(1+(3*i));
+                check(phaser.getPhase() == phase);
+                // register 3 more
+                phaser.register(); phaser.register(); phaser.register();
+                for (int z=0; z<(3*i); z++) {
+                   arriverList.add(arrivers.next());
+                }
+                for (Arriver arriver : arriverList)
+                    arriver.start();
+
+                toTheStartingGate();
+                phaser.arriveAndAwaitAdvance();
+
+                for (Arriver arriver : arriverList) {
+                    arriver.join();
+                    checkResult(arriver, null);
+                }
+                equal(phaser.getRegisteredParties(), 1 + (3*i));
+                equal(phaser.getArrivedParties(), 0);
+                arriverList.clear();
+                phase++;
+            }
+            atTheStartingGate = new Phaser(3);
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // One thread timed out
+        //----------------------------------------------------------------
+        try {
+            Phaser phaser = new Phaser(3);
+            Iterator<Arriver> arrivers = arriverIterator(phaser);
+            for (long timeout : new long[] { 0L, 5L }) {
+                for (int i = 0; i < 2; i++) {
+                    Awaiter a1 = awaiter(phaser, timeout, SECONDS); a1.start();
+                    Arriver a2 = arrivers.next();                   a2.start();
+                    toTheStartingGate();
+                    a1.join();
+                    checkResult(a1, TimeoutException.class);
+                    phaser.arrive();
+                    a2.join();
+                    checkResult(a2, null);
+                    check(!phaser.isTerminated());
+                }
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
+        // Barrier action completed normally
+        //----------------------------------------------------------------
+        try {
+            final AtomicInteger count = new AtomicInteger(0);
+            final Phaser[] kludge = new Phaser[1];
+            Phaser phaser = new Phaser(3) {
+                @Override
+                protected boolean onAdvance(int phase, int registeredParties) {
+                    int countPhase = count.getAndIncrement();
+                    equal(countPhase, phase);
+                    equal(kludge[0].getPhase(), phase);
+                    equal(kludge[0].getRegisteredParties(), registeredParties);
+                    if (phase >= 3)
+                        return true; // terminate
+
+                    return false;
+                }
+            };
+            kludge[0] = phaser;
+            equal(phaser.getRegisteredParties(), 3);
+            Iterator<Awaiter> awaiters = awaiterIterator(phaser);
+            for (int i = 0; i < 4; i++) {
+                Awaiter a1 = awaiters.next(); a1.start();
+                Awaiter a2 = awaiters.next(); a2.start();
+                toTheStartingGate();
+                while (phaser.getArrivedParties() < 2) Thread.yield();
+                phaser.arrive();
+                a1.join();
+                a2.join();
+                checkResult(a1, null);
+                checkResult(a2, null);
+                equal(count.get(), i+1);
+                if (i < 3) {
+                    check(!phaser.isTerminated());
+                    equal(phaser.getRegisteredParties(), 3);
+                    equal(phaser.getArrivedParties(), 0);
+                    equal(phaser.getUnarrivedParties(), 3);
+                    equal(phaser.getPhase(), count.get());
+                } else
+                    checkTerminated(phaser);
+            }
+        } catch (Throwable t) { unexpected(t); }
+
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    static volatile int passed = 0, failed = 0;
+    static void pass() {passed++;}
+    static void fail() {failed++; Thread.dumpStack();}
+    static void fail(String msg) {System.out.println(msg); fail();}
+    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    static void check(boolean cond) {if (cond) pass(); else fail();}
+    static void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        try {realMain(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java	Thu Nov 12 23:04:42 2009 +0000
@@ -21,6 +21,17 @@
  */
 
 /*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
  * @test
  * @bug 6725789
  * @summary Check for long overflow in task time comparison.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/forkjoin/Integrate.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,265 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6865571
+ * @summary Numerical Integration using fork/join
+ * @run main Integrate reps=1 forkPolicy=dynamic
+ * @run main Integrate reps=1 forkPolicy=serial
+ * @run main Integrate reps=1 forkPolicy=fork
+ */
+
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.RecursiveAction;
+
+/**
+ * Sample program using Gaussian Quadrature for numerical integration.
+ * This version uses a simplified hardwired function.  Inspired by a
+ * <A href="http://www.cs.uga.edu/~dkl/filaments/dist.html">
+ * Filaments</A> demo program.
+ */
+public final class Integrate {
+
+    static final double errorTolerance = 1.0e-11;
+    /** for time conversion */
+    static final long NPS = (1000L * 1000 * 1000);
+
+    static final int SERIAL = -1;
+    static final int DYNAMIC = 0;
+    static final int FORK = 1;
+
+    // the function to integrate
+    static double computeFunction(double x)  {
+        return (x * x + 1.0) * x;
+    }
+
+    static final double start = 0.0;
+    static final double end = 1536.0;
+    /*
+     * The number of recursive calls for
+     * integrate from start to end.
+     * (Empirically determined)
+     */
+    static final int calls = 263479047;
+
+    static String keywordValue(String[] args, String keyword) {
+        for (String arg : args)
+            if (arg.startsWith(keyword))
+                return arg.substring(keyword.length() + 1);
+        return null;
+    }
+
+    static int intArg(String[] args, String keyword, int defaultValue) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? defaultValue : Integer.parseInt(val);
+    }
+
+    static int policyArg(String[] args, String keyword, int defaultPolicy) {
+        String val = keywordValue(args, keyword);
+        if (val == null) return defaultPolicy;
+        if (val.equals("dynamic")) return DYNAMIC;
+        if (val.equals("serial")) return SERIAL;
+        if (val.equals("fork")) return FORK;
+        throw new Error();
+    }
+
+    /**
+     * Usage: Integrate [procs=N] [reps=N] forkPolicy=serial|dynamic|fork
+     */
+    public static void main(String[] args) throws Exception {
+        final int procs = intArg(args, "procs",
+                                 Runtime.getRuntime().availableProcessors());
+        final int forkPolicy = policyArg(args, "forkPolicy", DYNAMIC);
+
+        ForkJoinPool g = new ForkJoinPool(procs);
+        System.out.println("Integrating from " + start + " to " + end +
+                           " forkPolicy = " + forkPolicy);
+        long lastTime = System.nanoTime();
+
+        for (int reps = intArg(args, "reps", 10); reps > 0; reps--) {
+            double a;
+            if (forkPolicy == SERIAL)
+                a = SQuad.computeArea(g, start, end);
+            else if (forkPolicy == FORK)
+                a = FQuad.computeArea(g, start, end);
+            else
+                a = DQuad.computeArea(g, start, end);
+            long now = System.nanoTime();
+            double s = (double) (now - lastTime) / NPS;
+            lastTime = now;
+            System.out.printf("Calls/sec: %12d", (long) (calls / s));
+            System.out.printf(" Time: %7.3f", s);
+            System.out.printf(" Area: %12.1f", a);
+            System.out.println();
+        }
+        System.out.println(g);
+        g.shutdown();
+    }
+
+
+    // Sequential version
+    static final class SQuad extends RecursiveAction {
+        static double computeArea(ForkJoinPool pool, double l, double r) {
+            SQuad q = new SQuad(l, r, 0);
+            pool.invoke(q);
+            return q.area;
+        }
+
+        final double left;       // lower bound
+        final double right;      // upper bound
+        double area;
+
+        SQuad(double l, double r, double a) {
+            this.left = l; this.right = r; this.area = a;
+        }
+
+        public final void compute() {
+            double l = left;
+            double r = right;
+            area = recEval(l, r, (l * l + 1.0) * l, (r * r + 1.0) * r, area);
+        }
+
+        static final double recEval(double l, double r, double fl,
+                                    double fr, double a) {
+            double h = (r - l) * 0.5;
+            double c = l + h;
+            double fc = (c * c + 1.0) * c;
+            double hh = h * 0.5;
+            double al = (fl + fc) * hh;
+            double ar = (fr + fc) * hh;
+            double alr = al + ar;
+            if (Math.abs(alr - a) <= errorTolerance)
+                return alr;
+            else
+                return recEval(c, r, fc, fr, ar) + recEval(l, c, fl, fc, al);
+        }
+
+    }
+
+    //....................................
+
+    // ForkJoin version
+    static final class FQuad extends RecursiveAction {
+        static double computeArea(ForkJoinPool pool, double l, double r) {
+            FQuad q = new FQuad(l, r, 0);
+            pool.invoke(q);
+            return q.area;
+        }
+
+        final double left;       // lower bound
+        final double right;      // upper bound
+        double area;
+
+        FQuad(double l, double r, double a) {
+            this.left = l; this.right = r; this.area = a;
+        }
+
+        public final void compute() {
+            double l = left;
+            double r = right;
+            area = recEval(l, r, (l * l + 1.0) * l, (r * r + 1.0) * r, area);
+        }
+
+        static final double recEval(double l, double r, double fl,
+                                    double fr, double a) {
+            double h = (r - l) * 0.5;
+            double c = l + h;
+            double fc = (c * c + 1.0) * c;
+            double hh = h * 0.5;
+            double al = (fl + fc) * hh;
+            double ar = (fr + fc) * hh;
+            double alr = al + ar;
+            if (Math.abs(alr - a) <= errorTolerance)
+                return alr;
+            FQuad q = new FQuad(l, c, al);
+            q.fork();
+            ar = recEval(c, r, fc, fr, ar);
+            if (!q.tryUnfork()) {
+                q.quietlyHelpJoin();
+                return ar + q.area;
+            }
+            return ar + recEval(l, c, fl, fc, al);
+        }
+
+    }
+
+    // ...........................
+
+    // Version using on-demand Fork
+    static final class DQuad extends RecursiveAction {
+        static double computeArea(ForkJoinPool pool, double l, double r) {
+            DQuad q = new DQuad(l, r, 0);
+            pool.invoke(q);
+            return q.area;
+        }
+
+        final double left;       // lower bound
+        final double right;      // upper bound
+        double area;
+
+        DQuad(double l, double r, double a) {
+            this.left = l; this.right = r; this.area = a;
+        }
+
+        public final void compute() {
+            double l = left;
+            double r = right;
+            area = recEval(l, r, (l * l + 1.0) * l, (r * r + 1.0) * r, area);
+        }
+
+        static final double recEval(double l, double r, double fl,
+                                    double fr, double a) {
+            double h = (r - l) * 0.5;
+            double c = l + h;
+            double fc = (c * c + 1.0) * c;
+            double hh = h * 0.5;
+            double al = (fl + fc) * hh;
+            double ar = (fr + fc) * hh;
+            double alr = al + ar;
+            if (Math.abs(alr - a) <= errorTolerance)
+                return alr;
+            DQuad q = null;
+            if (getSurplusQueuedTaskCount() <= 3)
+                (q = new DQuad(l, c, al)).fork();
+            ar = recEval(c, r, fc, fr, ar);
+            if (q != null && !q.tryUnfork()) {
+                q.quietlyHelpJoin();
+                return ar + q.area;
+            }
+            return ar + recEval(l, c, fl, fc, al);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/forkjoin/NQueensCS.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,174 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6865571
+ * @summary Solve NQueens using fork/join
+ * @run main NQueensCS maxBoardSize=11 reps=1
+ * @run main NQueensCS maxBoardSize=11 reps=1 procs=8
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.RecursiveAction;
+
+public class NQueensCS extends RecursiveAction {
+
+    static long lastStealCount;
+    static int boardSize;
+
+    static final int[] expectedSolutions = new int[] {
+        0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200,
+        73712, 365596, 2279184, 14772512, 95815104, 666090624
+    }; // see http://www.durangobill.com/N_Queens.html
+
+    static String keywordValue(String[] args, String keyword) {
+        for (String arg : args)
+            if (arg.startsWith(keyword))
+                return arg.substring(keyword.length() + 1);
+        return null;
+    }
+
+    static int intArg(String[] args, String keyword, int defaultValue) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? defaultValue : Integer.parseInt(val);
+    }
+
+    /** for time conversion */
+    static final long NPS = (1000L * 1000L * 1000L);
+
+    /**
+     * Usage: NQueensCS [minBoardSize=N] [maxBoardSize=N] [procs=N] [reps=N]
+     */
+    public static void main(String[] args) throws Exception {
+        // Board sizes too small: hard to measure well.
+        // Board sizes too large: take too long to run.
+        final int minBoardSize = intArg(args, "minBoardSize",  8);
+        final int maxBoardSize = intArg(args, "maxBoardSize", 15);
+
+        final int procs = intArg(args, "procs", 0);
+
+        for (int reps = intArg(args, "reps", 10); reps > 0; reps--) {
+            ForkJoinPool g = (procs == 0) ?
+                new ForkJoinPool() :
+                new ForkJoinPool(procs);
+            lastStealCount = g.getStealCount();
+            for (int i = minBoardSize; i <= maxBoardSize; i++)
+                test(g, i);
+            System.out.println(g);
+            g.shutdown();
+        }
+    }
+
+    static void test(ForkJoinPool g, int i) throws Exception {
+        boardSize = i;
+        int ps = g.getParallelism();
+        long start = System.nanoTime();
+        NQueensCS task = new NQueensCS(new int[0]);
+        g.invoke(task);
+        int solutions = task.solutions;
+        long time = System.nanoTime() - start;
+        double secs = (double) time / NPS;
+        if (solutions != expectedSolutions[i])
+            throw new Error();
+        System.out.printf("NQueensCS %3d", i);
+        System.out.printf(" Time: %7.3f", secs);
+        long sc = g.getStealCount();
+        long ns = sc - lastStealCount;
+        lastStealCount = sc;
+        System.out.printf(" Steals/t: %5d", ns/ps);
+        System.out.println();
+    }
+
+    // Boards are represented as arrays where each cell
+    // holds the column number of the queen in that row
+
+    final int[] sofar;
+    NQueensCS nextSubtask; // to link subtasks
+    int solutions;
+    NQueensCS(int[] a) {
+        this.sofar = a;
+    }
+
+    public final void compute() {
+        NQueensCS subtasks;
+        int bs = boardSize;
+        if (sofar.length >= bs)
+            solutions = 1;
+        else if ((subtasks = explore(sofar, bs)) != null)
+            solutions = processSubtasks(subtasks);
+    }
+
+    private static NQueensCS explore(int[] array, int bs) {
+        int row = array.length;
+        NQueensCS s = null; // subtask list
+        outer:
+        for (int q = 0; q < bs; ++q) {
+            for (int i = 0; i < row; i++) {
+                int p = array[i];
+                if (q == p || q == p - (row - i) || q == p + (row - i))
+                    continue outer; // attacked
+            }
+            NQueensCS first = s; // lag forks to ensure 1 kept
+            if (first != null)
+                first.fork();
+            int[] next = Arrays.copyOf(array, row+1);
+            next[row] = q;
+            NQueensCS subtask = new NQueensCS(next);
+            subtask.nextSubtask = first;
+            s = subtask;
+        }
+        return s;
+    }
+
+    private static int processSubtasks(NQueensCS s) {
+        // Always run first the task held instead of forked
+        s.compute();
+        int ns = s.solutions;
+        s = s.nextSubtask;
+        // Then the unstolen ones
+        while (s != null && s.tryUnfork()) {
+            s.compute();
+            ns += s.solutions;
+            s = s.nextSubtask;
+        }
+        // Then wait for the stolen ones
+        while (s != null) {
+            s.join();
+            ns += s.solutions;
+            s = s.nextSubtask;
+        }
+        return ns;
+    }
+}
--- a/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java	Thu Nov 12 23:04:42 2009 +0000
@@ -115,7 +115,7 @@
             finally {
                 lock.unlock();
             }
-            if (completed != 2)
+            if (c != 2)
                 throw new Error("Completed != 2");
             int r = result;
             if (r == 0) // avoid overoptimization
--- a/test/java/util/concurrent/locks/ReentrantReadWriteLock/RWMap.java	Thu Nov 12 23:00:23 2009 +0000
+++ b/test/java/util/concurrent/locks/ReentrantReadWriteLock/RWMap.java	Thu Nov 12 23:04:42 2009 +0000
@@ -30,6 +30,7 @@
  * Expert Group and released to the public domain, as explained at
  * http://creativecommons.org/licenses/publicdomain
  */
+
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/Security/6657138/ComponentTest.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657138
+ * @summary Verifies that buttons and labels work well after the fix for 6657138
+ * @author Alexander Potochkin
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class ComponentTest extends JFrame {
+    private static JFrame frame;
+
+    public ComponentTest() {
+        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        setLayout(new FlowLayout());
+        add(new JButton("JButton"));
+        add(new JToggleButton("JToggleButton"));
+        add(new JCheckBox("JCheckBox"));
+        add(new JRadioButton("JRadioButton"));
+        add(new JLabel("JLabel"));
+        pack();
+        setLocationRelativeTo(null);
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        SwingUtilities.invokeAndWait(new Runnable() {
+            public void run() {
+                frame = new ComponentTest();
+                frame.setVisible(true);
+            }
+        });
+        toolkit.realSync();
+        UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
+        for (final UIManager.LookAndFeelInfo laf : lafs) {
+            SwingUtilities.invokeAndWait(new Runnable() {
+                public void run() {
+                    try {
+                        UIManager.setLookAndFeel(laf.getClassName());
+                    } catch (Exception e) {
+                        new RuntimeException(e);
+                    }
+                    SwingUtilities.updateComponentTreeUI(frame);
+                }
+            });
+            toolkit.realSync();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/Security/6657138/bug6657138.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657138
+ * @summary Verifies that buttons and labels don't share their ui's across appContexts
+ * @author Alexander Potochkin
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import javax.swing.plaf.ButtonUI;
+import javax.swing.plaf.ComponentUI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class bug6657138 implements Runnable {
+
+    private static Map<JComponent, Map<String, ComponentUI>> componentMap =
+            Collections.synchronizedMap(
+            new HashMap<JComponent, Map<String, ComponentUI>>());
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        try {
+            testUIMap();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static void testUIMap() throws Exception {
+        UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
+        Set<JComponent> components = componentMap.keySet();
+        for (JComponent c : components) {
+            Map<String, ComponentUI> uiMap = componentMap.get(c);
+
+            for (UIManager.LookAndFeelInfo laf : lafs) {
+                if ("Nimbus".equals(laf.getName())) {
+                    // for some unclear reasons
+                    // Nimbus ui delegate for a button is null
+                    // when this method is called from the new AppContext
+                    continue;
+                }
+                String className = laf.getClassName();
+                UIManager.setLookAndFeel(className);
+                ComponentUI ui = UIManager.getUI(c);
+                if (ui == null) {
+                    throw new RuntimeException("UI is null for " + c);
+                }
+                if (ui == uiMap.get(laf.getName())) {
+                    throw new RuntimeException(
+                            "Two AppContexts share the same UI delegate! \n" +
+                                    c + "\n" + ui);
+                }
+                uiMap.put(laf.getName(), ui);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        componentMap.put(new JButton("JButton"),
+                new HashMap<String, ComponentUI>());
+        componentMap.put(new JToggleButton("JToggleButton"),
+                new HashMap<String, ComponentUI>());
+        componentMap.put(new JRadioButton("JRadioButton"),
+                new HashMap<String, ComponentUI>());
+        componentMap.put(new JCheckBox("JCheckBox"),
+                new HashMap<String, ComponentUI>());
+        componentMap.put(new JCheckBox("JLabel"),
+                new HashMap<String, ComponentUI>());
+        testUIMap();
+        ThreadGroup group = new ThreadGroup("6657138");
+        Thread thread = new Thread(group, new bug6657138());
+        thread.start();
+        thread.join();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/ToolTipManager/Test6657026.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared ToolTipManager in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+import javax.swing.ToolTipManager;
+
+public class Test6657026 implements Runnable {
+
+    private static final int DISMISS = 4000;
+    private static final int INITIAL = 750;
+    private static final int RESHOW = 500;
+
+    public static void main(String[] args) throws InterruptedException {
+        ToolTipManager manager = ToolTipManager.sharedInstance();
+        if (DISMISS != manager.getDismissDelay()) {
+            throw new Error("unexpected dismiss delay");
+        }
+        if (INITIAL != manager.getInitialDelay()) {
+            throw new Error("unexpected initial delay");
+        }
+        if (RESHOW != manager.getReshowDelay()) {
+            throw new Error("unexpected reshow delay");
+        }
+        manager.setDismissDelay(DISMISS + 1);
+        manager.setInitialDelay(INITIAL + 1);
+        manager.setReshowDelay(RESHOW + 1);
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        ToolTipManager manager = ToolTipManager.sharedInstance();
+        if (DISMISS != manager.getDismissDelay()) {
+            throw new Error("shared dismiss delay");
+        }
+        if (INITIAL != manager.getInitialDelay()) {
+            throw new Error("shared initial delay");
+        }
+        if (RESHOW != manager.getReshowDelay()) {
+            throw new Error("shared reshow delay");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/UIManager/Test6657026.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared UIManager in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
+
+public class Test6657026 implements Runnable {
+
+    public static void main(String[] args) throws Exception {
+        if (UIManager.getInstalledLookAndFeels().length == 0) {
+            throw new Error("unexpected amount of look&feels");
+        }
+        UIManager.setInstalledLookAndFeels(new LookAndFeelInfo[0]);
+        if (UIManager.getInstalledLookAndFeels().length != 0) {
+            throw new Error("unexpected amount of look&feels");
+        }
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        if (UIManager.getInstalledLookAndFeels().length == 0) {
+            throw new Error("shared look&feels");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/plaf/basic/BasicSplitPaneUI/Test6657026.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared BasicSplitPaneUI in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import java.awt.event.ActionEvent;
+import java.util.Set;
+import javax.swing.JSplitPane;
+import javax.swing.plaf.basic.BasicSplitPaneUI;
+
+public class Test6657026 extends BasicSplitPaneUI implements Runnable {
+
+    public static void main(String[] args) throws InterruptedException {
+        if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()){
+            throw new Error("unexpected traversal keys");
+        }
+        new JSplitPane() {
+            public void setFocusTraversalKeys(int id, Set keystrokes) {
+                keystrokes.clear();
+                super.setFocusTraversalKeys(id, keystrokes);
+            }
+        };
+        if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()) {
+            throw new Error("shared traversal keys");
+        }
+        KEYBOARD_DIVIDER_MOVE_OFFSET = -KEYBOARD_DIVIDER_MOVE_OFFSET;
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()) {
+            throw new Error("shared traversal keys");
+        }
+        JSplitPane pane = new JSplitPane();
+        pane.setUI(this);
+
+        createFocusListener().focusGained(null); // allows actions
+        test(pane, "positiveIncrement", 3);
+        test(pane, "negativeIncrement", 0);
+    }
+
+    private static void test(JSplitPane pane, String action, int expected) {
+        ActionEvent event = new ActionEvent(pane, expected, action);
+        pane.getActionMap().get(action).actionPerformed(event);
+        int actual = pane.getDividerLocation();
+        if (actual != expected) {
+            throw new Error(actual + ", but expected " + expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/plaf/metal/MetalBorders/Test6657026.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests constancy of borders
+ * @author Sergey Malenkov
+ */
+
+import java.awt.Insets;
+import javax.swing.border.Border;
+import javax.swing.plaf.metal.MetalBorders.ButtonBorder;
+import javax.swing.plaf.metal.MetalBorders.MenuBarBorder;
+import javax.swing.plaf.metal.MetalBorders.MenuItemBorder;
+import javax.swing.plaf.metal.MetalBorders.PopupMenuBorder;
+
+public class Test6657026 {
+
+    private static final Insets NEGATIVE = new Insets(Integer.MIN_VALUE,
+                                                      Integer.MIN_VALUE,
+                                                      Integer.MIN_VALUE,
+                                                      Integer.MIN_VALUE);
+
+    public static void main(String[] args) {
+        new ButtonBorder() {{borderInsets = NEGATIVE;}};
+        new MenuBarBorder() {{borderInsets = NEGATIVE;}};
+        new MenuItemBorder() {{borderInsets = NEGATIVE;}};
+        new PopupMenuBorder() {{borderInsets = NEGATIVE;}};
+
+        test(create("ButtonBorder"));
+        test(create("MenuBarBorder"));
+        test(create("MenuItemBorder"));
+        test(create("PopupMenuBorder"));
+
+        test(create("Flush3DBorder"));
+        test(create("InternalFrameBorder"));
+        // NOT USED: test(create("FrameBorder"));
+        // NOT USED: test(create("DialogBorder"));
+        test(create("PaletteBorder"));
+        test(create("OptionDialogBorder"));
+        test(create("ScrollPaneBorder"));
+    }
+
+    private static Border create(String name) {
+        try {
+            name = "javax.swing.plaf.metal.MetalBorders$" + name;
+            return (Border) Class.forName(name).newInstance();
+        }
+        catch (Exception exception) {
+            throw new Error("unexpected exception", exception);
+        }
+    }
+
+    private static void test(Border border) {
+        Insets actual = border.getBorderInsets(null);
+        if (NEGATIVE.equals(actual)) {
+            throw new Error("unexpected insets in " + border.getClass());
+        }
+        Insets expected = (Insets) actual.clone();
+        // modify
+        actual.top++;
+        actual.left++;
+        actual.right++;
+        actual.bottom++;
+        // validate
+        if (!expected.equals(border.getBorderInsets(null))) {
+            throw new Error("shared insets in " + border.getClass());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/plaf/metal/MetalBumps/Test6657026.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared MetalBumps in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.text.AttributedCharacterIterator;
+import javax.swing.Icon;
+import javax.swing.plaf.metal.MetalBorders.ToolBarBorder;
+
+public class Test6657026 extends ToolBarBorder implements Runnable {
+
+    public static void main(String[] args) throws Exception {
+        new Test6657026().test();
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        test();
+    }
+
+    private void test() {
+        MyGraphics mg = new MyGraphics();
+        Icon icon = bumps;
+        icon.paintIcon(mg.component, mg, 0, 0);
+        if (mg.image != null) {
+            boolean failed = true;
+            int value = mg.image.getRGB(0, 0);
+            for (int x = 0; x < mg.image.getWidth(); x++) {
+                for (int y = 0; y < mg.image.getHeight(); y++) {
+                    int current = mg.image.getRGB(x, y);
+                    if (current != value) {
+                        mg.image.setRGB(x, y, value);
+                        failed = false;
+                    }
+
+                }
+            }
+            if (failed) {
+                throw new Error("shared metal bumps");
+            }
+        }
+    }
+
+    private static class MyGraphics extends Graphics {
+
+        private final Component component = new Component() {};
+        private BufferedImage image;
+
+        public Graphics create() {
+            return null;  // TODO: check
+        }
+
+        public void translate(int x, int y) {
+            // TODO: check
+        }
+
+        public Color getColor() {
+            return null;  // TODO: check
+        }
+
+        public void setColor(Color color) {
+            // TODO: check
+        }
+
+        public void setPaintMode() {
+            // TODO: check
+        }
+
+        public void setXORMode(Color c1) {
+            // TODO: check
+        }
+
+        public Font getFont() {
+            return null;  // TODO: check
+        }
+
+        public void setFont(Font font) {
+            // TODO: check
+        }
+
+        public FontMetrics getFontMetrics(Font font) {
+            return null;  // TODO: check
+        }
+
+        public Rectangle getClipBounds() {
+            return null;  // TODO: check
+        }
+
+        public void clipRect(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void setClip(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public Shape getClip() {
+            return null;  // TODO: check
+        }
+
+        public void setClip(Shape clip) {
+            // TODO: check
+        }
+
+        public void copyArea(int x, int y, int width, int height, int dx, int dy) {
+            // TODO: check
+        }
+
+        public void drawLine(int x1, int y1, int x2, int y2) {
+            // TODO: check
+        }
+
+        public void fillRect(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void clearRect(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+            // TODO: check
+        }
+
+        public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+            // TODO: check
+        }
+
+        public void drawOval(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void fillOval(int x, int y, int width, int height) {
+            // TODO: check
+        }
+
+        public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+            // TODO: check
+        }
+
+        public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+            // TODO: check
+        }
+
+        public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
+            // TODO: check
+        }
+
+        public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+            // TODO: check
+        }
+
+        public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+            // TODO: check
+        }
+
+        public void drawString(String str, int x, int y) {
+            // TODO: check
+        }
+
+        public void drawString(AttributedCharacterIterator iterator, int x, int y) {
+            // TODO: check
+        }
+
+        public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
+            if (img instanceof BufferedImage) {
+                this.image = (BufferedImage) img;
+            }
+            return false;  // TODO: check
+        }
+
+        public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) {
+            return false;  // TODO: check
+        }
+
+        public void dispose() {
+            // TODO: check
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/plaf/metal/MetalInternalFrameUI/Test6657026.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared MetalInternalFrameUI in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.JInternalFrame;
+import javax.swing.JPanel;
+import javax.swing.UIManager;
+import javax.swing.plaf.metal.MetalInternalFrameUI;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+
+public class Test6657026 extends MetalInternalFrameUI implements Runnable {
+
+    public static void main(String[] args) throws Exception {
+        UIManager.setLookAndFeel(new MetalLookAndFeel());
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+
+        new JInternalFrame().setContentPane(new JPanel());
+    }
+
+    public Test6657026() {
+        super(null);
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        IS_PALETTE = JInternalFrame.CONTENT_PANE_PROPERTY;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/swing/plaf/metal/MetalSliderUI/Test6657026.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6657026
+ * @summary Tests shared MetalSliderUI in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.JSlider;
+import javax.swing.UIManager;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+import javax.swing.plaf.metal.MetalSliderUI;
+
+public class Test6657026 extends MetalSliderUI implements Runnable {
+
+    public static void main(String[] args) throws Exception {
+        UIManager.setLookAndFeel(new MetalLookAndFeel());
+        JSlider slider = new JSlider();
+        test(slider);
+
+        ThreadGroup group = new ThreadGroup("$$$");
+        Thread thread = new Thread(group, new Test6657026());
+        thread.start();
+        thread.join();
+
+        test(slider);
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        JSlider slider = new JSlider();
+        test(slider);
+        tickLength = -10000;
+    }
+
+    private static void test(JSlider slider) {
+        MetalSliderUI ui = (MetalSliderUI) slider.getUI();
+        int actual = ui.getTickLength();
+        if (actual != 11) {
+            throw new Error(actual + ", but expected 11");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/start-Xvfb.sh	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,87 @@
+#!/bin/sh -f
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# Original Author: Tim Bell
+#
+usage() {
+   echo "Starts up an Xvfb dummy X server with fvwm2 window manager"
+   echo " usage:"
+   echo "    ${0} display_number_file"
+   echo "        display_number_file gets display number when it's ready"
+   exit
+ }
+#
+currentDir=`pwd`
+rm -f $1
+DD=":$$"
+DISPLAY=${DD}
+export DISPLAY
+cd /tmp
+#
+if [ ! -x "/usr/bin/X11/Xvfb" ]; then
+  # We have Solaris-flavored X windows, and the /usr/openwin Xvfb is
+  # a simple wrapper script around the Xsun server.  Massage the
+  # arguments: server number must be first; others are slightly
+  # different.
+  #
+  # Also the default Visual Class (DirectColor) triggers an awt bug
+  # (probably 4131533/6505852) and some tests will loop endlessly
+  # when they hit the display.  The workaround is:
+  #  1) Ask for PseudoColor instead.
+  #  2) Omit 32-bit depth.
+  /usr/bin/nohup /usr/openwin/bin/Xvfb ${DISPLAY} -dev vfb screen 0 1280x1024x24 pixdepths 8 16 24 defclass PseudoColor > ${currentDir}/nohup.$$ 2>&1 &
+else
+  # Linux...
+  /usr/bin/nohup /usr/bin/X11/Xvfb -fbdir ${currentDir} -pixdepths 8 16 24 32 ${DISPLAY} > ${currentDir}/nohup.$$ 2>&1 &
+fi
+WM="/usr/bin/X11/fvwm2"
+if [ ! -x ${WM} ] ; then
+  WM="/opt/sfw/bin/fvwm2"
+fi
+#
+# Wait for Xvfb to initialize:
+sleep 5
+#
+if [ -x "${WM}" ]; then
+# 2 JCK tests require a window manager
+# mwm fails (key name errors) and twm fails (hangs),
+# but fvwm2 works well.
+  /usr/bin/nohup ${WM} -display ${DISPLAY} -replace -f /dev/null > ${currentDir}/nohup.$$ 2>&1 &
+else
+  echo "Error: ${WM} not found"
+  exit 1
+fi
+#
+# Wait some more to see if the xhost command gets through:
+sleep 10
+# Allow access to all - this is a brute force approach,
+# but I do not see how it could be a security problem...
+DISPLAY="${DD}" xhost +
+#
+echo "Virtual frame buffer started on ${DISPLAY}"
+echo "$$" > $1
+wait
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,442 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ *
+ * @bug 6861062
+ * @summary Disable MD2 support
+ *
+ * @run main/othervm CPBuilder trustAnchor_SHA1withRSA_1024 0 true
+ * @run main/othervm CPBuilder trustAnchor_SHA1withRSA_512  0 true
+ * @run main/othervm CPBuilder intermediate_SHA1withRSA_1024_1024 1 true
+ * @run main/othervm CPBuilder intermediate_SHA1withRSA_1024_512  1 true
+ * @run main/othervm CPBuilder intermediate_SHA1withRSA_512_1024  1 true
+ * @run main/othervm CPBuilder intermediate_SHA1withRSA_512_512  1 true
+ * @run main/othervm CPBuilder intermediate_MD2withRSA_1024_1024  1 false
+ * @run main/othervm CPBuilder intermediate_MD2withRSA_1024_512  1 false
+ * @run main/othervm CPBuilder endentiry_SHA1withRSA_1024_1024  2 true
+ * @run main/othervm CPBuilder endentiry_SHA1withRSA_1024_512  2 true
+ * @run main/othervm CPBuilder endentiry_SHA1withRSA_512_1024  2 true
+ * @run main/othervm CPBuilder endentiry_SHA1withRSA_512_512  2 true
+ * @run main/othervm CPBuilder endentiry_MD2withRSA_1024_1024  2 false
+ * @run main/othervm CPBuilder endentiry_MD2withRSA_1024_512  2 false
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.SocketException;
+import java.util.*;
+import java.security.Security;
+import java.security.cert.*;
+import sun.security.util.DerInputStream;
+
+public class CPBuilder {
+
+    // SHA1withRSA 1024
+    static String trustAnchor_SHA1withRSA_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
+        "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" +
+        "AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH\n" +
+        "E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd\n" +
+        "rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID\n" +
+        "AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME\n" +
+        "QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" +
+        "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw\n" +
+        "DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z\n" +
+        "Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+\n" +
+        "UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc\n" +
+        "tas=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512
+    static String trustAnchor_SHA1withRSA_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
+        "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB\n" +
+        "BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv\n" +
+        "7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU\n" +
+        "g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ\n" +
+        "5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G\n" +
+        "A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b\n" +
+        "FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia\n" +
+        "U5r+8B9nzx+j2Zh3kw==\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 1024
+    static String intermediate_SHA1withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDhaFw0yOTA0MjMwMTExNDha\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADgYEAHze3wAcIe84zNOoN\n" +
+        "P8l9EmlVVoU30z3LB3hxq3m/dC/4gE5Z9Z8EG1wJw4qaxlTZ4dif12nbTTdofVhb\n" +
+        "Bd4syjo6fcUA4q7sfg9TFpoHQ+Ap7PgjK99moMKdMy50Xy8s6FPvaVkF89s66Z6y\n" +
+        "e4q7TSwe6QevGOZaL5N/iy2XGEs=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 512
+    static String intermediate_SHA1withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICDzCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADQQCYNmdkONfuk07XjRze\n" +
+        "WQyq2cfdae4uIdyUfa2rpgYMtSXuQW3/XrQGiz4G6WBXA2wo7folOOpAKYgvHPrm\n" +
+        "w6Dd\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 1024
+    static String intermediate_SHA1withRSA_512_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICDDCCAXWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
+        "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
+        "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
+        "PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
+        "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
+        "CSqGSIb3DQEBBQUAA4GBAE2VOlw5ySLT3gUzKCYEga4QPaSrf6lHHPi2g48LscEY\n" +
+        "h9qQXh4nuIVugReBIEf6N49RdT+M2cgRJo4sZ3ukYLGQzxNuttL5nPSuuvrAR1oG\n" +
+        "LUyzOWcUpKHbVHi6zlTt79RvTKZvLcduLutmtPtLJcM9PdiAI1wEooSgxTwZtB/Z\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 512
+    static String intermediate_SHA1withRSA_512_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIByzCCAXWgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
+        "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
+        "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
+        "PoAUg4Kwd47hdNQBp8grZsRJ5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
+        "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
+        "CSqGSIb3DQEBBQUAA0EAoCf0Zu559qcB4xPpzqkVsYiyW49S4Yc0mmQXb1yoQgLx\n" +
+        "O+DCkjG5d14+t1MsnkhB2izoQUMxQ3vDc1YnA/tEpw==\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 1024
+    static String intermediate_MD2withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICUDCCAbmgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADgYEAPtEjwbWuC5kc4DPc\n" +
+        "Ttf/wdbD8ZCdAWzcc3XF9q1TlvwVMNk6mbfM05y6ZVsztKTkwZ4EcvFu/yIqw1EB\n" +
+        "E1zlXQCaWXT3/ZMbqYZV4+mx+RUl8spUCb1tda25jnTg3mTOzB1iztm4gy903EMd\n" +
+        "m8omKDKeCgcw5dR4ITQYvyxe1as=\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 512
+    static String intermediate_MD2withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICDzCCAbmgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADQQBHok1v6xymtpB7N9xy\n" +
+        "0OmDT27uhmzlP0eOzJvXVxj3Oi9TLQJgCUJ9122MzfRAs1E1uJTtvuu+UmI80NQx\n" +
+        "KQdp\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 1024
+    static String endentiry_SHA1withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
+        "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
+        "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
+        "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
+        "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
+        "OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG\n" +
+        "9w0BAQUFAAOBgQAOfIeasDg91CR3jGfuAEVKwncM1OPFmniAUcdPm74cCAyJ90Me\n" +
+        "dhUElWPGoAuXGfiyZlOlGUYWqEroe/dnkmnotJjLWR+MA4ZyX3O1YI8T4W3deWcC\n" +
+        "J4WMCF7mp17SaYYKX9F0AxwNJFpUkbB41IkTxPr0MmzB1871/pbY8dLAvA==\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 512
+    static String endentiry_SHA1withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIB9jCCAaCgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
+        "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
+        "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
+        "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
+        "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
+        "OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG\n" +
+        "9w0BAQUFAANBADV6X+ea0ftEKXy7yKNAbdIp35893T6AVwbdclomPkeOs86OtoTG\n" +
+        "1BIzWSK9QE7W6Wbf63e2RdcqoLK+DxsuwUg=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 1024
+    static String endentiry_SHA1withRSA_512_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIB8zCCAVygAwIBAgIBBDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3\n" +
+        "DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo\n" +
+        "uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE\n" +
+        "AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU\n" +
+        "31g/ZkU6aXFAJVKhrrv0ebfAgeYwDQYJKoZIhvcNAQEFBQADgYEAUyW8PrEdbzLu\n" +
+        "B+h6UemBOJ024rYq90hJE/5wUEKPvxZ9vPEUgl+io6cGhL3cLfxfh6z5xtEGp4Tb\n" +
+        "NB0Ye3Qi01FBiNDY8s3rQRrmel6VysU8u+0Oi2jmQY6vZXn/zXN5rrTLITCaSicG\n" +
+        "dOMv1xLM83Ee432WWlDwKOUxhzDGpWc=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 512
+    static String endentiry_SHA1withRSA_512_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIBsjCCAVygAwIBAgIBBTANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3\n" +
+        "DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo\n" +
+        "uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE\n" +
+        "AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU\n" +
+        "N0CHiTYPtjyvpP2a6y6mhsZ6U40wDQYJKoZIhvcNAQEFBQADQQBG4grtrVEHick0\n" +
+        "z/6Lcl/MGyHT0c8KTXE0AMVXG1NRjAicAmYno/yDaJ9OmfymObKZKV9fF7yCW/N/\n" +
+        "TMU6m7N0\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 1024
+    static String endentiry_MD2withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICNzCCAaCgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
+        "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
+        "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
+        "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
+        "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
+        "OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG\n" +
+        "9w0BAQIFAAOBgQBxKsFf8NNQcXjDoKJJSG4Rk6ikcrhiGYuUI32+XHvs6hnav1Zc\n" +
+        "aJUpy7J4gMj/MnysMh/4AF9+m6zEEjuisXKUbYZhgtJxz+ukGSo163mJ8QJiAlRb\n" +
+        "Iwsy81r08mlSCR6jx2YhDAUxJIPC92R5Vb4CEutB7tWTwwz7vIHq330erA==\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 512
+    static String endentiry_MD2withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIB9jCCAaCgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
+        "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
+        "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
+        "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
+        "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
+        "OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG\n" +
+        "9w0BAQIFAANBAIX63Ypi9P71RnC/pcMbhD+wekRFsTzU593X3MC7tyBJtEXwvAZG\n" +
+        "iMxXF5A+ohlr7/CrkV7ZTL8PLxnJdY5Y8rQ=\n" +
+        "-----END CERTIFICATE-----";
+
+    static HashMap<String, String> certmap = new HashMap<String, String>();
+    static {
+        certmap.put("trustAnchor_SHA1withRSA_1024",
+                                    trustAnchor_SHA1withRSA_1024);
+        certmap.put("trustAnchor_SHA1withRSA_512",
+                                    trustAnchor_SHA1withRSA_512);
+        certmap.put("intermediate_SHA1withRSA_1024_1024",
+                                    intermediate_SHA1withRSA_1024_1024);
+        certmap.put("intermediate_SHA1withRSA_1024_512",
+                                    intermediate_SHA1withRSA_1024_512);
+        certmap.put("intermediate_SHA1withRSA_512_1024",
+                                    intermediate_SHA1withRSA_512_1024);
+        certmap.put("intermediate_SHA1withRSA_512_512",
+                                    intermediate_SHA1withRSA_512_512);
+        certmap.put("intermediate_MD2withRSA_1024_1024",
+                                    intermediate_MD2withRSA_1024_1024);
+        certmap.put("intermediate_MD2withRSA_1024_512",
+                                    intermediate_MD2withRSA_1024_512);
+        certmap.put("endentiry_SHA1withRSA_1024_1024",
+                                    endentiry_SHA1withRSA_1024_1024);
+        certmap.put("endentiry_SHA1withRSA_1024_512",
+                                    endentiry_SHA1withRSA_1024_512);
+        certmap.put("endentiry_SHA1withRSA_512_1024",
+                                    endentiry_SHA1withRSA_512_1024);
+        certmap.put("endentiry_SHA1withRSA_512_512",
+                                    endentiry_SHA1withRSA_512_512);
+        certmap.put("endentiry_MD2withRSA_1024_1024",
+                                    endentiry_MD2withRSA_1024_1024);
+        certmap.put("endentiry_MD2withRSA_1024_512",
+                                    endentiry_MD2withRSA_1024_512);
+    }
+
+    private static Set<TrustAnchor> generateTrustAnchors()
+            throws CertificateException {
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        HashSet<TrustAnchor> anchors = new HashSet<TrustAnchor>();
+
+        ByteArrayInputStream is =
+            new ByteArrayInputStream(trustAnchor_SHA1withRSA_1024.getBytes());
+        Certificate cert = cf.generateCertificate(is);
+        TrustAnchor anchor = new TrustAnchor((X509Certificate)cert, null);
+        anchors.add(anchor);
+
+        is = new ByteArrayInputStream(trustAnchor_SHA1withRSA_512.getBytes());
+        cert = cf.generateCertificate(is);
+        anchor = new TrustAnchor((X509Certificate)cert, null);
+        anchors.add(anchor);
+
+        return anchors;
+    }
+
+    private static CertStore generateCertificateStore() throws Exception {
+        Collection entries = new HashSet();
+
+        // generate certificate from certificate string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        for (String key : certmap.keySet()) {
+            String certStr = certmap.get(key);
+            ByteArrayInputStream is =
+                        new ByteArrayInputStream(certStr.getBytes());;
+            Certificate cert = cf.generateCertificate(is);
+            entries.add(cert);
+        }
+
+        return CertStore.getInstance("Collection",
+                            new CollectionCertStoreParameters(entries));
+    }
+
+    private static X509CertSelector generateSelector(String name)
+                throws Exception {
+        X509CertSelector selector = new X509CertSelector();
+
+        String certStr = certmap.get(name);
+        if (certStr == null) {
+            return null;
+        }
+
+        // generate certificate from certificate string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        ByteArrayInputStream is = new ByteArrayInputStream(certStr.getBytes());
+        X509Certificate target = (X509Certificate)cf.generateCertificate(is);
+
+        selector.setCertificate(target);
+
+        return selector;
+    }
+
+    private static boolean match(String name, Certificate cert)
+                throws Exception {
+        X509CertSelector selector = new X509CertSelector();
+
+        String certStr = certmap.get(name);
+        if (certStr == null) {
+            return false;
+        }
+
+        // generate certificate from certificate string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        ByteArrayInputStream is = new ByteArrayInputStream(certStr.getBytes());
+        X509Certificate target = (X509Certificate)cf.generateCertificate(is);
+
+        return target.equals(cert);
+    }
+
+    public static void main(String args[]) throws Exception {
+
+        CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
+
+        X509CertSelector selector = generateSelector(args[0]);
+        if (selector == null) {
+            // no target certificate, ignore it
+            return;
+        }
+
+        Set<TrustAnchor> anchors = generateTrustAnchors();
+        CertStore certs = generateCertificateStore();
+
+        PKIXBuilderParameters params =
+                new PKIXBuilderParameters(anchors, selector);
+        params.addCertStore(certs);
+        params.setRevocationEnabled(false);
+        params.setDate(new Date(109, 9, 1));   // 2009-09-01
+
+        boolean success = Boolean.valueOf(args[2]);
+        try {
+            PKIXCertPathBuilderResult result =
+                        (PKIXCertPathBuilderResult)builder.build(params);
+            if (!success) {
+                throw new Exception("expected algorithm disabled exception");
+            }
+
+            int length = Integer.parseInt(args[1]);
+            List<? extends Certificate> path =
+                                    result.getCertPath().getCertificates();
+            if (length != path.size()) {
+                throw new Exception("unexpected certification path length");
+            }
+
+            if (!path.isEmpty()) {    // the target is not a trust anchor
+                if (!match(args[0], path.get(0))) {
+                    throw new Exception("unexpected certificate");
+                }
+            }
+        } catch (CertPathBuilderException cpbe) {
+            if (success) {
+                throw new Exception("unexpected exception");
+            } else {
+                System.out.println("Get the expected exception " + cpbe);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ *
+ * @bug 6861062
+ * @summary Disable MD2 support
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.SocketException;
+import java.util.*;
+import java.security.Security;
+import java.security.cert.*;
+
+public class CPValidatorEndEntity {
+
+    // SHA1withRSA 1024
+    static String trustAnchor_SHA1withRSA_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
+        "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" +
+        "AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH\n" +
+        "E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd\n" +
+        "rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID\n" +
+        "AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME\n" +
+        "QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" +
+        "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw\n" +
+        "DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z\n" +
+        "Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+\n" +
+        "UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc\n" +
+        "tas=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512
+    static String trustAnchor_SHA1withRSA_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
+        "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB\n" +
+        "BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv\n" +
+        "7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU\n" +
+        "g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ\n" +
+        "5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G\n" +
+        "A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b\n" +
+        "FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia\n" +
+        "U5r+8B9nzx+j2Zh3kw==\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 1024
+    static String intermediate_SHA1withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDhaFw0yOTA0MjMwMTExNDha\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADgYEAHze3wAcIe84zNOoN\n" +
+        "P8l9EmlVVoU30z3LB3hxq3m/dC/4gE5Z9Z8EG1wJw4qaxlTZ4dif12nbTTdofVhb\n" +
+        "Bd4syjo6fcUA4q7sfg9TFpoHQ+Ap7PgjK99moMKdMy50Xy8s6FPvaVkF89s66Z6y\n" +
+        "e4q7TSwe6QevGOZaL5N/iy2XGEs=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 512
+    static String intermediate_SHA1withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICDzCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADQQCYNmdkONfuk07XjRze\n" +
+        "WQyq2cfdae4uIdyUfa2rpgYMtSXuQW3/XrQGiz4G6WBXA2wo7folOOpAKYgvHPrm\n" +
+        "w6Dd\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 1024
+    static String intermediate_SHA1withRSA_512_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICDDCCAXWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
+        "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
+        "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
+        "PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
+        "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
+        "CSqGSIb3DQEBBQUAA4GBAE2VOlw5ySLT3gUzKCYEga4QPaSrf6lHHPi2g48LscEY\n" +
+        "h9qQXh4nuIVugReBIEf6N49RdT+M2cgRJo4sZ3ukYLGQzxNuttL5nPSuuvrAR1oG\n" +
+        "LUyzOWcUpKHbVHi6zlTt79RvTKZvLcduLutmtPtLJcM9PdiAI1wEooSgxTwZtB/Z\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 512
+    static String intermediate_SHA1withRSA_512_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIByzCCAXWgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
+        "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
+        "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
+        "PoAUg4Kwd47hdNQBp8grZsRJ5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
+        "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
+        "CSqGSIb3DQEBBQUAA0EAoCf0Zu559qcB4xPpzqkVsYiyW49S4Yc0mmQXb1yoQgLx\n" +
+        "O+DCkjG5d14+t1MsnkhB2izoQUMxQ3vDc1YnA/tEpw==\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 1024
+    static String intermediate_MD2withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICUDCCAbmgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADgYEAPtEjwbWuC5kc4DPc\n" +
+        "Ttf/wdbD8ZCdAWzcc3XF9q1TlvwVMNk6mbfM05y6ZVsztKTkwZ4EcvFu/yIqw1EB\n" +
+        "E1zlXQCaWXT3/ZMbqYZV4+mx+RUl8spUCb1tda25jnTg3mTOzB1iztm4gy903EMd\n" +
+        "m8omKDKeCgcw5dR4ITQYvyxe1as=\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 512
+    static String intermediate_MD2withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICDzCCAbmgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADQQBHok1v6xymtpB7N9xy\n" +
+        "0OmDT27uhmzlP0eOzJvXVxj3Oi9TLQJgCUJ9122MzfRAs1E1uJTtvuu+UmI80NQx\n" +
+        "KQdp\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 1024
+    static String endentiry_SHA1withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
+        "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
+        "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
+        "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
+        "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
+        "OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG\n" +
+        "9w0BAQUFAAOBgQAOfIeasDg91CR3jGfuAEVKwncM1OPFmniAUcdPm74cCAyJ90Me\n" +
+        "dhUElWPGoAuXGfiyZlOlGUYWqEroe/dnkmnotJjLWR+MA4ZyX3O1YI8T4W3deWcC\n" +
+        "J4WMCF7mp17SaYYKX9F0AxwNJFpUkbB41IkTxPr0MmzB1871/pbY8dLAvA==\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 512
+    static String endentiry_SHA1withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIB9jCCAaCgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
+        "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
+        "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
+        "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
+        "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
+        "OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG\n" +
+        "9w0BAQUFAANBADV6X+ea0ftEKXy7yKNAbdIp35893T6AVwbdclomPkeOs86OtoTG\n" +
+        "1BIzWSK9QE7W6Wbf63e2RdcqoLK+DxsuwUg=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 1024
+    static String endentiry_SHA1withRSA_512_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIB8zCCAVygAwIBAgIBBDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3\n" +
+        "DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo\n" +
+        "uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE\n" +
+        "AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU\n" +
+        "31g/ZkU6aXFAJVKhrrv0ebfAgeYwDQYJKoZIhvcNAQEFBQADgYEAUyW8PrEdbzLu\n" +
+        "B+h6UemBOJ024rYq90hJE/5wUEKPvxZ9vPEUgl+io6cGhL3cLfxfh6z5xtEGp4Tb\n" +
+        "NB0Ye3Qi01FBiNDY8s3rQRrmel6VysU8u+0Oi2jmQY6vZXn/zXN5rrTLITCaSicG\n" +
+        "dOMv1xLM83Ee432WWlDwKOUxhzDGpWc=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 512
+    static String endentiry_SHA1withRSA_512_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIBsjCCAVygAwIBAgIBBTANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3\n" +
+        "DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo\n" +
+        "uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE\n" +
+        "AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU\n" +
+        "N0CHiTYPtjyvpP2a6y6mhsZ6U40wDQYJKoZIhvcNAQEFBQADQQBG4grtrVEHick0\n" +
+        "z/6Lcl/MGyHT0c8KTXE0AMVXG1NRjAicAmYno/yDaJ9OmfymObKZKV9fF7yCW/N/\n" +
+        "TMU6m7N0\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 1024
+    static String endentiry_MD2withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICNzCCAaCgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
+        "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
+        "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
+        "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
+        "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
+        "OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG\n" +
+        "9w0BAQIFAAOBgQBxKsFf8NNQcXjDoKJJSG4Rk6ikcrhiGYuUI32+XHvs6hnav1Zc\n" +
+        "aJUpy7J4gMj/MnysMh/4AF9+m6zEEjuisXKUbYZhgtJxz+ukGSo163mJ8QJiAlRb\n" +
+        "Iwsy81r08mlSCR6jx2YhDAUxJIPC92R5Vb4CEutB7tWTwwz7vIHq330erA==\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 512
+    static String endentiry_MD2withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIB9jCCAaCgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
+        "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
+        "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
+        "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
+        "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
+        "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
+        "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
+        "OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG\n" +
+        "9w0BAQIFAANBAIX63Ypi9P71RnC/pcMbhD+wekRFsTzU593X3MC7tyBJtEXwvAZG\n" +
+        "iMxXF5A+ohlr7/CrkV7ZTL8PLxnJdY5Y8rQ=\n" +
+        "-----END CERTIFICATE-----";
+
+    private static CertPath generateCertificatePath(String castr,
+            String eestr) throws CertificateException {
+        // generate certificate from cert strings
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        ByteArrayInputStream is;
+
+        is = new ByteArrayInputStream(castr.getBytes());
+        Certificate cacert = cf.generateCertificate(is);
+
+        is = new ByteArrayInputStream(eestr.getBytes());
+        Certificate eecert = cf.generateCertificate(is);
+
+        // generate certification path
+        List<Certificate> list = Arrays.asList(new Certificate[] {
+                        eecert, cacert});
+
+        return cf.generateCertPath(list);
+    }
+
+    private static Set<TrustAnchor> generateTrustAnchors()
+            throws CertificateException {
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        HashSet<TrustAnchor> anchors = new HashSet<TrustAnchor>();
+
+        ByteArrayInputStream is =
+            new ByteArrayInputStream(trustAnchor_SHA1withRSA_1024.getBytes());
+        Certificate cert = cf.generateCertificate(is);
+        TrustAnchor anchor = new TrustAnchor((X509Certificate)cert, null);
+        anchors.add(anchor);
+
+        is = new ByteArrayInputStream(trustAnchor_SHA1withRSA_512.getBytes());
+        cert = cf.generateCertificate(is);
+        anchor = new TrustAnchor((X509Certificate)cert, null);
+        anchors.add(anchor);
+
+        return anchors;
+    }
+
+    public static void main(String args[]) throws Exception {
+        try {
+            validate(endentiry_SHA1withRSA_1024_1024,
+                                    intermediate_SHA1withRSA_1024_1024);
+            validate(endentiry_SHA1withRSA_1024_512,
+                                    intermediate_SHA1withRSA_512_1024);
+            validate(endentiry_SHA1withRSA_512_1024,
+                                    intermediate_SHA1withRSA_1024_1024);
+            validate(endentiry_SHA1withRSA_512_512,
+                                    intermediate_SHA1withRSA_512_1024);
+        } catch (CertPathValidatorException cpve) {
+            throw new Exception(
+                "unexpect exception, it is valid cert", cpve);
+        }
+
+        try {
+            validate(endentiry_MD2withRSA_1024_1024,
+                                    intermediate_SHA1withRSA_1024_1024);
+            throw new Exception("expected algorithm disabled exception");
+        } catch (CertPathValidatorException cpve) {
+            System.out.println("Get the expected exception " + cpve);
+        }
+
+        try {
+            validate(endentiry_MD2withRSA_1024_512,
+                                    intermediate_SHA1withRSA_512_1024);
+            throw new Exception("expected algorithm disabled exception");
+        } catch (CertPathValidatorException cpve) {
+            System.out.println("Get the expected exception " + cpve);
+        }
+    }
+
+    private static void validate(String eecert, String cacert)
+            throws CertPathValidatorException, Exception {
+
+        CertPath path = generateCertificatePath(cacert, eecert);
+        Set<TrustAnchor> anchors = generateTrustAnchors();
+
+        PKIXParameters params = new PKIXParameters(anchors);
+
+        // disable certificate revocation checking
+        params.setRevocationEnabled(false);
+
+        // set the validation time
+        params.setDate(new Date(109, 9, 1));   // 2009-09-01
+
+        CertPathValidator validator = CertPathValidator.getInstance("PKIX");
+
+        validator.validate(path, params);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ *
+ * @bug 6861062
+ * @summary Disable MD2 support
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.SocketException;
+import java.util.*;
+import java.security.Security;
+import java.security.cert.*;
+
+public class CPValidatorIntermediate {
+
+    // SHA1withRSA 1024
+    static String trustAnchor_SHA1withRSA_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
+        "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" +
+        "AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH\n" +
+        "E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd\n" +
+        "rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID\n" +
+        "AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME\n" +
+        "QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" +
+        "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw\n" +
+        "DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z\n" +
+        "Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+\n" +
+        "UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc\n" +
+        "tas=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512
+    static String trustAnchor_SHA1withRSA_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
+        "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB\n" +
+        "BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv\n" +
+        "7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU\n" +
+        "g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ\n" +
+        "5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G\n" +
+        "A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b\n" +
+        "FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia\n" +
+        "U5r+8B9nzx+j2Zh3kw==\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 1024
+    static String intermediate_SHA1withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDhaFw0yOTA0MjMwMTExNDha\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADgYEAHze3wAcIe84zNOoN\n" +
+        "P8l9EmlVVoU30z3LB3hxq3m/dC/4gE5Z9Z8EG1wJw4qaxlTZ4dif12nbTTdofVhb\n" +
+        "Bd4syjo6fcUA4q7sfg9TFpoHQ+Ap7PgjK99moMKdMy50Xy8s6FPvaVkF89s66Z6y\n" +
+        "e4q7TSwe6QevGOZaL5N/iy2XGEs=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 1024 signed with RSA 512
+    static String intermediate_SHA1withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICDzCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADQQCYNmdkONfuk07XjRze\n" +
+        "WQyq2cfdae4uIdyUfa2rpgYMtSXuQW3/XrQGiz4G6WBXA2wo7folOOpAKYgvHPrm\n" +
+        "w6Dd\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 1024
+    static String intermediate_SHA1withRSA_512_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICDDCCAXWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
+        "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
+        "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
+        "PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
+        "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
+        "CSqGSIb3DQEBBQUAA4GBAE2VOlw5ySLT3gUzKCYEga4QPaSrf6lHHPi2g48LscEY\n" +
+        "h9qQXh4nuIVugReBIEf6N49RdT+M2cgRJo4sZ3ukYLGQzxNuttL5nPSuuvrAR1oG\n" +
+        "LUyzOWcUpKHbVHi6zlTt79RvTKZvLcduLutmtPtLJcM9PdiAI1wEooSgxTwZtB/Z\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512 signed with RSA 512
+    static String intermediate_SHA1withRSA_512_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIByzCCAXWgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
+        "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
+        "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
+        "PoAUg4Kwd47hdNQBp8grZsRJ5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
+        "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
+        "CSqGSIb3DQEBBQUAA0EAoCf0Zu559qcB4xPpzqkVsYiyW49S4Yc0mmQXb1yoQgLx\n" +
+        "O+DCkjG5d14+t1MsnkhB2izoQUMxQ3vDc1YnA/tEpw==\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 1024
+    static String intermediate_MD2withRSA_1024_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICUDCCAbmgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADgYEAPtEjwbWuC5kc4DPc\n" +
+        "Ttf/wdbD8ZCdAWzcc3XF9q1TlvwVMNk6mbfM05y6ZVsztKTkwZ4EcvFu/yIqw1EB\n" +
+        "E1zlXQCaWXT3/ZMbqYZV4+mx+RUl8spUCb1tda25jnTg3mTOzB1iztm4gy903EMd\n" +
+        "m8omKDKeCgcw5dR4ITQYvyxe1as=\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 1024 signed with RSA 512
+    static String intermediate_MD2withRSA_1024_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICDzCCAbmgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
+        "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
+        "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
+        "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
+        "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
+        "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
+        "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
+        "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
+        "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADQQBHok1v6xymtpB7N9xy\n" +
+        "0OmDT27uhmzlP0eOzJvXVxj3Oi9TLQJgCUJ9122MzfRAs1E1uJTtvuu+UmI80NQx\n" +
+        "KQdp\n" +
+        "-----END CERTIFICATE-----";
+
+    private static CertPath generateCertificatePath(String certStr)
+            throws CertificateException {
+        // generate certificate from cert strings
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        ByteArrayInputStream is;
+
+        is = new ByteArrayInputStream(certStr.getBytes());
+        Certificate cert = cf.generateCertificate(is);
+
+        // generate certification path
+        List<Certificate> list = Arrays.asList(new Certificate[] {cert});
+
+        return cf.generateCertPath(list);
+    }
+
+    private static Set<TrustAnchor> generateTrustAnchors()
+            throws CertificateException {
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        HashSet<TrustAnchor> anchors = new HashSet<TrustAnchor>();
+
+        ByteArrayInputStream is =
+            new ByteArrayInputStream(trustAnchor_SHA1withRSA_1024.getBytes());
+        Certificate cert = cf.generateCertificate(is);
+        TrustAnchor anchor = new TrustAnchor((X509Certificate)cert, null);
+        anchors.add(anchor);
+
+        is = new ByteArrayInputStream(trustAnchor_SHA1withRSA_512.getBytes());
+        cert = cf.generateCertificate(is);
+        anchor = new TrustAnchor((X509Certificate)cert, null);
+        anchors.add(anchor);
+
+        return anchors;
+    }
+
+    public static void main(String args[]) throws Exception {
+        try {
+            validate(intermediate_SHA1withRSA_1024_1024);
+            validate(intermediate_SHA1withRSA_1024_512);
+            validate(intermediate_SHA1withRSA_512_1024);
+            validate(intermediate_SHA1withRSA_512_512);
+        } catch (CertPathValidatorException cpve) {
+            throw new Exception(
+                "unexpect exception, it is valid cert", cpve);
+        }
+
+        try {
+            validate(intermediate_MD2withRSA_1024_1024);
+            throw new Exception("expected algorithm disabled exception");
+        } catch (CertPathValidatorException cpve) {
+            System.out.println("Get the expected exception " + cpve);
+        }
+
+        try {
+            validate(intermediate_MD2withRSA_1024_512);
+            throw new Exception("expected algorithm disabled exception");
+        } catch (CertPathValidatorException cpve) {
+            System.out.println("Get the expected exception " + cpve);
+        }
+    }
+
+    private static void validate(String intermediate)
+            throws CertPathValidatorException, Exception {
+
+        CertPath path = generateCertificatePath(intermediate);
+        Set<TrustAnchor> anchors = generateTrustAnchors();
+
+        PKIXParameters params = new PKIXParameters(anchors);
+
+        // disable certificate revocation checking
+        params.setRevocationEnabled(false);
+
+        // set the validation time
+        params.setDate(new Date(109, 9, 1));   // 2009-09-01
+
+        CertPathValidator validator = CertPathValidator.getInstance("PKIX");
+
+        validator.validate(path, params);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ *
+ * @bug 6861062
+ * @summary Disable MD2 support
+ *
+ * @author Xuelei Fan
+ */
+
+import java.io.*;
+import java.net.SocketException;
+import java.util.*;
+import java.security.Security;
+import java.security.cert.*;
+
+public class CPValidatorTrustAnchor {
+
+    static String selfSignedCertStr = null;
+
+    // SHA1withRSA 1024
+    static String trustAnchor_SHA1withRSA_1024 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
+        "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" +
+        "AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH\n" +
+        "E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd\n" +
+        "rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID\n" +
+        "AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME\n" +
+        "QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" +
+        "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw\n" +
+        "DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z\n" +
+        "Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+\n" +
+        "UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc\n" +
+        "tas=\n" +
+        "-----END CERTIFICATE-----";
+
+    // SHA1withRSA 512
+    static String trustAnchor_SHA1withRSA_512 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
+        "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB\n" +
+        "BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv\n" +
+        "7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU\n" +
+        "g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ\n" +
+        "5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G\n" +
+        "A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b\n" +
+        "FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia\n" +
+        "U5r+8B9nzx+j2Zh3kw==\n" +
+        "-----END CERTIFICATE-----";
+
+    // MD2withRSA 2048
+    static String trustAnchor_MD2withRSA_2048 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIDQzCCAiugAwIBAgIBADANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
+        "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDdaFw0zMDA3MTcwMTExNDda\n" +
+        "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIIBIjANBgkqhkiG9w0B\n" +
+        "AQEFAAOCAQ8AMIIBCgKCAQEArF5pINc5s+aUlmdYlxtAQ3V4TXFnP/XOYHxjfLuX\n" +
+        "eKO/kh78LMvbDisTPQ2yo9YEawwwbUU40xcuzgi0axXgKveHXYdUmTr0hEapq3rv\n" +
+        "g/q2EbOjyXvq4qK2RDoVCN8R3wXiytnY2OFALTx6zc2tW4imJ20svdNVtWhv2syj\n" +
+        "ZTmmRXAeFUbD4qKWAFij0I6pnSgVssvWzeyJUNemym+oiYyaSd7n5j1RNAqUKioo\n" +
+        "K/T0FOOiuPGMqottgx5YRHa6yapCP5QVWRQ+WBIYJY3Wyq7N+Es20LT6761Pk3to\n" +
+        "EFCzM7+zqT/c+pC079HOKXz+m2us+HKp5BKWNnbvgaYPOQIDAQABo4GJMIGGMB0G\n" +
+        "A1UdDgQWBBSrSukJf+mO5LTRasAGD9RRs7SASTBHBgNVHSMEQDA+gBSrSukJf+mO\n" +
+        "5LTRasAGD9RRs7SASaEjpCEwHzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1w\n" +
+        "bGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEC\n" +
+        "BQADggEBAHvsv+DqMJeIW/D+ltkhw37OdMzkMPp4E6Hbp03O3GZ5LfNGczHCb2uL\n" +
+        "sr5T7e/jaBFn6QfmqbOAYAHJSNq2bNNtTbatnHBLuVx13cfxmwk89Cg/tFeoUdcf\n" +
+        "m5hzurB6Ub6SsYMOxZHUYp/KxM9x9a7llC1bK3SKXwd4rVDlXh8DOBvdQNr5Q3yq\n" +
+        "JjY86bSXO14VzNxL/1rqHiszQdPyR/28SBsQVYSi0Zeyc4Yy1ui/cXu1+PWYw3YZ\n" +
+        "QUPHTnkVdPGwRiUqeZIcps+q+ePlQQmDu5qiLD6d8gsyGyY/RvCHWKO5Y9DuX9hs\n" +
+        "he/AhCWQx+TQYGLu0liQqLkGZydyRnA=\n" +
+        "-----END CERTIFICATE-----";
+
+    private static CertPath generateCertificatePath()
+            throws CertificateException {
+        // generate certificate from cert strings
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        ByteArrayInputStream is;
+
+        is = new ByteArrayInputStream(selfSignedCertStr.getBytes());
+        Certificate selfSignedCert = cf.generateCertificate(is);
+
+        // generate certification path
+        List<Certificate> list = Arrays.asList(new Certificate[] {
+                        selfSignedCert});
+
+        return cf.generateCertPath(list);
+    }
+
+    private static Set<TrustAnchor> generateTrustAnchors()
+            throws CertificateException {
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        ByteArrayInputStream is =
+                    new ByteArrayInputStream(selfSignedCertStr.getBytes());
+        Certificate selfSignedCert = cf.generateCertificate(is);
+
+        // generate a trust anchor
+        TrustAnchor anchor =
+            new TrustAnchor((X509Certificate)selfSignedCert, null);
+
+        return Collections.singleton(anchor);
+    }
+
+    public static void main(String args[]) throws Exception {
+        try {
+            validate(trustAnchor_SHA1withRSA_1024);
+            validate(trustAnchor_SHA1withRSA_512);
+        } catch (CertPathValidatorException cpve) {
+            throw new Exception(
+                "unexpect exception, it is valid cert", cpve);
+        }
+
+        try {
+            validate(trustAnchor_MD2withRSA_2048);
+            throw new Exception("expected algorithm disabled exception");
+        } catch (CertPathValidatorException cpve) {
+            System.out.println("Get the expected exception " + cpve);
+        }
+    }
+
+    private static void validate(String trustAnchor)
+            throws CertPathValidatorException, Exception {
+        selfSignedCertStr = trustAnchor;
+
+        CertPath path = generateCertificatePath();
+        Set<TrustAnchor> anchors = generateTrustAnchors();
+
+        PKIXParameters params = new PKIXParameters(anchors);
+
+        // disable certificate revocation checking
+        params.setRevocationEnabled(false);
+
+        // set the validation time
+        params.setDate(new Date(109, 9, 1));   // 2009-09-01
+
+        CertPathValidator validator = CertPathValidator.getInstance("PKIX");
+
+        validator.validate(path, params);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/certpath/DisabledAlgorithms/README	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,640 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+                  Certificates and CRLs
+
+Here lists the Certificates, which was generated by generate.sh, used in the
+test cases.
+
+The generate.sh depends on openssl, and it should be run under ksh. The
+script will create many directories and files, please run it in a
+directory outside of JDK workspace.
+
+1. root certifiate and key (SHA1withRSA 1024, root_cert_sha1_1024.pem)
+-----BEGIN CERTIFICATE-----
+MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa
+MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH
+E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd
+rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID
+AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME
+QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO
+BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw
+DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z
+Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+
+UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc
+tas=
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,DF5249E009A0FD79
+
+rc316yLipp/vH0i6rhEbEwZpZ+HfKIXnnp/bIIZv2+4lyGUDWrxN0Hk0TcSgWEKm
+dRGI2fsyWjTgaiHwwmusofXPAjB3s0I2rUUAHXk8/sEuiLLTICx2UAL8k6R33CSQ
+NKR8t+TluBW3Us71vibWauuMHa5860KiiLWdhkQVLin7m/JBGLtz0zQ0/lZ8CgEm
+p7eDupPi8FBClCyVewdpmKjgI2KPI4fVIZLMzLeGcWLaOQPN1ERcFWQ1CS/qjfMb
+F4rtpZ+AzCqP75XPhitT2CnZgaVDxHBtAZQVPuKONMdijKphjqiT/Sd86Gx6OEVE
+EwwmQya2Q/5aCuH96S00mj00oeIZ7ZtUcVQcch+saJy4vpuxK8pFcEDKmgsvL9+8
+Hho9RUXVUKRH67uA1NjQSK5+syEIj5sJCDcxOda4QGXeIq9ygaZswxF3nfvffrsa
+S6IVBXrx0G+Ascu29SHoI+zi3feQszQJIzijHoTTq6FacLHUWzfVuaYa47uaj5qa
+VYsMVCzi1eX486o7YKPKWiclNczQN86v5n9+c9uggXY12wSOmnf6BB1Ds+oL8JlU
+IZa67lAyg6G9joAb9rTXN2EE5OTArcFuImK8GHse/3wkIPMglBNnfwpvjC1U+vQm
+F7iXp+OxnZ5d9sBcrTBEZ9BDlTVlpiZI7EeS1oC8x6DDTdbJR/40Y3wJIDMI9q9T
+O5EnyXqbmQziO0Tgal43w6mMTUnhG34kqovwxy03mAOZb3yz/RgWlez9wQmPseiI
+2p2fQIjCPbGFNJt3rdyXOW/BRCii0970HEZeov/TVV/A0vUVajNAjA==
+-----END RSA PRIVATE KEY-----
+
+2. root certifiate and key (SHA1withRSA 512, root_cert_sha1_512.pem)
+-----BEGIN CERTIFICATE-----
+MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa
+MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB
+BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv
+7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU
+g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ
+5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G
+A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b
+FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia
+U5r+8B9nzx+j2Zh3kw==
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B8BDE38F08C6BB76
+
+eJzx2oZE0UXxWpzssSWtKBOCbm3ZXR6iBKX8iKoDUB5SzzmKr+XzxI7kyv92y0pe
+rNTuuCWpBsLdlz7h8Ipn4pBDYswGU5F9MQOEgIYx60OvGhZODHGRzJ05FXTeCmmu
+LLp6lGW4SWALcd8g/gJUn1/vp7f1VzQ7RwXWBn4/b34RRYtwr3E6nl4Hc2tEI1in
+OL+lCdAAyxjGK7KYFHJQK+1E8tYNrer3cejQDcNysGx4o0H123vfp3NtJ6U7LXyi
+D21y3zmPueJos8LluJiLRsONcrcI3mIfpPBsO+Yl2EJtzS9V6Aaq/YdPkwPHH6Y5
+lazGMPXq/nffb12fWLL7m5aFb3FNLwWi/qwEynWCEv7Vl/6kLk+aHhjTnYkLvLNH
+9maQFn6j0S3wqogRfW9BDbfC3fRHP6+8YjEEmQ0RTfE=
+-----END RSA PRIVATE KEY-----
+
+3. root certifiate and key (MD2withRSA 2048, root_cert_md2_2048.pem)
+-----BEGIN CERTIFICATE-----
+MIIDQzCCAiugAwIBAgIBADANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDdaFw0zMDA3MTcwMTExNDda
+MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEArF5pINc5s+aUlmdYlxtAQ3V4TXFnP/XOYHxjfLuX
+eKO/kh78LMvbDisTPQ2yo9YEawwwbUU40xcuzgi0axXgKveHXYdUmTr0hEapq3rv
+g/q2EbOjyXvq4qK2RDoVCN8R3wXiytnY2OFALTx6zc2tW4imJ20svdNVtWhv2syj
+ZTmmRXAeFUbD4qKWAFij0I6pnSgVssvWzeyJUNemym+oiYyaSd7n5j1RNAqUKioo
+K/T0FOOiuPGMqottgx5YRHa6yapCP5QVWRQ+WBIYJY3Wyq7N+Es20LT6761Pk3to
+EFCzM7+zqT/c+pC079HOKXz+m2us+HKp5BKWNnbvgaYPOQIDAQABo4GJMIGGMB0G
+A1UdDgQWBBSrSukJf+mO5LTRasAGD9RRs7SASTBHBgNVHSMEQDA+gBSrSukJf+mO
+5LTRasAGD9RRs7SASaEjpCEwHzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1w
+bGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEC
+BQADggEBAHvsv+DqMJeIW/D+ltkhw37OdMzkMPp4E6Hbp03O3GZ5LfNGczHCb2uL
+sr5T7e/jaBFn6QfmqbOAYAHJSNq2bNNtTbatnHBLuVx13cfxmwk89Cg/tFeoUdcf
+m5hzurB6Ub6SsYMOxZHUYp/KxM9x9a7llC1bK3SKXwd4rVDlXh8DOBvdQNr5Q3yq
+JjY86bSXO14VzNxL/1rqHiszQdPyR/28SBsQVYSi0Zeyc4Yy1ui/cXu1+PWYw3YZ
+QUPHTnkVdPGwRiUqeZIcps+q+ePlQQmDu5qiLD6d8gsyGyY/RvCHWKO5Y9DuX9hs
+he/AhCWQx+TQYGLu0liQqLkGZydyRnA=
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,3910D329AD49ECFC
+
+6K0OU3Xrl2H6kz7x7EHXkM0/Wd6jXBBwWsaroUIGnbIMmljJXPfgcuDUu6f5Imk1
+ndoU0GWjxa1QNjteAQQtFoLDP8rienLs0b969OcAxB0EOffQFkEfsfXdyEIgdwkD
+ETczwDIyd8Wj62ClydJES3jKB9Nc9kMIlsoZ+h24TyJeeRsHAtMrz+mlOHsUWDQ5
+FyYZelnx+fQ5maD3bura7xLiNl8CvgWz0wt2Wt4djdMGhQ3OWd0/GWweP+2xnL6n
+5tDJ5On50+Z5T8Jhx62yg+wQiBKAYnYw6OX3skJwWknuAvYz3Z3e12DHFx6w5EAU
+K7lg7fHMqHNirUkJOlYzgJ21ybV4uQmFRNQJwI9h6GVfdZWPEU+Ni42AlNgNYskF
+K19dONNNt0Gwkcm2VOYzwYGDyaQW2YIGDk1fbZdVSu/h/lyOC/RmorGWroAbYsyB
+/GUIilcLtQHPGI8XuojTS2/UWcKactpceN3UOnQkus3/smViEqqB/NQ/lcozgs0o
+7ZG6H6to7w1yb5VR2d7B2bS7MNJt1AsOB5ydAMYIccdHDTI7CfRK6axQ70O/JPnJ
+WLY2e41ig2uAWk/3fRb8L6d3keVcN7y4WnkXPbHhulqtxQo78iSQQAf7tDMBxWKx
+C5LQW3CxLkHKp6g22SDxl2LjJyu5nDbtIh3Pq+BCoA25uqXC4rPoWwV7EWYv8Z+Y
+E6dS98SEa+cDhpllvGzbTKgcP1VqtQbb9VT92UT1mFrklqRuQIxROeCe4wjp5TKo
+D2losUDdzpqBHkBNo2I8qZkgybeCvWEq73my2+JG1AAIFFB1kzfBNaBDGiGSuUuS
+5peV8156aaLg5pxdieoRJ3Y7eaWN1wH5CnRnafoB+lxSUsQO1a7y2LbpedrKjs+2
+AryPHQw7HLd8IQevmvd7BhJLdvlt+kXzWID/pUsSAYvI7aP4daQJuAt/kwmU27Gd
+wqhV8Tjbb84vFGmqGHtb2YbKfUrsPUNOLBF+U4SDAgBhEyhINQZyRDcqqoywO5Dr
+sV46nTEfwAgt88KFt2CEhiyvoJbtCj1iMJeAzuljwF4z4RzB1i3TK0MaJYID2rxB
+E1vK9EZIssk/NeImN2YCbuqOhU58jtOwYh3ruS+mZQm1APvJF9N4tCCVQsjWC6zY
+4eqs7T6VDFH4AaT7b3J3rTsEpWIDUfagetZs5kR9SiWJC7dU7r53gGg4avVyIIHD
++MYCS+auD9/nmVf4iYstVgJFMUJXC2EUOLi0r8KmDkCILl/K3X/W7QwFTnC07gLh
+/9HjWFJ0R6cyODzvE8NGPMeuJGUT2F+mA1vaAC/PBGz+61AF0BjWTZ7x2sH+tSPP
+/GVEaCgyzrKRX5XX+7DulTcmFj1JNfMmtbDaJa9WnwOI4qszBGrAcYeYTHXR6Yov
+Ux/P6RStfa+UwSjo8i3nfdgLk+RXCpN0srMjSmiQx8d5R/kISqXKDtQfS5M6gsoh
+ROz+6zZP8Gh8yakr1p4C6JUSiLDYP5qXzxr8bp+oxvpY7anEDAqx21HyExEAu+gy
+IrNl75FWqV8BbKxoFfe9LqyDaryXXA8oy6F+4BT/zRrxp+dym9pbd+OZR423BIij
+-----END RSA PRIVATE KEY-----
+
+4. subca certificate and key (SHA1withRSA 1024, root_cert_sha1_1024.pem signed)
+-----BEGIN CERTIFICATE-----
+MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDhaFw0yOTA0MjMwMTExNDha
+MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
+cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8
+BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg
+bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82
+AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl
+UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw
+HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw
+AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADgYEAHze3wAcIe84zNOoN
+P8l9EmlVVoU30z3LB3hxq3m/dC/4gE5Z9Z8EG1wJw4qaxlTZ4dif12nbTTdofVhb
+Bd4syjo6fcUA4q7sfg9TFpoHQ+Ap7PgjK99moMKdMy50Xy8s6FPvaVkF89s66Z6y
+e4q7TSwe6QevGOZaL5N/iy2XGEs=
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0480E76FD259323B
+
+npiifBm1mHq1Z9QgAV5T35Xbnea9VnwqYQWNfRRKmpfYSdkQJ0few18YtnfZwh9e
+LKCWx+lq1V4yDG4SbxXDq71Dyvx1vZY+w4h+6M1+6KGFG1VDBfN3e5aLgK8EG9pZ
+yHZH7iB7HiQXH5q53jL6NUZn55C3XEk1sErpK7R1c0Y8Qp2TGiu+lck3K+zR9GiO
+5aJMKbShReB0Nfy3JJNKRFSd95QMTTjbq6iIvhN8O02bo4I4I3HTyD8qyR7ViiHl
+FmOukjwn4fjJvK0WYKYUjod8oEiMdR2nr73eOGZBAnEorDGQ8VnnCAleSv74is1k
+W7M07UP7EJJq9hSZfeMqk5QivtWrqvWG1SWxpTowKTEAyTn7u5U13k0DiRcsg0WT
+4mSMiLOhUNgIWcHElbTQPSVDcVznhNk0dWPDwKoUjp+orCuH+NvHKBAu+hnuip3e
+Ji7WGrHXI7QxAr5qr5ogl5x4yH4drIbq9fUea3NTuGPuPyu9fWjOSDmqPRKRMJFR
+UxxVFcyrW8iSBV5cvB7M1ADS40y6l4ryYmKjXbsOI4Ci8LJWJ4ZB61WQP7TvPQGS
+mNFmTTB2dwbpimr4KjV9j2bA9x0jAsjlcQZ5j1GOeyYCEDGKDJw0XD/zI+j0dpVc
+eu8YtuJGTyO1h+HiI3D9LrMuyUxxckvFHKe00+4xMz1hpqVo/kxe6gqf/9ES4M/h
+6/NeTzeqyJF2rgxK6KJJdmaKVYI+bvAQ3cKl+RZmgOjx4eig58N5uthqFgU7rQ+e
+GM9/y8C9WpPqITcJlY7I/7AkqvYDBwBsH/9mf4g9OUbC1Ah+MX8UIQ==
+-----END RSA PRIVATE KEY-----
+
+
+5. subca certificate and key (SHA1withRSA 1024, root_cert_sha1_512.pem signed)
+-----BEGIN CERTIFICATE-----
+MIICDzCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
+MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
+cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8
+BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg
+bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82
+AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl
+UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw
+HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw
+AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADQQCYNmdkONfuk07XjRze
+WQyq2cfdae4uIdyUfa2rpgYMtSXuQW3/XrQGiz4G6WBXA2wo7folOOpAKYgvHPrm
+w6Dd
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0480E76FD259323B
+
+npiifBm1mHq1Z9QgAV5T35Xbnea9VnwqYQWNfRRKmpfYSdkQJ0few18YtnfZwh9e
+LKCWx+lq1V4yDG4SbxXDq71Dyvx1vZY+w4h+6M1+6KGFG1VDBfN3e5aLgK8EG9pZ
+yHZH7iB7HiQXH5q53jL6NUZn55C3XEk1sErpK7R1c0Y8Qp2TGiu+lck3K+zR9GiO
+5aJMKbShReB0Nfy3JJNKRFSd95QMTTjbq6iIvhN8O02bo4I4I3HTyD8qyR7ViiHl
+FmOukjwn4fjJvK0WYKYUjod8oEiMdR2nr73eOGZBAnEorDGQ8VnnCAleSv74is1k
+W7M07UP7EJJq9hSZfeMqk5QivtWrqvWG1SWxpTowKTEAyTn7u5U13k0DiRcsg0WT
+4mSMiLOhUNgIWcHElbTQPSVDcVznhNk0dWPDwKoUjp+orCuH+NvHKBAu+hnuip3e
+Ji7WGrHXI7QxAr5qr5ogl5x4yH4drIbq9fUea3NTuGPuPyu9fWjOSDmqPRKRMJFR
+UxxVFcyrW8iSBV5cvB7M1ADS40y6l4ryYmKjXbsOI4Ci8LJWJ4ZB61WQP7TvPQGS
+mNFmTTB2dwbpimr4KjV9j2bA9x0jAsjlcQZ5j1GOeyYCEDGKDJw0XD/zI+j0dpVc
+eu8YtuJGTyO1h+HiI3D9LrMuyUxxckvFHKe00+4xMz1hpqVo/kxe6gqf/9ES4M/h
+6/NeTzeqyJF2rgxK6KJJdmaKVYI+bvAQ3cKl+RZmgOjx4eig58N5uthqFgU7rQ+e
+GM9/y8C9WpPqITcJlY7I/7AkqvYDBwBsH/9mf4g9OUbC1Ah+MX8UIQ==
+-----END RSA PRIVATE KEY-----
+
+
+6. subca certificate and key (SHA1withRSA 512, root_cert_sha1_1024.pem signed)
+-----BEGIN CERTIFICATE-----
+MIICDDCCAXWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
+MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
+cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV
+lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA
+AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw
+PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD
+VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G
+CSqGSIb3DQEBBQUAA4GBAE2VOlw5ySLT3gUzKCYEga4QPaSrf6lHHPi2g48LscEY
+h9qQXh4nuIVugReBIEf6N49RdT+M2cgRJo4sZ3ukYLGQzxNuttL5nPSuuvrAR1oG
+LUyzOWcUpKHbVHi6zlTt79RvTKZvLcduLutmtPtLJcM9PdiAI1wEooSgxTwZtB/Z
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0A94F7EA4C89CA33
+
+tfKdAZVSrpeS/hU4+mGYcGGx3nNqrE+CzDAfLadVuXz5ju5p9oFhLTZj99wK+uHn
+prrWmDNOdYKRBJn7h40WV6zi4lR3JgnuYNxH8fxO3PI+HQ9IuvdoTyqUeXTP4Zj1
+BCnr1k1D2WGDXvnh+saq9qRpMKThjK/OF0YmDa07PI5NOBdMA3EmkNYfwib2GfBV
+el4FVkfnPQkLGahTh3SC62TzPlnsAgirCeua7ZLPqN3fkZkYbXZd9op2D31n7cBP
+zztg0ah8WF4gPOd/BBZeR9XDog5qm/wzyBj0F6ClHRPjpGYhAm2Vw66xOBlGFYI9
+lVmFQzrPcDNlFTybzhl5C6Qy4cPQh+QErDWxljVI52oYYmY/KRmUGGL7hEG8ZGOn
+EUgFrEJyAY7w4wpBC5n9SotwyPXhwKQ1uCBq+1zElPw=
+-----END RSA PRIVATE KEY-----
+
+7. subca certificate and key (SHA1withRSA 512, root_cert_sha1_512.pem signed)
+-----BEGIN CERTIFICATE-----
+MIIByzCCAXWgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
+MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
+cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV
+lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA
+AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw
+PoAUg4Kwd47hdNQBp8grZsRJ5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD
+VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G
+CSqGSIb3DQEBBQUAA0EAoCf0Zu559qcB4xPpzqkVsYiyW49S4Yc0mmQXb1yoQgLx
+O+DCkjG5d14+t1MsnkhB2izoQUMxQ3vDc1YnA/tEpw==
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0A94F7EA4C89CA33
+
+tfKdAZVSrpeS/hU4+mGYcGGx3nNqrE+CzDAfLadVuXz5ju5p9oFhLTZj99wK+uHn
+prrWmDNOdYKRBJn7h40WV6zi4lR3JgnuYNxH8fxO3PI+HQ9IuvdoTyqUeXTP4Zj1
+BCnr1k1D2WGDXvnh+saq9qRpMKThjK/OF0YmDa07PI5NOBdMA3EmkNYfwib2GfBV
+el4FVkfnPQkLGahTh3SC62TzPlnsAgirCeua7ZLPqN3fkZkYbXZd9op2D31n7cBP
+zztg0ah8WF4gPOd/BBZeR9XDog5qm/wzyBj0F6ClHRPjpGYhAm2Vw66xOBlGFYI9
+lVmFQzrPcDNlFTybzhl5C6Qy4cPQh+QErDWxljVI52oYYmY/KRmUGGL7hEG8ZGOn
+EUgFrEJyAY7w4wpBC5n9SotwyPXhwKQ1uCBq+1zElPw=
+-----END RSA PRIVATE KEY-----
+
+8. subca certificate and key (MD2withRSA 1024, root_cert_sha1_1024.pem signed)
+-----BEGIN CERTIFICATE-----
+MIICUDCCAbmgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
+MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
+cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8
+BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg
+bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82
+AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl
+UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw
+HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw
+AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADgYEAPtEjwbWuC5kc4DPc
+Ttf/wdbD8ZCdAWzcc3XF9q1TlvwVMNk6mbfM05y6ZVsztKTkwZ4EcvFu/yIqw1EB
+E1zlXQCaWXT3/ZMbqYZV4+mx+RUl8spUCb1tda25jnTg3mTOzB1iztm4gy903EMd
+m8omKDKeCgcw5dR4ITQYvyxe1as=
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0480E76FD259323B
+
+npiifBm1mHq1Z9QgAV5T35Xbnea9VnwqYQWNfRRKmpfYSdkQJ0few18YtnfZwh9e
+LKCWx+lq1V4yDG4SbxXDq71Dyvx1vZY+w4h+6M1+6KGFG1VDBfN3e5aLgK8EG9pZ
+yHZH7iB7HiQXH5q53jL6NUZn55C3XEk1sErpK7R1c0Y8Qp2TGiu+lck3K+zR9GiO
+5aJMKbShReB0Nfy3JJNKRFSd95QMTTjbq6iIvhN8O02bo4I4I3HTyD8qyR7ViiHl
+FmOukjwn4fjJvK0WYKYUjod8oEiMdR2nr73eOGZBAnEorDGQ8VnnCAleSv74is1k
+W7M07UP7EJJq9hSZfeMqk5QivtWrqvWG1SWxpTowKTEAyTn7u5U13k0DiRcsg0WT
+4mSMiLOhUNgIWcHElbTQPSVDcVznhNk0dWPDwKoUjp+orCuH+NvHKBAu+hnuip3e
+Ji7WGrHXI7QxAr5qr5ogl5x4yH4drIbq9fUea3NTuGPuPyu9fWjOSDmqPRKRMJFR
+UxxVFcyrW8iSBV5cvB7M1ADS40y6l4ryYmKjXbsOI4Ci8LJWJ4ZB61WQP7TvPQGS
+mNFmTTB2dwbpimr4KjV9j2bA9x0jAsjlcQZ5j1GOeyYCEDGKDJw0XD/zI+j0dpVc
+eu8YtuJGTyO1h+HiI3D9LrMuyUxxckvFHKe00+4xMz1hpqVo/kxe6gqf/9ES4M/h
+6/NeTzeqyJF2rgxK6KJJdmaKVYI+bvAQ3cKl+RZmgOjx4eig58N5uthqFgU7rQ+e
+GM9/y8C9WpPqITcJlY7I/7AkqvYDBwBsH/9mf4g9OUbC1Ah+MX8UIQ==
+-----END RSA PRIVATE KEY-----
+
+
+9. subca certificate and key (MD2withRSA 1024, root_cert_sha1_512.pem signed)
+-----BEGIN CERTIFICATE-----
+MIICDzCCAbmgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
+MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
+cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8
+BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg
+bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82
+AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl
+UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw
+HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw
+AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADQQBHok1v6xymtpB7N9xy
+0OmDT27uhmzlP0eOzJvXVxj3Oi9TLQJgCUJ9122MzfRAs1E1uJTtvuu+UmI80NQx
+KQdp
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,0480E76FD259323B
+
+npiifBm1mHq1Z9QgAV5T35Xbnea9VnwqYQWNfRRKmpfYSdkQJ0few18YtnfZwh9e
+LKCWx+lq1V4yDG4SbxXDq71Dyvx1vZY+w4h+6M1+6KGFG1VDBfN3e5aLgK8EG9pZ
+yHZH7iB7HiQXH5q53jL6NUZn55C3XEk1sErpK7R1c0Y8Qp2TGiu+lck3K+zR9GiO
+5aJMKbShReB0Nfy3JJNKRFSd95QMTTjbq6iIvhN8O02bo4I4I3HTyD8qyR7ViiHl
+FmOukjwn4fjJvK0WYKYUjod8oEiMdR2nr73eOGZBAnEorDGQ8VnnCAleSv74is1k
+W7M07UP7EJJq9hSZfeMqk5QivtWrqvWG1SWxpTowKTEAyTn7u5U13k0DiRcsg0WT
+4mSMiLOhUNgIWcHElbTQPSVDcVznhNk0dWPDwKoUjp+orCuH+NvHKBAu+hnuip3e
+Ji7WGrHXI7QxAr5qr5ogl5x4yH4drIbq9fUea3NTuGPuPyu9fWjOSDmqPRKRMJFR
+UxxVFcyrW8iSBV5cvB7M1ADS40y6l4ryYmKjXbsOI4Ci8LJWJ4ZB61WQP7TvPQGS
+mNFmTTB2dwbpimr4KjV9j2bA9x0jAsjlcQZ5j1GOeyYCEDGKDJw0XD/zI+j0dpVc
+eu8YtuJGTyO1h+HiI3D9LrMuyUxxckvFHKe00+4xMz1hpqVo/kxe6gqf/9ES4M/h
+6/NeTzeqyJF2rgxK6KJJdmaKVYI+bvAQ3cKl+RZmgOjx4eig58N5uthqFgU7rQ+e
+GM9/y8C9WpPqITcJlY7I/7AkqvYDBwBsH/9mf4g9OUbC1Ah+MX8UIQ==
+-----END RSA PRIVATE KEY-----
+
+
+a. end entity certificate and key
+            (SHA1withRSA 1024, subca_cert_sha1_1024_1024.pem signed)
+-----BEGIN CERTIFICATE-----
+MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
+NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
+cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt
+vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v
+z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6
+c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07
+OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG
+9w0BAQUFAAOBgQAOfIeasDg91CR3jGfuAEVKwncM1OPFmniAUcdPm74cCAyJ90Me
+dhUElWPGoAuXGfiyZlOlGUYWqEroe/dnkmnotJjLWR+MA4ZyX3O1YI8T4W3deWcC
+J4WMCF7mp17SaYYKX9F0AxwNJFpUkbB41IkTxPr0MmzB1871/pbY8dLAvA==
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1FE5A37B770AF83D
+
+042bWtt4q0cB8pRuPUlMVncTP/WAz+mmPw3jXI3LFOBZeK6zFEDpI5M9c2JO+rqp
+Za5UkYuIg69V7LngriqRynkRGGQp3xASMLr5NVbKHTE/Ol/iIuxKaCkumZmGXB/z
+8bxQF5XN4tbKT4s3sWWmmKMicg6MHvySi3QVRG11PHRu/q7CEFPzJKRQ3fpaNcKD
+NTBI5F6GP9ENa/eog4WGENjXS0v4Wa3IfaOhjKXrSxjLUqLH0C8g5WWg5IrXXtuI
+pgyJ2kkE3Y/ChU7p7R42we6tBZqF5SiL5kFDn86DmHgCslTiZkIoE5i644sp03Sd
+XkHyHu0VIeYp3nDwRA7S98837W4F6i1BnXA5f3EaE3rNGjsxK8zL2pvdCcDYbese
+ETfba16HMzLXe1b4RSI3gwhlQ2MNKBwvskkQESf/Ew1DskBY0MCYFxo6hIp6LqMo
+HAl5kvCwvuYL2jBdQhkKxU+Leu5Ei8Ie9XYNVy4yUeUAMnSUkVaEs/I8z+Mk8oYq
+4QWqOc66XLcI13coDoxmv54kye3RjqdmZI8mg/3LCFotwceDuXyD43/vVhoTPEnp
+CqXafV2pw4y95skMHmktI2qvSahaM4P6GGXl8HqmP3b+8V5mxMhNtVnuUha2kouw
+DLNFUTg1cCLahM5SRolyA/XTGh7JOkJMYWPeJwN7l3K+lBtHHfj6DHtKEjUcyZFd
++Z55pDoAERumB6+BCnt6X2/0kEDV219RmsgxkGTWdFs+M7Y6EYYRtlinH4nqL6UD
+eHWitYIatAHOvdHeNrbXN9L5P3tsUB4HzFa46WWtKqRtbCVTuPVZdw==
+-----END RSA PRIVATE KEY-----
+
+b. end entity certificate and key
+            (SHA1withRSA 1024, subca_cert_sha1_512_1024.pem signed)
+-----BEGIN CERTIFICATE-----
+MIIB9jCCAaCgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
+NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
+cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt
+vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v
+z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6
+c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07
+OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG
+9w0BAQUFAANBADV6X+ea0ftEKXy7yKNAbdIp35893T6AVwbdclomPkeOs86OtoTG
+1BIzWSK9QE7W6Wbf63e2RdcqoLK+DxsuwUg=
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1FE5A37B770AF83D
+
+042bWtt4q0cB8pRuPUlMVncTP/WAz+mmPw3jXI3LFOBZeK6zFEDpI5M9c2JO+rqp
+Za5UkYuIg69V7LngriqRynkRGGQp3xASMLr5NVbKHTE/Ol/iIuxKaCkumZmGXB/z
+8bxQF5XN4tbKT4s3sWWmmKMicg6MHvySi3QVRG11PHRu/q7CEFPzJKRQ3fpaNcKD
+NTBI5F6GP9ENa/eog4WGENjXS0v4Wa3IfaOhjKXrSxjLUqLH0C8g5WWg5IrXXtuI
+pgyJ2kkE3Y/ChU7p7R42we6tBZqF5SiL5kFDn86DmHgCslTiZkIoE5i644sp03Sd
+XkHyHu0VIeYp3nDwRA7S98837W4F6i1BnXA5f3EaE3rNGjsxK8zL2pvdCcDYbese
+ETfba16HMzLXe1b4RSI3gwhlQ2MNKBwvskkQESf/Ew1DskBY0MCYFxo6hIp6LqMo
+HAl5kvCwvuYL2jBdQhkKxU+Leu5Ei8Ie9XYNVy4yUeUAMnSUkVaEs/I8z+Mk8oYq
+4QWqOc66XLcI13coDoxmv54kye3RjqdmZI8mg/3LCFotwceDuXyD43/vVhoTPEnp
+CqXafV2pw4y95skMHmktI2qvSahaM4P6GGXl8HqmP3b+8V5mxMhNtVnuUha2kouw
+DLNFUTg1cCLahM5SRolyA/XTGh7JOkJMYWPeJwN7l3K+lBtHHfj6DHtKEjUcyZFd
++Z55pDoAERumB6+BCnt6X2/0kEDV219RmsgxkGTWdFs+M7Y6EYYRtlinH4nqL6UD
+eHWitYIatAHOvdHeNrbXN9L5P3tsUB4HzFa46WWtKqRtbCVTuPVZdw==
+-----END RSA PRIVATE KEY-----
+
+c. end entity certificate and key
+            (SHA1withRSA 512, subca_cert_sha1_1024_1024.pem signed)
+-----BEGIN CERTIFICATE-----
+MIIB8zCCAVygAwIBAgIBBDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
+NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
+cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3
+DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo
+uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE
+AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU
+31g/ZkU6aXFAJVKhrrv0ebfAgeYwDQYJKoZIhvcNAQEFBQADgYEAUyW8PrEdbzLu
+B+h6UemBOJ024rYq90hJE/5wUEKPvxZ9vPEUgl+io6cGhL3cLfxfh6z5xtEGp4Tb
+NB0Ye3Qi01FBiNDY8s3rQRrmel6VysU8u+0Oi2jmQY6vZXn/zXN5rrTLITCaSicG
+dOMv1xLM83Ee432WWlDwKOUxhzDGpWc=
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,153918982D82A26E
+
+5w5MNd16M1draSfIFAuWNfP3869l9y8vMI1kOcxqsxjeG6YfgKUyu6PEYlj1R7d1
+/+UwVs9RGm3V7AwV4G1Qpnd+jaMLpgPVMP12sHPnslBE4SQe9bAZ+X5i2/5uesHv
+bF7OBMqsYW8+Kgsy1Ac0pBx/8yoFYdD3KYFnIP20kV2Xxy4PtQQ6tHJ33dGslTNU
+qrcJsyUyYj6wORlb7huuP5Ua8f28Xs/KvnNJG0094kC1WHi3Raf4AoD/rvraVtCQ
+5jrK9se8D6su+S3SEW0YndxivbNx3xJu2O72e7lS6yb5ht3U7xNSSWTffIlW1okI
+zjscK0iv9S+x452mLIFUgkmriVJLFfjTMRCbhS1J6q9FXLDdre/2O18FO2TvwRIE
+6Bwt2utfOAGccRHLsdgcXkv+ngCTCkuCnmh2XZWqmvA=
+-----END RSA PRIVATE KEY-----
+
+d. end entity certificate and key
+            (SHA1withRSA 512, subca_cert_sha1_512_1024.pem signed)
+-----BEGIN CERTIFICATE-----
+MIIBsjCCAVygAwIBAgIBBTANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
+NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
+cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3
+DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo
+uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE
+AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU
+N0CHiTYPtjyvpP2a6y6mhsZ6U40wDQYJKoZIhvcNAQEFBQADQQBG4grtrVEHick0
+z/6Lcl/MGyHT0c8KTXE0AMVXG1NRjAicAmYno/yDaJ9OmfymObKZKV9fF7yCW/N/
+TMU6m7N0
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,153918982D82A26E
+
+5w5MNd16M1draSfIFAuWNfP3869l9y8vMI1kOcxqsxjeG6YfgKUyu6PEYlj1R7d1
+/+UwVs9RGm3V7AwV4G1Qpnd+jaMLpgPVMP12sHPnslBE4SQe9bAZ+X5i2/5uesHv
+bF7OBMqsYW8+Kgsy1Ac0pBx/8yoFYdD3KYFnIP20kV2Xxy4PtQQ6tHJ33dGslTNU
+qrcJsyUyYj6wORlb7huuP5Ua8f28Xs/KvnNJG0094kC1WHi3Raf4AoD/rvraVtCQ
+5jrK9se8D6su+S3SEW0YndxivbNx3xJu2O72e7lS6yb5ht3U7xNSSWTffIlW1okI
+zjscK0iv9S+x452mLIFUgkmriVJLFfjTMRCbhS1J6q9FXLDdre/2O18FO2TvwRIE
+6Bwt2utfOAGccRHLsdgcXkv+ngCTCkuCnmh2XZWqmvA=
+-----END RSA PRIVATE KEY-----
+
+e. end entity certificate and key
+            (MD2withRSA 1024, subca_cert_sha1_1024_1024.pem signed)
+-----BEGIN CERTIFICATE-----
+MIICNzCCAaCgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
+NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
+cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt
+vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v
+z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6
+c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07
+OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG
+9w0BAQIFAAOBgQBxKsFf8NNQcXjDoKJJSG4Rk6ikcrhiGYuUI32+XHvs6hnav1Zc
+aJUpy7J4gMj/MnysMh/4AF9+m6zEEjuisXKUbYZhgtJxz+ukGSo163mJ8QJiAlRb
+Iwsy81r08mlSCR6jx2YhDAUxJIPC92R5Vb4CEutB7tWTwwz7vIHq330erA==
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1FE5A37B770AF83D
+
+042bWtt4q0cB8pRuPUlMVncTP/WAz+mmPw3jXI3LFOBZeK6zFEDpI5M9c2JO+rqp
+Za5UkYuIg69V7LngriqRynkRGGQp3xASMLr5NVbKHTE/Ol/iIuxKaCkumZmGXB/z
+8bxQF5XN4tbKT4s3sWWmmKMicg6MHvySi3QVRG11PHRu/q7CEFPzJKRQ3fpaNcKD
+NTBI5F6GP9ENa/eog4WGENjXS0v4Wa3IfaOhjKXrSxjLUqLH0C8g5WWg5IrXXtuI
+pgyJ2kkE3Y/ChU7p7R42we6tBZqF5SiL5kFDn86DmHgCslTiZkIoE5i644sp03Sd
+XkHyHu0VIeYp3nDwRA7S98837W4F6i1BnXA5f3EaE3rNGjsxK8zL2pvdCcDYbese
+ETfba16HMzLXe1b4RSI3gwhlQ2MNKBwvskkQESf/Ew1DskBY0MCYFxo6hIp6LqMo
+HAl5kvCwvuYL2jBdQhkKxU+Leu5Ei8Ie9XYNVy4yUeUAMnSUkVaEs/I8z+Mk8oYq
+4QWqOc66XLcI13coDoxmv54kye3RjqdmZI8mg/3LCFotwceDuXyD43/vVhoTPEnp
+CqXafV2pw4y95skMHmktI2qvSahaM4P6GGXl8HqmP3b+8V5mxMhNtVnuUha2kouw
+DLNFUTg1cCLahM5SRolyA/XTGh7JOkJMYWPeJwN7l3K+lBtHHfj6DHtKEjUcyZFd
++Z55pDoAERumB6+BCnt6X2/0kEDV219RmsgxkGTWdFs+M7Y6EYYRtlinH4nqL6UD
+eHWitYIatAHOvdHeNrbXN9L5P3tsUB4HzFa46WWtKqRtbCVTuPVZdw==
+-----END RSA PRIVATE KEY-----
+
+f. end entity certificate and key
+            (MD2withRSA 1024, subca_cert_sha1_512_1024.pem signed)
+-----BEGIN CERTIFICATE-----
+MIIB9jCCAaCgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
+NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
+cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG
+9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt
+vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v
+z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6
+c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07
+OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG
+9w0BAQIFAANBAIX63Ypi9P71RnC/pcMbhD+wekRFsTzU593X3MC7tyBJtEXwvAZG
+iMxXF5A+ohlr7/CrkV7ZTL8PLxnJdY5Y8rQ=
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,1FE5A37B770AF83D
+
+042bWtt4q0cB8pRuPUlMVncTP/WAz+mmPw3jXI3LFOBZeK6zFEDpI5M9c2JO+rqp
+Za5UkYuIg69V7LngriqRynkRGGQp3xASMLr5NVbKHTE/Ol/iIuxKaCkumZmGXB/z
+8bxQF5XN4tbKT4s3sWWmmKMicg6MHvySi3QVRG11PHRu/q7CEFPzJKRQ3fpaNcKD
+NTBI5F6GP9ENa/eog4WGENjXS0v4Wa3IfaOhjKXrSxjLUqLH0C8g5WWg5IrXXtuI
+pgyJ2kkE3Y/ChU7p7R42we6tBZqF5SiL5kFDn86DmHgCslTiZkIoE5i644sp03Sd
+XkHyHu0VIeYp3nDwRA7S98837W4F6i1BnXA5f3EaE3rNGjsxK8zL2pvdCcDYbese
+ETfba16HMzLXe1b4RSI3gwhlQ2MNKBwvskkQESf/Ew1DskBY0MCYFxo6hIp6LqMo
+HAl5kvCwvuYL2jBdQhkKxU+Leu5Ei8Ie9XYNVy4yUeUAMnSUkVaEs/I8z+Mk8oYq
+4QWqOc66XLcI13coDoxmv54kye3RjqdmZI8mg/3LCFotwceDuXyD43/vVhoTPEnp
+CqXafV2pw4y95skMHmktI2qvSahaM4P6GGXl8HqmP3b+8V5mxMhNtVnuUha2kouw
+DLNFUTg1cCLahM5SRolyA/XTGh7JOkJMYWPeJwN7l3K+lBtHHfj6DHtKEjUcyZFd
++Z55pDoAERumB6+BCnt6X2/0kEDV219RmsgxkGTWdFs+M7Y6EYYRtlinH4nqL6UD
+eHWitYIatAHOvdHeNrbXN9L5P3tsUB4HzFa46WWtKqRtbCVTuPVZdw==
+-----END RSA PRIVATE KEY-----
+
+h. root CRL issuer
+-----BEGIN CERTIFICATE-----
+MIICKzCCAZSgAwIBAgIBCjANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDgxNjMwNTdaFw0yOTA0MjUxNjMwNTda
+MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCy6RoQ6nMdeGJ6ijfjqDu3tDmeGLgnvfBcUKvcsvz9Ji3m
+oGnTzECo1oLV+A4/TJxOlak+ZiQ5KVyvfMcXLJeT6dRpXQZ+uc6TT3SkBq94VFzX
+qkk08z42JNdk1s5uyW8nRfg7+xntajQVrysoPYNDhu21cPnjDkRiBsIdS7+75QID
+AQABo3cwdTAdBgNVHQ4EFgQUGcJU6xWo66kI1QBvlfTQKxxmx9IwRwYDVR0jBEAw
+PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD
+VQQKEwdFeGFtcGxlggEAMAsGA1UdDwQEAwIBAjANBgkqhkiG9w0BAQQFAAOBgQBx
+uKL59VInPdCi+8JL4B+S5YjlPL4ZOBHTjS0JlNxtjbGZdfs+3E9PUAdqhMJO4vq7
+XD+hGtgZtwSqGaSUYAtpLdoCr7vvPkcrxYTG2Ak+UiTbZhmJeSswKgFaCmjjdMCy
+y64UP2DQfn6Zi0wCfeao0m9s3zRLuJpgaQGiSHTQKA==
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,41E4237825CE0148
+
+9nbfd7dsaS+fkFYrU1+wTcevjdRLF/j9DUVQh/2bsFlVEYgeL8A+XpvpbXHYBd7H
+oBreofDNseibHe4EgISGPK8RymjYutQqPpbHwXd25jlUuUapvvuCj8V6qnhgpqEo
+zXL1Nd2c6KZgdySosyWy8JfIBZJ3kwiSkXVwzs8R4bAGrg1VS80GuszvCv8Fzjoc
+LuesX6fViE9yFzLsyOvn/W12DKhTXwiXTQYLUupM8zI9Kpozbea52ZIPMJ9HEiaY
+JgwNj05w33VxTe/tq3R9vS2Ee6aM4odi6CQEheLsUAnyE0BTsITKzwwTI25WTv25
+W+gwSF3V49a34MojTdlORq5iH0b3rYl7OMdk+99elJSkyQIbVwwOCFrKuSXYXvV7
+s9iMPFUbi+bZ3oP6zM5kVUcH6KyVeYfkuLf2+k1vPlav8/W5v+WfnvUNOBx76Ira
+BzVPYmm2V+YFiFL1hugm5Wv+yyx8QcfgXbvhNHoIEj7hh6Ac48FhtqEcBHjuT/gy
+7atJJUdOH6hhmD34hkHGnhcDE15ZOczxTLRC9450h5HKsZ0FILRlCBZLmiedycs2
+zqhUpR4jzDG9jKrlDU4ErfMgPLjveZc3/VT3bc+TYfuC8szCaQ5XX1JVcabZ+HQw
+pwmA1ONZDVsFzwbJy9+5bgXX+wLD5kaez8EHNDS5PgqgL0UdrWjdRi6e1RwlTDEw
+g/d7TZm/iQeL1iUIfkPA1f0ByYIiyd3XQqiQ/Mf1C16lQkhTHDwofFJdL8otT2Ha
+dk6fa7lBOnrpbRKUdpJpYfyqHg80BYNPu6BacVXlYqtJtkFK04qHbA==
+-----END RSA PRIVATE KEY-----
+
+i. CRL issued by root CRL issuer
+-----BEGIN X509 CRL-----
+MIH2MGECAQEwDQYJKoZIhvcNAQEFBQAwHzELMAkGA1UEBhMCVVMxEDAOBgNVBAoT
+B0V4YW1wbGUXDTA5MDgwODE2MzU1MFoXDTI4MTAwNzE2MzU1MFqgDjAMMAoGA1Ud
+FAQDAgEAMA0GCSqGSIb3DQEBBQUAA4GBAJCd7e25MruuWJP/KmenGC6CR22pQuG+
+XhRaAtpHkNRls8+TfBxm2PtRrXCAcDb68kNLdwvlAlCUwmL6HOx4VB3r+8QRUlDa
+T48wVp1ojGU2b2XbPtXiYZBXW6hBsFHGDJM/IAGJPE2PbVYGlBc23A9V9WyPyThi
+9XXG1iOTIJ6u
+-----END X509 CRL-----
+
+j. subca CRL issuer
+-----BEGIN CERTIFICATE-----
+MIICPTCCAaagAwIBAgIBCzANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDgxNjMwNThaFw0yOTA0MjUxNjMwNTha
+MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
+cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8KICP0bdOZVlR9gZu7TgD
+znXgSMER1IQtompgr1mWeZjX4LmRck3/ogHoxwC4RbNPKI3KIihcVdFHw2jgvE0M
+mpf2lI50tmhnLitM8P0/q8xUU/KncipADo4hkM5TbpjPeGUBTGLKzGrq7yyT9Uli
+Z74rrp1mS59TxcEI2YQMIQIDAQABo3cwdTAdBgNVHQ4EFgQUDGgpD4L8V3aBJPLx
+C7diZ0M0wWMwRwYDVR0jBEAwPoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8x
+CzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMAsGA1UdDwQEAwIBAjAN
+BgkqhkiG9w0BAQQFAAOBgQCcXqRge5UuW0duf/XnUWP4hrm4Q9EHJaiHZDYxI+WW
+Ca3OXdsrpgGi+RSgeMtQzlZ7YAwyYVV91U4BnX6s/97Vp5xbR3wr8Qbx67inM8Lp
+Tuo+e0nyTxwlwi9cSyy5MfJ8jfzaD+n8akhV+sx0Mmiv77YlrShP24lod55gJHKC
+vQ==
+-----END CERTIFICATE-----
+
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,16EC4E2C0855BD5C
+
+dJHcUsnACMhfESAalWrWrfARnUgGhpp3vupjePUiBJ86YmKaNNr6GAwDukg3EJvs
+tboO1QQziLSf9pP7gw82Vp5YctEkk7vJVvCcq3QkZAsjNUHf3m3ne2qg8HngufzY
+IS/C3EtKuMr3oqa7P8wvMcsBs1G1ga/YqCWoKzowXhybaYPe20fwUNRtgqgdS5Gy
+bAzQB9R+Ua2tCaXb3CBYnrczsYFPhjuULr4qbWgHVBWhnkS3OIz71WqcCoXmvD3s
+bsjoZRCJUM6Zavyzs0kVGZogiPdr+KUyzjNNsnxle5cEET6nqkYR16UT/Fvemz9Q
+szh/y0gCi1nZb6cw5e9BJyF1GlobzxWyMwwY9L4vZNaBNaVRun+6dRWy0svaPuEy
+fV/9Y0/la9scyA5yNHz8xud3Njhj2ghyG5Nqbs3N/pPXRVdh7WNFBnc+L/SIBhhB
+/Ha9+OZdqyuMf3G+I1+WVADQr8xQP8/yLEvybZYtssjnuCmQSLPDDQFnp2Z3spax
++AT+T4dRimMjf0mZK/NlRJU9PWqMHzsJGBY1A903oAiiHiRFD10z8vyPBigSDF2W
+ct6a8WI1prKho6HbMqeIlSPk+HkdCGZedNNbvRlKl4Y56IsHGAhb3wvQ+94049P9
+wu5thK69jNb7ie3YEefAZTb5kD0h+oB8BILOJ5B29C04JdDe6P6hjGKD7x3nRhHM
+nyCUMB/fhYpoXdDhz8CeJ77hFt2zFZRstlDctQsDqLkC0AdvlOFsEFqGM4AkBGcV
+f6Y+ykNQB3vEWPZsWqVXHB2vQvk00R55tgu+R5JJ45NLG2TqyOp/4A==
+-----END RSA PRIVATE KEY-----
+
+k. CRL issued by subca CRL issuer
+-----BEGIN X509 CRL-----
+MIIBLTCBlwIBATANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQMA4GA1UE
+ChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMRcNMDkwODA4MTYzNTUxWhcNMjgx
+MDA3MTYzNTUxWjAiMCACAQIXDTA5MDgwODE2MzU1MFowDDAKBgNVHRUEAwoBBKAO
+MAwwCgYDVR0UBAMCAQAwDQYJKoZIhvcNAQECBQADgYEAbIs7ws4/M24NYrIO0XY6
+UVxni0ZoQa+1R7NwU6unr4jFEVD+W/b+JEMfm0RUmpSa7HrUYsw+NycD3m5CD6VJ
+U4iuGGeJvHdrYJiPIYkEiFQnhAGOj8oS/nWtPvDKbuBMZI9atKkypby9At8h9URq
+1g/KSIM3rd1PYADdcPsok4I=
+-----END X509 CRL-----
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/certpath/DisabledAlgorithms/generate.sh	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,255 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#!/bin/ksh
+#
+# needs ksh to run the script.
+set -e
+
+OPENSSL=openssl
+
+# generate a self-signed root certificate
+if [ ! -f root/finished ]; then
+    if [ ! -d root ]; then
+        mkdir root
+    fi
+
+    # SHA1withRSA 1024
+    ${OPENSSL} req -x509 -newkey rsa:1024 -keyout root/root_key_1024.pem \
+        -out root/root_cert_sha1_1024.pem -subj "/C=US/O=Example" \
+        -config openssl.cnf -reqexts cert_issuer -days 7650 -sha1 \
+        -passin pass:passphrase -passout pass:passphrase
+
+    # SHA1withRSA 512
+    ${OPENSSL} req -x509 -newkey rsa:512 -keyout root/root_key_512.pem \
+        -out root/root_cert_sha1_512.pem -subj "/C=US/O=Example" \
+        -config openssl.cnf -reqexts cert_issuer -days 7650 -sha1 \
+        -passin pass:passphrase -passout pass:passphrase
+
+    # MD2withRSA 2048
+    ${OPENSSL} req -x509 -newkey rsa:2048 -keyout root/root_key_2048.pem \
+        -out root/root_cert_md2_2048.pem -subj "/C=US/O=Example" \
+        -config openssl.cnf -reqexts cert_issuer -days 7650 -md2 \
+        -passin pass:passphrase -passout pass:passphrase
+
+    openssl req -newkey rsa:1024 -keyout root/root_crlissuer_key.pem \
+        -out root/root_crlissuer_req.pem -subj "/C=US/O=Example" -days 7650 \
+        -passin pass:passphrase -passout pass:passphrase
+
+    openssl x509 -req -in root/root_crlissuer_req.pem -extfile openssl.cnf \
+        -extensions crl_issuer -CA root/root_cert_sha1_1024.pem \
+        -CAkey root/root_key_1024.pem -out root/root_crlissuer_cert.pem \
+        -CAcreateserial -CAserial root/root_cert.srl -days 7200 \
+        -passin pass:passphrase
+
+    touch root/finished
+fi
+
+
+# generate subca cert issuer
+if [ ! -f subca/finished ]; then
+    if [ ! -d subca ]; then
+        mkdir subca
+    fi
+
+    # RSA 1024
+    ${OPENSSL} req -newkey rsa:1024 -keyout subca/subca_key_1024.pem \
+        -out subca/subca_req_1024.pem -subj "/C=US/O=Example/OU=Class-1" \
+        -days 7650 -passin pass:passphrase -passout pass:passphrase
+
+    # RSA 512
+    ${OPENSSL} req -newkey rsa:512 -keyout subca/subca_key_512.pem \
+        -out subca/subca_req_512.pem -subj "/C=US/O=Example/OU=Class-1" \
+        -days 7650 -passin pass:passphrase -passout pass:passphrase
+
+    # SHA1withRSA 1024 signed with RSA 1024
+    ${OPENSSL} x509 -req -in subca/subca_req_1024.pem -extfile openssl.cnf \
+        -extensions cert_issuer -CA root/root_cert_sha1_1024.pem \
+        -CAkey root/root_key_1024.pem -out subca/subca_cert_sha1_1024_1024.pem \
+        -CAcreateserial -sha1 \
+        -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
+
+    # SHA1withRSA 1024 signed with RSA 512
+    ${OPENSSL} x509 -req -in subca/subca_req_1024.pem -extfile openssl.cnf \
+        -extensions cert_issuer -CA root/root_cert_sha1_512.pem \
+        -CAkey root/root_key_512.pem -out subca/subca_cert_sha1_1024_512.pem \
+        -CAcreateserial -sha1 \
+        -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
+
+    # SHA1withRSA 512 signed with RSA 1024
+    ${OPENSSL} x509 -req -in subca/subca_req_512.pem -extfile openssl.cnf \
+        -extensions cert_issuer -CA root/root_cert_sha1_1024.pem \
+        -CAkey root/root_key_1024.pem -out subca/subca_cert_sha1_512_1024.pem \
+        -CAcreateserial -sha1 \
+        -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
+
+    # SHA1withRSA 512 signed with RSA 512
+    ${OPENSSL} x509 -req -in subca/subca_req_512.pem -extfile openssl.cnf \
+        -extensions cert_issuer -CA root/root_cert_sha1_512.pem \
+        -CAkey root/root_key_512.pem -out subca/subca_cert_sha1_512_512.pem \
+        -CAcreateserial -sha1 \
+        -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
+
+    # MD2withRSA 1024 signed with RSA 1024
+    ${OPENSSL} x509 -req -in subca/subca_req_1024.pem -extfile openssl.cnf \
+        -extensions cert_issuer -CA root/root_cert_sha1_1024.pem \
+        -CAkey root/root_key_1024.pem -out subca/subca_cert_md2_1024_1024.pem \
+        -CAcreateserial -md2 \
+        -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
+
+    # MD2withRSA 1024 signed with RSA 512
+    ${OPENSSL} x509 -req -in subca/subca_req_1024.pem -extfile openssl.cnf \
+        -extensions cert_issuer -CA root/root_cert_sha1_512.pem \
+        -CAkey root/root_key_512.pem -out subca/subca_cert_md2_1024_512.pem \
+        -CAcreateserial -md2 \
+        -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
+
+    openssl req -newkey rsa:1024 -keyout subca/subca_crlissuer_key.pem \
+        -out subca/subca_crlissuer_req.pem -subj "/C=US/O=Example/OU=Class-1" \
+        -days 7650 -passin pass:passphrase -passout pass:passphrase
+
+    openssl x509 -req -in subca/subca_crlissuer_req.pem -extfile openssl.cnf \
+        -extensions crl_issuer -CA root/root_cert_sha1_1024.pem \
+        -CAkey root/root_key_1024.pem -out subca/subca_crlissuer_cert.pem \
+        -CAcreateserial -CAserial root/root_cert.srl -days 7200 \
+        -passin pass:passphrase
+
+    touch subca/finished
+fi
+
+
+# generate certifiacte for Alice
+if [ ! -f subca/alice/finished ]; then
+    if [ ! -d subca/alice ]; then
+        mkdir -p subca/alice
+    fi
+
+    # RSA 1024
+    ${OPENSSL} req -newkey rsa:1024 -keyout subca/alice/alice_key_1024.pem \
+        -out subca/alice/alice_req_1024.pem \
+        -subj "/C=US/O=Example/OU=Class-1/CN=Alice" -days 7650 \
+        -passin pass:passphrase -passout pass:passphrase
+
+    # RSA 512
+    ${OPENSSL} req -newkey rsa:512 -keyout subca/alice/alice_key_512.pem \
+        -out subca/alice/alice_req_512.pem \
+        -subj "/C=US/O=Example/OU=Class-1/CN=Alice" -days 7650 \
+        -passin pass:passphrase -passout pass:passphrase
+
+    # SHA1withRSA 1024 signed with RSA 1024
+    ${OPENSSL} x509 -req -in subca/alice/alice_req_1024.pem \
+        -extfile openssl.cnf -extensions ee_of_subca \
+        -CA subca/subca_cert_sha1_1024_1024.pem \
+        -CAkey subca/subca_key_1024.pem \
+        -out subca/alice/alice_cert_sha1_1024_1024.pem -CAcreateserial -sha1 \
+        -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
+
+    # SHA1withRSA 1024 signed with RSA 512
+    ${OPENSSL} x509 -req -in subca/alice/alice_req_1024.pem \
+        -extfile openssl.cnf -extensions ee_of_subca \
+        -CA subca/subca_cert_sha1_512_1024.pem \
+        -CAkey subca/subca_key_512.pem \
+        -out subca/alice/alice_cert_sha1_1024_512.pem -CAcreateserial -sha1 \
+        -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
+
+    # SHA1withRSA 512 signed with RSA 1024
+    ${OPENSSL} x509 -req -in subca/alice/alice_req_512.pem \
+        -extfile openssl.cnf -extensions ee_of_subca \
+        -CA subca/subca_cert_sha1_1024_1024.pem \
+        -CAkey subca/subca_key_1024.pem \
+        -out subca/alice/alice_cert_sha1_512_1024.pem -CAcreateserial -sha1 \
+        -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
+
+    # SHA1withRSA 512 signed with RSA 512
+    ${OPENSSL} x509 -req -in subca/alice/alice_req_512.pem \
+        -extfile openssl.cnf -extensions ee_of_subca \
+        -CA subca/subca_cert_sha1_512_1024.pem \
+        -CAkey subca/subca_key_512.pem \
+        -out subca/alice/alice_cert_sha1_512_512.pem -CAcreateserial -sha1 \
+        -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
+
+    # MD2withRSA 1024 signed with RSA 1024
+    ${OPENSSL} x509 -req -in subca/alice/alice_req_1024.pem \
+        -extfile openssl.cnf -extensions ee_of_subca \
+        -CA subca/subca_cert_sha1_1024_1024.pem \
+        -CAkey subca/subca_key_1024.pem \
+        -out subca/alice/alice_cert_md2_1024_1024.pem -CAcreateserial -md2 \
+        -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
+
+    # MD2withRSA 1024 signed with RSA 512
+    ${OPENSSL} x509 -req -in subca/alice/alice_req_1024.pem \
+        -extfile openssl.cnf -extensions ee_of_subca \
+        -CA subca/subca_cert_sha1_512_1024.pem \
+        -CAkey subca/subca_key_512.pem \
+        -out subca/alice/alice_cert_md2_1024_512.pem -CAcreateserial -md2 \
+        -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
+
+    touch subca/alice/finished
+fi
+
+if [ ! -f root/revoked ]; then
+    if [ ! -d root ]; then
+        mkdir root
+    fi
+
+    if [ ! -f root/index.txt ]; then
+        touch root/index.txt
+        echo 00 > root/crlnumber
+    fi
+
+    openssl ca -gencrl -config openssl.cnf -name ca_top -crldays 7000 -md sha1 \
+        -crl_reason superseded -keyfile root/root_crlissuer_key.pem \
+        -cert root/root_crlissuer_cert.pem -out root/top_crl.pem \
+        -passin pass:passphrase
+
+    touch root/revoked
+fi
+
+if [ ! -f subca/revoked ]; then
+    if [ ! -d subca ]; then
+        mkdir subca
+    fi
+
+    if [ ! -f subca/index.txt ]; then
+        touch subca/index.txt
+        echo 00 > subca/crlnumber
+    fi
+
+    # revoke alice's SHA1withRSA 1024 signed with RSA 1024
+    openssl ca -revoke subca/alice/alice_cert_sha1_1024_1024.pem \
+        -config openssl.cnf \
+        -name ca_subca -crl_reason superseded \
+        -keyfile subca/subca_crlissuer_key.pem \
+        -cert subca/subca_crlissuer_cert.pem -passin pass:passphrase
+
+    openssl ca -gencrl -config openssl.cnf \
+        -name ca_subca -crldays 7000 -md md2 \
+        -crl_reason superseded -keyfile subca/subca_crlissuer_key.pem \
+        -cert subca/subca_crlissuer_cert.pem \
+        -out subca/subca_crl.pem \
+        -passin pass:passphrase
+
+    touch subca/revoked
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/certpath/DisabledAlgorithms/openssl.cnf	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,206 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# OpenSSL configuration file.
+#
+
+HOME                = .
+RANDFILE            = $ENV::HOME/.rnd
+
+[ ca ]
+default_ca          = CA_default
+
+[ CA_default ]
+dir                 = ./top
+certs               = $dir/certs
+crl_dir             = $dir/crl
+database            = $dir/index.txt
+unique_subject      = no
+new_certs_dir       = $dir/newcerts
+certificate         = $dir/cacert.pem
+serial              = $dir/serial
+crlnumber           = $dir/crlnumber
+crl                 = $dir/crl.pem
+private_key         = $dir/private/cakey.pem
+RANDFILE            = $dir/private/.rand
+x509_extensions     = v3_ca
+
+name_opt            = ca_default
+cert_opt            = ca_default
+
+default_days        = 7650
+default_crl_days    = 30
+default_md          = sha1
+preserve            = no
+
+policy              = policy_anything
+
+[ ca_top ]
+dir                 = ./root
+certs               = $dir/certs
+crl_dir             = $dir/crl
+database            = $dir/index.txt
+unique_subject      = no
+new_certs_dir       = $dir/newcerts
+certificate         = $dir/cacert.pem
+serial              = $dir/serial
+crlnumber           = $dir/crlnumber
+crl                 = $dir/crl.pem
+private_key         = $dir/private/cakey.pem
+RANDFILE            = $dir/private/.rand
+
+x509_extensions     = v3_ca
+
+name_opt            = ca_default
+cert_opt            = ca_default
+
+default_days        = 7650
+default_crl_days    = 30
+default_md          = sha1
+preserve            = no
+
+policy              = policy_anything
+
+[ ca_subca ]
+dir                 = ./subca
+certs               = $dir/certs
+crl_dir             = $dir/crl
+database            = $dir/index.txt
+unique_subject      = no
+new_certs_dir       = $dir/newcerts
+
+certificate         = $dir/cacert.pem
+serial              = $dir/serial
+crlnumber           = $dir/crlnumber
+crl                 = $dir/crl.pem
+private_key         = $dir/private/cakey.pem
+RANDFILE            = $dir/private/.rand
+
+x509_extensions     = usr_cert
+
+name_opt            = ca_default
+cert_opt            = ca_default
+
+default_days        = 7650
+default_crl_days    = 30
+default_md          = sha1
+preserve            = no
+
+policy              = policy_anything
+
+[ policy_match ]
+countryName         = match
+stateOrProvinceName = match
+organizationName    = match
+organizationalUnitName  = optional
+commonName          = supplied
+emailAddress        = optional
+
+[ policy_anything ]
+countryName         = optional
+stateOrProvinceName = optional
+localityName        = optional
+organizationName    = optional
+organizationalUnitName  = optional
+commonName          = supplied
+emailAddress        = optional
+
+[ req ]
+default_bits        = 1024
+default_keyfile     = privkey.pem
+distinguished_name  = req_distinguished_name
+attributes          = req_attributes
+x509_extensions     = v3_ca
+
+string_mask = nombstr
+
+[ req_distinguished_name ]
+countryName         = Country Name (2 letter code)
+countryName_default = NO
+countryName_min     = 2
+countryName_max     = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default  = A-State
+
+localityName        = Locality Name (eg, city)
+
+0.organizationName  = Organization Name (eg, company)
+0.organizationName_default   = Internet Widgits Pty Ltd
+
+organizationalUnitName       = Organizational Unit Name (eg, section)
+
+commonName              = Common Name (eg, YOUR name)
+commonName_max          = 64
+
+emailAddress            = Email Address
+emailAddress_max        = 64
+
+[ req_attributes ]
+challengePassword       = A challenge password
+challengePassword_min   = 4
+challengePassword_max   = 20
+unstructuredName        = An optional company name
+
+
+[ usr_cert ]
+keyUsage                = nonRepudiation, digitalSignature, keyEncipherment
+
+subjectKeyIdentifier    = hash
+authorityKeyIdentifier  = keyid,issuer
+
+[ v3_req ]
+basicConstraints        = CA:FALSE
+keyUsage                = nonRepudiation, digitalSignature, keyEncipherment
+subjectAltName          = email:example@openjdk.net, RID:1.2.3.4:true
+
+[ v3_ca ]
+subjectKeyIdentifier    = hash
+authorityKeyIdentifier  = keyid:always,issuer:always
+basicConstraints        = critical,CA:true
+keyUsage                = keyCertSign
+
+[ cert_issuer ]
+subjectKeyIdentifier    = hash
+authorityKeyIdentifier  = keyid:always,issuer:always
+basicConstraints        = critical,CA:true
+keyUsage                = keyCertSign
+
+
+[ crl_issuer ]
+subjectKeyIdentifier    = hash
+authorityKeyIdentifier  = keyid:always,issuer:always
+keyUsage                = cRLSign
+
+
+[ crl_ext ]
+authorityKeyIdentifier  = keyid:always,issuer:always
+
+[ ee_of_subca ]
+keyUsage    = nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
+
+subjectKeyIdentifier    = hash
+authorityKeyIdentifier  = keyid,issuer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/util/DerValue/BadValue.java	Thu Nov 12 23:04:42 2009 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6864911
+ * @summary ASN.1/DER input stream parser needs more work
+ */
+
+import java.io.*;
+import sun.security.util.*;
+import sun.misc.IOUtils;
+
+public class BadValue {
+
+    public static void main(String[] args) throws Exception {
+
+        // Test IOUtils.readFully
+
+        // We have 4 bytes
+        InputStream in = new ByteArrayInputStream(new byte[10]);
+        byte[] bs = IOUtils.readFully(in, 4, true);
+        if (bs.length != 4 || in.available() != 6) {
+            throw new Exception("First read error");
+        }
+        // But only 6 left
+        bs = IOUtils.readFully(in, 10, false);
+        if (bs.length != 6 || in.available() != 0) {
+            throw new Exception("Second read error");
+        }
+        // MAX read as much as it can
+        in = new ByteArrayInputStream(new byte[10]);
+        bs = IOUtils.readFully(in, Integer.MAX_VALUE, true);
+        if (bs.length != 10 || in.available() != 0) {
+            throw new Exception("Second read error");
+        }
+        // MAX ignore readAll
+        in = new ByteArrayInputStream(new byte[10]);
+        bs = IOUtils.readFully(in, Integer.MAX_VALUE, false);
+        if (bs.length != 10 || in.available() != 0) {
+            throw new Exception("Second read error");
+        }
+        // 20>10, readAll means failure
+        in = new ByteArrayInputStream(new byte[10]);
+        try {
+            bs = IOUtils.readFully(in, 20, true);
+            throw new Exception("Third read error");
+        } catch (EOFException e) {
+            // OK
+        }
+        int bignum = 10 * 1024 * 1024;
+        bs = IOUtils.readFully(new SuperSlowStream(bignum), -1, true);
+        if (bs.length != bignum) {
+            throw new Exception("Fourth read error");
+        }
+
+        // Test DerValue
+        byte[] input = {0x04, (byte)0x84, 0x40, 0x00, 0x42, 0x46, 0x4b};
+        try {
+            new DerValue(new ByteArrayInputStream(input));
+        } catch (IOException ioe) {
+            // This is OK
+        }
+    }
+}
+
+/**
+ * An InputStream contains a given number of bytes, but only returns one byte
+ * per read.
+ */
+class SuperSlowStream extends InputStream {
+    private int p;
+    /**
+     * @param Initial capacity
+     */
+    public SuperSlowStream(int capacity) {
+        p = capacity;
+    }
+    @Override
+    public int read() throws IOException {
+        if (p > 0) {
+            p--;
+            return 0;
+        } else {
+            return -1;
+        }
+    }
+    @Override
+    public int read(byte b[], int off, int len) throws IOException {
+        if (len == 0) return 0;
+        if (p > 0) {
+            p--;
+            b[off] = 0;
+            return 1;
+        } else {
+            return -1;
+        }
+    }
+}