--- a/jdk/.hgtags Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/.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/jdk/make/common/Defs-linux.gmk Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/common/Defs.gmk Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/common/Program.gmk Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/common/Release.gmk Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/common/Rules.gmk Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/java/instrument/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/java/java/FILES_java.gmk Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/java/jli/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/java/main/java/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/java/main/javaw/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/java/nio/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/java/nio/genBuffer.sh Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/java/redist/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/java/version/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/javax/sound/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/javax/sound/SoundDefs.gmk Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/jdk_generic_profile.sh Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/jprt.properties Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/launchers/Makefile.launcher Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/netbeans/jconsole/build.properties Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/netbeans/jconsole/build.xml Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/sun/awt/mapfile-vers Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/sun/awt/mapfile-vers-linux Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/sun/jconsole/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/sun/nio/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/make/tools/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifToggleButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/awt/KeyboardFocusManager.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/awt/color/ICC_Profile.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/beans/MetaData.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/lang/ClassLoader.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/math/BigInteger.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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 <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 <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/jdk/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 <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 <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/jdk/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]?, a string,} or some other $fulltype$
- * buffer into this buffer;{#if[!byte]? 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 string} into a buffer.
- *
-#else[byte]
- *
- * content, by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an existing
- * $fulltype$ array {#if[char]?or 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 <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 <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> <tt>></tt> <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, off, 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 <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> <tt>></tt> <tt>remaining()</tt>,
- * then no $fulltype$s are transferred and a {@link
- * BufferOverflowException} is thrown.
- *
- * <p> Otherwise, this method copies
- * <i>n</i> = <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 <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> <tt>></tt> <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, off, 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 <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 <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 - start</tt> <tt>></tt> <tt>remaining()</tt>,
- * then no $fulltype$s are transferred and a {@link
- * BufferOverflowException} is thrown.
- *
- * <p> Otherwise, this method copies
- * <i>n</i> = <tt>end</tt> - <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, start, 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 <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 <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 <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> + <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 <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> = <tt>position()</tt> is copied
- * to index zero, the $fulltype$ at index <i>p</i> + 1 is copied
- * to index one, and so forth until the $fulltype$ at index
- * <tt>limit()</tt> - 1 is copied to index
- * <i>n</i> = <tt>limit()</tt> - <tt>1</tt> - <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> - <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> - 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() + 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> + <tt>start</tt>, and its limit will be
- * <tt>position()</tt> + <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 <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 <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 <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/jdk/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]?, a string,} or some other $fulltype$
+ * buffer into this buffer;{#if[!byte]? 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 string} into a buffer.
+ *
+#else[byte]
+ *
+ * content, by {@link #wrap($type$[]) </code><i>wrapping</i><code>} an existing
+ * $fulltype$ array {#if[char]?or 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 <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 <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> <tt>></tt> <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, off, 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 <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> <tt>></tt> <tt>remaining()</tt>,
+ * then no $fulltype$s are transferred and a {@link
+ * BufferOverflowException} is thrown.
+ *
+ * <p> Otherwise, this method copies
+ * <i>n</i> = <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 <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> <tt>></tt> <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, off, 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 <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 <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 - start</tt> <tt>></tt> <tt>remaining()</tt>,
+ * then no $fulltype$s are transferred and a {@link
+ * BufferOverflowException} is thrown.
+ *
+ * <p> Otherwise, this method copies
+ * <i>n</i> = <tt>end</tt> - <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, start, 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 <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 <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 <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> + <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 <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> = <tt>position()</tt> is copied
+ * to index zero, the $fulltype$ at index <i>p</i> + 1 is copied
+ * to index one, and so forth until the $fulltype$ at index
+ * <tt>limit()</tt> - 1 is copied to index
+ * <i>n</i> = <tt>limit()</tt> - <tt>1</tt> - <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> - <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> - 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() + 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> + <tt>start</tt>, and its limit will be
+ * <tt>position()</tt> + <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 <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 <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 <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/jdk/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 $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 <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 <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/jdk/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 $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 <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 <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/jdk/src/share/classes/java/security/MessageDigest.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/AbstractList.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/AbstractQueue.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/Arrays.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/DualPivotQuicksort.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/Formatter.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/HashMap.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/HashSet.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/LinkedList.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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 ? e==null : 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 ? get(i)==null : 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 ? get(i)==null : 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 ? get(i)==null : 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/jdk/src/share/classes/java/util/Random.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/CountDownLatch.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/ExecutorService.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/src/share/classes/java/util/concurrent/locks/Condition.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/java/util/concurrent/package-info.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/ToolTipManager.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/UIManager.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/basic/BasicButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/basic/BasicLabelUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/basic/BasicToggleButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/metal/MetalBumps.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/metal/MetalButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/metal/MetalLabelUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/metal/MetalSliderUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/applet/AppletClassLoader.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/awt/image/ImageRepresentation.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/src/share/classes/sun/misc/Resource.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/security/util/DerValue.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/security/validator/SimpleValidator.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/security/validator/ValidatorException.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/classes/sun/text/bidi/BidiBase.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/src/share/classes/sun/util/calendar/ZoneInfoFile.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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 <java.home>/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/jdk/src/share/native/com/sun/media/sound/SoundDefs.h Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/native/sun/awt/image/awt_ImageRep.c Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/src/solaris/classes/java/util/prefs/FileSystemPreferences.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/windows/classes/sun/awt/Win32GraphicsDevice.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/Makefile Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/test/demo/jvmti/DemoRun.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/test/java/nio/Buffer/genBasic.sh Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/nio/channels/FileChannel/Transfer.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/test/java/nio/file/Path/CopyAndMove.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/nio/file/Path/Links.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/Arrays/Sorting.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/Collection/BiggernYours.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/Collection/IteratorAtEnd.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/Collection/MOAT.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/Collections/CheckedNull.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/Collections/RacingCollections.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/PriorityQueue/RemoveContains.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/BlockingQueue/LastElement.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/RWMap.java Thu Nov 12 23:00:23 2009 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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;
+ }
+ }
+}