# HG changeset patch # User lana # Date 1259216070 28800 # Node ID 6fd07b9034781937faabde644a8bb3f87b7fe85c # Parent b62c74b1772e6735ac5599b754eb14f50d0ab770# Parent 5f452be1691ed26f43680fdab38908d6d5376d0a Merge diff -r b62c74b1772e -r 6fd07b903478 .hgtags --- a/.hgtags Wed Nov 25 21:27:06 2009 +0300 +++ b/.hgtags Wed Nov 25 22:14:30 2009 -0800 @@ -48,3 +48,6 @@ b3f3240135f0c10b9f2481c174b81b7fcf0daa60 jdk7-b71 460639b036f327282832a4fe52b7aa45688afd50 jdk7-b72 f708138c9aca4b389872838fe6773872fce3609e jdk7-b73 +eacb36e30327e7ae33baa068e82ddccbd91eaae2 jdk7-b74 +8885b22565077236a927e824ef450742e434a230 jdk7-b75 +8fb602395be0f7d5af4e7e93b7df2d960faf9d17 jdk7-b76 diff -r b62c74b1772e -r 6fd07b903478 make/common/Defs-linux.gmk --- a/make/common/Defs-linux.gmk Wed Nov 25 21:27:06 2009 +0300 +++ b/make/common/Defs-linux.gmk Wed Nov 25 22:14:30 2009 -0800 @@ -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) # diff -r b62c74b1772e -r 6fd07b903478 make/common/Defs.gmk --- a/make/common/Defs.gmk Wed Nov 25 21:27:06 2009 +0300 +++ b/make/common/Defs.gmk Wed Nov 25 22:14:30 2009 -0800 @@ -667,12 +667,7 @@ LINTFLAGS = $(LINTFLAGS_$(VARIANT)) $(LINTFLAGS_COMMON) \ $(OTHER_LINTFLAGS) -# this should be moved into Defs-.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 diff -r b62c74b1772e -r 6fd07b903478 make/common/Program.gmk --- a/make/common/Program.gmk Wed Nov 25 21:27:06 2009 +0300 +++ b/make/common/Program.gmk Wed Nov 25 22:14:30 2009 -0800 @@ -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) # diff -r b62c74b1772e -r 6fd07b903478 make/common/Release.gmk --- a/make/common/Release.gmk Wed Nov 25 21:27:06 2009 +0300 +++ b/make/common/Release.gmk Wed Nov 25 22:14:30 2009 -0800 @@ -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) # diff -r b62c74b1772e -r 6fd07b903478 make/common/Rules.gmk --- a/make/common/Rules.gmk Wed Nov 25 21:27:06 2009 +0300 +++ b/make/common/Rules.gmk Wed Nov 25 22:14:30 2009 -0800 @@ -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) diff -r b62c74b1772e -r 6fd07b903478 make/common/shared/Defs-java.gmk --- a/make/common/shared/Defs-java.gmk Wed Nov 25 21:27:06 2009 +0300 +++ b/make/common/shared/Defs-java.gmk Wed Nov 25 22:14:30 2009 -0800 @@ -165,11 +165,6 @@ JAVADOC_CMD = $(JAVA_TOOLS_DIR)/javadoc $(JAVA_TOOLS_FLAGS:%=-J%) endif -#always use the bootstrap javah until bug-ID 6889255 is fixed. These -#five lines should be removed as part of that fix: -JAVAH_CMD = $(JAVA_TOOLS_DIR)/javah \ - $(JAVAHFLAGS) - # Override of what javac to use (see deploy workspace) ifdef JAVAC JAVAC_CMD = $(JAVAC) diff -r b62c74b1772e -r 6fd07b903478 make/docs/CORE_PKGS.gmk --- a/make/docs/CORE_PKGS.gmk Wed Nov 25 21:27:06 2009 +0300 +++ b/make/docs/CORE_PKGS.gmk Wed Nov 25 22:14:30 2009 -0800 @@ -160,10 +160,8 @@ javax.lang.model.type \ javax.lang.model.util \ javax.management \ - javax.management.event \ javax.management.loading \ javax.management.monitor \ - javax.management.namespace \ javax.management.relation \ javax.management.openmbean \ javax.management.timer \ diff -r b62c74b1772e -r 6fd07b903478 make/java/instrument/Makefile --- a/make/java/instrument/Makefile Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/instrument/Makefile Wed Nov 25 22:14:30 2009 -0800 @@ -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 diff -r b62c74b1772e -r 6fd07b903478 make/java/java/FILES_java.gmk --- a/make/java/java/FILES_java.gmk Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/java/FILES_java.gmk Wed Nov 25 22:14:30 2009 -0800 @@ -251,6 +251,7 @@ java/util/IdentityHashMap.java \ java/util/EnumMap.java \ java/util/Arrays.java \ + java/util/DualPivotQuicksort.java \ java/util/TimSort.java \ java/util/ComparableTimSort.java \ java/util/ConcurrentModificationException.java \ @@ -258,6 +259,7 @@ java/util/ServiceConfigurationError.java \ java/util/Timer.java \ java/util/TimerTask.java \ + java/util/Objects.java \ java/util/UUID.java \ java/util/concurrent/AbstractExecutorService.java \ java/util/concurrent/ArrayBlockingQueue.java \ @@ -285,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 \ @@ -300,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 \ diff -r b62c74b1772e -r 6fd07b903478 make/java/jli/Makefile --- a/make/java/jli/Makefile Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/jli/Makefile Wed Nov 25 22:14:30 2009 -0800 @@ -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 # diff -r b62c74b1772e -r 6fd07b903478 make/java/main/java/Makefile --- a/make/java/main/java/Makefile Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/main/java/Makefile Wed Nov 25 22:14:30 2009 -0800 @@ -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) diff -r b62c74b1772e -r 6fd07b903478 make/java/main/javaw/Makefile --- a/make/java/main/javaw/Makefile Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/main/javaw/Makefile Wed Nov 25 22:14:30 2009 -0800 @@ -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)"' + diff -r b62c74b1772e -r 6fd07b903478 make/java/net/Makefile --- a/make/java/net/Makefile Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/net/Makefile Wed Nov 25 22:14:30 2009 -0800 @@ -83,7 +83,7 @@ # # Find platform specific native code # -vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http $(PLATFORM_SRC)/native/sun/net/spi +vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm $(PLATFORM_SRC)/native/sun/net/spi # # Include rules diff -r b62c74b1772e -r 6fd07b903478 make/java/nio/Makefile --- a/make/java/nio/Makefile Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/nio/Makefile Wed Nov 25 22:14:30 2009 -0800 @@ -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 diff -r b62c74b1772e -r 6fd07b903478 make/java/nio/genBuffer.sh --- a/make/java/nio/genBuffer.sh Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/nio/genBuffer.sh Wed Nov 25 22:14:30 2009 -0800 @@ -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 diff -r b62c74b1772e -r 6fd07b903478 make/java/redist/Makefile --- a/make/java/redist/Makefile Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/redist/Makefile Wed Nov 25 22:14:30 2009 -0800 @@ -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 @@ -211,7 +216,7 @@ $(LIB_LOCATION)/$(KERNEL_LOCATION)/$(JVM_NAME): $(HOTSPOT_KERNEL_PATH)/$(JVM_NAME) $(install-file) -$(LIB_LOCATION)/$(LIBJSIG_NAME): $(HOTSPOT_SERVER_PATH)/$(LIBJSIG_NAME) +$(LIB_LOCATION)/$(LIBJSIG_NAME): $(HOTSPOT_IMPORT_PATH)/$(ARCH_VM_SUBDIR)/$(LIBJSIG_NAME) $(install-import-file) $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(LIBJSIG_NAME) \ diff -r b62c74b1772e -r 6fd07b903478 make/java/version/Makefile --- a/make/java/version/Makefile Wed Nov 25 21:27:06 2009 +0300 +++ b/make/java/version/Makefile Wed Nov 25 22:14:30 2009 -0800 @@ -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' \ diff -r b62c74b1772e -r 6fd07b903478 make/javax/sound/Makefile --- a/make/javax/sound/Makefile Wed Nov 25 21:27:06 2009 +0300 +++ b/make/javax/sound/Makefile Wed Nov 25 22:14:30 2009 -0800 @@ -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) diff -r b62c74b1772e -r 6fd07b903478 make/javax/sound/SoundDefs.gmk --- a/make/javax/sound/SoundDefs.gmk Wed Nov 25 21:27:06 2009 +0300 +++ b/make/javax/sound/SoundDefs.gmk Wed Nov 25 22:14:30 2009 -0800 @@ -55,21 +55,25 @@ endif # PLATFORM solaris -ifeq ($(ARCH), i586) - CPPFLAGS += -DX_ARCH=X_I586 -endif # ARCH i586 +ifeq ($(ZERO_BUILD), true) + CPPFLAGS += -DX_ARCH=X_ZERO +else + ifeq ($(ARCH), i586) + CPPFLAGS += -DX_ARCH=X_I586 + endif # ARCH i586 -ifeq ($(ARCH), sparc) - CPPFLAGS += -DX_ARCH=X_SPARC -endif # ARCH sparc + ifeq ($(ARCH), sparc) + CPPFLAGS += -DX_ARCH=X_SPARC + endif # ARCH sparc -ifeq ($(ARCH), sparcv9) - CPPFLAGS += -DX_ARCH=X_SPARCV9 -endif # ARCH sparcv9 + ifeq ($(ARCH), sparcv9) + CPPFLAGS += -DX_ARCH=X_SPARCV9 + endif # ARCH sparcv9 -ifeq ($(ARCH), amd64) - CPPFLAGS += -DX_ARCH=X_AMD64 -endif # ARCH amd64 + ifeq ($(ARCH), amd64) + CPPFLAGS += -DX_ARCH=X_AMD64 + endif # ARCH amd64 +endif # files needed for MIDI i/o diff -r b62c74b1772e -r 6fd07b903478 make/jdk_generic_profile.sh --- a/make/jdk_generic_profile.sh Wed Nov 25 21:27:06 2009 +0300 +++ b/make/jdk_generic_profile.sh Wed Nov 25 22:14:30 2009 -0800 @@ -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 diff -r b62c74b1772e -r 6fd07b903478 make/jprt.properties --- a/make/jprt.properties Wed Nov 25 21:27:06 2009 +0300 +++ b/make/jprt.properties Wed Nov 25 22:14:30 2009 -0800 @@ -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 diff -r b62c74b1772e -r 6fd07b903478 make/launchers/Makefile.launcher --- a/make/launchers/Makefile.launcher Wed Nov 25 21:27:06 2009 +0300 +++ b/make/launchers/Makefile.launcher Wed Nov 25 22:14:30 2009 -0800 @@ -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 diff -r b62c74b1772e -r 6fd07b903478 make/netbeans/jconsole/build.properties --- a/make/netbeans/jconsole/build.properties Wed Nov 25 21:27:06 2009 +0300 +++ b/make/netbeans/jconsole/build.properties Wed Nov 25 22:14:30 2009 -0800 @@ -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=\ diff -r b62c74b1772e -r 6fd07b903478 make/netbeans/jconsole/build.xml --- a/make/netbeans/jconsole/build.xml Wed Nov 25 21:27:06 2009 +0300 +++ b/make/netbeans/jconsole/build.xml Wed Nov 25 22:14:30 2009 -0800 @@ -35,7 +35,7 @@ +# http://www.aad.gov.au/default.asp?casid=37079 +# +# +# We have more background information here: +# +# http://www.timeanddate.com/news/time/antarctica-new-times.html +# + # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/Casey 0 - zzz 1969 - 8:00 - WST # Western (Aus) Standard Time + 8:00 - WST 2009 Oct 18 2:00 + # Western (Aus) Standard Time + 11:00 - CAST # Casey Time Zone Antarctica/Davis 0 - zzz 1957 Jan 13 7:00 - DAVT 1964 Nov # Davis Time 0 - zzz 1969 Feb - 7:00 - DAVT + 7:00 - DAVT 2009 Oct 18 2:0 + 5:00 - DAVT Zone Antarctica/Mawson 0 - zzz 1954 Feb 13 - 6:00 - MAWT # Mawson Time + 6:00 - MAWT 2009 Oct 18 2:00 + # Mawson Time + 5:00 - MAWT # References: # # Casey Weather (1998-02-26) diff -r b62c74b1772e -r 6fd07b903478 make/sun/javazic/tzdata/asia --- a/make/sun/javazic/tzdata/asia Wed Nov 25 21:27:06 2009 +0300 +++ b/make/sun/javazic/tzdata/asia Wed Nov 25 22:14:30 2009 -0800 @@ -21,7 +21,6 @@ # CA 95054 USA or visit www.sun.com if you need additional information or # have any questions. # -#
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -194,11 +193,30 @@
 #
 # No DST end date has been announced yet.
 
-# From Arthur David Olson (2009-07-11):
-# Arbitrarily end DST at the end of 2009 so that a POSIX-sytle time zone string
-# can appear in the Dhaka binary file and for the benefit of old glibc
-# reimplementations of the time zone software that mishandle permanent DST.
-# A change will be required once the end date is known.
+# From Alexander Krivenyshev (2009-09-25):
+# Bangladesh won't go back to Standard Time from October 1, 2009, 
+# instead it will continue DST measure till the cabinet makes a fresh decision. 
+#
+# Following report by same newspaper-"The Daily Star Friday":
+# "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
+# 
+# http://www.thedailystar.net/newDesign/news-details.php?nid=107021
+# 
+# or
+# 
+# http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html
+# 
+
+# From Steffen Thorsen (2009-10-13):
+# IANS (Indo-Asian News Service) now reports:
+# Bangladesh has decided that the clock advanced by an hour to make 
+# maximum use of daylight hours as an energy saving measure would 
+# "continue for an indefinite period."
+#
+# One of many places where it is published:
+# 
+# http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html
+# 
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dhaka	6:01:40 -	LMT	1890
@@ -208,8 +226,7 @@
 			6:30	-	BURT	1951 Sep 30
 			6:00	-	DACT	1971 Mar 26 # Dacca Time
 			6:00	-	BDT	2009 Jun 19 23:00 # Bangladesh Time
-			6:00	1:00	BDST	2010
-			6:00	-	BDT
+			6:00	1:00	BDST
 
 # Bhutan
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -373,14 +390,84 @@
 			5:00	-	KAST	1980 May
 			8:00	PRC	C%sT
 
+
+# From Lee Yiu Chung (2009-10-24):
+# I found there are some mistakes for the historial DST rule for Hong
+# Kong. Accoring to the DST record from Hong Kong Observatory (actually,
+# it is not [an] observatory, but the official meteorological agency of HK,
+# and also serves as the official timing agency), there are some missing
+# and incorrect rules. Although the exact switch over time is missing, I
+# think 3:30 is correct. The official DST record for Hong Kong can be
+# obtained from
+# 
+# http://www.hko.gov.hk/gts/time/Summertime.htm
+# .
+
+# From Arthur David Olson (2009-10-28):
+# Here are the dates given at
+# 
+# http://www.hko.gov.hk/gts/time/Summertime.htm
+# 
+# as of 2009-10-28:
+# Year        Period
+# 1941        1 Apr to 30 Sep
+# 1942        Whole year 
+# 1943        Whole year
+# 1944        Whole year
+# 1945        Whole year
+# 1946        20 Apr to 1 Dec
+# 1947        13 Apr to 30 Dec
+# 1948        2 May to 31 Oct
+# 1949        3 Apr to 30 Oct
+# 1950        2 Apr to 29 Oct
+# 1951        1 Apr to 28 Oct
+# 1952        6 Apr to 25 Oct
+# 1953        5 Apr to 1 Nov
+# 1954        21 Mar to 31 Oct
+# 1955        20 Mar to 6 Nov
+# 1956        18 Mar to 4 Nov
+# 1957        24 Mar to 3 Nov
+# 1958        23 Mar to 2 Nov
+# 1959        22 Mar to 1 Nov
+# 1960        20 Mar to 6 Nov
+# 1961        19 Mar to 5 Nov
+# 1962        18 Mar to 4 Nov
+# 1963        24 Mar to 3 Nov
+# 1964        22 Mar to 1 Nov
+# 1965        18 Apr to 17 Oct
+# 1966        17 Apr to 16 Oct
+# 1967        16 Apr to 22 Oct
+# 1968        21 Apr to 20 Oct
+# 1969        20 Apr to 19 Oct
+# 1970        19 Apr to 18 Oct
+# 1971        18 Apr to 17 Oct
+# 1972        16 Apr to 22 Oct
+# 1973        22 Apr to 21 Oct
+# 1973/74     30 Dec 73 to 20 Oct 74
+# 1975        20 Apr to 19 Oct
+# 1976        18 Apr to 17 Oct
+# 1977        Nil
+# 1978        Nil
+# 1979        13 May to 21 Oct
+# 1980 to Now Nil
+# The page does not give start or end times of day.
+# The page does not give a start date for 1942.
+# The page does not givw an end date for 1945.
+# The Japanese occupation of Hong Kong began on 1941-12-25.
+# The Japanese surrender of Hong Kong was signed 1945-09-15.
+# For lack of anything better, use start of those days as the transition times.
+
 # Hong Kong (Xianggang)
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	HK	1941	only	-	Apr	1	3:30	1:00	S
+Rule	HK	1941	only	-	Sep	30	3:30	0	-
 Rule	HK	1946	only	-	Apr	20	3:30	1:00	S
 Rule	HK	1946	only	-	Dec	1	3:30	0	-
 Rule	HK	1947	only	-	Apr	13	3:30	1:00	S
 Rule	HK	1947	only	-	Dec	30	3:30	0	-
 Rule	HK	1948	only	-	May	2	3:30	1:00	S
-Rule	HK	1948	1952	-	Oct	lastSun	3:30	0	-
+Rule	HK	1948	1951	-	Oct	lastSun	3:30	0	-
+Rule	HK	1952	only	-	Oct	25	3:30	0	-
 Rule	HK	1949	1953	-	Apr	Sun>=1	3:30	1:00	S
 Rule	HK	1953	only	-	Nov	1	3:30	0	-
 Rule	HK	1954	1964	-	Mar	Sun>=18	3:30	1:00	S
@@ -388,13 +475,15 @@
 Rule	HK	1955	1964	-	Nov	Sun>=1	3:30	0	-
 Rule	HK	1965	1977	-	Apr	Sun>=16	3:30	1:00	S
 Rule	HK	1965	1977	-	Oct	Sun>=16	3:30	0	-
-Rule	HK	1979	1980	-	May	Sun>=8	3:30	1:00	S
-Rule	HK	1979	1980	-	Oct	Sun>=16	3:30	0	-
+Rule	HK	1973	only	-	Dec	30	3:30	1:00	S
+Rule	HK	1979	only	-	May	Sun>=8	3:30	1:00	S
+Rule	HK	1979	only	-	Oct	Sun>=16	3:30	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Hong_Kong	7:36:36 -	LMT	1904 Oct 30
+			8:00	HK	HK%sT	1941 Dec 25
+			9:00	-	JST	1945 Sep 15
 			8:00	HK	HK%sT
 
-
 ###############################################################################
 
 # Taiwan
@@ -1696,16 +1785,66 @@
 # advance clocks in the country by one hour from April 15 to
 # conserve energy"
 
-# From Arthur David Olson (2009-04-10):
-# Assume for now that Pakistan will end DST in 2009 as it did in 2008.
+# From Steffen Thorsen (2009-09-17):
+# "The News International," Pakistan reports that: "The Federal
+# Government has decided to restore the previous time by moving the
+# clocks backward by one hour from October 1. A formal announcement to
+# this effect will be made after the Prime Minister grants approval in
+# this regard." 
+# 
+# http://www.thenews.com.pk/updates.asp?id=87168
+# 
+
+# From Alexander Krivenyshev (2009-09-28):
+# According to Associated Press Of Pakistan, it is confirmed that
+# Pakistan clocks across the country would be turned back by an hour from October
+# 1, 2009.
+#
+# "Clocks to go back one hour from 1 Oct"
+# 
+# http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2
+# 
+# or
+# 
+# http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm
+# 
+
+# From Steffen Thorsen (2009-09-29):
+# Alexander Krivenyshev wrote:
+# > According to Associated Press Of Pakistan, it is confirmed that
+# > Pakistan clocks across the country would be turned back by an hour from October
+# > 1, 2009.
+#
+# Now they seem to have changed their mind, November 1 is the new date:
+# 
+# http://www.thenews.com.pk/top_story_detail.asp?Id=24742
+# 
+# "The country's clocks will be reversed by one hour on November 1.
+# Officials of Federal Ministry for Interior told this to Geo News on
+# Monday."
+#
+# And more importantly, it seems that these dates will be kept every year:
+# "It has now been decided that clocks will be wound forward by one hour
+# on April 15 and reversed by an hour on November 1 every year without
+# obtaining prior approval, the officials added."
+#
+# We have confirmed this year's end date with both with the Ministry of
+# Water and Power and the Pakistan Electric Power Company:
+# 
+# http://www.timeanddate.com/news/time/pakistan-ends-dst09.html
+# 
+
+# From Christoph Goehre (2009-10-01):
+# [T]he German Consulate General in Karachi reported me today that Pakistan
+# will go back to standard time on 1st of November.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule Pakistan	2002	only	-	Apr	Sun>=2	0:01	1:00	S
 Rule Pakistan	2002	only	-	Oct	Sun>=2	0:01	0	-
 Rule Pakistan	2008	only	-	Jun	1	0:00	1:00	S
 Rule Pakistan	2008	only	-	Nov	1	0:00	0	-
-Rule Pakistan	2009	only	-	Apr	15	0:00	1:00	S
-Rule Pakistan	2009	only	-	Nov	1	0:00	0	-
+Rule Pakistan	2009	max	-	Apr	15	0:00	1:00	S
+Rule Pakistan	2009	max	-	Nov	1	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Karachi	4:28:12 -	LMT	1907
 			5:30	-	IST	1942 Sep
@@ -1858,6 +1997,42 @@
 # http://www.worldtimezone.com/dst_news/dst_news_westbank01.html
 # 
 
+# From Steffen Thorsen (2009-08-31):
+# Palestine's Council of Ministers announced that they will revert back to
+# winter time on Friday, 2009-09-04.
+#
+# One news source:
+# 
+# http://www.safa.ps/ara/?action=showdetail&seid=4158
+# 
+# (Palestinian press agency, Arabic),
+# Google translate: "Decided that the Palestinian government in Ramallah
+# headed by Salam Fayyad, the start of work in time for the winter of
+# 2009, starting on Friday approved the fourth delay Sept. clock sixty
+# minutes per hour as of Friday morning."
+#
+# We are not sure if Gaza will do the same, last year they had a different
+# end date, we will keep this page updated:
+# 
+# http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html
+# 
+
+# From Alexander Krivenyshev (2009-09-02):
+# Seems that Gaza Strip will go back to Winter Time same date as West Bank.
+#
+# According to Palestinian Ministry Of Interior, West Bank and Gaza Strip plan
+# to change time back to Standard time on September 4, 2009.
+#
+# "Winter time unite the West Bank and Gaza"
+# (from Palestinian National Authority):
+# 
+# http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html
+# 
+
 # The rules for Egypt are stolen from the `africa' file.
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule EgyptAsia	1957	only	-	May	10	0:00	1:00	S
@@ -1876,7 +2051,7 @@
 Rule Palestine	2007	only	-	Sep	Thu>=8	2:00	0	-
 Rule Palestine	2008	only	-	Aug	lastFri	2:00	0	-
 Rule Palestine	2009	max	-	Mar	lastFri	0:00	1:00	S
-Rule Palestine	2009	max	-	Sep	lastMon	2:00	0	-
+Rule Palestine	2009	max	-	Sep	Fri>=1	2:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Gaza	2:17:52	-	LMT	1900 Oct
@@ -2154,9 +2329,23 @@
 # http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
 # 
 
+# From Steffen Thorsen (2009-10-27):
+# The Syrian Arab News Network on 2009-09-29 reported that Syria will 
+# revert back to winter (standard) time on midnight between Thursday 
+# 2009-10-29 and Friday 2009-10-30:
+# 
+# http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
+# 
+
+# From Arthur David Olson (2009-10-28):
+# We'll see if future DST switching times turn out to be end of the last
+# Thursday of the month or the start of the last Friday of the month or
+# something else. For now, use the start of the last Friday.
+
 Rule	Syria	2008	only	-	Apr	Fri>=1	0:00	1:00	S
-Rule	Syria	2008	max	-	Nov	1	0:00	0	-
+Rule	Syria	2008	only	-	Nov	1	0:00	0	-
 Rule	Syria	2009	max	-	Mar	lastFri	0:00	1:00	S
+Rule	Syria	2009	max	-	Oct	lastFri	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
diff -r b62c74b1772e -r 6fd07b903478 make/sun/javazic/tzdata/australasia
--- a/make/sun/javazic/tzdata/australasia	Wed Nov 25 21:27:06 2009 +0300
+++ b/make/sun/javazic/tzdata/australasia	Wed Nov 25 22:14:30 2009 -0800
@@ -465,10 +465,56 @@
 # http://www.worldtimezone.com/dst_news/dst_news_samoa01.html
 # 
 
+# From Steffen Thorsen (2009-08-27):
+# Samoa's parliament passed the Daylight Saving Bill 2009, and will start 
+# daylight saving time on the first Sunday of October 2009 and end on the 
+# last Sunday of March 2010. We hope that the full text will be published 
+# soon, but we believe that the bill is only valid for 2009-2010. Samoa's 
+# Daylight Saving Act 2009 will be enforced as soon as the Head of State 
+# executes a proclamation publicizing this Act.
+#
+# Some background information here, which will be updated once we have 
+# more details:
+# 
+# http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html
+# 
+
+# From Alexander Krivenyshev (2009-10-03):
+# First, my deepest condolences to people of Samoa islands and all families and
+# loved ones around the world who lost their lives in the earthquake and tsunami.
+#
+# Considering the recent devastation on Samoa by earthquake and tsunami and that
+# many government offices/ ministers are closed- not sure if "Daylight Saving
+# Bill 2009" will be implemented in next few days- on October 4, 2009.
+#
+# Here is reply from Consulate-General of Samoa in New Zealand
+# ---------------------------
+# Consul General
+# consulgeneral@samoaconsulate.org.nz
+#
+# Talofa Alexander,
+#
+# Thank you for your sympathy for our country but at this time we have not
+# been informed about the Daylight Savings Time Change.  Most Ministries in
+# Apia are closed or relocating due to weather concerns.
+#
+# When we do find out if they are still proceeding with the time change we
+# will advise you soonest.
+#
+# Kind Regards,
+# Lana
+# for: Consul General
+
+# From Steffen Thorsen (2009-10-05):
+# We have called a hotel in Samoa and asked about local time there - they 
+# are still on standard time.
+
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
 			-11:30	-	SAMT	1950		# Samoa Time
-			-11:00	-	WST			# Samoa Time
+			-11:00	-	WST	2009 Oct 4
+			-11:00	1:00	WSDT	2010 Mar 28
+			-11:00	-	WST
 
 # Solomon Is
 # excludes Bougainville, for which see Papua New Guinea
diff -r b62c74b1772e -r 6fd07b903478 make/sun/javazic/tzdata/europe
--- a/make/sun/javazic/tzdata/europe	Wed Nov 25 21:27:06 2009 +0300
+++ b/make/sun/javazic/tzdata/europe	Wed Nov 25 22:14:30 2009 -0800
@@ -2094,9 +2094,43 @@
 			 6:00	Russia	NOV%sT	1992 Jan 19 2:00s
 			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
 			 6:00	Russia	NOV%sT
+
+# From Alexander Krivenyshev (2009-10-13):
+# Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
+# March 28, 2010:
+# from current Russia Zone 6 - Krasnoyarsk Time Zone (KRA) UTC +0700
+# to Russia Zone 5 - Novosibirsk Time Zone (NOV) UTC +0600
+#
+# This is according to Government of Russia decree # 740, on September
+# 14, 2009 "Application in the territory of the Kemerovo region the Fifth
+# time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
+#
+# Russian Government web site (Russian language)
+# 
+# http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm
+# 
+# or Russian-English translation by WorldTimeZone.com with reference
+# map to local region and new Russia Time Zone map after March 28, 2010
+# 
+# http://www.worldtimezone.com/dst_news/dst_news_russia03.html
+# 
+#
+# Thus, when Russia will switch to DST on the night of March 28, 2010
+# Kemerovo region (Kemerovo oblast') will not change the clock.
+#
+# As a result, Kemerovo oblast' will be in the same time zone as
+# Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
+
+Zone Asia/Novokuznetsk	 5:48:48 -	NMT	1920 Jan  6
+			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
+			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
+			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
+			 7:00	Russia	KRA%sT	2010 Mar 28 2:00s
+			 6:00	Russia	NOV%sT # Novosibirsk/Novokuznetsk Time
+
 #
 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Kemerovskaya oblast', Krasnoyarskij kraj,
+# Krasnoyarskij kraj,
 # Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
 # Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
 Zone Asia/Krasnoyarsk	 6:11:20 -	LMT	1920 Jan  6
diff -r b62c74b1772e -r 6fd07b903478 make/sun/javazic/tzdata/southamerica
--- a/make/sun/javazic/tzdata/southamerica	Wed Nov 25 21:27:06 2009 +0300
+++ b/make/sun/javazic/tzdata/southamerica	Wed Nov 25 22:14:30 2009 -0800
@@ -237,9 +237,23 @@
 # http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc
 # 
 
+# From fullinet (2009-10-18):
+# As announced in
+# 
+# http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356
+# 
+# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change")
+#
+# "Por el momento, el Gobierno Nacional resolvio no modificar la hora
+# oficial, decision que estaba en estudio para su implementacion el
+# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio
+# que la Argentina hoy, en estas condiciones meteorologicas, no necesita
+# la modificacion del huso horario, ya que 2009 nos encuentra con
+# crecimiento en la produccion y distribucion energetica."
+
 Rule	Arg	2007	only	-	Dec	30	0:00	1:00	S
-Rule	Arg	2008	max	-	Mar	Sun>=15	0:00	0	-
-Rule	Arg	2008	max	-	Oct	Sun>=15	0:00	1:00	S
+Rule	Arg	2008	2009	-	Mar	Sun>=15	0:00	0	-
+Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
  
 # From Mariano Absatz (2004-05-21):
 # Today it was officially published that the Province of Mendoza is changing
@@ -411,15 +425,40 @@
 # during 2009, this timezone change will run from 00:00 the third Sunday
 # in March until 24:00 of the second Saturday in October.
 
-# From Arthur David Olson (2009-03-16):
-# The unofficial claim at
-# 
-# http://www.timeanddate.com/news/time/san-luis-new-time-zone.html
+# From Mariano Absatz (2009-10-16):
+# ...the Province of San Luis is a case in itself.
+#
+# The Law at
+# 
-# is that "The province will most likely follow the next daylight saving schedule,
-# which is planned for the second Sunday in October."
+# is ambiguous because establishes a calendar from the 2nd Sunday in
+# October at 0:00 thru the 2nd Saturday in March at 24:00 and the
+# complement of that starting on the 2nd Sunday of March at 0:00 and
+# ending on the 2nd Saturday of March at 24:00.
+#
+# This clearly breaks every time the 1st of March or October is a Sunday.
+#
+# IMHO, the "spirit of the Law" is to make the changes at 0:00 on the 2nd
+# Sunday of October and March.
+#
+# The problem is that the changes in the rest of the Provinces that did
+# change in 2007/2008, were made according to the Federal Law and Decrees
+# that did so on the 3rd Sunday of October and March.
+#
+# In fact, San Luis actually switched from UTC-4 to UTC-3 last Sunday
+# (October 11th) at 0:00.
+#
+# So I guess a new set of rules, besides "Arg", must be made and the last
+# America/Argentina/San_Luis entries should change to use these...
+#
+# I'm enclosing a patch that does what I say... regretfully, the San Luis
+# timezone must be called "WART/WARST" even when most of the time (like,
+# right now) WARST == ART... that is, since last Sunday, all the country
+# is using UTC-3, but in my patch, San Luis calls it "WARST" and the rest
+# of the country calls it "ART".
+# ...
 
-#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 #
 # Buenos Aires (BA), Capital Federal (CF),
@@ -552,6 +591,10 @@
 			-3:00	-	ART
 #
 # San Luis (SL)
+
+Rule	SanLuis	2008	max	-	Mar	Sun>=8	0:00	0	-
+Rule	SanLuis	2007	max	-	Oct	Sun>=8	0:00	1:00	S
+
 Zone America/Argentina/San_Luis -4:25:24 - LMT	1894 Oct 31
 			-4:16:48 -	CMT	1920 May
 			-4:00	-	ART	1930 Dec
@@ -566,8 +609,7 @@
 			-3:00	-	ART	2004 May 31
 			-4:00	-	WART	2004 Jul 25
 			-3:00	Arg	AR%sT	2008 Jan 21
-			-3:00	-	ART	2009 Mar 15
-			-4:00	Arg	WAR%sT
+			-4:00	SanLuis	WAR%sT
 #
 # Santa Cruz (SC)
 Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
diff -r b62c74b1772e -r 6fd07b903478 make/sun/javazic/tzdata/zone.tab
--- a/make/sun/javazic/tzdata/zone.tab	Wed Nov 25 21:27:06 2009 +0300
+++ b/make/sun/javazic/tzdata/zone.tab	Wed Nov 25 22:14:30 2009 -0800
@@ -352,6 +352,7 @@
 RU	+5651+06036	Asia/Yekaterinburg	Moscow+02 - Urals
 RU	+5500+07324	Asia/Omsk	Moscow+03 - west Siberia
 RU	+5502+08255	Asia/Novosibirsk	Moscow+03 - Novosibirsk
+RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 - Novokuznetsk
 RU	+5601+09250	Asia/Krasnoyarsk	Moscow+04 - Yenisei River
 RU	+5216+10420	Asia/Irkutsk	Moscow+05 - Lake Baikal
 RU	+6200+12940	Asia/Yakutsk	Moscow+06 - Lena River
diff -r b62c74b1772e -r 6fd07b903478 make/sun/jconsole/Makefile
--- a/make/sun/jconsole/Makefile	Wed Nov 25 21:27:06 2009 +0300
+++ b/make/sun/jconsole/Makefile	Wed Nov 25 22:14:30 2009 -0800
@@ -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' $< > $@
 
diff -r b62c74b1772e -r 6fd07b903478 make/sun/net/FILES_java.gmk
--- a/make/sun/net/FILES_java.gmk	Wed Nov 25 21:27:06 2009 +0300
+++ b/make/sun/net/FILES_java.gmk	Wed Nov 25 22:14:30 2009 -0800
@@ -45,8 +45,14 @@
 	sun/net/dns/ResolverConfiguration.java \
 	sun/net/dns/ResolverConfigurationImpl.java \
 	sun/net/ftp/FtpClient.java \
+	sun/net/ftp/FtpClientProvider.java \
+	sun/net/ftp/FtpDirEntry.java \
+	sun/net/ftp/FtpReplyCode.java \
+	sun/net/ftp/FtpDirParser.java \
 	sun/net/ftp/FtpLoginException.java \
 	sun/net/ftp/FtpProtocolException.java \
+	sun/net/ftp/impl/FtpClient.java \
+	sun/net/ftp/impl/DefaultFtpClientProvider.java \
 	sun/net/spi/DefaultProxySelector.java \
 	sun/net/spi/nameservice/NameServiceDescriptor.java \
 	sun/net/spi/nameservice/NameService.java \
@@ -79,7 +85,6 @@
 	sun/net/www/http/Hurryable.java \
 	sun/net/www/protocol/http/Handler.java \
 	sun/net/www/protocol/http/HttpURLConnection.java \
-	sun/net/www/protocol/http/HttpLogFormatter.java \
 	sun/net/www/protocol/http/HttpAuthenticator.java \
 	sun/net/www/protocol/http/AuthenticationHeader.java \
 	sun/net/www/protocol/http/AuthenticationInfo.java \
@@ -89,11 +94,13 @@
 	sun/net/www/protocol/http/AuthScheme.java \
 	sun/net/www/protocol/http/BasicAuthentication.java \
 	sun/net/www/protocol/http/DigestAuthentication.java \
-	sun/net/www/protocol/http/NTLMAuthentication.java \
 	sun/net/www/protocol/http/NTLMAuthenticationProxy.java \
 	sun/net/www/protocol/http/NegotiateAuthentication.java \
-	sun/net/www/protocol/http/NegotiatorImpl.java \
-	sun/net/www/protocol/http/NegotiateCallbackHandler.java \
+	sun/net/www/protocol/http/Negotiator.java \
+	sun/net/www/protocol/http/ntlm/NTLMAuthentication.java \
+	sun/net/www/protocol/http/spnego/NegotiatorImpl.java \
+	sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java \
+	sun/net/www/protocol/http/logging/HttpLogFormatter.java \
 	sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java \
 	sun/net/www/protocol/https/HttpsClient.java \
 	sun/net/www/protocol/https/DefaultHostnameVerifier.java \
@@ -128,7 +135,7 @@
 	sun/net/idn/StringPrep.java
 
 ifeq ($(PLATFORM), windows)
-    FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java 
+    FILES_java += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java 
 endif
 
 ifeq ($(PLATFORM), solaris)
diff -r b62c74b1772e -r 6fd07b903478 make/sun/nio/Makefile
--- a/make/sun/nio/Makefile	Wed Nov 25 21:27:06 2009 +0300
+++ b/make/sun/nio/Makefile	Wed Nov 25 22:14:30 2009 -0800
@@ -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
diff -r b62c74b1772e -r 6fd07b903478 make/sun/security/other/Makefile
--- a/make/sun/security/other/Makefile	Wed Nov 25 21:27:06 2009 +0300
+++ b/make/sun/security/other/Makefile	Wed Nov 25 22:14:30 2009 -0800
@@ -39,6 +39,7 @@
     sun/security/provider \
     sun/security/rsa \
     sun/security/ssl \
+    sun/security/ssl/krb5 \
     sun/security/timestamp \
     sun/security/validator \
     sun/security/x509 \
diff -r b62c74b1772e -r 6fd07b903478 make/tools/Makefile
--- a/make/tools/Makefile	Wed Nov 25 21:27:06 2009 +0300
+++ b/make/tools/Makefile	Wed Nov 25 22:14:30 2009 -0800
@@ -38,7 +38,6 @@
   compile_properties        \
   dir_diff                  \
   dtdbuilder                \
-  fontchecker               \
   freetypecheck             \
   generate_break_iterator   \
   GenerateCharacter         \
diff -r b62c74b1772e -r 6fd07b903478 make/tools/fontchecker/Makefile
--- a/make/tools/fontchecker/Makefile	Wed Nov 25 21:27:06 2009 +0300
+++ /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
-
diff -r b62c74b1772e -r 6fd07b903478 make/tools/src/build/tools/fontchecker/FontCheckDummy.java
--- a/make/tools/src/build/tools/fontchecker/FontCheckDummy.java	Wed Nov 25 21:27:06 2009 +0300
+++ /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).
- *
- * 
- * 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.
- * 
- * - * @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. - *

- * @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. - *
- * This methods attempts to create an instance of font from - * a string that represents path to the font file. - *

- * @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. - *
- * 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); - } -} diff -r b62c74b1772e -r 6fd07b903478 make/tools/src/build/tools/fontchecker/FontChecker.java --- a/make/tools/src/build/tools/fontchecker/FontChecker.java Wed Nov 25 21:27:06 2009 +0300 +++ /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. - * - *
- * 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.
- *
- * 
- * - * @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. - *
- * Stops the timer and interrupts the current thread which is - * still waiting on I/O from the child process. - *

- * @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. - *
- * 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. - *
- * This method is used to test whether a font specified by the given - * path is valid and does not crash the system. - *

- * @param fontPath a string representation of font path - * to standard out during while this font is tried - * @return returns true if font is OK, and - * false 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. - *
- * This method goes through every font in system's font path and verifies - * its integrity via the tryFont method. - *

- * @param restart true if checking of fonts should continue - * after the first bad font is found, and false otherwise - * @return returns true if all fonts are valid, - * false 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); - } -} diff -r b62c74b1772e -r 6fd07b903478 make/tools/src/build/tools/fontchecker/FontCheckerConstants.java --- a/make/tools/src/build/tools/fontchecker/FontCheckerConstants.java Wed Nov 25 21:27:06 2009 +0300 +++ /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; -} diff -r b62c74b1772e -r 6fd07b903478 make/tools/src/build/tools/fontchecker/FontFileFilter.java --- a/make/tools/src/build/tools/fontchecker/FontFileFilter.java Wed Nov 25 21:27:06 2009 +0300 +++ /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. - */ - -/* - *
- * This class filters TrueType font files from other file
- * found in the font path.
- *
- * 
- * - * @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. - *
- * 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. - *

- * @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; - } - -} diff -r b62c74b1772e -r 6fd07b903478 make/tools/src/build/tools/fontchecker/README.txt --- a/make/tools/src/build/tools/fontchecker/README.txt Wed Nov 25 21:27:06 2009 +0300 +++ /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 - -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. diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java --- a/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Wed Nov 25 22:14:30 2009 -0800 @@ -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 a = new PrivilegedAction() { + 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 a = new PrivilegedAction() { + 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; + } + } } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonUI.java --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxUI.java --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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; } } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonUI.java --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/motif/MotifToggleButtonUI.java --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifToggleButtonUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifToggleButtonUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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) { diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java Wed Nov 25 22:14:30 2009 -0800 @@ -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; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/defaults/JmxProperties.java --- a/src/share/classes/com/sun/jmx/defaults/JmxProperties.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/defaults/JmxProperties.java Wed Nov 25 22:14:30 2009 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -177,18 +177,6 @@ "javax.management.relation"; /** - * Logger name for Namespaces. - */ - public static final String NAMESPACE_LOGGER_NAME = - "javax.management.namespace"; - - /** - * Logger name for Namespaces. - */ - public static final Logger NAMESPACE_LOGGER = - Logger.getLogger(NAMESPACE_LOGGER_NAME); - - /** * Logger for Relation Service. */ public static final Logger RELATION_LOGGER = diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/defaults/ServiceName.java --- a/src/share/classes/com/sun/jmx/defaults/ServiceName.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/defaults/ServiceName.java Wed Nov 25 22:14:30 2009 -0800 @@ -69,9 +69,9 @@ /** * The version of the JMX specification implemented by this product. *
- * The value is 2.0. + * The value is 1.4. */ - public static final String JMX_SPEC_VERSION = "2.0"; + public static final String JMX_SPEC_VERSION = "1.4"; /** * The vendor of the JMX specification implemented by this product. diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/event/DaemonThreadFactory.java --- a/src/share/classes/com/sun/jmx/event/DaemonThreadFactory.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -public class DaemonThreadFactory implements ThreadFactory { - public DaemonThreadFactory(String nameTemplate) { - this(nameTemplate, null); - } - - // nameTemplate should be a format with %d in it, which will be replaced - // by a sequence number of threads created by this factory. - public DaemonThreadFactory(String nameTemplate, ThreadGroup threadGroup) { - if (logger.debugOn()) { - logger.debug("DaemonThreadFactory", - "Construct a new daemon factory: "+nameTemplate); - } - - if (threadGroup == null) { - SecurityManager s = System.getSecurityManager(); - threadGroup = (s != null) ? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); - } - - this.nameTemplate = nameTemplate; - this.threadGroup = threadGroup; - } - - public Thread newThread(Runnable r) { - final String name = - String.format(nameTemplate, threadNumber.getAndIncrement()); - Thread t = new Thread(threadGroup, r, name, 0); - t.setDaemon(true); - if (t.getPriority() != Thread.NORM_PRIORITY) - t.setPriority(Thread.NORM_PRIORITY); - - if (logger.debugOn()) { - logger.debug("newThread", - "Create a new daemon thread with the name "+t.getName()); - } - - return t; - } - - private final String nameTemplate; - private final ThreadGroup threadGroup; - private final AtomicInteger threadNumber = new AtomicInteger(1); - - private static final ClassLogger logger = - new ClassLogger("com.sun.jmx.event", "DaemonThreadFactory"); -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/event/EventBuffer.java --- a/src/share/classes/com/sun/jmx/event/EventBuffer.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.management.remote.NotificationResult; -import javax.management.remote.TargetedNotification; - -public class EventBuffer { - - public EventBuffer() { - this(Integer.MAX_VALUE, null); - } - - public EventBuffer(int capacity) { - this(capacity, new ArrayList()); - } - - public EventBuffer(int capacity, final List list) { - if (logger.traceOn()) { - logger.trace("EventBuffer", "New buffer with the capacity: " - +capacity); - } - if (capacity < 1) { - throw new IllegalArgumentException( - "The capacity must be bigger than 0"); - } - - if (list == null) { - throw new NullPointerException("Null list."); - } - - this.capacity = capacity; - this.list = list; - } - - public void add(TargetedNotification tn) { - if (logger.traceOn()) { - logger.trace("add", "Add one notif."); - } - - synchronized(lock) { - if (list.size() == capacity) { // have to throw one - passed++; - list.remove(0); - - if (logger.traceOn()) { - logger.trace("add", "Over, remove the oldest one."); - } - } - - list.add(tn); - lock.notify(); - } - } - - public void add(TargetedNotification[] tns) { - if (tns == null || tns.length == 0) { - return; - } - - if (logger.traceOn()) { - logger.trace("add", "Add notifs: "+tns.length); - } - - synchronized(lock) { - final int d = list.size() - capacity + tns.length; - if (d > 0) { // have to throw - passed += d; - if (logger.traceOn()) { - logger.trace("add", - "Over, remove the oldest: "+d); - } - if (tns.length <= capacity){ - list.subList(0, d).clear(); - } else { - list.clear(); - TargetedNotification[] tmp = - new TargetedNotification[capacity]; - System.arraycopy(tns, tns.length-capacity, tmp, 0, capacity); - tns = tmp; - } - } - - Collections.addAll(list,tns); - lock.notify(); - } - } - - public NotificationResult fetchNotifications(long startSequenceNumber, - long timeout, - int maxNotifications) { - if (logger.traceOn()) { - logger.trace("fetchNotifications", - "Being called: " - +startSequenceNumber+" " - +timeout+" "+maxNotifications); - } - if (startSequenceNumber < 0 || - timeout < 0 || - maxNotifications < 0) { - throw new IllegalArgumentException("Negative value."); - } - - TargetedNotification[] tns = new TargetedNotification[0]; - long earliest = startSequenceNumber < passed ? - passed : startSequenceNumber; - long next = earliest; - - final long startTime = System.currentTimeMillis(); - long toWait = timeout; - synchronized(lock) { - int toSkip = (int)(startSequenceNumber - passed); - - // skip those before startSequenceNumber. - while (!closed && toSkip > 0) { - toWait = timeout - (System.currentTimeMillis() - startTime); - if (list.size() == 0) { - if (toWait <= 0) { - // the notification of startSequenceNumber - // does not arrive yet. - return new NotificationResult(startSequenceNumber, - startSequenceNumber, - new TargetedNotification[0]); - } - - waiting(toWait); - continue; - } - - if (toSkip <= list.size()) { - list.subList(0, toSkip).clear(); - passed += toSkip; - - break; - } else { - passed += list.size(); - toSkip -= list.size(); - - list.clear(); - } - } - - earliest = passed; - - if (list.size() == 0) { - toWait = timeout - (System.currentTimeMillis() - startTime); - - waiting(toWait); - } - - if (list.size() == 0) { - tns = new TargetedNotification[0]; - } else if (list.size() <= maxNotifications) { - tns = list.toArray(new TargetedNotification[0]); - } else { - tns = new TargetedNotification[maxNotifications]; - for (int i=0; i 0) { - try { - lock.wait(toWait); - - toWait = timeout - (System.currentTimeMillis() - startTime); - } catch (InterruptedException ire) { - logger.trace("waiting", ire); - break; - } - } - } - } - - private final int capacity; - private final List list; - private boolean closed; - - private long passed = 0; - private final int[] lock = new int[0]; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "EventBuffer"); -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/event/EventClientFactory.java --- a/src/share/classes/com/sun/jmx/event/EventClientFactory.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.event; - -import javax.management.event.*; - -/** - * Implemented by objects which are using an {@link EventClient} to - * subscribe for Notifications. - * - */ -public interface EventClientFactory { - /** - * Returns the {@code EventClient} that the object implementing this - * interface uses to subscribe for Notifications. This method returns - * {@code null} if no {@code EventClient} can be used - e.g. because - * the underlying server does not have any {@link EventDelegate}. - * - * @return an {@code EventClient} or {@code null}. - **/ - public EventClient getEventClient(); - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/event/EventConnection.java --- a/src/share/classes/com/sun/jmx/event/EventConnection.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright 2002-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. - */ - -package com.sun.jmx.event; - -import java.io.IOException; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import javax.management.MBeanServerConnection; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.event.EventConsumer; -import javax.management.event.NotificationManager; - -/** - * Override the methods related to the notification to use the - * Event service. - */ -public interface EventConnection extends MBeanServerConnection, EventConsumer { - public EventClient getEventClient(); - - public static class Factory { - public static EventConnection make( - final MBeanServerConnection mbsc, - final EventClient eventClient) - throws IOException { - if (!mbsc.isRegistered(EventClientDelegate.OBJECT_NAME)) { - throw new IOException( - "The server does not support the event service."); - } - InvocationHandler ih = new InvocationHandler() { - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - Class intf = method.getDeclaringClass(); - try { - if (intf.isInstance(eventClient)) - return method.invoke(eventClient, args); - else - return method.invoke(mbsc, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - }; - // It is important to declare NotificationManager.class first - // in the array below, so that the relevant addNL and removeNL - // methods will show up with method.getDeclaringClass() as - // being from that interface and not MBeanServerConnection. - return (EventConnection) Proxy.newProxyInstance( - NotificationManager.class.getClassLoader(), - new Class[] { - NotificationManager.class, EventConnection.class, - }, - ih); - } - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/event/EventParams.java --- a/src/share/classes/com/sun/jmx/event/EventParams.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.mbeanserver.GetPropertyAction; -import com.sun.jmx.remote.util.ClassLogger; -import java.security.AccessController; -import javax.management.event.EventClient; - -/** - * - * @author sjiang - */ -public class EventParams { - public static final String DEFAULT_LEASE_TIMEOUT = - "com.sun.event.lease.time"; - - - @SuppressWarnings("cast") // cast for jdk 1.5 - public static long getLeaseTimeout() { - long timeout = EventClient.DEFAULT_REQUESTED_LEASE_TIME; - try { - final GetPropertyAction act = - new GetPropertyAction(DEFAULT_LEASE_TIMEOUT); - final String s = (String)AccessController.doPrivileged(act); - if (s != null) { - timeout = Long.parseLong(s); - } - } catch (RuntimeException e) { - logger.fine("getLeaseTimeout", "exception getting property", e); - } - - return timeout; - } - - /** Creates a new instance of EventParams */ - private EventParams() { - } - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "EventParams"); -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/event/LeaseManager.java --- a/src/share/classes/com/sun/jmx/event/LeaseManager.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; - -/** - *

Manage a renewable lease. The lease can be renewed indefinitely - * but if the lease runs to its current expiry date without being renewed - * then the expiry callback is invoked. If the lease has already expired - * when renewal is attempted then the lease method returns zero.

- * @author sjiang - * @author emcmanus - */ -// The synchronization logic of this class is tricky to deal correctly with the -// case where the lease expires at the same time as the |lease| or |stop| method -// is called. If the lease is active then the field |scheduled| represents -// the expiry task; otherwise |scheduled| is null. Renewing or stopping the -// lease involves canceling this task and setting |scheduled| either to a new -// task (to renew) or to null (to stop). -// -// Suppose the expiry task runs at the same time as the |lease| method is called. -// If the task enters its synchronized block before the method starts, then -// it will set |scheduled| to null and the method will return 0. If the method -// starts before the task enters its synchronized block, then the method will -// cancel the task which will see that when it later enters the block. -// Similar reasoning applies to the |stop| method. It is not expected that -// different threads will call |lease| or |stop| simultaneously, although the -// logic should be correct then too. -public class LeaseManager { - public LeaseManager(Runnable callback) { - this(callback, EventParams.getLeaseTimeout()); - } - - public LeaseManager(Runnable callback, long timeout) { - if (logger.traceOn()) { - logger.trace("LeaseManager", "new manager with lease: "+timeout); - } - if (callback == null) { - throw new NullPointerException("Null callback."); - } - if (timeout <= 0) - throw new IllegalArgumentException("Timeout must be positive: " + timeout); - - this.callback = callback; - schedule(timeout); - } - - /** - *

Renew the lease for the given time. The new time can be shorter - * than the previous one, in which case the lease will expire earlier - * than it would have.

- * - *

Calling this method after the lease has expired will return zero - * immediately and have no other effect.

- * - * @param timeout the new lifetime. If zero, the lease - * will expire immediately. - */ - public synchronized long lease(long timeout) { - if (logger.traceOn()) { - logger.trace("lease", "new lease to: "+timeout); - } - - if (timeout < 0) - throw new IllegalArgumentException("Negative lease: " + timeout); - - if (scheduled == null) - return 0L; - - scheduled.cancel(false); - - if (logger.traceOn()) - logger.trace("lease", "start lease: "+timeout); - schedule(timeout); - - return timeout; - } - - private class Expire implements Runnable { - ScheduledFuture task; - - public void run() { - synchronized (LeaseManager.this) { - if (task.isCancelled()) - return; - scheduled = null; - } - callback.run(); - executor.shutdown(); - } - } - - private synchronized void schedule(long timeout) { - Expire expire = new Expire(); - scheduled = executor.schedule(expire, timeout, TimeUnit.MILLISECONDS); - expire.task = scheduled; - } - - /** - *

Cancel the lease without calling the expiry callback.

- */ - public synchronized void stop() { - logger.trace("stop", "canceling lease"); - scheduled.cancel(false); - scheduled = null; - try { - executor.shutdown(); - } catch (SecurityException e) { - // OK: caller doesn't have RuntimePermission("modifyThread") - // which is unlikely in reality but triggers a test failure otherwise - logger.trace("stop", "exception from executor.shutdown", e); - } - } - - private final Runnable callback; - private ScheduledFuture scheduled; // If null, the lease has expired. - - private static final ThreadFactory threadFactory = - new DaemonThreadFactory("JMX LeaseManager %d"); - private final ScheduledExecutorService executor - = Executors.newScheduledThreadPool(1, threadFactory); - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "LeaseManager"); - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/event/LeaseRenewer.java --- a/src/share/classes/com/sun/jmx/event/LeaseRenewer.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.concurrent.Callable; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -/** - * - * @author sjiang - */ -public class LeaseRenewer { - public LeaseRenewer(ScheduledExecutorService scheduler, Callable doRenew) { - if (logger.traceOn()) { - logger.trace("LeaseRenewer", "New LeaseRenewer."); - } - - if (doRenew == null) { - throw new NullPointerException("Null job to call server."); - } - - this.doRenew = doRenew; - nextRenewTime = System.currentTimeMillis(); - - this.scheduler = scheduler; - future = this.scheduler.schedule(myRenew, 0, TimeUnit.MILLISECONDS); - } - - public void close() { - if (logger.traceOn()) { - logger.trace("close", "Close the lease."); - } - - synchronized(lock) { - if (closed) { - return; - } else { - closed = true; - } - } - - try { - future.cancel(false); // not interrupt if running - } catch (Exception e) { - // OK - if (logger.debugOn()) { - logger.debug("close", "Failed to cancel the leasing job.", e); - } - } - } - - public boolean closed() { - synchronized(lock) { - return closed; - } - } - - // ------------------------------ - // private - // ------------------------------ - private final Runnable myRenew = new Runnable() { - public void run() { - synchronized(lock) { - if (closed()) { - return; - } - } - - long next = nextRenewTime - System.currentTimeMillis(); - if (next < MIN_MILLIS) { - try { - if (logger.traceOn()) { - logger.trace("myRenew-run", ""); - } - next = doRenew.call().longValue(); - - } catch (Exception e) { - logger.fine("myRenew-run", "Failed to renew lease", e); - close(); - } - - if (next > 0 && next < Long.MAX_VALUE) { - next = next/2; - next = (next < MIN_MILLIS) ? MIN_MILLIS : next; - } else { - close(); - } - } - - nextRenewTime = System.currentTimeMillis() + next; - - if (logger.traceOn()) { - logger.trace("myRenew-run", "Next leasing: "+next); - } - - synchronized(lock) { - if (!closed) { - future = scheduler.schedule(this, next, TimeUnit.MILLISECONDS); - } - } - } - }; - - private final Callable doRenew; - private ScheduledFuture future; - private boolean closed = false; - private long nextRenewTime; - - private final int[] lock = new int[0]; - - private final ScheduledExecutorService scheduler; - - private static final long MIN_MILLIS = 50; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "LeaseRenewer"); -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/event/ReceiverBuffer.java --- a/src/share/classes/com/sun/jmx/event/ReceiverBuffer.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.management.remote.NotificationResult; -import javax.management.remote.TargetedNotification; - - -public class ReceiverBuffer { - public void addNotifs(NotificationResult nr) { - if (nr == null) { - return; - } - - TargetedNotification[] tns = nr.getTargetedNotifications(); - - if (logger.traceOn()) { - logger.trace("addNotifs", "" + tns.length); - } - - long impliedStart = nr.getEarliestSequenceNumber(); - final long missed = impliedStart - start; - start = nr.getNextSequenceNumber(); - - if (missed > 0) { - if (logger.traceOn()) { - logger.trace("addNotifs", - "lost: "+missed); - } - - lost += missed; - } - - Collections.addAll(notifList, nr.getTargetedNotifications()); - } - - public TargetedNotification[] removeNotifs() { - if (logger.traceOn()) { - logger.trace("removeNotifs", String.valueOf(notifList.size())); - } - - if (notifList.size() == 0) { - return null; - } - - TargetedNotification[] ret = notifList.toArray( - new TargetedNotification[]{}); - notifList.clear(); - - return ret; - } - - public int size() { - return notifList.size(); - } - - public int removeLost() { - int ret = lost; - lost = 0; - return ret; - } - - private List notifList - = new ArrayList(); - private long start = 0; - private int lost = 0; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "ReceiverBuffer"); -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java --- a/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.concurrent.Executor; -import java.util.concurrent.RejectedExecutionException; - -/** - *

A task that is repeatedly run by an Executor. The task will be - * repeated as long as the {@link #isSuspended()} method returns true. Once - * that method returns false, the task is no longer executed until someone - * calls {@link #resume()}.

- * @author sjiang - */ -public abstract class RepeatedSingletonJob implements Runnable { - public RepeatedSingletonJob(Executor executor) { - if (executor == null) { - throw new NullPointerException("Null executor!"); - } - - this.executor = executor; - } - - public boolean isWorking() { - return working; - } - - public void resume() { - - synchronized(this) { - if (!working) { - if (logger.traceOn()) { - logger.trace("resume", ""); - } - working = true; - execute(); - } - } - } - - public abstract void task(); - public abstract boolean isSuspended(); - - public void run() { - if (logger.traceOn()) { - logger.trace("run", "execute the task"); - } - try { - task(); - } catch (Exception e) { - // A correct task() implementation should not throw exceptions. - // It may cause isSuspended() to start returning true, though. - logger.trace("run", "failed to execute the task", e); - } - - synchronized(this) { - if (!isSuspended()) { - execute(); - } else { - if (logger.traceOn()) { - logger.trace("run", "suspend the task"); - } - working = false; - } - } - - } - - private void execute() { - try { - executor.execute(this); - } catch (RejectedExecutionException e) { - logger.warning( - "execute", - "Executor threw exception (" + this.getClass().getName() + ")", - e); - throw new RejectedExecutionException( - "Executor.execute threw exception -" + - "should not be possible", e); - // User-supplied Executor should not be configured in a way that - // might cause this exception, for example if it is shared between - // several client objects and doesn't have capacity for one job - // from each one. CR 6732037 will add text to the spec explaining - // the problem. The rethrown exception will propagate either out - // of resume() to user code, or out of run() to the Executor - // (which will probably ignore it). - } - } - - private boolean working = false; - private final Executor executor; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "RepeatedSingletonJob"); -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java --- a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Wed Nov 25 22:14:30 2009 -0800 @@ -30,16 +30,15 @@ import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; import com.sun.jmx.mbeanserver.DynamicMBean2; import com.sun.jmx.mbeanserver.Introspector; -import com.sun.jmx.mbeanserver.MBeanInjector; import com.sun.jmx.mbeanserver.MBeanInstantiator; import com.sun.jmx.mbeanserver.ModifiableClassLoaderRepository; import com.sun.jmx.mbeanserver.NamedObject; -import com.sun.jmx.mbeanserver.NotifySupport; import com.sun.jmx.mbeanserver.Repository; import com.sun.jmx.mbeanserver.Repository.RegistrationContext; import com.sun.jmx.mbeanserver.Util; import com.sun.jmx.remote.util.EnvHelp; +import java.io.ObjectInputStream; import java.lang.ref.WeakReference; import java.security.AccessControlContext; import java.security.AccessController; @@ -48,10 +47,7 @@ import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; import java.util.List; -import java.util.Queue; import java.util.Set; import java.util.WeakHashMap; import java.util.logging.Level; @@ -61,7 +57,6 @@ import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.DynamicMBean; -import javax.management.DynamicWrapperMBean; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.IntrospectionException; @@ -70,7 +65,6 @@ import javax.management.ListenerNotFoundException; import javax.management.MBeanException; import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; import javax.management.MBeanPermission; import javax.management.MBeanRegistration; import javax.management.MBeanRegistrationException; @@ -81,19 +75,19 @@ import javax.management.NotCompliantMBeanException; import javax.management.Notification; import javax.management.NotificationBroadcaster; -import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationEmitter; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.ObjectInstance; import javax.management.ObjectName; +import javax.management.OperationsException; import javax.management.QueryEval; import javax.management.QueryExp; import javax.management.ReflectionException; import javax.management.RuntimeErrorException; import javax.management.RuntimeMBeanException; import javax.management.RuntimeOperationsException; -import javax.management.namespace.JMXNamespace; +import javax.management.loading.ClassLoaderRepository; /** * This is the default class for MBean manipulation on the agent side. It @@ -116,8 +110,7 @@ * * @since 1.5 */ -public class DefaultMBeanServerInterceptor - extends MBeanServerInterceptorSupport { +public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor { /** The MBeanInstantiator object used by the * DefaultMBeanServerInterceptor */ @@ -142,14 +135,9 @@ new WeakHashMap>(); - private final NamespaceDispatchInterceptor dispatcher; - /** The default domain of the object names */ private final String domain; - /** The mbeanServerName */ - private final String mbeanServerName; - /** The sequence number identifying the notifications sent */ // Now sequence number is handled by MBeanServerDelegate. // private int sequenceNumber=0; @@ -168,13 +156,11 @@ * @param instantiator The MBeanInstantiator that will be used to * instantiate MBeans and take care of class loading issues. * @param repository The repository to use for this MBeanServer. - * @param dispatcher The dispatcher used by this MBeanServer */ public DefaultMBeanServerInterceptor(MBeanServer outer, MBeanServerDelegate delegate, MBeanInstantiator instantiator, - Repository repository, - NamespaceDispatchInterceptor dispatcher) { + Repository repository) { if (outer == null) throw new IllegalArgumentException("outer MBeanServer cannot be null"); if (delegate == null) throw new @@ -189,8 +175,6 @@ this.instantiator = instantiator; this.repository = repository; this.domain = repository.getDefaultDomain(); - this.dispatcher = dispatcher; - this.mbeanServerName = Util.getMBeanServerSecurityName(delegate); } public ObjectInstance createMBean(String className, ObjectName name) @@ -269,8 +253,8 @@ name = nonDefaultDomain(name); } - checkMBeanPermission(mbeanServerName,className, null, null, "instantiate"); - checkMBeanPermission(mbeanServerName,className, null, name, "registerMBean"); + checkMBeanPermission(className, null, null, "instantiate"); + checkMBeanPermission(className, null, name, "registerMBean"); /* Load the appropriate class. */ if (withDefaultLoaderRepository) { @@ -334,7 +318,7 @@ final String infoClassName = getNewMBeanClassName(object); - checkMBeanPermission(mbeanServerName,infoClassName, null, name, "registerMBean"); + checkMBeanPermission(infoClassName, null, name, "registerMBean"); checkMBeanTrustPermission(theClass); return registerObject(infoClassName, object, name); @@ -443,8 +427,7 @@ DynamicMBean instance = getMBean(name); // may throw InstanceNotFoundException - checkMBeanPermission(mbeanServerName, instance, null, name, - "unregisterMBean"); + checkMBeanPermission(instance, null, name, "unregisterMBean"); if (instance instanceof MBeanRegistration) preDeregisterInvoke((MBeanRegistration) instance); @@ -478,8 +461,7 @@ name = nonDefaultDomain(name); DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, - instance, null, name, "getObjectInstance"); + checkMBeanPermission(instance, null, name, "getObjectInstance"); final String className = getClassName(instance); @@ -491,7 +473,7 @@ if (sm != null) { // Check if the caller has the right to invoke 'queryMBeans' // - checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryMBeans"); + checkMBeanPermission((String) null, null, null, "queryMBeans"); // Perform query without "query". // @@ -504,7 +486,7 @@ new HashSet(list.size()); for (ObjectInstance oi : list) { try { - checkMBeanPermission(mbeanServerName,oi.getClassName(), null, + checkMBeanPermission(oi.getClassName(), null, oi.getObjectName(), "queryMBeans"); allowedList.add(oi); } catch (SecurityException e) { @@ -537,7 +519,7 @@ if (sm != null) { // Check if the caller has the right to invoke 'queryNames' // - checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryNames"); + checkMBeanPermission((String) null, null, null, "queryNames"); // Perform query without "query". // @@ -550,7 +532,7 @@ new HashSet(list.size()); for (ObjectInstance oi : list) { try { - checkMBeanPermission(mbeanServerName, oi.getClassName(), null, + checkMBeanPermission(oi.getClassName(), null, oi.getObjectName(), "queryNames"); allowedList.add(oi); } catch (SecurityException e) { @@ -602,7 +584,7 @@ if (sm != null) { // Check if the caller has the right to invoke 'getDomains' // - checkMBeanPermission(mbeanServerName, (String) null, null, null, "getDomains"); + checkMBeanPermission((String) null, null, null, "getDomains"); // Return domains // @@ -614,8 +596,8 @@ List result = new ArrayList(domains.length); for (int i = 0; i < domains.length; i++) { try { - ObjectName dom = ObjectName.valueOf(domains[i] + ":x=x"); - checkMBeanPermission(mbeanServerName, (String) null, null, dom, "getDomains"); + ObjectName dom = Util.newObjectName(domains[i] + ":x=x"); + checkMBeanPermission((String) null, null, dom, "getDomains"); result.add(domains[i]); } catch (SecurityException e) { // OK: Do not add this domain to the list @@ -659,8 +641,7 @@ } final DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, attribute, - name, "getAttribute"); + checkMBeanPermission(instance, attribute, name, "getAttribute"); try { return instance.getAttribute(attribute); @@ -705,7 +686,7 @@ // Check if the caller has the right to invoke 'getAttribute' // - checkMBeanPermission(mbeanServerName, classname, null, name, "getAttribute"); + checkMBeanPermission(classname, null, name, "getAttribute"); // Check if the caller has the right to invoke 'getAttribute' // on each specific attribute @@ -714,8 +695,7 @@ new ArrayList(attributes.length); for (String attr : attributes) { try { - checkMBeanPermission(mbeanServerName, classname, attr, - name, "getAttribute"); + checkMBeanPermission(classname, attr, name, "getAttribute"); allowedList.add(attr); } catch (SecurityException e) { // OK: Do not add this attribute to the list @@ -760,8 +740,7 @@ } DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, attribute.getName(), - name, "setAttribute"); + checkMBeanPermission(instance, attribute.getName(), name, "setAttribute"); try { instance.setAttribute(attribute); @@ -803,7 +782,7 @@ // Check if the caller has the right to invoke 'setAttribute' // - checkMBeanPermission(mbeanServerName, classname, null, name, "setAttribute"); + checkMBeanPermission(classname, null, name, "setAttribute"); // Check if the caller has the right to invoke 'setAttribute' // on each specific attribute @@ -811,7 +790,7 @@ allowedAttributes = new AttributeList(attributes.size()); for (Attribute attribute : attributes.asList()) { try { - checkMBeanPermission(mbeanServerName, classname, attribute.getName(), + checkMBeanPermission(classname, attribute.getName(), name, "setAttribute"); allowedAttributes.add(attribute); } catch (SecurityException e) { @@ -835,8 +814,7 @@ name = nonDefaultDomain(name); DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, operationName, - name, "invoke"); + checkMBeanPermission(instance, operationName, name, "invoke"); try { return instance.invoke(operationName, params, signature); } catch (Throwable t) { @@ -919,12 +897,6 @@ DynamicMBean mbean = Introspector.makeDynamicMBean(object); - //Access the ObjectName template value only if the provided name is null - if(name == null) { - name = Introspector.templateToObjectName(mbean.getMBeanInfo(). - getDescriptor(), mbean); - } - return registerDynamicMBean(classname, mbean, name); } @@ -953,8 +925,6 @@ ResourceContext context = null; try { - mbean = injectResources(mbean, server, logicalName); - if (mbean instanceof DynamicMBean2) { try { ((DynamicMBean2) mbean).preRegister2(server, logicalName); @@ -973,8 +943,7 @@ ObjectName.getInstance(nonDefaultDomain(logicalName)); } - checkMBeanPermission(mbeanServerName, classname, null, logicalName, - "registerMBean"); + checkMBeanPermission(classname, null, logicalName, "registerMBean"); if (logicalName == null) { final RuntimeException wrapped = @@ -988,10 +957,9 @@ // Register the MBean with the repository. // Returns the resource context that was used. // The returned context does nothing for regular MBeans. - // For ClassLoader MBeans and JMXNamespace (and JMXDomain) - // MBeans - the context makes it possible to register these + // For ClassLoader MBeans the context makes it possible to register these // objects with the appropriate framework artifacts, such as - // the CLR or the dispatcher, from within the repository lock. + // the CLR, from within the repository lock. // In case of success, we also need to call context.done() at the // end of this method. // @@ -1045,27 +1013,6 @@ else return name; } - private static DynamicMBean injectResources( - DynamicMBean mbean, MBeanServer mbs, ObjectName name) - throws MBeanRegistrationException { - try { - Object resource = getResource(mbean); - MBeanInjector.inject(resource, mbs, name); - if (MBeanInjector.injectsSendNotification(resource)) { - MBeanNotificationInfo[] mbnis = - mbean.getMBeanInfo().getNotifications(); - NotificationBroadcasterSupport nbs = - new NotificationBroadcasterSupport(mbnis); - MBeanInjector.injectSendNotification(resource, nbs); - mbean = NotifySupport.wrap(mbean, nbs); - } - return mbean; - } catch (Throwable t) { - throwMBeanRegistrationException(t, "injecting @Resources"); - return null; // not reached - } - } - private static void postRegister( ObjectName logicalName, DynamicMBean mbean, boolean registrationDone, boolean registerFailed) { @@ -1151,19 +1098,12 @@ } private static Object getResource(DynamicMBean mbean) { - if (mbean instanceof DynamicWrapperMBean) - return ((DynamicWrapperMBean) mbean).getWrappedObject(); + if (mbean instanceof DynamicMBean2) + return ((DynamicMBean2) mbean).getResource(); else return mbean; } - private static ClassLoader getResourceLoader(DynamicMBean mbean) { - if (mbean instanceof DynamicWrapperMBean) - return ((DynamicWrapperMBean) mbean).getWrappedClassLoader(); - else - return mbean.getClass().getClassLoader(); - } - private ObjectName nonDefaultDomain(ObjectName name) { if (name == null || name.getDomain().length() > 0) return name; @@ -1177,7 +1117,7 @@ if one is supplied where it shouldn't be). */ final String completeName = domain + name; - return ObjectName.valueOf(completeName); + return Util.newObjectName(completeName); } public String getDefaultDomain() { @@ -1243,8 +1183,7 @@ } DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, null, - name, "addNotificationListener"); + checkMBeanPermission(instance, null, name, "addNotificationListener"); NotificationBroadcaster broadcaster = getNotificationBroadcaster(name, instance, @@ -1381,8 +1320,7 @@ } DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, null, name, - "removeNotificationListener"); + checkMBeanPermission(instance, null, name, "removeNotificationListener"); /* We could simplify the code by assigning broadcaster after assigning listenerWrapper, but that would change the error @@ -1415,8 +1353,8 @@ Class reqClass) { if (reqClass.isInstance(instance)) return reqClass.cast(instance); - if (instance instanceof DynamicWrapperMBean) - instance = ((DynamicWrapperMBean) instance).getWrappedObject(); + if (instance instanceof DynamicMBean2) + instance = ((DynamicMBean2) instance).getResource(); if (reqClass.isInstance(instance)) return reqClass.cast(instance); final RuntimeException exc = @@ -1452,7 +1390,7 @@ throw new JMRuntimeException("MBean " + name + "has no MBeanInfo"); - checkMBeanPermission(mbeanServerName, mbi.getClassName(), null, name, "getMBeanInfo"); + checkMBeanPermission(mbi.getClassName(), null, name, "getMBeanInfo"); return mbi; } @@ -1461,8 +1399,7 @@ throws InstanceNotFoundException { final DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, - instance, null, name, "isInstanceOf"); + checkMBeanPermission(instance, null, name, "isInstanceOf"); try { Object resource = getResource(instance); @@ -1474,20 +1411,12 @@ if (resourceClassName.equals(className)) return true; - final ClassLoader cl = getResourceLoader(instance); + final ClassLoader cl = resource.getClass().getClassLoader(); final Class classNameClass = Class.forName(className, false, cl); if (classNameClass.isInstance(resource)) return true; - // Ensure that isInstanceOf(NotificationEmitter) is true when - // the MBean is a NotificationEmitter by virtue of a @Resource - // annotation specifying a SendNotification resource. - // This is a hack. - if (instance instanceof NotificationBroadcaster && - classNameClass.isAssignableFrom(NotificationEmitter.class)) - return true; - final Class resourceClass = Class.forName(resourceClassName, false, cl); return classNameClass.isAssignableFrom(resourceClass); } catch (Exception x) { @@ -1513,9 +1442,8 @@ throws InstanceNotFoundException { DynamicMBean instance = getMBean(mbeanName); - checkMBeanPermission(mbeanServerName, instance, null, mbeanName, - "getClassLoaderFor"); - return getResourceLoader(instance); + checkMBeanPermission(instance, null, mbeanName, "getClassLoaderFor"); + return getResource(instance).getClass().getClassLoader(); } /** @@ -1529,13 +1457,12 @@ throws InstanceNotFoundException { if (loaderName == null) { - checkMBeanPermission(mbeanServerName, (String) null, null, null, "getClassLoader"); + checkMBeanPermission((String) null, null, null, "getClassLoader"); return server.getClass().getClassLoader(); } DynamicMBean instance = getMBean(loaderName); - checkMBeanPermission(mbeanServerName, instance, null, loaderName, - "getClassLoader"); + checkMBeanPermission(instance, null, loaderName, "getClassLoader"); Object resource = getResource(instance); @@ -1757,6 +1684,49 @@ } } + public Object instantiate(String className) throws ReflectionException, + MBeanException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object instantiate(String className, ObjectName loaderName) throws ReflectionException, + MBeanException, + InstanceNotFoundException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object instantiate(String className, Object[] params, + String[] signature) throws ReflectionException, MBeanException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object instantiate(String className, ObjectName loaderName, + Object[] params, String[] signature) throws ReflectionException, + MBeanException, + InstanceNotFoundException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public ObjectInputStream deserialize(ObjectName name, byte[] data) throws InstanceNotFoundException, + OperationsException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public ObjectInputStream deserialize(String className, byte[] data) throws OperationsException, + ReflectionException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public ObjectInputStream deserialize(String className, ObjectName loaderName, + byte[] data) throws InstanceNotFoundException, OperationsException, + ReflectionException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public ClassLoaderRepository getClassLoaderRepository() { + throw new UnsupportedOperationException("Not supported yet."); + } + private static class ListenerWrapper implements NotificationListener { ListenerWrapper(NotificationListener l, ObjectName name, Object mbean) { @@ -1834,30 +1804,26 @@ return mbean.getMBeanInfo().getClassName(); } - private static void checkMBeanPermission(String mbeanServerName, - DynamicMBean mbean, + private static void checkMBeanPermission(DynamicMBean mbean, String member, ObjectName objectName, String actions) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - checkMBeanPermission(mbeanServerName, - safeGetClassName(mbean), + checkMBeanPermission(safeGetClassName(mbean), member, objectName, actions); } } - private static void checkMBeanPermission(String mbeanServerName, - String classname, + private static void checkMBeanPermission(String classname, String member, ObjectName objectName, String actions) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - Permission perm = new MBeanPermission(mbeanServerName, - classname, + Permission perm = new MBeanPermission(classname, member, objectName, actions); @@ -1923,12 +1889,6 @@ throws InstanceAlreadyExistsException, MBeanRegistrationException { - // this will throw an exception if the pair (resource, logicalName) - // violates namespace conventions - for instance, if logicalName - // ends with // but resource is not a JMXNamespace. - // - checkResourceObjectNameConstraints(resource, logicalName); - // Creates a registration context, if needed. // final ResourceContext context = @@ -1996,56 +1956,6 @@ /** - * Checks that the ObjectName is legal with regards to the - * type of the MBean resource. - * If the MBean name is domain:type=JMXDomain, the - * MBean must be a JMXDomain. - * If the MBean name is namespace//:type=JMXNamespace, the - * MBean must be a JMXNamespace. - * If the MBean is a JMXDomain, its name - * must be domain:type=JMXDomain. - * If the MBean is a JMXNamespace, its name - * must be namespace//:type=JMXNamespace. - */ - private void checkResourceObjectNameConstraints(Object resource, - ObjectName logicalName) - throws MBeanRegistrationException { - try { - dispatcher.checkLocallyRegistrable(resource, logicalName); - } catch (Throwable x) { - DefaultMBeanServerInterceptor.throwMBeanRegistrationException(x, "validating ObjectName"); - } - } - - /** - * Registers a JMXNamespace with the dispatcher. - * This method is called by the ResourceContext from within the - * repository lock. - * @param namespace The JMXNamespace - * @param logicalName The JMXNamespaceMBean ObjectName - * @param postQueue A queue that will be processed after postRegister. - */ - private void addJMXNamespace(JMXNamespace namespace, - final ObjectName logicalName, - final Queue postQueue) { - dispatcher.addInterceptorFor(logicalName, namespace, postQueue); - } - - /** - * Unregisters a JMXNamespace from the dispatcher. - * This method is called by the ResourceContext from within the - * repository lock. - * @param namespace The JMXNamespace - * @param logicalName The JMXNamespaceMBean ObjectName - * @param postQueue A queue that will be processed after postDeregister. - */ - private void removeJMXNamespace(JMXNamespace namespace, - final ObjectName logicalName, - final Queue postQueue) { - dispatcher.removeInterceptorFor(logicalName, namespace, postQueue); - } - - /** * Registers a ClassLoader with the CLR. * This method is called by the ResourceContext from within the * repository lock. @@ -2100,51 +2010,6 @@ /** - * Creates a ResourceContext for a JMXNamespace MBean. - * The resource context makes it possible to add the JMXNamespace to - * (ResourceContext.registering) or resp. remove the JMXNamespace from - * (ResourceContext.unregistered) the NamespaceDispatchInterceptor - * when the associated MBean is added to or resp. removed from the - * repository. - * Note: JMXDomains are special sub classes of JMXNamespaces and - * are also handled by this object. - * - * @param namespace The JMXNamespace MBean being registered or - * unregistered. - * @param logicalName The name of the JMXNamespace MBean. - * @return a ResourceContext that takes in charge the addition or removal - * of the namespace to or from the NamespaceDispatchInterceptor. - */ - private ResourceContext createJMXNamespaceContext( - final JMXNamespace namespace, - final ObjectName logicalName) { - final Queue doneTaskQueue = new LinkedList(); - return new ResourceContext() { - - public void registering() { - addJMXNamespace(namespace, logicalName, doneTaskQueue); - } - - public void unregistered() { - removeJMXNamespace(namespace, logicalName, - doneTaskQueue); - } - - public void done() { - for (Runnable r : doneTaskQueue) { - try { - r.run(); - } catch (RuntimeException x) { - MBEANSERVER_LOGGER.log(Level.FINE, - "Failed to process post queue for "+ - logicalName, x); - } - } - } - }; - } - - /** * Creates a ResourceContext for a ClassLoader MBean. * The resource context makes it possible to add the ClassLoader to * (ResourceContext.registering) or resp. remove the ClassLoader from @@ -2180,8 +2045,7 @@ * Creates a ResourceContext for the given resource. * If the resource does not need a ResourceContext, returns * ResourceContext.NONE. - * At this time, only JMXNamespaces and ClassLoaders need a - * ResourceContext. + * At this time, only ClassLoaders need a ResourceContext. * * @param resource The resource being registered or unregistered. * @param logicalName The name of the associated MBean. @@ -2189,10 +2053,6 @@ */ private ResourceContext makeResourceContextFor(Object resource, ObjectName logicalName) { - if (resource instanceof JMXNamespace) { - return createJMXNamespaceContext((JMXNamespace) resource, - logicalName); - } if (resource instanceof ClassLoader) { return createClassLoaderContext((ClassLoader) resource, logicalName); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java --- a/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,551 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.interceptor; - - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Queue; -import java.util.Set; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.IntrospectionException; -import javax.management.InvalidAttributeValueException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.namespace.JMXNamespace; - -/** - * A dispatcher that dispatches to MBeanServers. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -// -// This is the base class for implementing dispatchers. We have two concrete -// dispatcher implementations: -// -// * A NamespaceDispatchInterceptor, which dispatch calls to existing -// namespace interceptors -// * A DomainDispatchInterceptor, which dispatch calls to existing domain -// interceptors. -// -// With the JMX Namespaces feature, the JMX MBeanServer is now structured -// as follows: -// -// The JMX MBeanServer delegates to a NamespaceDispatchInterceptor, -// which either dispatches to a namespace, or delegates to the -// DomainDispatchInterceptor (if the object name contained no namespace). -// The DomainDispatchInterceptor in turn either dispatches to a domain (if -// there is a JMXDomain for that domain) or delegates to the -// DefaultMBeanServerInterceptor (if there is no JMXDomain for that -// domain). This makes the following picture: -// -// JMX MBeanServer (outer shell) -// | -// | -// NamespaceDispatchInterceptor -// / \ -// no namespace in object name? \ -// / \ -// / dispatch to namespace -// DomainDispatchInterceptor -// / \ -// no JMXDomain for domain? \ -// / \ -// / dispatch to domain -// DefaultMBeanServerInterceptor -// / -// invoke locally registered MBean -// -// The logic for maintaining a map of interceptors -// and dispatching to impacted interceptor, is implemented in this -// base class, which both NamespaceDispatchInterceptor and -// DomainDispatchInterceptor extend. -// -public abstract class DispatchInterceptor - - extends MBeanServerInterceptorSupport { - - /** - * This is an abstraction which allows us to handle queryNames - * and queryMBeans with the same algorithm. There are some subclasses - * where we need to override both queryNames & queryMBeans to apply - * the same transformation (usually aggregation of results when - * several namespaces/domains are impacted) to both algorithms. - * Usually the only thing that varies between the algorithm of - * queryNames & the algorithm of queryMBean is the type of objects - * in the returned Set. By using a QueryInvoker we can implement the - * transformation only once and apply it to both queryNames & - * queryMBeans. - * @see QueryInterceptor below, and its subclass in - * {@link DomainDispatcher}. - **/ - static abstract class QueryInvoker { - abstract Set query(MBeanServer mbs, - ObjectName pattern, QueryExp query); - } - - /** - * Used to perform queryNames. A QueryInvoker that invokes - * queryNames on an MBeanServer. - **/ - final static QueryInvoker queryNamesInvoker = - new QueryInvoker() { - Set query(MBeanServer mbs, - ObjectName pattern, QueryExp query) { - return mbs.queryNames(pattern,query); - } - }; - - /** - * Used to perform queryMBeans. A QueryInvoker that invokes - * queryMBeans on an MBeanServer. - **/ - final static QueryInvoker queryMBeansInvoker = - new QueryInvoker() { - Set query(MBeanServer mbs, - ObjectName pattern, QueryExp query) { - return mbs.queryMBeans(pattern,query); - } - }; - - /** - * We use this class to intercept queries. - * There's a special case for JMXNamespace MBeans, because - * "namespace//*:*" matches both "namespace//domain:k=v" and - * "namespace//:type=JMXNamespace". - * Therefore, queries may need to be forwarded to more than - * on interceptor and the results aggregated... - */ - static class QueryInterceptor { - final MBeanServer wrapped; - QueryInterceptor(MBeanServer mbs) { - wrapped = mbs; - } - Set query(ObjectName pattern, QueryExp query, - QueryInvoker invoker, MBeanServer server) { - return invoker.query(server, pattern, query); - } - - public Set queryNames(ObjectName pattern, QueryExp query) { - return query(pattern,query,queryNamesInvoker,wrapped); - } - - public Set queryMBeans(ObjectName pattern, - QueryExp query) { - return query(pattern,query,queryMBeansInvoker,wrapped); - } - } - - // We don't need a ConcurrentHashMap here because getkeys() returns - // an array of keys. Therefore there's no risk to have a - // ConcurrentModificationException. We must however take into - // account the fact that there can be no interceptor for - // some of the returned keys if the map is being modified by - // another thread, or by a callback within the same thread... - // See getKeys() in this class and query() in DomainDispatcher. - // - private final Map handlerMap = - Collections.synchronizedMap( - new HashMap()); - - // The key at which an interceptor for accessing the named MBean can be - // found in the handlerMap. Note: there doesn't need to be an interceptor - // for that key in the Map. - // - abstract String getHandlerKey(ObjectName name); - - // Returns an interceptor for that name, or null if there's no interceptor - // for that name. - abstract MBeanServer getInterceptorOrNullFor(ObjectName name); - - // Returns a QueryInterceptor for that pattern. - abstract QueryInterceptor getInterceptorForQuery(ObjectName pattern); - - // Returns the ObjectName of the JMXNamespace (or JMXDomain) for that - // key (a namespace or a domain name). - abstract ObjectName getHandlerNameFor(String key); - - // Creates an interceptor for the given key, name, JMXNamespace (or - // JMXDomain). Note: this will be either a NamespaceInterceptor - // wrapping a JMXNamespace, if this object is an instance of - // NamespaceDispatchInterceptor, or a DomainInterceptor wrapping a - // JMXDomain, if this object is an instance of DomainDispatchInterceptor. - abstract T createInterceptorFor(String key, ObjectName name, - N jmxNamespace, Queue postRegisterQueue); - // - // The next interceptor in the chain. - // - // For the NamespaceDispatchInterceptor, this the DomainDispatchInterceptor. - // For the DomainDispatchInterceptor, this is the - // DefaultMBeanServerInterceptor. - // - // The logic of when to invoke the next interceptor in the chain depends - // on the logic of the concrete dispatcher class. - // - // For instance, the NamespaceDispatchInterceptor invokes the next - // interceptor when the object name doesn't contain any namespace. - // - // On the other hand, the DomainDispatchInterceptor invokes the - // next interceptor when there's no interceptor for the accessed domain. - // - abstract MBeanServer getNextInterceptor(); - - // hook for cleanup in subclasses. - void interceptorReleased(T interceptor, - Queue postDeregisterQueue) { - // hook - } - - // Hook for subclasses. - MBeanServer getInterceptorForCreate(ObjectName name) - throws MBeanRegistrationException { - final MBeanServer ns = getInterceptorOrNullFor(name); - if (ns == null) // name cannot be null here. - throw new MBeanRegistrationException( - new IllegalArgumentException("No such MBean handler: " + - getHandlerKey(name) + " for " +name)); - return ns; - } - - // Hook for subclasses. - MBeanServer getInterceptorForInstance(ObjectName name) - throws InstanceNotFoundException { - final MBeanServer ns = getInterceptorOrNullFor(name); - if (ns == null) // name cannot be null here. - throw new InstanceNotFoundException(String.valueOf(name)); - return ns; - } - - // sanity checks - void validateHandlerNameFor(String key, ObjectName name) { - if (key == null || key.equals("")) - throw new IllegalArgumentException("invalid key for "+name+": "+key); - final ObjectName handlerName = getHandlerNameFor(key); - if (!name.equals(handlerName)) - throw new IllegalArgumentException("bad handler name: "+name+ - ". Should be: "+handlerName); - } - - // Called by the DefaultMBeanServerInterceptor when an instance - // of JMXNamespace (or a subclass of it) is registered as an MBean. - // This method is usually invoked from within the repository lock, - // hence the necessity of the postRegisterQueue. - public void addInterceptorFor(ObjectName name, N jmxNamespace, - Queue postRegisterQueue) { - final String key = getHandlerKey(name); - validateHandlerNameFor(key,name); - synchronized (handlerMap) { - final T exists = - handlerMap.get(key); - if (exists != null) - throw new IllegalArgumentException(key+ - ": handler already exists"); - - final T ns = createInterceptorFor(key,name,jmxNamespace, - postRegisterQueue); - handlerMap.put(key,ns); - } - } - - // Called by the DefaultMBeanServerInterceptor when an instance - // of JMXNamespace (or a subclass of it) is deregistered. - // This method is usually invoked from within the repository lock, - // hence the necessity of the postDeregisterQueue. - public void removeInterceptorFor(ObjectName name, N jmxNamespace, - Queue postDeregisterQueue) { - final String key = getHandlerKey(name); - final T ns; - synchronized(handlerMap) { - ns = handlerMap.remove(key); - } - interceptorReleased(ns,postDeregisterQueue); - } - - // Get the interceptor for that key. - T getInterceptor(String key) { - synchronized (handlerMap) { - return handlerMap.get(key); - } - } - - // We return an array of keys, which makes it possible to make - // concurrent modifications of the handlerMap, provided that - // the code which loops over the keys is prepared to handle null - // interceptors. - // See declaration of handlerMap above, and see also query() in - // DomainDispatcher - // - public String[] getKeys() { - synchronized (handlerMap) { - final int size = handlerMap.size(); - return handlerMap.keySet().toArray(new String[size]); - } - } - - // From MBeanServer - public final ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - return getInterceptorForCreate(name).createMBean(className,name); - } - - // From MBeanServer - public final ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException{ - return getInterceptorForCreate(name).createMBean(className,name,loaderName); - } - - // From MBeanServer - public final ObjectInstance createMBean(String className, ObjectName name, - Object params[], String signature[]) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException{ - return getInterceptorForCreate(name). - createMBean(className,name,params,signature); - } - - // From MBeanServer - public final ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName, Object params[], - String signature[]) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException{ - return getInterceptorForCreate(name).createMBean(className,name,loaderName, - params,signature); - } - - // From MBeanServer - public final ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, MBeanRegistrationException, - NotCompliantMBeanException { - return getInterceptorForCreate(name).registerMBean(object,name); - } - - // From MBeanServer - public final void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { - getInterceptorForInstance(name).unregisterMBean(name); - } - - // From MBeanServer - public final ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - return getInterceptorForInstance(name).getObjectInstance(name); - } - - // From MBeanServer - public final Set queryMBeans(ObjectName name, - QueryExp query) { - final QueryInterceptor queryInvoker = - getInterceptorForQuery(name); - if (queryInvoker == null) return Collections.emptySet(); - else return queryInvoker.queryMBeans(name,query); - } - - // From MBeanServer - public final Set queryNames(ObjectName name, QueryExp query) { - final QueryInterceptor queryInvoker = - getInterceptorForQuery(name); - if (queryInvoker == null) return Collections.emptySet(); - else return queryInvoker.queryNames(name,query); - } - - // From MBeanServer - public final boolean isRegistered(ObjectName name) { - final MBeanServer mbs = getInterceptorOrNullFor(name); - if (mbs == null) return false; - else return mbs.isRegistered(name); - } - - // From MBeanServer - public Integer getMBeanCount() { - return getNextInterceptor().getMBeanCount(); - } - - // From MBeanServer - public final Object getAttribute(ObjectName name, String attribute) - throws MBeanException, AttributeNotFoundException, - InstanceNotFoundException, ReflectionException { - return getInterceptorForInstance(name).getAttribute(name,attribute); - } - - // From MBeanServer - public final AttributeList getAttributes(ObjectName name, - String[] attributes) - throws InstanceNotFoundException, ReflectionException { - return getInterceptorForInstance(name).getAttributes(name,attributes); - } - - // From MBeanServer - public final void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException { - getInterceptorForInstance(name).setAttribute(name,attribute); - } - - // From MBeanServer - public final AttributeList setAttributes(ObjectName name, - AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - return getInterceptorForInstance(name).setAttributes(name,attributes); - } - - // From MBeanServer - public final Object invoke(ObjectName name, String operationName, - Object params[], String signature[]) - throws InstanceNotFoundException, MBeanException, - ReflectionException { - return getInterceptorForInstance(name).invoke(name,operationName,params, - signature); - } - - // From MBeanServer - public String getDefaultDomain() { - return getNextInterceptor().getDefaultDomain(); - } - - /** - * Returns the list of domains in which any MBean is currently - * registered. - */ - public abstract String[] getDomains(); - - // From MBeanServer - public final void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - getInterceptorForInstance(name). - addNotificationListener(name,listener,filter, - handback); - } - - - // From MBeanServer - public final void addNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - getInterceptorForInstance(name). - addNotificationListener(name,listener,filter, - handback); - } - - // From MBeanServer - public final void removeNotificationListener(ObjectName name, - ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - getInterceptorForInstance(name). - removeNotificationListener(name,listener); - } - - // From MBeanServer - public final void removeNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - getInterceptorForInstance(name). - removeNotificationListener(name,listener,filter, - handback); - } - - - // From MBeanServer - public final void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - getInterceptorForInstance(name). - removeNotificationListener(name,listener); - } - - // From MBeanServer - public final void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - getInterceptorForInstance(name). - removeNotificationListener(name,listener,filter, - handback); - } - - // From MBeanServer - public final MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException { - return getInterceptorForInstance(name).getMBeanInfo(name); - } - - - // From MBeanServer - public final boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - return getInterceptorForInstance(name).isInstanceOf(name,className); - } - - // From MBeanServer - public final ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - return getInterceptorForInstance(mbeanName). - getClassLoaderFor(mbeanName); - } - - // From MBeanServer - public final ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - return getInterceptorForInstance(loaderName). - getClassLoader(loaderName); - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java --- a/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,350 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.interceptor; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.mbeanserver.MBeanInstantiator; -import com.sun.jmx.mbeanserver.Repository; -import com.sun.jmx.mbeanserver.Util; -import com.sun.jmx.namespace.DomainInterceptor; -import java.util.Queue; -import java.util.Set; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.ObjectName; -import javax.management.QueryExp; -import javax.management.namespace.JMXDomain; -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; - -/** - * A dispatcher that dispatch incoming MBeanServer requests to - * DomainInterceptors. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -// -// See comments in DispatchInterceptor. -// -class DomainDispatchInterceptor - extends DispatchInterceptor { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - private static final ObjectName ALL_DOMAINS = - JMXDomain.getDomainObjectName("*"); - - - /** - * A QueryInterceptor that perform & aggregates queries spanning several - * domains. - */ - final static class AggregatingQueryInterceptor extends QueryInterceptor { - - private final DomainDispatchInterceptor parent; - AggregatingQueryInterceptor(DomainDispatchInterceptor dispatcher) { - super(dispatcher.nextInterceptor); - parent = dispatcher; - } - - /** - * Perform queryNames or queryMBeans, depending on which QueryInvoker - * is passed as argument. This is closures without closures. - **/ - @Override - Set query(ObjectName pattern, QueryExp query, - QueryInvoker invoker, MBeanServer localNamespace) { - final Set local = invoker.query(localNamespace, pattern, query); - - // Add all matching MBeans from local namespace. - final Set res = Util.cloneSet(local); - - if (pattern == null) pattern = ObjectName.WILDCARD; - final boolean all = pattern.getDomain().equals("*"); - - final String domain = pattern.getDomain(); - - // If there's no domain pattern, just include the pattern's domain. - // Otherwiae, loop over all virtual domains (parent.getKeys()). - final String[] keys = - (pattern.isDomainPattern() ? - parent.getKeys() : new String[]{domain}); - - // Add all matching MBeans from each virtual domain - // - for (String key : keys) { - // Only invoke those virtual domain which are selected - // by the domain pattern - // - if (!all && !Util.isDomainSelected(key, domain)) - continue; - - try { - final MBeanServer mbs = parent.getInterceptor(key); - - // mbs can be null if the interceptor was removed - // concurrently... - // See handlerMap and getKeys() in DispatchInterceptor - // - if (mbs == null) continue; - - // If the domain is selected, we can replace the pattern - // by the actual domain. This is safer if we want to avoid - // a domain (which could be backed up by an MBeanServer) to - // return names from outside the domain. - // So instead of asking the domain handler for "foo" to - // return all names which match "?o*:type=Bla,*" we're - // going to ask it to return all names which match - // "foo:type=Bla,*" - // - final ObjectName subPattern = pattern.withDomain(key); - res.addAll(invoker.query(mbs, subPattern, query)); - } catch (Exception x) { - LOG.finest("Ignoring exception " + - "when attempting to query namespace "+key+": "+x); - continue; - } - } - return res; - } - } - - private final DefaultMBeanServerInterceptor nextInterceptor; - private final String mbeanServerName; - private final MBeanServerDelegate delegate; - - /** - * Creates a DomainDispatchInterceptor with the specified - * repository instance. - * - * @param outer A pointer to the MBeanServer object that must be - * passed to the MBeans when invoking their - * {@link javax.management.MBeanRegistration} interface. - * @param delegate A pointer to the MBeanServerDelegate associated - * with the new MBeanServer. The new MBeanServer must register - * this MBean in its MBean repository. - * @param instantiator The MBeanInstantiator that will be used to - * instantiate MBeans and take care of class loading issues. - * @param repository The repository to use for this MBeanServer - */ - public DomainDispatchInterceptor(MBeanServer outer, - MBeanServerDelegate delegate, - MBeanInstantiator instantiator, - Repository repository, - NamespaceDispatchInterceptor namespaces) { - nextInterceptor = new DefaultMBeanServerInterceptor(outer, - delegate, instantiator,repository,namespaces); - mbeanServerName = Util.getMBeanServerSecurityName(delegate); - this.delegate = delegate; - } - - final boolean isLocalHandlerNameFor(String domain, - ObjectName handlerName) { - if (domain == null) return true; - return handlerName.getDomain().equals(domain) && - JMXDomain.TYPE_ASSIGNMENT.equals( - handlerName.getKeyPropertyListString()); - } - - @Override - void validateHandlerNameFor(String key, ObjectName name) { - super.validateHandlerNameFor(key,name); - final String[] domains = nextInterceptor.getDomains(); - for (int i=0;i postRegisterQueue) { - final DomainInterceptor ns = - new DomainInterceptor(mbeanServerName,handler,key); - ns.addPostRegisterTask(postRegisterQueue, delegate); - if (LOG.isLoggable(Level.FINER)) { - LOG.finer("DomainInterceptor created: "+ns); - } - return ns; - } - - @Override - final void interceptorReleased(DomainInterceptor interceptor, - Queue postDeregisterQueue) { - interceptor.addPostDeregisterTask(postDeregisterQueue, delegate); - } - - @Override - final DefaultMBeanServerInterceptor getNextInterceptor() { - return nextInterceptor; - } - - /** - * Returns the list of domains in which any MBean is currently - * registered. - */ - @Override - public String[] getDomains() { - // A JMXDomain is registered in its own domain. - // Therefore, nextInterceptor.getDomains() contains all domains. - // In addition, nextInterceptor will perform the necessary - // MBeanPermission checks for getDomains(). - // - return nextInterceptor.getDomains(); - } - - /** - * Returns the number of MBeans registered in the MBean server. - */ - @Override - public Integer getMBeanCount() { - int count = getNextInterceptor().getMBeanCount(); - final String[] keys = getKeys(); - for (String key:keys) { - final MBeanServer mbs = getInterceptor(key); - if (mbs == null) continue; - count += mbs.getMBeanCount(); - } - return count; - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java --- a/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.interceptor; - -import java.io.ObjectInputStream; -import javax.management.InstanceNotFoundException; -import javax.management.MBeanException; -import javax.management.ObjectName; -import javax.management.OperationsException; -import javax.management.ReflectionException; -import javax.management.loading.ClassLoaderRepository; - -/** - * An abstract class for MBeanServerInterceptorSupport. - * Some methods in MBeanServerInterceptor should never be called. - * This base class provides an implementation of these methods that simply - * throw an {@link UnsupportedOperationException}. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public abstract class MBeanServerInterceptorSupport - implements MBeanServerInterceptor { - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className) - throws ReflectionException, MBeanException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, ObjectName loaderName) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, Object[] params, - String[] signature) throws ReflectionException, MBeanException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, ObjectName loaderName, - Object[] params, String[] signature) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(ObjectName name, byte[] data) - throws InstanceNotFoundException, OperationsException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(String className, byte[] data) - throws OperationsException, ReflectionException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(String className, - ObjectName loaderName, byte[] data) - throws InstanceNotFoundException, OperationsException, - ReflectionException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public ClassLoaderRepository getClassLoaderRepository() { - throw new UnsupportedOperationException("Not applicable."); - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java --- a/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,297 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.interceptor; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.mbeanserver.MBeanInstantiator; -import com.sun.jmx.mbeanserver.Repository; -import com.sun.jmx.mbeanserver.Util; -import com.sun.jmx.namespace.NamespaceInterceptor; - -import java.util.Queue; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.ObjectName; -import javax.management.RuntimeOperationsException; -import javax.management.namespace.JMXDomain; -import javax.management.namespace.JMXNamespace; -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; - -/** - * A dispatcher that dispatches to NamespaceInterceptors. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class NamespaceDispatchInterceptor - extends DispatchInterceptor { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - private static final int NAMESPACE_SEPARATOR_LENGTH = - NAMESPACE_SEPARATOR.length(); - private static final ObjectName X3 = ObjectName.valueOf("x:x=x"); - - private final DomainDispatchInterceptor nextInterceptor; - private final String serverName; - - /** - * Creates a NamespaceDispatchInterceptor with the specified - * repository instance. - *

Do not forget to call initialize(outer,delegate) - * before using this object. - * - * @param outer A pointer to the MBeanServer object that must be - * passed to the MBeans when invoking their - * {@link javax.management.MBeanRegistration} interface. - * @param delegate A pointer to the MBeanServerDelegate associated - * with the new MBeanServer. The new MBeanServer must register - * this MBean in its MBean repository. - * @param instantiator The MBeanInstantiator that will be used to - * instantiate MBeans and take care of class loading issues. - * @param repository The repository to use for this MBeanServer - */ - public NamespaceDispatchInterceptor(MBeanServer outer, - MBeanServerDelegate delegate, - MBeanInstantiator instantiator, - Repository repository) { - nextInterceptor = new DomainDispatchInterceptor(outer,delegate, - instantiator,repository,this); - serverName = Util.getMBeanServerSecurityName(delegate); - } - - /** - * Get first name space in ObjectName path. Ignore leading namespace - * separators. Includes the trailing //. - * - * Examples: - *

-     *  For ObjectName:                   Returns:
-     *  foo//bar//baz:x=x         ->      "foo//"
-     *  foo//:type=JMXNamespace   ->      "foo//"
-     *  foo//:x=x                 ->      "foo//"
-     *  foo////:x=x               ->      "foo//"
-     *  //foo//bar//baz:x=x       ->      "//"
-     *  ////foo//bar//baz:x=x     ->      "//"
-     *  //:x=x                    ->      "//"
-     *  foo:x=x                   ->      ""
-     *  (null)                    ->      ""
-     *  :x=x                      ->      ""
-     *
-     * 
- **/ - static String getFirstNamespaceWithSlash(ObjectName name) { - if (name == null) return ""; - final String domain = name.getDomain(); - if (domain.equals("")) return ""; - - // go to next separator - final int end = domain.indexOf(NAMESPACE_SEPARATOR); - if (end == -1) return ""; // no namespace - - // This is the first element in the namespace path. - final String namespace = - domain.substring(0,end+NAMESPACE_SEPARATOR_LENGTH); - - return namespace; - } - - /** - * Called by the DefaultMBeanServerInterceptor, just before adding an - * MBean to the repository. - * - * @param resource the MBean to be registered. - * @param logicalName the name of the MBean to be registered. - */ - final void checkLocallyRegistrable(Object resource, - ObjectName logicalName) { - if (!(resource instanceof JMXNamespace) && - logicalName.getDomain().contains(NAMESPACE_SEPARATOR)) - throw new IllegalArgumentException(String.valueOf(logicalName)+ - ": Invalid ObjectName for an instance of " + - resource.getClass().getName()); - } - - // Removes the trailing //. namespaceWithSlash should be either - // "" or a namespace path ending with //. - // - private final String getKeyFor(String namespaceWithSlash) { - final int end = namespaceWithSlash.length() - - NAMESPACE_SEPARATOR_LENGTH; - if (end <= 0) return ""; - final String key = namespaceWithSlash.substring(0,end); - return key; - } - - @Override - final MBeanServer getInterceptorOrNullFor(ObjectName name) { - final String namespace = getFirstNamespaceWithSlash(name); - - // Leading separators should trigger instance not found exception. - // returning null here has this effect. - // - if (namespace.equals(NAMESPACE_SEPARATOR)) { - LOG.finer("ObjectName starts with: "+namespace); - return null; - } - - // namespace="" means that there was no namespace path in the - // ObjectName. => delegate to the next interceptor (local MBS) - // name.getDomain()=namespace means that we have an ObjectName of - // the form blah//:x=x. This is either a JMXNamespace or a non - // existent MBean. => delegate to the next interceptor (local MBS) - if (namespace.equals("") || name.getDomain().equals(namespace)) { - LOG.finer("dispatching to local name space"); - return nextInterceptor; - } - - // There was a namespace path in the ObjectName. Returns the - // interceptor that handles it, or null if there is no such - // interceptor. - final String key = getKeyFor(namespace); - final NamespaceInterceptor ns = getInterceptor(key); - if (LOG.isLoggable(Level.FINER)) { - if (ns != null) { - LOG.finer("dispatching to name space: " + key); - } else { - LOG.finer("no handler for: " + key); - } - } - return ns; - } - - @Override - final QueryInterceptor getInterceptorForQuery(ObjectName pattern) { - final String namespace = getFirstNamespaceWithSlash(pattern); - - // Leading separators should trigger instance not found exception. - // returning null here has this effect. - // - if (namespace.equals(NAMESPACE_SEPARATOR)) { - LOG.finer("ObjectName starts with: "+namespace); - return null; - } - - // namespace="" means that there was no namespace path in the - // ObjectName. => delegate to the next interceptor (local MBS) - // name.getDomain()=namespace means that we have an ObjectName of - // the form blah//:x=x. This is either a JMXNamespace or a non - // existent MBean. => delegate to the next interceptor (local MBS) - if (namespace.equals("") || pattern.getDomain().equals(namespace)) { - LOG.finer("dispatching to local name space"); - return new QueryInterceptor(nextInterceptor); - } - - // This is a 'hack' to check whether the first namespace is a pattern. - // We wan to throw RTOE wrapping IAE in that case - if (X3.withDomain(namespace).isDomainPattern()) { - throw new RuntimeOperationsException( - new IllegalArgumentException("Pattern not allowed in namespace path")); - } - - // There was a namespace path in the ObjectName. Returns the - // interceptor that handles it, or null if there is no such - // interceptor. - // - final String key = getKeyFor(namespace); - final NamespaceInterceptor ns = getInterceptor(key); - if (LOG.isLoggable(Level.FINER)) { - if (ns != null) { - LOG.finer("dispatching to name space: " + key); - } else { - LOG.finer("no handler for: " + key); - } - } - if (ns == null) return null; - return new QueryInterceptor(ns); - } - - @Override - final ObjectName getHandlerNameFor(String key) { - return ObjectName.valueOf(key+NAMESPACE_SEPARATOR, - "type", JMXNamespace.TYPE); - } - - @Override - final public String getHandlerKey(ObjectName name) { - final String namespace = getFirstNamespaceWithSlash(name); - // namespace is either "" or a namespace ending with // - return getKeyFor(namespace); - } - - @Override - final NamespaceInterceptor createInterceptorFor(String key, - ObjectName name, JMXNamespace handler, - Queue postRegisterQueue) { - final NamespaceInterceptor ns = - new NamespaceInterceptor(serverName,handler,key); - if (LOG.isLoggable(Level.FINER)) { - LOG.finer("NamespaceInterceptor created: "+ns); - } - return ns; - } - - @Override - final DomainDispatchInterceptor getNextInterceptor() { - return nextInterceptor; - } - - /** - * Returns the list of domains in which any MBean is currently - * registered. - */ - @Override - public String[] getDomains() { - return nextInterceptor.getDomains(); - } - - @Override - public void addInterceptorFor(ObjectName name, JMXNamespace handler, - Queue postRegisterQueue) { - if (handler instanceof JMXDomain) - nextInterceptor.addInterceptorFor(name, - (JMXDomain)handler,postRegisterQueue); - else super.addInterceptorFor(name,handler,postRegisterQueue); - } - - @Override - public void removeInterceptorFor(ObjectName name, JMXNamespace handler, - Queue postDeregisterQueue) { - if (handler instanceof JMXDomain) - nextInterceptor.removeInterceptorFor(name,(JMXDomain)handler, - postDeregisterQueue); - else super.removeInterceptorFor(name,handler,postDeregisterQueue); - } - - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java --- a/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,442 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.interceptor; - -import com.sun.jmx.mbeanserver.Util; -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; -import java.util.TreeSet; -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.DynamicMBean; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.IntrospectionException; -import javax.management.InvalidAttributeValueException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.MBeanServerSupport; -import javax.management.remote.IdentityMBeanServerForwarder; - -/** - *

An {@link MBeanServerForwarder} that simulates the existence of a - * given MBean. Requests for that MBean, call it X, are intercepted by the - * forwarder, and requests for any other MBean are forwarded to the next - * forwarder in the chain. Requests such as queryNames which can span both the - * X and other MBeans are handled by merging the results for X with the results - * from the next forwarder, unless the "visible" parameter is false, in which - * case X is invisible to such requests.

- */ -public class SingleMBeanForwarder extends IdentityMBeanServerForwarder { - - private final ObjectName mbeanName; - private final boolean visible; - private DynamicMBean mbean; - - private MBeanServer mbeanMBS = new MBeanServerSupport() { - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) { - return mbean; - } else { - throw new InstanceNotFoundException(name.toString()); - } - } - - @Override - protected Set getNames() { - return Collections.singleton(mbeanName); - } - - @Override - public NotificationEmitter getNotificationEmitterFor( - ObjectName name) { - if (mbean instanceof NotificationEmitter) - return (NotificationEmitter) mbean; - return null; - } - - // This will only be called if mbeanName has an empty domain. - // In that case a getAttribute (e.g.) of that name will have the - // domain replaced by MBeanServerSupport with the default domain, - // so we must be sure that the default domain is empty too. - @Override - public String getDefaultDomain() { - return mbeanName.getDomain(); - } - }; - - public SingleMBeanForwarder( - ObjectName mbeanName, DynamicMBean mbean, boolean visible) { - this.mbeanName = mbeanName; - this.visible = visible; - setSingleMBean(mbean); - } - - protected void setSingleMBean(DynamicMBean mbean) { - this.mbean = mbean; - } - - @Override - public void addNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.addNotificationListener(name, listener, filter, handback); - else - super.addNotificationListener(name, listener, filter, handback); - } - - @Override - public void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.addNotificationListener(name, listener, filter, handback); - else - super.addNotificationListener(name, listener, filter, handback); - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName, Object[] params, - String[] signature) - throws ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - else - return super.createMBean(className, name, loaderName, params, signature); - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - return super.createMBean(className, name, params, signature); - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - return super.createMBean(className, name, loaderName); - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - return super.createMBean(className, name); - } - - @Override - public Object getAttribute(ObjectName name, String attribute) - throws MBeanException, - AttributeNotFoundException, - InstanceNotFoundException, - ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.getAttribute(name, attribute); - else - return super.getAttribute(name, attribute); - } - - @Override - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.getAttributes(name, attributes); - else - return super.getAttributes(name, attributes); - } - - @Override - public ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - if (mbeanName.equals(loaderName)) - return mbeanMBS.getClassLoader(loaderName); - else - return super.getClassLoader(loaderName); - } - - @Override - public ClassLoader getClassLoaderFor(ObjectName name) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - return mbeanMBS.getClassLoaderFor(name); - else - return super.getClassLoaderFor(name); - } - - @Override - public String[] getDomains() { - String[] domains = super.getDomains(); - if (!visible) - return domains; - TreeSet domainSet = new TreeSet(Arrays.asList(domains)); - domainSet.add(mbeanName.getDomain()); - return domainSet.toArray(new String[domainSet.size()]); - } - - @Override - public Integer getMBeanCount() { - Integer count = super.getMBeanCount(); - if (visible && !super.isRegistered(mbeanName)) - count++; - return count; - } - - @Override - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, - IntrospectionException, - ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.getMBeanInfo(name); - else - return super.getMBeanInfo(name); - } - - @Override - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - return mbeanMBS.getObjectInstance(name); - else - return super.getObjectInstance(name); - } - - @Override - public Object invoke(ObjectName name, String operationName, Object[] params, - String[] signature) - throws InstanceNotFoundException, - MBeanException, - ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.invoke(name, operationName, params, signature); - else - return super.invoke(name, operationName, params, signature); - } - - @Override - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - return mbeanMBS.isInstanceOf(name, className); - else - return super.isInstanceOf(name, className); - } - - @Override - public boolean isRegistered(ObjectName name) { - if (mbeanName.equals(name)) - return true; - else - return super.isRegistered(name); - } - - /** - * This is a ugly hack. Although jmx.context//*:* matches jmx.context//:* - * queryNames(jmx.context//*:*,null) must not return jmx.context//:* - * @param pattern the pattern to match against. must not be null. - * @return true if mbeanName can be included, false if it must not. - */ - private boolean applies(ObjectName pattern) { - // we know pattern is not null. - if (!visible || !pattern.apply(mbeanName)) - return false; - - final String dompat = pattern.getDomain(); - if (!dompat.contains(JMXNamespaces.NAMESPACE_SEPARATOR)) - return true; // We already checked that patterns apply. - - if (mbeanName.getDomain().endsWith(JMXNamespaces.NAMESPACE_SEPARATOR)) { - // only matches if pattern ends with // - return dompat.endsWith(JMXNamespaces.NAMESPACE_SEPARATOR); - } - - // should not come here, unless mbeanName contains a // in the - // middle of its domain, which would be weird. - // let query on mbeanMBS proceed and take care of that. - // - return true; - } - - @Override - public Set queryMBeans(ObjectName name, QueryExp query) { - Set names = super.queryMBeans(name, query); - if (visible) { - if (name == null || applies(name) ) { - // Don't assume mbs.queryNames returns a writable set. - names = Util.cloneSet(names); - names.addAll(mbeanMBS.queryMBeans(name, query)); - } - } - return names; - } - - @Override - public Set queryNames(ObjectName name, QueryExp query) { - Set names = super.queryNames(name, query); - if (visible) { - if (name == null || applies(name)) { - // Don't assume mbs.queryNames returns a writable set. - names = Util.cloneSet(names); - names.addAll(mbeanMBS.queryNames(name, query)); - } - } - return names; - } - - - @Override - public ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, - MBeanRegistrationException, - NotCompliantMBeanException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - else - return super.registerMBean(object, name); - } - - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, - ListenerNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.removeNotificationListener(name, listener, filter, handback); - else - super.removeNotificationListener(name, listener, filter, handback); - } - - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.removeNotificationListener(name, listener); - else - super.removeNotificationListener(name, listener); - } - - @Override - public void removeNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, - ListenerNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.removeNotificationListener(name, listener, filter, handback); - else - super.removeNotificationListener(name, listener, filter, handback); - } - - @Override - public void removeNotificationListener(ObjectName name, ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.removeNotificationListener(name, listener); - else - super.removeNotificationListener(name, listener); - } - - @Override - public void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, - AttributeNotFoundException, - InvalidAttributeValueException, - MBeanException, - ReflectionException { - if (mbeanName.equals(name)) - mbeanMBS.setAttribute(name, attribute); - else - super.setAttribute(name, attribute); - } - - @Override - public AttributeList setAttributes(ObjectName name, - AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.setAttributes(name, attributes); - else - return super.setAttributes(name, attributes); - } - - @Override - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, - MBeanRegistrationException { - if (mbeanName.equals(name)) - mbeanMBS.unregisterMBean(name); - else - super.unregisterMBean(name); - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java --- a/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java Wed Nov 25 22:14:30 2009 -0800 @@ -31,15 +31,13 @@ import javax.management.Descriptor; import javax.management.MBeanException; -import javax.management.openmbean.MXBeanMapping; -import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenType; final class ConvertingMethod { - static ConvertingMethod from(Method m, MXBeanMappingFactory mappingFactory) { + static ConvertingMethod from(Method m) { try { - return new ConvertingMethod(m, mappingFactory); + return new ConvertingMethod(m); } catch (OpenDataException ode) { final String msg = "Method " + m.getDeclaringClass().getName() + "." + m.getName() + " has parameter or return type that " + @@ -53,7 +51,7 @@ } Descriptor getDescriptor() { - return Introspector.descriptorForElement(method, false); + return Introspector.descriptorForElement(method); } Type getGenericReturnType() { @@ -206,9 +204,9 @@ return method.getDeclaringClass() + "." + method.getName(); } - private ConvertingMethod(Method m, MXBeanMappingFactory mappingFactory) - throws OpenDataException { + private ConvertingMethod(Method m) throws OpenDataException { this.method = m; + MXBeanMappingFactory mappingFactory = MXBeanMappingFactory.DEFAULT; returnMapping = mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory); Type[] params = m.getGenericParameterTypes(); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java --- a/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Wed Nov 25 22:14:30 2009 -0800 @@ -28,8 +28,6 @@ import static com.sun.jmx.mbeanserver.Util.*; import static com.sun.jmx.mbeanserver.MXBeanIntrospector.typeName; -import javax.management.openmbean.MXBeanMappingClass; - import static javax.management.openmbean.SimpleType.*; import com.sun.jmx.remote.util.EnvHelp; @@ -69,8 +67,6 @@ import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeDataView; import javax.management.openmbean.CompositeType; -import javax.management.openmbean.MXBeanMapping; -import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenType; import javax.management.openmbean.SimpleType; @@ -165,34 +161,29 @@ private static final class Mappings extends WeakHashMap> {} - private static final Map factoryMappings = - new WeakHashMap(); + private static final Mappings mappings = new Mappings(); - private static final Map permanentMappings = newMap(); + /** Following List simply serves to keep a reference to predefined + MXBeanMappings so they don't get garbage collected. */ + private static final List permanentMappings = newList(); - private static synchronized MXBeanMapping getMapping( - Type type, MXBeanMappingFactory factory) { - Mappings mappings = factoryMappings.get(factory); - if (mappings == null) { - mappings = new Mappings(); - factoryMappings.put(factory, mappings); - } + private static synchronized MXBeanMapping getMapping(Type type) { WeakReference wr = mappings.get(type); return (wr == null) ? null : wr.get(); } - private static synchronized void putMapping( - Type type, MXBeanMapping mapping, MXBeanMappingFactory factory) { - Mappings mappings = factoryMappings.get(factory); - if (mappings == null) { - mappings = new Mappings(); - factoryMappings.put(factory, mappings); - } + private static synchronized void putMapping(Type type, MXBeanMapping mapping) { WeakReference wr = new WeakReference(mapping); mappings.put(type, wr); } + private static synchronized void putPermanentMapping( + Type type, MXBeanMapping mapping) { + putMapping(type, mapping); + permanentMappings.add(mapping); + } + static { /* Set up the mappings for Java types that map to SimpleType. */ @@ -213,7 +204,7 @@ throw new Error(e); } final MXBeanMapping mapping = new IdentityMapping(c, t); - permanentMappings.put(c, mapping); + putPermanentMapping(c, mapping); if (c.getName().startsWith("java.lang.")) { try { @@ -221,7 +212,7 @@ final Class primitiveType = (Class) typeField.get(null); final MXBeanMapping primitiveMapping = new IdentityMapping(primitiveType, t); - permanentMappings.put(primitiveType, primitiveMapping); + putPermanentMapping(primitiveType, primitiveMapping); if (primitiveType != void.class) { final Class primitiveArrayType = Array.newInstance(primitiveType, 0).getClass(); @@ -230,8 +221,8 @@ final MXBeanMapping primitiveArrayMapping = new IdentityMapping(primitiveArrayType, primitiveArrayOpenType); - permanentMappings.put(primitiveArrayType, - primitiveArrayMapping); + putPermanentMapping(primitiveArrayType, + primitiveArrayMapping); } } catch (NoSuchFieldException e) { // OK: must not be a primitive wrapper @@ -255,7 +246,7 @@ MXBeanMapping mapping; - mapping = getMapping(objType, null); + mapping = getMapping(objType); if (mapping != null) return mapping; @@ -268,7 +259,7 @@ inProgress.remove(objType); } - putMapping(objType, mapping, factory); + putMapping(objType, mapping); return mapping; } @@ -278,14 +269,6 @@ /* It's not yet worth formalizing these tests by having for example an array of factory classes, each of which says whether it recognizes the Type (Chain of Responsibility pattern). */ - MXBeanMapping mapping = permanentMappings.get(objType); - if (mapping != null) - return mapping; - Class erasure = erasure(objType); - MXBeanMappingClass mappingClass = - erasure.getAnnotation(MXBeanMappingClass.class); - if (mappingClass != null) - return makeAnnotationMapping(mappingClass, objType, factory); if (objType instanceof GenericArrayType) { Type componentType = ((GenericArrayType) objType).getGenericComponentType(); @@ -313,51 +296,6 @@ throw new OpenDataException("Cannot map type: " + objType); } - private static MXBeanMapping - makeAnnotationMapping(MXBeanMappingClass mappingClass, - Type objType, - MXBeanMappingFactory factory) - throws OpenDataException { - Class c = mappingClass.value(); - Constructor cons; - try { - cons = c.getConstructor(Type.class); - } catch (NoSuchMethodException e) { - final String msg = - "Annotation @" + MXBeanMappingClass.class.getName() + - " must name a class with a public constructor that has a " + - "single " + Type.class.getName() + " argument"; - OpenDataException ode = new OpenDataException(msg); - ode.initCause(e); - throw ode; - } - try { - return cons.newInstance(objType); - } catch (Exception e) { - final String msg = - "Could not construct a " + c.getName() + " for @" + - MXBeanMappingClass.class.getName(); - OpenDataException ode = new OpenDataException(msg); - ode.initCause(e); - throw ode; - } - } - - private static Class erasure(Type t) { - if (t instanceof Class) - return (Class) t; - if (t instanceof ParameterizedType) - return erasure(((ParameterizedType) t).getRawType()); - /* Other cases: GenericArrayType, TypeVariable, WildcardType. - * Returning the erasure of GenericArrayType is not necessary because - * anyway we will be recursing on the element type, and we'll erase - * then. Returning the erasure of the other two would mean returning - * the type bound (e.g. Foo in or ) - * and since we don't treat this as Foo elsewhere we shouldn't here. - */ - return Object.class; - } - private static > MXBeanMapping makeEnumMapping(Class enumClass, Class fake) { return new EnumMapping(Util.>cast(enumClass)); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java --- a/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java Wed Nov 25 22:14:30 2009 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 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 @@ -25,7 +25,7 @@ package com.sun.jmx.mbeanserver; -import javax.management.DynamicWrapperMBean; +import javax.management.DynamicMBean; import javax.management.MBeanServer; import javax.management.ObjectName; @@ -35,7 +35,17 @@ * * @since 1.6 */ -public interface DynamicMBean2 extends DynamicWrapperMBean { +public interface DynamicMBean2 extends DynamicMBean { + /** + * The resource corresponding to this MBean. This is the object whose + * class name should be reflected by the MBean's + * getMBeanInfo().getClassName() for example. For a "plain" + * DynamicMBean it will be "this". For an MBean that wraps another + * object, like javax.management.StandardMBean, it will be the wrapped + * object. + */ + public Object getResource(); + /** * The name of this MBean's class, as used by permission checks. * This is typically equal to getResource().getClass().getName(). diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/Introspector.java --- a/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Wed Nov 25 22:14:30 2009 -0800 @@ -25,14 +25,9 @@ package com.sun.jmx.mbeanserver; -import com.sun.jmx.remote.util.EnvHelp; -import java.beans.BeanInfo; -import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Array; import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; @@ -40,39 +35,21 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; -import javax.management.AttributeNotFoundException; -import javax.management.Description; import javax.management.Descriptor; -import javax.management.DescriptorFields; import javax.management.DescriptorKey; import javax.management.DynamicMBean; import javax.management.ImmutableDescriptor; -import javax.management.MBean; import javax.management.MBeanInfo; -import javax.management.MXBean; import javax.management.NotCompliantMBeanException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.MXBeanMappingFactory; -import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; -import com.sun.jmx.mbeanserver.Util; import com.sun.jmx.remote.util.EnvHelp; import java.beans.BeanInfo; import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.management.AttributeNotFoundException; -import javax.management.JMX; -import javax.management.ObjectName; -import javax.management.ObjectNameTemplate; import javax.management.openmbean.CompositeData; -import javax.management.openmbean.MXBeanMappingFactory; /** * This class contains the methods for performing all the tests needed to verify @@ -82,13 +59,7 @@ */ public class Introspector { - /** - * Pattern used to extract Attribute Names from ObjectNameTemplate Annotation - * For example, in the following example, the Name attribute value is - * retrieved : ":type=MyType, name={Name}" - */ - private static Pattern OBJECT_NAME_PATTERN_TEMPLATE = - Pattern.compile("(\\{[^\\}]+\\})|(=\"\\{[^\\}]+\\}\")"); + /* * ------------------------------------------ * PRIVATE CONSTRUCTORS @@ -164,10 +135,6 @@ public static void checkCompliance(Class mbeanClass) throws NotCompliantMBeanException { - - // Check that @Resource is used correctly (if it used). - MBeanInjector.validate(mbeanClass); - // Is DynamicMBean? // if (DynamicMBean.class.isAssignableFrom(mbeanClass)) @@ -190,36 +157,16 @@ } catch (NotCompliantMBeanException e) { mxbeanException = e; } - // Is @MBean or @MXBean class? - // In fact we find @MBean or @MXBean as a hacky variant of - // getStandardMBeanInterface or getMXBeanInterface. If we get here - // then nothing worked. final String msg = "MBean class " + mbeanClass.getName() + " does not implement " + - "DynamicMBean; does not follow the Standard MBean conventions (" + - mbeanException.toString() + "); does not follow the MXBean conventions (" + - mxbeanException.toString() + "); and does not have or inherit the @" + - MBean.class.getSimpleName() + " or @" + MXBean.class.getSimpleName() + - " annotation"; + "DynamicMBean, and neither follows the Standard MBean conventions (" + + mbeanException.toString() + ") nor the MXBean conventions (" + + mxbeanException.toString() + ")"; throw new NotCompliantMBeanException(msg); } - /** - *

Make a DynamicMBean out of the existing MBean object. The object - * may already be a DynamicMBean, or it may be a Standard MBean or - * MXBean, possibly defined using {@code @MBean} or {@code @MXBean}.

- * @param mbean the object to convert to a DynamicMBean. - * @param a type parameter defined for implementation convenience - * (which would have to be removed if this method were part of the public - * API). - * @return the converted DynamicMBean. - * @throws NotCompliantMBeanException if {@code mbean} is not a compliant - * MBean object, including the case where it is null. - */ public static DynamicMBean makeDynamicMBean(T mbean) - throws NotCompliantMBeanException { - if (mbean == null) - throw new NotCompliantMBeanException("Null MBean object"); + throws NotCompliantMBeanException { if (mbean instanceof DynamicMBean) return (DynamicMBean) mbean; final Class mbeanClass = mbean.getClass(); @@ -240,18 +187,8 @@ // to be an MBean or an MXBean. We will call checkCompliance() // to generate the appropriate exception. } - if (c != null) { - MXBeanMappingFactory factory; - try { - factory = MXBeanMappingFactory.forInterface(c); - } catch (IllegalArgumentException e) { - NotCompliantMBeanException ncmbe = - new NotCompliantMBeanException(e.getMessage()); - ncmbe.initCause(e); - throw ncmbe; - } - return new MXBeanSupport(mbean, c, factory); - } + if (c != null) + return new MXBeanSupport(mbean, c); checkCompliance(mbeanClass); throw new NotCompliantMBeanException("Not compliant"); // not reached } @@ -280,10 +217,9 @@ return testCompliance(baseClass, null); } - public static void testComplianceMXBeanInterface(Class interfaceClass, - MXBeanMappingFactory factory) + public static void testComplianceMXBeanInterface(Class interfaceClass) throws NotCompliantMBeanException { - MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass); + MXBeanIntrospector.getInstance().getAnalyzer(interfaceClass); } /** @@ -352,8 +288,6 @@ */ public static Class getStandardMBeanInterface(Class baseClass) throws NotCompliantMBeanException { - if (baseClass.isAnnotationPresent(MBean.class)) - return baseClass; Class current = baseClass; Class mbeanInterface = null; while (current != null) { @@ -384,8 +318,6 @@ */ public static Class getMXBeanInterface(Class baseClass) throws NotCompliantMBeanException { - if (hasMXBeanAnnotation(baseClass)) - return baseClass; try { return MXBeanSupport.findMXBeanInterface(baseClass); } catch (Exception e) { @@ -393,61 +325,12 @@ } } - public static Class getStandardOrMXBeanInterface( - Class baseClass, boolean mxbean) - throws NotCompliantMBeanException { - if (mxbean) - return getMXBeanInterface(baseClass); - else - return getStandardMBeanInterface(baseClass); - } - - public static ObjectName templateToObjectName(Descriptor descriptor, - DynamicMBean mbean) - throws NotCompliantMBeanException { - String template = (String) - descriptor.getFieldValue(JMX.OBJECT_NAME_TEMPLATE); - if(template == null) return null; - try { - Matcher m = OBJECT_NAME_PATTERN_TEMPLATE.matcher(template); - while (m.find()){ - String grp = m.group(); - System.out.println("GROUP " + grp); - String attributeName = null; - boolean quote = false; - if(grp.startsWith("=\"{")) { - attributeName = grp.substring(3, grp.length() - 2); - quote = true; - } else - attributeName = grp.substring(1, grp.length() - 1); - - Object attributeValue = mbean.getAttribute(attributeName); - String validValue = quote ? - "=" + ObjectName.quote(attributeValue.toString()) : - attributeValue.toString(); - template = template.replace(grp, validValue); - } - return new ObjectName(template); - }catch(Exception ex) { - NotCompliantMBeanException ncex = new - NotCompliantMBeanException(ObjectNameTemplate.class. - getSimpleName() + " annotation value [" + template + "] " + - "is invalid. " + ex); - ncex.initCause(ex); - throw ncex; - } - } - /* * ------------------------------------------ * PRIVATE METHODS * ------------------------------------------ */ - static boolean hasMXBeanAnnotation(Class c) { - MXBean m = c.getAnnotation(MXBean.class); - return (m != null && m.value()); - } /** * Try to find the MBean interface corresponding to the class aName @@ -469,77 +352,11 @@ return null; } - public static String descriptionForElement(AnnotatedElement elmt) { - if (elmt == null) - return null; - Description d = elmt.getAnnotation(Description.class); - if (d == null) - return null; - return d.value(); - } - - public static String descriptionForParameter( - Annotation[] parameterAnnotations) { - for (Annotation a : parameterAnnotations) { - if (a instanceof Description) - return ((Description) a).value(); - } - return null; - } - - public static String nameForParameter( - Annotation[] parameterAnnotations) { - for (Annotation a : parameterAnnotations) { - Class ac = a.annotationType(); - // You'd really have to go out of your way to have more than - // one @Name annotation, so we don't check for that. - if (ac.getSimpleName().equals("Name")) { - try { - Method value = ac.getMethod("value"); - if (value.getReturnType() == String.class && - value.getParameterTypes().length == 0) { - return (String) value.invoke(a); - } - } catch (Exception e) { - MBEANSERVER_LOGGER.log( - Level.WARNING, - "Unexpected exception getting @" + ac.getName(), - e); - } - } - } - return null; - } - - public static Descriptor descriptorForElement(final AnnotatedElement elmt, - boolean isSetter) { + public static Descriptor descriptorForElement(final AnnotatedElement elmt) { if (elmt == null) return ImmutableDescriptor.EMPTY_DESCRIPTOR; final Annotation[] annots = elmt.getAnnotations(); - Descriptor descr = descriptorForAnnotations(annots); - String[] exceptions = {}; - if(elmt instanceof Method) - exceptions = getAllExceptions(((Method) elmt).getExceptionTypes()); - else - if(elmt instanceof Constructor) - exceptions = getAllExceptions(((Constructor) elmt). - getExceptionTypes()); - - if(exceptions.length > 0 ) { - String fieldName = isSetter ? JMX.SET_EXCEPTIONS_FIELD : - JMX.EXCEPTIONS_FIELD; - - String[] fieldNames = {fieldName}; - Object[] fieldValues = {exceptions}; - descr = ImmutableDescriptor.union(descr, - new ImmutableDescriptor(fieldNames, fieldValues)); - } - - return descr; - } - - public static Descriptor descriptorForAnnotation(Annotation annot) { - return descriptorForAnnotations(new Annotation[] {annot}); + return descriptorForAnnotations(annots); } public static Descriptor descriptorForAnnotations(Annotation[] annots) { @@ -547,9 +364,36 @@ return ImmutableDescriptor.EMPTY_DESCRIPTOR; Map descriptorMap = new HashMap(); for (Annotation a : annots) { - if (a instanceof DescriptorFields) - addDescriptorFieldsToMap(descriptorMap, (DescriptorFields) a); - addAnnotationFieldsToMap(descriptorMap, a); + Class c = a.annotationType(); + Method[] elements = c.getMethods(); + for (Method element : elements) { + DescriptorKey key = element.getAnnotation(DescriptorKey.class); + if (key != null) { + String name = key.value(); + Object value; + try { + value = element.invoke(a); + } catch (RuntimeException e) { + // we don't expect this - except for possibly + // security exceptions? + // RuntimeExceptions shouldn't be "UndeclaredThrowable". + // anyway... + // + throw e; + } catch (Exception e) { + // we don't expect this + throw new UndeclaredThrowableException(e); + } + value = annotationToField(value); + Object oldValue = descriptorMap.put(name, value); + if (oldValue != null && !equals(oldValue, value)) { + final String msg = + "Inconsistent values for descriptor field " + name + + " from annotations: " + value + " :: " + oldValue; + throw new IllegalArgumentException(msg); + } + } + } } if (descriptorMap.isEmpty()) @@ -559,76 +403,6 @@ } /** - * Array of thrown excepions. - * @param exceptions can be null; - * @return An Array of Exception class names. Size is 0 if method is null. - */ - private static String[] getAllExceptions(Class[] exceptions) { - Set set = new LinkedHashSet(); - for(Classex : exceptions) - set.add(ex.getName()); - - String[] arr = new String[set.size()]; - return set.toArray(arr); - } - - private static void addDescriptorFieldsToMap( - Map descriptorMap, DescriptorFields df) { - for (String field : df.value()) { - int eq = field.indexOf('='); - if (eq < 0) { - throw new IllegalArgumentException( - "@DescriptorFields string must contain '=': " + - field); - } - String name = field.substring(0, eq); - String value = field.substring(eq + 1); - addToMap(descriptorMap, name, value); - } - } - - private static void addAnnotationFieldsToMap( - Map descriptorMap, Annotation a) { - Class c = a.annotationType(); - Method[] elements = c.getMethods(); - for (Method element : elements) { - DescriptorKey key = element.getAnnotation(DescriptorKey.class); - if (key != null) { - String name = key.value(); - Object value; - try { - value = element.invoke(a); - } catch (RuntimeException e) { - // we don't expect this - except for possibly - // security exceptions? - // RuntimeExceptions shouldn't be "UndeclaredThrowable". - // anyway... - throw e; - } catch (Exception e) { - // we don't expect this - throw new UndeclaredThrowableException(e); - } - if (!key.omitIfDefault() || - !equals(value, element.getDefaultValue())) { - value = annotationToField(value); - addToMap(descriptorMap, name, value); - } - } - } - } - - private static void addToMap( - Map descriptorMap, String name, Object value) { - Object oldValue = descriptorMap.put(name, value); - if (oldValue != null && !equals(oldValue, value)) { - final String msg = - "Inconsistent values for descriptor field " + name + - " from annotations: " + value + " :: " + oldValue; - throw new IllegalArgumentException(msg); - } - } - - /** * Throws a NotCompliantMBeanException or a SecurityException. * @param notCompliant the class which was under examination * @param cause the raeson why NotCompliantMBeanException should diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java --- a/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Wed Nov 25 22:14:30 2009 -0800 @@ -25,14 +25,14 @@ package com.sun.jmx.mbeanserver; +import com.sun.jmx.interceptor.DefaultMBeanServerInterceptor; +import com.sun.jmx.interceptor.MBeanServerInterceptor; import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; -import com.sun.jmx.interceptor.NamespaceDispatchInterceptor; import java.io.ObjectInputStream; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedExceptionAction; -import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.logging.Level; @@ -108,8 +108,6 @@ /** The MBeanServerDelegate object representing the MBean Server */ private final MBeanServerDelegate mBeanServerDelegateObject; - private final String mbeanServerName; - /** * Package: Creates an MBeanServer with the * specified default domain name, outer interface, and delegate. @@ -241,10 +239,9 @@ final Repository repository = new Repository(domain); this.mbsInterceptor = - new NamespaceDispatchInterceptor(outer, delegate, instantiator, + new DefaultMBeanServerInterceptor(outer, delegate, instantiator, repository); this.interceptorsEnabled = interceptors; - this.mbeanServerName = Util.getMBeanServerSecurityName(delegate); initialize(); } @@ -940,8 +937,7 @@ throws ReflectionException, MBeanException { /* Permission check */ - checkMBeanPermission(mbeanServerName, className, null, null, - "instantiate"); + checkMBeanPermission(className, null, null, "instantiate"); return instantiator.instantiate(className); } @@ -978,8 +974,7 @@ InstanceNotFoundException { /* Permission check */ - checkMBeanPermission(mbeanServerName, className, null, - null, "instantiate"); + checkMBeanPermission(className, null, null, "instantiate"); ClassLoader myLoader = outerShell.getClass().getClassLoader(); return instantiator.instantiate(className, loaderName, myLoader); @@ -1017,8 +1012,7 @@ throws ReflectionException, MBeanException { /* Permission check */ - checkMBeanPermission(mbeanServerName, className, null, null, - "instantiate"); + checkMBeanPermission(className, null, null, "instantiate"); ClassLoader myLoader = outerShell.getClass().getClassLoader(); return instantiator.instantiate(className, params, signature, @@ -1061,8 +1055,7 @@ InstanceNotFoundException { /* Permission check */ - checkMBeanPermission(mbeanServerName, className, null, - null, "instantiate"); + checkMBeanPermission(className, null, null, "instantiate"); ClassLoader myLoader = outerShell.getClass().getClassLoader(); return instantiator.instantiate(className,loaderName,params,signature, @@ -1333,8 +1326,7 @@ **/ public ClassLoaderRepository getClassLoaderRepository() { /* Permission check */ - checkMBeanPermission(mbeanServerName, null, null, - null, "getClassLoaderRepository"); + checkMBeanPermission(null, null, null, "getClassLoaderRepository"); return secureClr; } @@ -1487,16 +1479,14 @@ // SECURITY CHECKS //---------------- - private static void checkMBeanPermission(String serverName, - String classname, + private static void checkMBeanPermission(String classname, String member, ObjectName objectName, String actions) throws SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - Permission perm = new MBeanPermission(serverName, - classname, + Permission perm = new MBeanPermission(classname, member, objectName, actions); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java Wed Nov 25 22:14:30 2009 -0800 @@ -33,10 +33,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import javax.management.MBean; -import javax.management.MXBean; -import javax.management.ManagedAttribute; -import javax.management.ManagedOperation; import javax.management.NotCompliantMBeanException; /** @@ -55,15 +51,15 @@ */ class MBeanAnalyzer { - static interface MBeanVisitor { + static interface MBeanVisitor { public void visitAttribute(String attributeName, M getter, - M setter) throws X; + M setter); public void visitOperation(String operationName, - M operation) throws X; + M operation); } - void visit(MBeanVisitor visitor) throws X { + void visit(MBeanVisitor visitor) { // visit attributes for (Map.Entry> entry : attrMap.entrySet()) { String name = entry.getKey(); @@ -108,7 +104,10 @@ private MBeanAnalyzer(Class mbeanType, MBeanIntrospector introspector) throws NotCompliantMBeanException { - introspector.checkCompliance(mbeanType); + if (!mbeanType.isInterface()) { + throw new NotCompliantMBeanException("Not an interface: " + + mbeanType.getName()); + } try { initMaps(mbeanType, introspector); @@ -129,26 +128,18 @@ for (Method m : methods) { final String name = m.getName(); final int nParams = m.getParameterTypes().length; - final boolean managedOp = m.isAnnotationPresent(ManagedOperation.class); - final boolean managedAttr = m.isAnnotationPresent(ManagedAttribute.class); - if (managedOp && managedAttr) { - throw new NotCompliantMBeanException("Method " + name + - " has both @ManagedOperation and @ManagedAttribute"); - } final M cm = introspector.mFrom(m); String attrName = ""; - if (!managedOp) { - if (name.startsWith("get")) - attrName = name.substring(3); - else if (name.startsWith("is") - && m.getReturnType() == boolean.class) - attrName = name.substring(2); - } + if (name.startsWith("get")) + attrName = name.substring(3); + else if (name.startsWith("is") + && m.getReturnType() == boolean.class) + attrName = name.substring(2); if (attrName.length() != 0 && nParams == 0 - && m.getReturnType() != void.class && !managedOp) { + && m.getReturnType() != void.class) { // It's a getter // Check we don't have both isX and getX AttrMethods am = attrMap.get(attrName); @@ -165,7 +156,7 @@ attrMap.put(attrName, am); } else if (name.startsWith("set") && name.length() > 3 && nParams == 1 && - m.getReturnType() == void.class && !managedOp) { + m.getReturnType() == void.class) { // It's a setter attrName = name.substring(3); AttrMethods am = attrMap.get(attrName); @@ -178,9 +169,6 @@ } am.setter = cm; attrMap.put(attrName, am); - } else if (managedAttr) { - throw new NotCompliantMBeanException("Method " + name + - " has @ManagedAttribute but is not a valid getter or setter"); } else { // It's an operation List cms = opMap.get(name); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,295 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.mbeanserver; - -import java.lang.ref.WeakReference; -import java.security.PrivilegedAction; -import java.util.Map; -import java.util.WeakHashMap; -import javax.annotation.Resource; -import javax.management.MBeanServer; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; - -import static com.sun.jmx.mbeanserver.Util.newMap; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.management.SendNotification; - -public class MBeanInjector { - // There are no instances of this class - private MBeanInjector() { - } - - private static Class[] injectedClasses = { - MBeanServer.class, ObjectName.class, SendNotification.class, - }; - - public static void inject(Object mbean, MBeanServer mbs, ObjectName name) - throws Exception { - ClassInjector injector = injectorForClass(mbean.getClass()); - injector.inject(mbean, MBeanServer.class, mbs); - injector.inject(mbean, ObjectName.class, name); - } - - public static boolean injectsSendNotification(Object mbean) - throws NotCompliantMBeanException { - ClassInjector injector = injectorForClass(mbean.getClass()); - return injector.injects(SendNotification.class); - } - - public static void injectSendNotification(Object mbean, SendNotification sn) - throws Exception { - ClassInjector injector = injectorForClass(mbean.getClass()); - injector.inject(mbean, SendNotification.class, sn); - } - - public static void validate(Class c) throws NotCompliantMBeanException { - injectorForClass(c); - } - - private static class ClassInjector { - private Map, List> fields; - private Map, List> methods; - - ClassInjector(Class c) throws NotCompliantMBeanException { - fields = newMap(); - methods = newMap(); - - Class sup = c.getSuperclass(); - ClassInjector supInjector; - if (sup == null) { - supInjector = null; - } else { - supInjector = injectorForClass(sup); - fields.putAll(supInjector.fields); - methods.putAll(supInjector.methods); - } - - addMembers(c); - eliminateOverriddenMethods(); - - // If we haven't added any new fields or methods to what we - // inherited, then we can share the parent's maps. - if (supInjector != null) { - if (fields.equals(supInjector.fields)) - fields = supInjector.fields; - if (methods.equals(supInjector.methods)) - methods = supInjector.methods; - } - } - - boolean injects(Class c) { - return (fields.get(c) != null || methods.get(c) != null); - } - - void inject(Object instance, Class type, T resource) - throws Exception { - List fs = fields.get(type); - if (fs != null) { - for (Field f : fs) - f.set(instance, resource); - } - List ms = methods.get(type); - if (ms != null) { - for (Method m : ms) { - try { - m.invoke(instance, resource); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof Error) - throw (Error) cause; - else - throw (Exception) cause; - } - } - } - } - - private void eliminateOverriddenMethods() { - /* Covariant overriding is unlikely, but it is possible that the - * parent has a @Resource method that we override with another - * @Resource method. We don't want to invoke both methods, - * because polymorphism means we would actually invoke the same - * method twice. - */ - for (Map.Entry, List> entry : methods.entrySet()) { - List list = entry.getValue(); - list = MBeanAnalyzer.eliminateCovariantMethods(list); - entry.setValue(list); - } - } - - /* - * Find Fields or Methods within the given Class that we can inject - * resource references into. Suppose we want to know if a Field can get - * a reference to an ObjectName. We'll accept fields like this: - * - * @Resource - * private transient ObjectName name; - * - * or like this: - * - * @Resource(type = ObjectName.class) - * private transient Object name; - * - * but not like this: - * - * @Resource - * private transient Object name; - * - * (Plain @Resource is equivalent to @Resource(type = Object.class).) - * - * We don't want to inject into everything that might possibly accept - * an ObjectName reference, because examples like the last one above - * could also accept an MBeanServer reference or any other sort of - * reference. - * - * So we accept a Field if it has a @Resource annotation and either - * (a) its type is exactly ObjectName and its @Resource type is - * compatible with ObjectName (e.g. it is Object); or - * (b) its type is compatible with ObjectName and its @Resource type - * is exactly ObjectName. Fields that meet these criteria will not - * meet the same criteria with respect to other types such as MBeanServer. - * - * The same logic applies mutatis mutandis to Methods such as this: - * - * @Resource - * private void setObjectName1(ObjectName name) - * @Resource(type = Object.class) - * private void setObjectName2(Object name) - */ - private void addMembers(final Class c) - throws NotCompliantMBeanException { - AccessibleObject[][] memberArrays = - AccessController.doPrivileged( - new PrivilegedAction() { - public AccessibleObject[][] run() { - return new AccessibleObject[][] { - c.getDeclaredFields(), c.getDeclaredMethods() - }; - } - }); - for (AccessibleObject[] members : memberArrays) { - for (final AccessibleObject member : members) { - Resource res = member.getAnnotation(Resource.class); - if (res == null) - continue; - - final Field field; - final Method method; - final Class memberType; - final int modifiers; - if (member instanceof Field) { - field = (Field) member; - memberType = field.getType(); - modifiers = field.getModifiers(); - method = null; - } else { - field = null; - method = (Method) member; - Class[] paramTypes = method.getParameterTypes(); - if (paramTypes.length != 1) { - throw new NotCompliantMBeanException( - "@Resource method must have exactly 1 " + - "parameter: " + method); - } - if (method.getReturnType() != void.class) { - throw new NotCompliantMBeanException( - "@Resource method must return void: " + - method); - } - memberType = paramTypes[0]; - modifiers = method.getModifiers(); - } - - if (Modifier.isStatic(modifiers)) { - throw new NotCompliantMBeanException( - "@Resource method or field cannot be static: " + - member); - } - - for (Class injectedClass : injectedClasses) { - Class[] types = {memberType, res.type()}; - boolean accept = false; - for (int i = 0; i < 2; i++) { - if (types[i] == injectedClass && - types[1 - i].isAssignableFrom(injectedClass)) { - accept = true; - break; - } - } - if (accept) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - member.setAccessible(true); - return null; - } - }); - addToMap(fields, injectedClass, field); - addToMap(methods, injectedClass, method); - } - } - } - } - } - - private static void addToMap(Map> map, K key, V value) { - if (value == null) - return; - List list = map.get(key); - if (list == null) - list = Collections.singletonList(value); - else { - if (list.size() == 1) - list = new ArrayList(list); - list.add(value); - } - map.put(key, list); - } - } - - private static synchronized ClassInjector injectorForClass(Class c) - throws NotCompliantMBeanException { - WeakReference wr = injectorMap.get(c); - ClassInjector ci = (wr == null) ? null : wr.get(); - if (ci == null) { - ci = new ClassInjector(c); - injectorMap.put(c, new WeakReference(ci)); - } - return ci; - } - - private static Map, WeakReference> injectorMap = - new WeakHashMap, WeakReference>(); -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Nov 25 22:14:30 2009 -0800 @@ -614,15 +614,6 @@ } /** - * Returns the class of a primitive type. - * @param name The type for which we the associated class. - * @return the class, or null if name is not primitive. - */ - public static Class primitiveType(String name) { - return primitiveClasses.get(name); - } - - /** * Load a class with the specified loader, or with this object * class loader if the specified loader is null. **/ diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java Wed Nov 25 22:14:30 2009 -0800 @@ -36,28 +36,20 @@ import java.lang.reflect.Type; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.WeakHashMap; -import javax.management.Description; import javax.management.Descriptor; import javax.management.ImmutableDescriptor; import javax.management.IntrospectionException; import javax.management.InvalidAttributeValueException; -import javax.management.MBean; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanNotificationInfo; import javax.management.MBeanOperationInfo; -import javax.management.MXBean; -import javax.management.ManagedAttribute; -import javax.management.ManagedOperation; import javax.management.NotCompliantMBeanException; import javax.management.NotificationBroadcaster; -import javax.management.NotificationInfo; -import javax.management.NotificationInfos; import javax.management.ReflectionException; /** @@ -79,7 +71,7 @@ * ancestor with ConvertingMethod. But that would mean an extra object * for every Method in every Standard MBean interface. */ -public abstract class MBeanIntrospector { +abstract class MBeanIntrospector { static final class PerInterfaceMap extends WeakHashMap, WeakReference>> {} @@ -159,27 +151,7 @@ * may be null. */ abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, - M getter, M setter) throws IntrospectionException; - - final String getAttributeDescription( - String attributeName, String defaultDescription, - Method getter, Method setter) throws IntrospectionException { - String g = Introspector.descriptionForElement(getter); - String s = Introspector.descriptionForElement(setter); - if (g == null) { - if (s == null) - return defaultDescription; - else - return s; - } else if (s == null || g.equals(s)) { - return g; - } else { - throw new IntrospectionException( - "Inconsistent @Description on getter and setter for " + - "attribute " + attributeName); - } - } - + M getter, M setter); /** * Construct an MBeanOperationInfo for the given operation based on * the M it was derived from. @@ -201,36 +173,10 @@ abstract Descriptor getMBeanDescriptor(Class resourceClass); /** - * Get any additional Descriptor entries for this introspector instance. - * If there is a non-default MXBeanMappingFactory, it will appear in - * this Descriptor. - * @return Additional Descriptor entries, or an empty Descriptor if none. - */ - Descriptor getSpecificMBeanDescriptor() { - return ImmutableDescriptor.EMPTY_DESCRIPTOR; - } - - void checkCompliance(Class mbeanType) throws NotCompliantMBeanException { - if (!mbeanType.isInterface() && - !mbeanType.isAnnotationPresent(MBean.class) && - !Introspector.hasMXBeanAnnotation(mbeanType)) { - throw new NotCompliantMBeanException("Not an interface and " + - "does not have @" + MBean.class.getSimpleName() + - " or @" + MXBean.class.getSimpleName() + " annotation: " + - mbeanType.getName()); - } - } - - /** * Get the methods to be analyzed to build the MBean interface. */ List getMethods(final Class mbeanType) throws Exception { - if (mbeanType.isInterface()) - return Arrays.asList(mbeanType.getMethods()); - - final List methods = newList(); - getAnnotatedMethods(mbeanType, methods); - return methods; + return Arrays.asList(mbeanType.getMethods()); } final PerInterface getPerInterface(Class mbeanInterface) @@ -265,14 +211,11 @@ * the MBeanInfo's Descriptor. */ private MBeanInfo makeInterfaceMBeanInfo(Class mbeanInterface, - MBeanAnalyzer analyzer) throws IntrospectionException { + MBeanAnalyzer analyzer) { final MBeanInfoMaker maker = new MBeanInfoMaker(); analyzer.visit(maker); - final String defaultDescription = + final String description = "Information on the management interface of the MBean"; - String description = Introspector.descriptionForElement(mbeanInterface); - if (description == null) - description = defaultDescription; return maker.makeMBeanInfo(mbeanInterface, description); } @@ -370,11 +313,11 @@ /** A visitor that constructs the per-interface MBeanInfo. */ private class MBeanInfoMaker - implements MBeanAnalyzer.MBeanVisitor { + implements MBeanAnalyzer.MBeanVisitor { public void visitAttribute(String attributeName, M getter, - M setter) throws IntrospectionException { + M setter) { MBeanAttributeInfo mbai = getMBeanAttributeInfo(attributeName, getter, setter); @@ -403,7 +346,7 @@ new ImmutableDescriptor(interfaceClassName); final Descriptor mbeanDescriptor = getBasicMBeanDescriptor(); final Descriptor annotatedDescriptor = - Introspector.descriptorForElement(mbeanInterface, false); + Introspector.descriptorForElement(mbeanInterface); final Descriptor descriptor = DescriptorCache.getInstance().union( classNameDescriptor, @@ -442,32 +385,20 @@ * Return the MBeanInfo for the given resource, based on the given * per-interface data. */ - final MBeanInfo getMBeanInfo(Object resource, PerInterface perInterface) - throws NotCompliantMBeanException { + final MBeanInfo getMBeanInfo(Object resource, PerInterface perInterface) { MBeanInfo mbi = getClassMBeanInfo(resource.getClass(), perInterface); - MBeanNotificationInfo[] notifs; - try { - notifs = findNotifications(resource); - } catch (RuntimeException e) { - NotCompliantMBeanException x = - new NotCompliantMBeanException(e.getMessage()); - x.initCause(e); - throw x; - } - Descriptor d = getSpecificMBeanDescriptor(); - boolean anyNotifs = (notifs != null && notifs.length > 0); - if (!anyNotifs && ImmutableDescriptor.EMPTY_DESCRIPTOR.equals(d)) + MBeanNotificationInfo[] notifs = findNotifications(resource); + if (notifs == null || notifs.length == 0) return mbi; else { - d = ImmutableDescriptor.union(d, mbi.getDescriptor()); return new MBeanInfo(mbi.getClassName(), mbi.getDescription(), mbi.getAttributes(), mbi.getConstructors(), mbi.getOperations(), notifs, - d); + mbi.getDescriptor()); } } @@ -507,145 +438,29 @@ } } - /* - * Add to "methods" every public method that has the @ManagedAttribute - * or @ManagedOperation annotation, in the given class or any of - * its superclasses or superinterfaces. - * - * We always add superclass or superinterface methods first, so that - * the stable sort used by eliminateCovariantMethods will put the - * method from the most-derived class last. This means that we will - * see the version of the @ManagedAttribute (or ...Operation) annotation - * from that method, which might have a different description or whatever. - */ - public static void getAnnotatedMethods(Class c, List methods) - throws Exception { - Class sup = c.getSuperclass(); - if (sup != null) - getAnnotatedMethods(sup, methods); - Class[] intfs = c.getInterfaces(); - for (Class intf : intfs) - getAnnotatedMethods(intf, methods); - for (Method m : c.getMethods()) { - // We are careful not to add m if it is inherited from a parent - // class or interface, because duplicate methods lead to nasty - // behaviour in eliminateCovariantMethods. - if (m.getDeclaringClass() == c && - (m.isAnnotationPresent(ManagedAttribute.class) || - m.isAnnotationPresent(ManagedOperation.class))) - methods.add(m); + static MBeanNotificationInfo[] findNotifications(Object moi) { + if (!(moi instanceof NotificationBroadcaster)) + return null; + MBeanNotificationInfo[] mbn = + ((NotificationBroadcaster) moi).getNotificationInfo(); + if (mbn == null) + return null; + MBeanNotificationInfo[] result = + new MBeanNotificationInfo[mbn.length]; + for (int i = 0; i < mbn.length; i++) { + MBeanNotificationInfo ni = mbn[i]; + if (ni.getClass() != MBeanNotificationInfo.class) + ni = (MBeanNotificationInfo) ni.clone(); + result[i] = ni; } - } - - /* - * Return the array of MBeanNotificationInfo for the given MBean object. - * If the object implements NotificationBroadcaster and its - * getNotificationInfo() method returns a non-empty array, then that - * is the result. Otherwise, if the object has a @NotificationInfo - * or @NotificationInfos annotation, then its contents form the result. - * Otherwise, the result is null. - */ - static MBeanNotificationInfo[] findNotifications(Object moi) { - if (moi instanceof NotificationBroadcaster) { - MBeanNotificationInfo[] mbn = - ((NotificationBroadcaster) moi).getNotificationInfo(); - if (mbn != null && mbn.length > 0) { - MBeanNotificationInfo[] result = - new MBeanNotificationInfo[mbn.length]; - for (int i = 0; i < mbn.length; i++) { - MBeanNotificationInfo ni = mbn[i]; - if (ni.getClass() != MBeanNotificationInfo.class) - ni = (MBeanNotificationInfo) ni.clone(); - result[i] = ni; - } - return result; - } - } else { - try { - if (!MBeanInjector.injectsSendNotification(moi)) - return null; - } catch (NotCompliantMBeanException e) { - throw new RuntimeException(e); - } - } - return findNotificationsFromAnnotations(moi.getClass()); - } - - public static MBeanNotificationInfo[] findNotificationsFromAnnotations( - Class mbeanClass) { - Class c = getAnnotatedNotificationInfoClass(mbeanClass); - if (c == null) - return null; - NotificationInfo ni = c.getAnnotation(NotificationInfo.class); - NotificationInfos nis = c.getAnnotation(NotificationInfos.class); - List list = newList(); - if (ni != null) - list.add(ni); - if (nis != null) - list.addAll(Arrays.asList(nis.value())); - if (list.isEmpty()) - return null; - List mbnis = newList(); - for (NotificationInfo x : list) { - // The Descriptor includes any fields explicitly specified by - // x.descriptorFields(), plus any fields from the contained - // @Description annotation. - Descriptor d = new ImmutableDescriptor(x.descriptorFields()); - d = ImmutableDescriptor.union( - d, Introspector.descriptorForAnnotation(x.description())); - MBeanNotificationInfo mbni = new MBeanNotificationInfo( - x.types(), x.notificationClass().getName(), - x.description().value(), d); - mbnis.add(mbni); - } - return mbnis.toArray(new MBeanNotificationInfo[mbnis.size()]); - } - - private static final Map, WeakReference>> - annotatedNotificationInfoClasses = newWeakHashMap(); - - private static Class getAnnotatedNotificationInfoClass(Class baseClass) { - synchronized (annotatedNotificationInfoClasses) { - WeakReference> wr = - annotatedNotificationInfoClasses.get(baseClass); - if (wr != null) - return wr.get(); - Class c = null; - if (baseClass.isAnnotationPresent(NotificationInfo.class) || - baseClass.isAnnotationPresent(NotificationInfos.class)) { - c = baseClass; - } else { - Class[] intfs = baseClass.getInterfaces(); - for (Class intf : intfs) { - Class c1 = getAnnotatedNotificationInfoClass(intf); - if (c1 != null) { - if (c != null) { - throw new IllegalArgumentException( - "Class " + baseClass.getName() + " inherits " + - "@NotificationInfo(s) from both " + - c.getName() + " and " + c1.getName()); - } - c = c1; - } - } - } - // Record the result of the search. If no @NotificationInfo(s) - // were found, c is null, and we store a WeakReference(null). - // This prevents us from having to search again and fail again. - annotatedNotificationInfoClasses.put(baseClass, - new WeakReference>(c)); - return c; - } + return result; } private static MBeanConstructorInfo[] findConstructors(Class c) { Constructor[] cons = c.getConstructors(); MBeanConstructorInfo[] mbc = new MBeanConstructorInfo[cons.length]; for (int i = 0; i < cons.length; i++) { - String descr = "Public constructor of the MBean"; - Description d = cons[i].getAnnotation(Description.class); - if (d != null) - descr = d.value(); + final String descr = "Public constructor of the MBean"; mbc[i] = new MBeanConstructorInfo(descr, cons[i]); } return mbc; diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java Wed Nov 25 22:14:30 2009 -0800 @@ -37,7 +37,7 @@ import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.management.ReflectionException; -import javax.management.openmbean.MXBeanMappingFactory; +import com.sun.jmx.mbeanserver.MXBeanMappingFactory; /** * Base class for MBeans. There is one instance of this class for @@ -121,8 +121,7 @@ public abstract class MBeanSupport implements DynamicMBean2, MBeanRegistration { - MBeanSupport(T resource, Class mbeanInterfaceType, - MXBeanMappingFactory mappingFactory) + MBeanSupport(T resource, Class mbeanInterfaceType) throws NotCompliantMBeanException { if (mbeanInterfaceType == null) throw new NotCompliantMBeanException("Null MBean interface"); @@ -133,14 +132,13 @@ throw new NotCompliantMBeanException(msg); } this.resource = resource; - MBeanIntrospector introspector = getMBeanIntrospector(mappingFactory); + MBeanIntrospector introspector = getMBeanIntrospector(); this.perInterface = introspector.getPerInterface(mbeanInterfaceType); this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface); } /** Return the appropriate introspector for this type of MBean. */ - abstract MBeanIntrospector - getMBeanIntrospector(MXBeanMappingFactory mappingFactory); + abstract MBeanIntrospector getMBeanIntrospector(); /** * Return a cookie for this MBean. This cookie will be passed to @@ -262,14 +260,10 @@ return resource.getClass().getName(); } - public final Object getWrappedObject() { + public final Object getResource() { return resource; } - public final ClassLoader getWrappedClassLoader() { - return resource.getClass().getClassLoader(); - } - public final Class getMBeanInterface() { return perInterface.getMBeanInterface(); } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java Wed Nov 25 22:14:30 2009 -0800 @@ -28,26 +28,18 @@ import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap; import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap; import java.lang.annotation.Annotation; -import java.lang.ref.WeakReference; import java.lang.reflect.GenericArrayType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.Map; -import java.util.WeakHashMap; -import javax.management.Description; import javax.management.Descriptor; import javax.management.ImmutableDescriptor; -import javax.management.IntrospectionException; -import javax.management.JMX; import javax.management.MBeanAttributeInfo; import javax.management.MBeanException; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; -import javax.management.ManagedOperation; import javax.management.NotCompliantMBeanException; -import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.OpenMBeanAttributeInfoSupport; import javax.management.openmbean.OpenMBeanOperationInfoSupport; import javax.management.openmbean.OpenMBeanParameterInfo; @@ -60,36 +52,10 @@ * @since 1.6 */ class MXBeanIntrospector extends MBeanIntrospector { - /* We keep one MXBeanIntrospector per MXBeanMappingFactory, since the results - * of the introspection depend on the factory. The MXBeanIntrospector - * has a reference back to the factory, so we wrap it in a WeakReference. - * It will be strongly referenced by any MXBeanSupport instances using it; - * if there are none then it is OK to gc it. - */ - private static final - Map> map = - new WeakHashMap>(); + private static final MXBeanIntrospector instance = new MXBeanIntrospector(); - static MXBeanIntrospector getInstance(MXBeanMappingFactory factory) { - if (factory == null) - factory = MXBeanMappingFactory.DEFAULT; - synchronized (map) { - MXBeanIntrospector intro; - WeakReference wr = map.get(factory); - if (wr != null) { - intro = wr.get(); - if (intro != null) - return intro; - } - intro = new MXBeanIntrospector(factory); - wr = new WeakReference(intro); - map.put(factory, wr); - return intro; - } - } - - private MXBeanIntrospector(MXBeanMappingFactory factory) { - this.mappingFactory = factory; + static MXBeanIntrospector getInstance() { + return instance; } @Override @@ -115,7 +81,7 @@ @Override ConvertingMethod mFrom(Method m) { - return ConvertingMethod.from(m, mappingFactory); + return ConvertingMethod.from(m); } @Override @@ -176,17 +142,13 @@ @Override MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, - ConvertingMethod getter, ConvertingMethod setter) - throws IntrospectionException { + ConvertingMethod getter, ConvertingMethod setter) { final boolean isReadable = (getter != null); final boolean isWritable = (setter != null); final boolean isIs = isReadable && getName(getter).startsWith("is"); - final String description = getAttributeDescription( - attributeName, attributeName, - getter == null ? null : getter.getMethod(), - setter == null ? null : setter.getMethod()); + final String description = attributeName; final OpenType openType; final Type originalType; @@ -235,17 +197,13 @@ MBeanOperationInfo getMBeanOperationInfo(String operationName, ConvertingMethod operation) { final Method method = operation.getMethod(); - String description = operationName; + final String description = operationName; /* Ideally this would be an empty string, but - OMBOperationInfo constructor forbids that. */ - Description d = method.getAnnotation(Description.class); - if (d != null) - description = d.value(); + OMBOperationInfo constructor forbids that. Also, we + could consult an annotation to get a useful + description. */ - int impact = MBeanOperationInfo.UNKNOWN; - ManagedOperation annot = method.getAnnotation(ManagedOperation.class); - if (annot != null) - impact = annot.impact().getCode(); + final int impact = MBeanOperationInfo.UNKNOWN; final OpenType returnType = operation.getOpenReturnType(); final Type originalReturnType = operation.getGenericReturnType(); @@ -257,15 +215,8 @@ boolean openParameterTypes = true; Annotation[][] annots = method.getParameterAnnotations(); for (int i = 0; i < paramTypes.length; i++) { - String paramName = Introspector.nameForParameter(annots[i]); - if (paramName == null) - paramName = "p" + i; - - String paramDescription = - Introspector.descriptionForParameter(annots[i]); - if (paramDescription == null) - paramDescription = paramName; - + final String paramName = "p" + i; + final String paramDescription = paramName; final OpenType openType = paramTypes[i]; final Type originalType = originalParamTypes[i]; Descriptor descriptor = @@ -292,7 +243,7 @@ Descriptor descriptor = typeDescriptor(returnType, originalReturnType); descriptor = ImmutableDescriptor.union(descriptor, - Introspector.descriptorForElement(method, false)); + Introspector.descriptorForElement(method)); final MBeanOperationInfo oi; if (openReturnType && openParameterTypes) { /* If the return value and all the parameters can be faithfully @@ -343,17 +294,6 @@ return ImmutableDescriptor.EMPTY_DESCRIPTOR; } - @Override - Descriptor getSpecificMBeanDescriptor() { - if (mappingFactory == MXBeanMappingFactory.DEFAULT) - return ImmutableDescriptor.EMPTY_DESCRIPTOR; - else { - return new ImmutableDescriptor( - JMX.MXBEAN_MAPPING_FACTORY_CLASS_FIELD + "=" + - mappingFactory.getClass().getName()); - } - } - private static Descriptor typeDescriptor(OpenType openType, Type originalType) { return new ImmutableDescriptor( @@ -421,7 +361,5 @@ private final PerInterfaceMap perInterfaceMap = new PerInterfaceMap(); - private final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap(); - - private final MXBeanMappingFactory mappingFactory; + private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap(); } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java Wed Nov 25 22:14:30 2009 -0800 @@ -25,8 +25,6 @@ package com.sun.jmx.mbeanserver; -import com.sun.jmx.remote.util.EnvHelp; -import java.io.InvalidObjectException; import static com.sun.jmx.mbeanserver.Util.*; import java.util.Map; import java.lang.ref.WeakReference; @@ -85,181 +83,87 @@ * * From the above, it is clear that the logic for getX on an MXBean is * the same as for setX on a proxy, and vice versa. - * - * The above describes the logic for "plain" MXBeanLookup, represented - * by MXBeanLookup.Plain. When namespaces enter the picture, we see - * MXBeanLookup.Prefix. Here, the idea is that the name of the ModuleMXBean - * might be a//m:m=m. In this case, we don't accept a reference to - * an MXBean object, since that would require different namespaces to know - * each others' objects. We only accept proxies. Suppose you have a proxy - * for a//m:m=m, call it moduleProxy, and you call - * moduleProxy.setProduct(productProxy). Then if productProxy is for - * a//p:p=p we should convert this to just p:p=p. If productProxy is for - * a//b//p:p=p we should convert it to b//p:p=p. Conversely, if getProduct - * returns an ObjectName like b//p:p=p then we should convert it into a proxy - * for a//b//p:p=p. */ -public abstract class MXBeanLookup { +public class MXBeanLookup { private MXBeanLookup(MBeanServerConnection mbsc) { this.mbsc = mbsc; } - static MXBeanLookup lookupFor(MBeanServerConnection mbsc, String prefix) { - if (prefix == null) - return Plain.lookupFor(mbsc); - else - return new Prefix(mbsc, prefix); - } - - abstract T objectNameToMXBean(ObjectName name, Class type) - throws InvalidObjectException; - - abstract ObjectName mxbeanToObjectName(Object mxbean) - throws OpenDataException; - - static class Plain extends MXBeanLookup { - Plain(MBeanServerConnection mbsc) { - super(mbsc); - } - - static Plain lookupFor(MBeanServerConnection mbsc) { - synchronized (mbscToLookup) { - WeakReference weakLookup = mbscToLookup.get(mbsc); - Plain lookup = (weakLookup == null) ? null : weakLookup.get(); - if (lookup == null) { - lookup = new Plain(mbsc); - mbscToLookup.put(mbsc, new WeakReference(lookup)); - } - return lookup; + static MXBeanLookup lookupFor(MBeanServerConnection mbsc) { + synchronized (mbscToLookup) { + WeakReference weakLookup = mbscToLookup.get(mbsc); + MXBeanLookup lookup = (weakLookup == null) ? null : weakLookup.get(); + if (lookup == null) { + lookup = new MXBeanLookup(mbsc); + mbscToLookup.put(mbsc, new WeakReference(lookup)); } - } - - @Override - synchronized T objectNameToMXBean(ObjectName name, Class type) { - WeakReference wr = objectNameToProxy.get(name); - if (wr != null) { - Object proxy = wr.get(); - if (type.isInstance(proxy)) - return type.cast(proxy); - } - T proxy = JMX.newMXBeanProxy(mbsc, name, type); - objectNameToProxy.put(name, new WeakReference(proxy)); - return proxy; - } - - @Override - synchronized ObjectName mxbeanToObjectName(Object mxbean) - throws OpenDataException { - String wrong; - if (mxbean instanceof Proxy) { - InvocationHandler ih = Proxy.getInvocationHandler(mxbean); - if (ih instanceof MBeanServerInvocationHandler) { - MBeanServerInvocationHandler mbsih = - (MBeanServerInvocationHandler) ih; - if (mbsih.getMBeanServerConnection().equals(mbsc)) - return mbsih.getObjectName(); - else - wrong = "proxy for a different MBeanServer"; - } else - wrong = "not a JMX proxy"; - } else { - ObjectName name = mxbeanToObjectName.get(mxbean); - if (name != null) - return name; - wrong = "not an MXBean registered in this MBeanServer"; - } - String s = (mxbean == null) ? - "null" : "object of type " + mxbean.getClass().getName(); - throw new OpenDataException( - "Could not convert " + s + " to an ObjectName: " + wrong); - // Message will be strange if mxbean is null but it is not - // supposed to be. - } - - synchronized void addReference(ObjectName name, Object mxbean) - throws InstanceAlreadyExistsException { - ObjectName existing = mxbeanToObjectName.get(mxbean); - if (existing != null) { - String multiname = AccessController.doPrivileged( - new GetPropertyAction("jmx.mxbean.multiname")); - if (!"true".equalsIgnoreCase(multiname)) { - throw new InstanceAlreadyExistsException( - "MXBean already registered with name " + existing); - } - } - mxbeanToObjectName.put(mxbean, name); - } - - synchronized boolean removeReference(ObjectName name, Object mxbean) { - if (name.equals(mxbeanToObjectName.get(mxbean))) { - mxbeanToObjectName.remove(mxbean); - return true; - } else - return false; - /* removeReference can be called when the above condition fails, - * notably if you try to register the same MXBean twice. - */ - } - - private final WeakIdentityHashMap - mxbeanToObjectName = WeakIdentityHashMap.make(); - private final Map> - objectNameToProxy = newMap(); - private static WeakIdentityHashMap> - mbscToLookup = WeakIdentityHashMap.make(); - } - - private static class Prefix extends MXBeanLookup { - private final String prefix; - - Prefix(MBeanServerConnection mbsc, String prefix) { - super(mbsc); - this.prefix = prefix; - } - - @Override - T objectNameToMXBean(ObjectName name, Class type) - throws InvalidObjectException { - String domain = prefix + name.getDomain(); - try { - name = name.withDomain(domain); - } catch (IllegalArgumentException e) { - throw EnvHelp.initCause( - new InvalidObjectException(e.getMessage()), e); - } - return JMX.newMXBeanProxy(mbsc, name, type); - } - - @Override - ObjectName mxbeanToObjectName(Object mxbean) - throws OpenDataException { - ObjectName name = proxyToObjectName(mxbean); - String domain = name.getDomain(); - if (!domain.startsWith(prefix)) { - throw new OpenDataException( - "Proxy's name does not start with " + - prefix + ": " + name); - } - try { - name = name.withDomain(domain.substring(prefix.length())); - } catch (IllegalArgumentException e) { - throw EnvHelp.initCause( - new OpenDataException(e.getMessage()), e); - } - return name; + return lookup; } } - ObjectName proxyToObjectName(Object proxy) { - InvocationHandler ih = Proxy.getInvocationHandler(proxy); - if (ih instanceof MBeanServerInvocationHandler) { - MBeanServerInvocationHandler mbsih = - (MBeanServerInvocationHandler) ih; - if (mbsih.getMBeanServerConnection().equals(mbsc)) - return mbsih.getObjectName(); + synchronized T objectNameToMXBean(ObjectName name, Class type) { + WeakReference wr = objectNameToProxy.get(name); + if (wr != null) { + Object proxy = wr.get(); + if (type.isInstance(proxy)) + return type.cast(proxy); } - return null; + T proxy = JMX.newMXBeanProxy(mbsc, name, type); + objectNameToProxy.put(name, new WeakReference(proxy)); + return proxy; + } + + synchronized ObjectName mxbeanToObjectName(Object mxbean) + throws OpenDataException { + String wrong; + if (mxbean instanceof Proxy) { + InvocationHandler ih = Proxy.getInvocationHandler(mxbean); + if (ih instanceof MBeanServerInvocationHandler) { + MBeanServerInvocationHandler mbsih = + (MBeanServerInvocationHandler) ih; + if (mbsih.getMBeanServerConnection().equals(mbsc)) + return mbsih.getObjectName(); + else + wrong = "proxy for a different MBeanServer"; + } else + wrong = "not a JMX proxy"; + } else { + ObjectName name = mxbeanToObjectName.get(mxbean); + if (name != null) + return name; + wrong = "not an MXBean registered in this MBeanServer"; + } + String s = (mxbean == null) ? + "null" : "object of type " + mxbean.getClass().getName(); + throw new OpenDataException( + "Could not convert " + s + " to an ObjectName: " + wrong); + // Message will be strange if mxbean is null but it is not + // supposed to be. + } + + synchronized void addReference(ObjectName name, Object mxbean) + throws InstanceAlreadyExistsException { + ObjectName existing = mxbeanToObjectName.get(mxbean); + if (existing != null) { + String multiname = AccessController.doPrivileged( + new GetPropertyAction("jmx.mxbean.multiname")); + if (!"true".equalsIgnoreCase(multiname)) { + throw new InstanceAlreadyExistsException( + "MXBean already registered with name " + existing); + } + } + mxbeanToObjectName.put(mxbean, name); + } + + synchronized boolean removeReference(ObjectName name, Object mxbean) { + if (name.equals(mxbeanToObjectName.get(mxbean))) { + mxbeanToObjectName.remove(mxbean); + return true; + } else + return false; + /* removeReference can be called when the above condition fails, + * notably if you try to register the same MXBean twice. + */ } static MXBeanLookup getLookup() { @@ -273,5 +177,12 @@ private static final ThreadLocal currentLookup = new ThreadLocal(); - final MBeanServerConnection mbsc; + private final MBeanServerConnection mbsc; + private final WeakIdentityHashMap + mxbeanToObjectName = WeakIdentityHashMap.make(); + private final Map> + objectNameToProxy = newMap(); + private static final WeakIdentityHashMap> + mbscToLookup = WeakIdentityHashMap.make(); } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java Wed Nov 25 22:14:30 2009 -0800 @@ -0,0 +1,210 @@ +/* + * Copyright 2007-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. + */ + +package com.sun.jmx.mbeanserver; + +import java.io.InvalidObjectException; +import java.lang.reflect.Type; +import javax.management.openmbean.OpenDataException; +import javax.management.openmbean.OpenType; + +/** + *

A custom mapping between Java types and Open types for use in MXBeans. + * To define such a mapping, subclass this class and define at least the + * {@link #fromOpenValue fromOpenValue} and {@link #toOpenValue toOpenValue} + * methods, and optionally the {@link #checkReconstructible} method. + * Then either use an {@link MXBeanMappingClass} annotation on your custom + * Java types, or include this MXBeanMapping in an + * {@link MXBeanMappingFactory}.

+ * + *

For example, suppose we have a class {@code MyLinkedList}, which looks + * like this:

+ * + *
+ * public class MyLinkedList {
+ *     public MyLinkedList(String name, MyLinkedList next) {...}
+ *     public String getName() {...}
+ *     public MyLinkedList getNext() {...}
+ * }
+ * 
+ * + *

This is not a valid type for MXBeans, because it contains a + * self-referential property "next" defined by the {@code getNext()} + * method. MXBeans do not support recursive types. So we would like + * to specify a mapping for {@code MyLinkedList} explicitly. When an + * MXBean interface contains {@code MyLinkedList}, that will be mapped + * into a {@code String[]}, which is a valid Open Type.

+ * + *

To define this mapping, we first subclass {@code MXBeanMapping}:

+ * + *
+ * public class MyLinkedListMapping extends MXBeanMapping {
+ *     public MyLinkedListMapping(Type type) throws OpenDataException {
+ *         super(MyLinkedList.class, ArrayType.getArrayType(SimpleType.STRING));
+ *         if (type != MyLinkedList.class)
+ *             throw new OpenDataException("Mapping only valid for MyLinkedList");
+ *     }
+ *
+ *     {@literal @Override}
+ *     public Object fromOpenValue(Object openValue) throws InvalidObjectException {
+ *         String[] array = (String[]) openValue;
+ *         MyLinkedList list = null;
+ *         for (int i = array.length - 1; i >= 0; i--)
+ *             list = new MyLinkedList(array[i], list);
+ *         return list;
+ *     }
+ *
+ *     {@literal @Override}
+ *     public Object toOpenValue(Object javaValue) throws OpenDataException {
+ *         ArrayList<String> array = new ArrayList<String>();
+ *         for (MyLinkedList list = (MyLinkedList) javaValue; list != null;
+ *              list = list.getNext())
+ *             array.add(list.getName());
+ *         return array.toArray(new String[0]);
+ *     }
+ * }
+ * 
+ * + *

The call to the superclass constructor specifies what the + * original Java type is ({@code MyLinkedList.class}) and what Open + * Type it is mapped to ({@code + * ArrayType.getArrayType(SimpleType.STRING)}). The {@code + * fromOpenValue} method says how we go from the Open Type ({@code + * String[]}) to the Java type ({@code MyLinkedList}), and the {@code + * toOpenValue} method says how we go from the Java type to the Open + * Type.

+ * + *

With this mapping defined, we can annotate the {@code MyLinkedList} + * class appropriately:

+ * + *
+ * {@literal @MXBeanMappingClass}(MyLinkedListMapping.class)
+ * public class MyLinkedList {...}
+ * 
+ * + *

Now we can use {@code MyLinkedList} in an MXBean interface and it + * will work.

+ * + *

If we are unable to modify the {@code MyLinkedList} class, + * we can define an {@link MXBeanMappingFactory}. See the documentation + * of that class for further details.

+ * + * @see MXBean specification, section + * "Custom MXBean type mappings" + */ +public abstract class MXBeanMapping { + private final Type javaType; + private final OpenType openType; + private final Class openClass; + + /** + *

Construct a mapping between the given Java type and the given + * Open Type.

+ * + * @param javaType the Java type (for example, {@code MyLinkedList}). + * @param openType the Open Type (for example, {@code + * ArrayType.getArrayType(SimpleType.STRING)}) + * + * @throws NullPointerException if either argument is null. + */ + protected MXBeanMapping(Type javaType, OpenType openType) { + if (javaType == null || openType == null) + throw new NullPointerException("Null argument"); + this.javaType = javaType; + this.openType = openType; + this.openClass = makeOpenClass(javaType, openType); + } + + /** + *

The Java type that was supplied to the constructor.

+ * @return the Java type that was supplied to the constructor. + */ + public final Type getJavaType() { + return javaType; + } + + /** + *

The Open Type that was supplied to the constructor.

+ * @return the Open Type that was supplied to the constructor. + */ + public final OpenType getOpenType() { + return openType; + } + + /** + *

The Java class that corresponds to instances of the + * {@linkplain #getOpenType() Open Type} for this mapping.

+ * @return the Java class that corresponds to instances of the + * Open Type for this mapping. + * @see OpenType#getClassName + */ + public final Class getOpenClass() { + return openClass; + } + + private static Class makeOpenClass(Type javaType, OpenType openType) { + if (javaType instanceof Class && ((Class) javaType).isPrimitive()) + return (Class) javaType; + try { + String className = openType.getClassName(); + return Class.forName(className, false, null); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); // should not happen + } + } + + /** + *

Convert an instance of the Open Type into the Java type. + * @param openValue the value to be converted. + * @return the converted value. + * @throws InvalidObjectException if the value cannot be converted. + */ + public abstract Object fromOpenValue(Object openValue) + throws InvalidObjectException; + + /** + *

Convert an instance of the Java type into the Open Type. + * @param javaValue the value to be converted. + * @return the converted value. + * @throws OpenDataException if the value cannot be converted. + */ + public abstract Object toOpenValue(Object javaValue) + throws OpenDataException; + + + /** + *

Throw an appropriate InvalidObjectException if we will not + * be able to convert back from the open data to the original Java + * object. The {@link #fromOpenValue fromOpenValue} throws an + * exception if a given open data value cannot be converted. This + * method throws an exception if no open data values can + * be converted. The default implementation of this method never + * throws an exception. Subclasses can override it as + * appropriate.

+ * @throws InvalidObjectException if {@code fromOpenValue} will throw + * an exception no matter what its argument is. + */ + public void checkReconstructible() throws InvalidObjectException {} +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java Wed Nov 25 22:14:30 2009 -0800 @@ -0,0 +1,124 @@ +/* + * Copyright 2007-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. + */ + +package com.sun.jmx.mbeanserver; + +import javax.management.openmbean.*; +import com.sun.jmx.mbeanserver.MXBeanMapping; +import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory; +import java.lang.reflect.Type; + +/** + *

Defines how types are mapped for a given MXBean or set of MXBeans. + * An {@code MXBeanMappingFactory} can be specified either through the + * {@link MXBeanMappingFactoryClass} annotation, or through the + * {@link javax.management.JMX.MBeanOptions JMX.MBeanOptions} argument to a + * {@link javax.management.StandardMBean StandardMBean} constructor or MXBean + * proxy.

+ * + *

An {@code MXBeanMappingFactory} must return an {@code MXBeanMapping} + * for any Java type that appears in the MXBeans that the factory is being + * used for. Usually it does that by handling any custom types, and + * forwarding everything else to the {@linkplain #DEFAULT default mapping + * factory}.

+ * + *

Consider the {@code MyLinkedList} example from the {@link MXBeanMapping} + * documentation. If we are unable to change the {@code MyLinkedList} class + * to add an {@link MXBeanMappingClass} annotation, we could achieve the same + * effect by defining {@code MyLinkedListMappingFactory} as follows:

+ * + *
+ * public class MyLinkedListMappingFactory extends MXBeanMappingFactory {
+ *     public MyLinkedListMappingFactory() {}
+ *
+ *     public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
+ *     throws OpenDataException {
+ *         if (t == MyLinkedList.class)
+ *             return new MyLinkedListMapping(t);
+ *         else
+ *             return MXBeanMappingFactory.DEFAULT.mappingForType(t, f);
+ *     }
+ * }
+ * 
+ * + *

The mapping factory handles only the {@code MyLinkedList} class. + * Every other type is forwarded to the default mapping factory. + * This includes types such as {@code MyLinkedList[]} and + * {@code List}; the default mapping factory will recursively + * invoke {@code MyLinkedListMappingFactory} to map the contained + * {@code MyLinkedList} type.

+ * + *

Once we have defined {@code MyLinkedListMappingFactory}, we can use + * it in an MXBean interface like this:

+ * + *
+ * {@literal @MXBeanMappingFactoryClass}(MyLinkedListMappingFactory.class)
+ * public interface SomethingMXBean {
+ *     public MyLinkedList getSomething();
+ * }
+ * 
+ * + *

Alternatively we can annotate the package that {@code SomethingMXBean} + * appears in, or we can supply the factory to a {@link + * javax.management.StandardMBean StandardMBean} constructor or MXBean + * proxy.

+ * + * @see MXBean specification, section + * "Custom MXBean type mappings" + */ +public abstract class MXBeanMappingFactory { + /** + *

Construct an instance of this class.

+ */ + protected MXBeanMappingFactory() {} + + /** + *

Mapping factory that applies the default rules for MXBean + * mappings, as described in the MXBean specification.

+ */ + public static final MXBeanMappingFactory DEFAULT = + new DefaultMXBeanMappingFactory(); + + /** + *

Return the mapping for the given Java type. Typically, a + * mapping factory will return mappings for types it handles, and + * forward other types to another mapping factory, most often + * the {@linkplain #DEFAULT default one}.

+ * @param t the Java type to be mapped. + * @param f the original mapping factory that was consulted to do + * the mapping. A mapping factory should pass this parameter intact + * if it forwards a type to another mapping factory. In the example, + * this is how {@code MyLinkedListMappingFactory} works for types + * like {@code MyLinkedList[]} and {@code List}. + * @return the mapping for the given type. + * @throws OpenDataException if this type cannot be mapped. This + * exception is appropriate if the factory is supposed to handle + * all types of this sort (for example, all linked lists), but + * cannot handle this particular type. + */ + public abstract MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f) + throws OpenDataException; +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java Wed Nov 25 22:14:30 2009 -0800 @@ -32,10 +32,8 @@ import javax.management.Attribute; import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; -import javax.management.openmbean.MXBeanMappingFactory; /**

Helper class for an {@link InvocationHandler} that forwards methods from an @@ -47,7 +45,7 @@ @since 1.6 */ public class MXBeanProxy { - public MXBeanProxy(Class mxbeanInterface, MXBeanMappingFactory factory) { + public MXBeanProxy(Class mxbeanInterface) { if (mxbeanInterface == null) throw new IllegalArgumentException("Null parameter"); @@ -55,7 +53,7 @@ final MBeanAnalyzer analyzer; try { analyzer = - MXBeanIntrospector.getInstance(factory).getAnalyzer(mxbeanInterface); + MXBeanIntrospector.getInstance().getAnalyzer(mxbeanInterface); } catch (NotCompliantMBeanException e) { throw new IllegalArgumentException(e); } @@ -63,7 +61,7 @@ } private class Visitor - implements MBeanAnalyzer.MBeanVisitor { + implements MBeanAnalyzer.MBeanVisitor { public void visitAttribute(String attributeName, ConvertingMethod getter, ConvertingMethod setter) { @@ -161,8 +159,7 @@ Handler handler = handlerMap.get(method); ConvertingMethod cm = handler.getConvertingMethod(); - String prefix = extractPrefix(name); - MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc, prefix); + MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc); MXBeanLookup oldLookup = MXBeanLookup.getLookup(); try { MXBeanLookup.setLookup(lookup); @@ -174,17 +171,5 @@ } } - private static String extractPrefix(ObjectName name) - throws MalformedObjectNameException { - String domain = name.getDomain(); - int slashslash = domain.lastIndexOf("//"); - if (slashslash > 0 && domain.charAt(slashslash - 1) == '/') - slashslash--; - if (slashslash >= 0) - return domain.substring(0, slashslash + 2); - else - return null; - } - private final Map handlerMap = newMap(); } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java Wed Nov 25 22:14:30 2009 -0800 @@ -35,7 +35,6 @@ import javax.management.MBeanServer; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; -import javax.management.openmbean.MXBeanMappingFactory; /** * Base class for MXBeans. @@ -62,16 +61,14 @@ if it does not implement the class {@code mxbeanInterface} or if that class is not a valid MXBean interface. */ - public MXBeanSupport(T resource, Class mxbeanInterface, - MXBeanMappingFactory mappingFactory) + public MXBeanSupport(T resource, Class mxbeanInterface) throws NotCompliantMBeanException { - super(resource, mxbeanInterface, mappingFactory); + super(resource, mxbeanInterface); } @Override - MBeanIntrospector - getMBeanIntrospector(MXBeanMappingFactory mappingFactory) { - return MXBeanIntrospector.getInstance(mappingFactory); + MBeanIntrospector getMBeanIntrospector() { + return MXBeanIntrospector.getInstance(); } @Override @@ -159,8 +156,8 @@ // eventually we could have some logic to supply a default name synchronized (lock) { - this.mxbeanLookup = MXBeanLookup.Plain.lookupFor(server); - this.mxbeanLookup.addReference(name, getWrappedObject()); + this.mxbeanLookup = MXBeanLookup.lookupFor(server); + this.mxbeanLookup.addReference(name, getResource()); this.objectName = name; } } @@ -169,19 +166,13 @@ public void unregister() { synchronized (lock) { if (mxbeanLookup != null) { - if (mxbeanLookup.removeReference(objectName, getWrappedObject())) + if (mxbeanLookup.removeReference(objectName, getResource())) objectName = null; } - // XXX: need to revisit the whole register/unregister logic in - // the face of wrapping. The mxbeanLookup!=null test is a hack. - // If you wrap an MXBean in a MyWrapperMBean and register it, - // the lookup table should contain the wrapped object. But that - // implies that MyWrapperMBean calls register, which today it - // can't within the public API. } } private final Object lock = new Object(); // for mxbeanLookup and objectName - private MXBeanLookup.Plain mxbeanLookup; + private MXBeanLookup mxbeanLookup; private ObjectName objectName; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/NotificationMBeanSupport.java --- a/src/share/classes/com/sun/jmx/mbeanserver/NotificationMBeanSupport.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.mbeanserver; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -import javax.management.openmbean.MXBeanMappingFactory; - -/** - *

A variant of {@code StandardMBeanSupport} where the only - * methods included are public getters. This is used by - * {@code QueryNotificationFilter} to pretend that a Notification is - * an MBean so it can have a query evaluated on it. Standard queries - * never set attributes or invoke methods but custom queries could and - * we don't want to allow that. Also we don't want to fail if a - * Notification happens to have inconsistent types in a pair of getX and - * setX methods, and we want to include the Object.getClass() method. - */ -public class NotificationMBeanSupport extends StandardMBeanSupport { - public NotificationMBeanSupport(T n) - throws NotCompliantMBeanException { - super(n, Util.>cast(n.getClass())); - } - - @Override - MBeanIntrospector getMBeanIntrospector(MXBeanMappingFactory ignored) { - return introspector; - } - - private static class Introspector extends StandardMBeanIntrospector { - @Override - void checkCompliance(Class mbeanType) {} - - @Override - List getMethods(final Class mbeanType) - throws Exception { - List methods = new ArrayList(); - for (Method m : mbeanType.getMethods()) { - String name = m.getName(); - Class ret = m.getReturnType(); - if (m.getParameterTypes().length == 0) { - if ((name.startsWith("is") && name.length() > 2 && - ret == boolean.class) || - (name.startsWith("get") && name.length() > 3 && - ret != void.class)) { - methods.add(m); - } - } - } - return methods; - } - - } - private static final MBeanIntrospector introspector = - new Introspector(); -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java --- a/src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.mbeanserver; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.DynamicMBean; -import javax.management.DynamicWrapperMBean; -import javax.management.InvalidAttributeValueException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanRegistration; -import javax.management.MBeanServer; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.ReflectionException; - -/** - * Create wrappers for DynamicMBean that implement NotificationEmitter - * and SendNotification. - */ -public class NotifySupport - implements DynamicMBean2, NotificationEmitter, MBeanRegistration { - - private final DynamicMBean mbean; - private final NotificationBroadcasterSupport nbs; - - public static DynamicMBean wrap( - DynamicMBean mbean, NotificationBroadcasterSupport nbs) { - return new NotifySupport(mbean, nbs); - } - - private NotifySupport(DynamicMBean mbean, NotificationBroadcasterSupport nbs) { - this.mbean = mbean; - this.nbs = nbs; - } - - public static NotificationBroadcasterSupport getNB(DynamicMBean mbean) { - if (mbean instanceof NotifySupport) - return ((NotifySupport) mbean).nbs; - else - return null; - } - - public String getClassName() { - if (mbean instanceof DynamicMBean2) - return ((DynamicMBean2) mbean).getClassName(); - Object w = mbean; - if (w instanceof DynamicWrapperMBean) - w = ((DynamicWrapperMBean) w).getWrappedObject(); - return w.getClass().getName(); - } - - public void preRegister2(MBeanServer mbs, ObjectName name) throws Exception { - if (mbean instanceof DynamicMBean2) - ((DynamicMBean2) mbean).preRegister2(mbs, name); - } - - public void registerFailed() { - if (mbean instanceof DynamicMBean2) - ((DynamicMBean2) mbean).registerFailed(); - } - - public Object getWrappedObject() { - if (mbean instanceof DynamicWrapperMBean) - return ((DynamicWrapperMBean) mbean).getWrappedObject(); - else - return mbean; - } - - public ClassLoader getWrappedClassLoader() { - if (mbean instanceof DynamicWrapperMBean) - return ((DynamicWrapperMBean) mbean).getWrappedClassLoader(); - else - return mbean.getClass().getClassLoader(); - } - - public Object getAttribute(String attribute) throws AttributeNotFoundException, - MBeanException, - ReflectionException { - return mbean.getAttribute(attribute); - } - - public void setAttribute(Attribute attribute) throws AttributeNotFoundException, - InvalidAttributeValueException, - MBeanException, - ReflectionException { - mbean.setAttribute(attribute); - } - - public AttributeList setAttributes(AttributeList attributes) { - return mbean.setAttributes(attributes); - } - - public Object invoke(String actionName, Object[] params, String[] signature) - throws MBeanException, ReflectionException { - return mbean.invoke(actionName, params, signature); - } - - public MBeanInfo getMBeanInfo() { - return mbean.getMBeanInfo(); - } - - public AttributeList getAttributes(String[] attributes) { - return mbean.getAttributes(attributes); - } - - public void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) throws ListenerNotFoundException { - nbs.removeNotificationListener(listener, filter, handback); - } - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - nbs.removeNotificationListener(listener); - } - - public MBeanNotificationInfo[] getNotificationInfo() { - return nbs.getNotificationInfo(); - } - - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) { - nbs.addNotificationListener(listener, filter, handback); - } - - public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { - if (mbr() != null) - return mbr().preRegister(server, name); - else - return name; - } - - public void postRegister(Boolean registrationDone) { - if (mbr() != null) - mbr().postRegister(registrationDone); - } - - public void preDeregister() throws Exception { - if (mbr() != null) - mbr().preDeregister(); - } - - public void postDeregister() { - if (mbr() != null) - mbr().postDeregister(); - } - - private MBeanRegistration mbr() { - if (mbean instanceof MBeanRegistration) - return (MBeanRegistration) mbean; - else - return null; - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java --- a/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java Wed Nov 25 22:14:30 2009 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-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 @@ -231,7 +231,7 @@ /** * Visitor that sets up the method maps (operations, getters, setters). */ - private class InitMaps implements MBeanAnalyzer.MBeanVisitor { + private class InitMaps implements MBeanAnalyzer.MBeanVisitor { public void visitAttribute(String attributeName, M getter, M setter) { diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/PerThreadGroupPool.java --- a/src/share/classes/com/sun/jmx/mbeanserver/PerThreadGroupPool.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright 1999-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. - */ - -package com.sun.jmx.mbeanserver; - -import java.lang.ref.WeakReference; -import java.util.concurrent.ThreadPoolExecutor; - -/** - *

A factory for ThreadPoolExecutor objects that allows the same object to - * be shared by all users of the factory that are in the same ThreadGroup.

- */ -// We return a ThreadPoolExecutor rather than the more general ExecutorService -// because we need to be able to call allowCoreThreadTimeout so that threads in -// the pool will eventually be destroyed when the pool is no longer in use. -// Otherwise these threads would keep the ThreadGroup alive forever. -public class PerThreadGroupPool { - private final WeakIdentityHashMap> map = - WeakIdentityHashMap.make(); - - public static interface Create { - public T createThreadPool(ThreadGroup group); - } - - private PerThreadGroupPool() {} - - public static PerThreadGroupPool make() { - return new PerThreadGroupPool(); - } - - public synchronized T getThreadPoolExecutor(Create create) { - // Find out if there's already an existing executor for the calling - // thread and reuse it. Otherwise, create a new one and store it in - // the executors map. If there is a SecurityManager, the group of - // System.getSecurityManager() is used, else the group of the calling - // thread. - SecurityManager s = System.getSecurityManager(); - ThreadGroup group = (s != null) ? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); - WeakReference wr = map.get(group); - T executor = (wr == null) ? null : wr.get(); - if (executor == null) { - executor = create.createThreadPool(group); - executor.allowCoreThreadTimeOut(true); - map.put(group, new WeakReference(executor)); - } - return executor; - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/Repository.java --- a/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Wed Nov 25 22:14:30 2009 -0800 @@ -396,7 +396,7 @@ // Set domain to default if domain is empty and not already set if (dom.length() == 0) - name = ObjectName.valueOf(domain + name.toString()); + name = Util.newObjectName(domain + name.toString()); // Do we have default domain ? if (dom == domain) { // ES: OK (dom & domain are interned) @@ -573,7 +573,7 @@ // Pattern matching in the domain name (*, ?) final String dom2Match = name.getDomain(); for (String dom : domainTb.keySet()) { - if (Util.wildpathmatch(dom, dom2Match)) { + if (Util.wildmatch(dom, dom2Match)) { final Map moiTb = domainTb.get(dom); if (allNames) result.addAll(moiTb.values()); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java --- a/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java Wed Nov 25 22:14:30 2009 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 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 @@ -35,7 +35,6 @@ import javax.management.MBeanAttributeInfo; import javax.management.MBeanException; import javax.management.MBeanOperationInfo; -import javax.management.ManagedOperation; import javax.management.NotCompliantMBeanException; import javax.management.NotificationBroadcaster; import javax.management.NotificationBroadcasterSupport; @@ -119,32 +118,22 @@ @Override MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, - Method getter, Method setter) throws IntrospectionException { + Method getter, Method setter) { - String description = getAttributeDescription( - attributeName, "Attribute exposed for management", - getter, setter); - return new MBeanAttributeInfo(attributeName, description, - getter, setter); + final String description = "Attribute exposed for management"; + try { + return new MBeanAttributeInfo(attributeName, description, + getter, setter); + } catch (IntrospectionException e) { + throw new RuntimeException(e); // should not happen + } } @Override MBeanOperationInfo getMBeanOperationInfo(String operationName, Method operation) { - final String defaultDescription = "Operation exposed for management"; - String description = Introspector.descriptionForElement(operation); - if (description == null) - description = defaultDescription; - - int impact = MBeanOperationInfo.UNKNOWN; - ManagedOperation annot = operation.getAnnotation(ManagedOperation.class); - if (annot != null) - impact = annot.impact().getCode(); - - MBeanOperationInfo mboi = new MBeanOperationInfo(description, operation); - return new MBeanOperationInfo( - mboi.getName(), mboi.getDescription(), mboi.getSignature(), - mboi.getReturnType(), impact, mboi.getDescriptor()); + final String description = "Operation exposed for management"; + return new MBeanOperationInfo(description, operation); } @Override diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java --- a/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java Wed Nov 25 22:14:30 2009 -0800 @@ -31,7 +31,6 @@ import javax.management.MBeanServer; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; -import javax.management.openmbean.MXBeanMappingFactory; /** * Base class for Standard MBeans. @@ -58,11 +57,11 @@ */ public StandardMBeanSupport(T resource, Class mbeanInterfaceType) throws NotCompliantMBeanException { - super(resource, mbeanInterfaceType, (MXBeanMappingFactory) null); + super(resource, mbeanInterfaceType); } @Override - MBeanIntrospector getMBeanIntrospector(MXBeanMappingFactory ignored) { + MBeanIntrospector getMBeanIntrospector() { return StandardMBeanIntrospector.getInstance(); } @@ -84,14 +83,13 @@ @Override public MBeanInfo getMBeanInfo() { MBeanInfo mbi = super.getMBeanInfo(); - Class resourceClass = getWrappedObject().getClass(); - if (!getMBeanInterface().isInterface() || - StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass)) + Class resourceClass = getResource().getClass(); + if (StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass)) return mbi; return new MBeanInfo(mbi.getClassName(), mbi.getDescription(), mbi.getAttributes(), mbi.getConstructors(), mbi.getOperations(), - MBeanIntrospector.findNotifications(getWrappedObject()), + MBeanIntrospector.findNotifications(getResource()), mbi.getDescriptor()); } } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/mbeanserver/Util.java --- a/src/share/classes/com/sun/jmx/mbeanserver/Util.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/mbeanserver/Util.java Wed Nov 25 22:14:30 2009 -0800 @@ -25,8 +25,6 @@ package com.sun.jmx.mbeanserver; -import com.sun.jmx.defaults.JmxProperties; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -40,25 +38,18 @@ import java.util.Map; import java.util.Set; import java.util.SortedMap; -import java.util.SortedSet; import java.util.TreeMap; -import java.util.TreeSet; -import java.util.WeakHashMap; -import java.util.logging.Level; -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerFactory; -import javax.management.ObjectInstance; +import javax.management.MalformedObjectNameException; import javax.management.ObjectName; -import javax.management.loading.ClassLoaderRepository; -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; public class Util { - private final static int NAMESPACE_SEPARATOR_LENGTH = - NAMESPACE_SEPARATOR.length(); - public final static char[] ILLEGAL_MBEANSERVER_NAME_CHARS=";:*?". - toCharArray(); - + public static ObjectName newObjectName(String string) { + try { + return new ObjectName(string); + } catch (MalformedObjectNameException e) { + throw new IllegalArgumentException(e); + } + } static Map newMap() { return new HashMap(); @@ -89,10 +80,6 @@ return new LinkedHashMap(); } - static WeakHashMap newWeakHashMap() { - return new WeakHashMap(); - } - static Set newSet() { return new HashSet(); } @@ -251,451 +238,4 @@ public static boolean wildmatch(String str, String pat) { return wildmatch(str,pat,0,str.length(),0,pat.length()); } - - /** - * Matches a string against a pattern, as a name space path. - * This is a special matching where * and ?? don't match //. - * The string is split in sub-strings separated by //, and the - * pattern is split in sub-patterns separated by //. Each sub-string - * is matched against its corresponding sub-pattern. - * so ////...// matches ////...// - * only if n==q and for ( i = 1 => n) elt-i matches pat-i. - * - * In addition, if we encounter a pattern element which is exactly - * **, it can match any number of path-elements - but it must match at - * least one element. - * When we encounter such a meta-wildcard, we remember its position - * and the position in the string path, and we advance both the pattern - * and the string. Later, if we encounter a mismatch in pattern & string, - * we rewind the position in pattern to just after the meta-wildcard, - * and we backtrack the string to i+1 element after the position - * we had when we first encountered the meta-wildcard, i being the - * position when we last backtracked the string. - * - * The backtracking logic is an adaptation of the logic in wildmatch - * above. - * See test/javax/mangement/ObjectName/ApplyWildcardTest.java - * - * Note: this thing is called 'wild' - and that's for a reason ;-) - **/ - public static boolean wildpathmatch(String str, String pat) { - final int strlen = str.length(); - final int patlen = pat.length(); - int stri = 0; - int pati = 0; - - int starstri; // index for backtrack if "**" attempt fails - int starpati; // index for backtrack if "**" attempt fails - - starstri = starpati = -1; - - while (true) { - // System.out.println("pati="+pati+", stri="+stri); - final int strend = str.indexOf(NAMESPACE_SEPARATOR, stri); - final int patend = pat.indexOf(NAMESPACE_SEPARATOR, pati); - - // no // remaining in either string or pattern: simple wildmatch - // until end of string. - if (strend == -1 && patend == -1) { - // System.out.println("last sub pattern, last sub element..."); - // System.out.println("wildmatch("+str.substring(stri,strlen)+ - // ","+pat.substring(pati,patlen)+")"); - return wildmatch(str,pat,stri,strlen,pati,patlen); - } - - // no // remaining in string, but at least one remaining in - // pattern - // => no match - if (strend == -1) { - // System.out.println("pattern has more // than string..."); - return false; - } - - // strend is != -1, but patend might. - // detect wildcard ** - if (patend == pati+2 && pat.charAt(pati)=='*' && - pat.charAt(pati+1)=='*') { - // if we reach here we know that neither strend nor patend are - // equals to -1. - stri = strend + NAMESPACE_SEPARATOR_LENGTH; - pati = patend + NAMESPACE_SEPARATOR_LENGTH; - starpati = pati; // position just after **// in pattern - starstri = stri; // we eat 1 element in string, and remember - // the position for backtracking and eating - // one more element if needed. - // System.out.println("starpati="+pati); - continue; - } - - // This is a bit hacky: * can match // when // is at the end - // of the string, so we include the // delimiter in the pattern - // matching. Either we're in the middle of the path, so including - // // both at the end of the pattern and at the end of the string - // has no effect - match(*//,dfsd//) is equivalent to match(*,dfsd) - // or we're at the end of the pattern path, in which case - // including // at the end of the string will have the desired - // effect (provided that we detect the end of matching correctly, - // see further on). - // - final int endpat = - ((patend > -1)?patend+NAMESPACE_SEPARATOR_LENGTH:patlen); - final int endstr = - ((strend > -1)?strend+NAMESPACE_SEPARATOR_LENGTH:strlen); - - // if we reach the end of the pattern, or if elt-i & pat-i - // don't match, we have a mismatch. - - // Note: we know that strend != -1, therefore patend==-1 - // indicates a mismatch unless pattern can match - // a // at the end, and strend+2=strlen. - // System.out.println("wildmatch("+str.substring(stri,endstr)+","+ - // pat.substring(pati,endpat)+")"); - if (!wildmatch(str,pat,stri,endstr,pati,endpat)) { - - // System.out.println("nomatch"); - // if we have a mismatch and didn't encounter any meta-wildcard, - // we return false. String & pattern don't match. - if (starpati < 0) return false; - - // If we reach here, we had a meta-wildcard. - // We need to backtrack to the wildcard, and make it eat an - // additional string element. - // - stri = str.indexOf(NAMESPACE_SEPARATOR, starstri); - // System.out.println("eating one additional element? "+stri); - - // If there's no more elements to eat, string and pattern - // don't match => return false. - if (stri == -1) return false; - - // Backtrack to where we were when we last matched against - // the meta-wildcard, make it eat an additional path element, - // remember the new positions, and continue from there... - // - stri = stri + NAMESPACE_SEPARATOR_LENGTH; - starstri = stri; - pati = starpati; - // System.out.println("skiping to stri="+stri); - continue; - } - - // Here we know that strend > -1 but we can have patend == -1. - // - // So if we reach here, we know pat-i+//? has matched - // elt-i+// - // - // If patend==-1, we know that there was no delimiter - // at the end of the pattern, that we are at the last pattern, - // and therefore that pat-i has matched elt-i+// - // - // In that case we can consider that we have a match only if - // elt-i is also the last path element in the string, which is - // equivalent to saying that strend+2==strlen. - // - if (patend == -1 && starpati == -1) - return (strend+NAMESPACE_SEPARATOR_LENGTH==strlen); - - // patend != -1, or starpati > -1 so there remains something - // to match. - - // go to next pair: elt-(i+1) pat-(i+1); - stri = strend + NAMESPACE_SEPARATOR_LENGTH; - pati = (patend==-1)?pati:(patend + NAMESPACE_SEPARATOR_LENGTH); - } - } - - /** - * Returns true if the ObjectName's {@code domain} is selected by the - * given {@code pattern}. - */ - public static boolean isDomainSelected(String domain, String pattern) { - if (domain == null || pattern == null) - throw new IllegalArgumentException("null"); - return Util.wildpathmatch(domain,pattern); - } - - /** - * Filters a set of ObjectName according to a given pattern. - * - * @param pattern the pattern that the returned names must match. - * @param all the set of names to filter. - * @return a set of ObjectName from which non matching names - * have been removed. - */ - public static Set filterMatchingNames(ObjectName pattern, - Set all) { - // If no pattern, just return all names - if (pattern == null - || all.isEmpty() - || ObjectName.WILDCARD.equals(pattern)) - return all; - - // If there's a pattern, do the matching. - final Set res = equivalentEmptySet(all); - for (ObjectName n : all) if (pattern.apply(n)) res.add(n); - return res; - } - - - /** - * Filters a set of ObjectInstance according to a given pattern. - * - * @param pattern the pattern that the returned names must match. - * @param all the set of instances to filter. - * @return a set of ObjectInstance from which non matching instances - * have been removed. - */ - public static Set - filterMatchingInstances(ObjectName pattern, - Set all) { - // If no pattern, just return all names - if (pattern == null - || all.isEmpty() - || ObjectName.WILDCARD.equals(pattern)) - return all; - - // If there's a pattern, do the matching. - final Set res = equivalentEmptySet(all); - for (ObjectInstance n : all) { - if (n == null) continue; - if (pattern.apply(n.getObjectName())) - res.add(n); - } - return res; - } - - /** - * An abstract ClassLoaderRepository that contains a single class loader. - **/ - private final static class SingleClassLoaderRepository - implements ClassLoaderRepository { - private final ClassLoader singleLoader; - - SingleClassLoaderRepository(ClassLoader loader) { - this.singleLoader = loader; - } - - ClassLoader getSingleClassLoader() { - return singleLoader; - } - - private Class loadClass(String className, ClassLoader loader) - throws ClassNotFoundException { - return Class.forName(className, false, loader); - } - - public Class loadClass(String className) - throws ClassNotFoundException { - return loadClass(className, getSingleClassLoader()); - } - - public Class loadClassWithout(ClassLoader exclude, - String className) throws ClassNotFoundException { - final ClassLoader loader = getSingleClassLoader(); - if (exclude != null && exclude.equals(loader)) - throw new ClassNotFoundException(className); - return loadClass(className, loader); - } - - public Class loadClassBefore(ClassLoader stop, String className) - throws ClassNotFoundException { - return loadClassWithout(stop, className); - } - } - - /** - * Returns a ClassLoaderRepository that contains a single class loader. - * @param loader the class loader contained in the returned repository. - * @return a ClassLoaderRepository that contains the single loader. - */ - public static ClassLoaderRepository getSingleClassLoaderRepository( - final ClassLoader loader) { - return new SingleClassLoaderRepository(loader); - } - - /** - * Returns the name of the given MBeanServer that should be put in a - * permission you need. - * This corresponds to the - * {@code *[;mbeanServerName=[;*]]} property - * embedded in the MBeanServerId attribute of the - * server's {@link MBeanServerDelegate}. - * - * @param server The MBean server - * @return the name of the MBeanServer, or "*" if the name couldn't be - * obtained, or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} - * if there was no name. - */ - public static String getMBeanServerSecurityName(MBeanServer server) { - final String notfound = "*"; - try { - final String mbeanServerId = (String) - server.getAttribute(MBeanServerDelegate.DELEGATE_NAME, - "MBeanServerId"); - final String found = extractMBeanServerName(mbeanServerId); - if (found.length()==0) - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME; - return found; - } catch (Exception x) { - logshort("Failed to retrieve MBeanServerName for server, " + - "using \"*\"",x); - return notfound; - } - } - - /** - * Returns the name of the MBeanServer embedded in the given - * mbeanServerId. If the given mbeanServerId doesn't contain any name, - * an empty String is returned. - * The MBeanServerId is expected to be of the form: - * {@code *[;mbeanServerName=[;*]]} - * @param mbeanServerId The MBean server ID - * @return the name of the MBeanServer if found, or "" if the name was - * not present in the mbeanServerId. - */ - public static String extractMBeanServerName(String mbeanServerId) { - if (mbeanServerId==null) return ""; - final String beginMarker=";mbeanServerName="; - final String endMarker=";"; - final int found = mbeanServerId.indexOf(beginMarker); - if (found < 0) return ""; - final int start = found + beginMarker.length(); - final int stop = mbeanServerId.indexOf(endMarker, start); - return mbeanServerId.substring(start, - (stop < 0 ? mbeanServerId.length() : stop)); - } - - /** - * Insert the given mbeanServerName into the given mbeanServerId. - * If mbeanServerName is null, empty, or equals to "-", the returned - * mbeanServerId will not contain any mbeanServerName. - * @param mbeanServerId The mbeanServerId in which to insert - * mbeanServerName - * @param mbeanServerName The mbeanServerName - * @return an mbeanServerId containing the given mbeanServerName - * @throws IllegalArgumentException if mbeanServerId already contains - * a different name, or if the given mbeanServerName is not valid. - */ - public static String insertMBeanServerName(String mbeanServerId, - String mbeanServerName) { - final String found = extractMBeanServerName(mbeanServerId); - if (found.length() > 0 && - found.equals(checkServerName(mbeanServerName))) - return mbeanServerId; - if (found.length() > 0 && !isMBeanServerNameUndefined(found)) - throw new IllegalArgumentException( - "MBeanServerName already defined"); - if (isMBeanServerNameUndefined(mbeanServerName)) - return mbeanServerId; - final String beginMarker=";mbeanServerName="; - return mbeanServerId+beginMarker+checkServerName(mbeanServerName); - } - - /** - * Returns true if the given mbeanServerName corresponds to an - * undefined MBeanServerName. - * The mbeanServerName is considered undefined if it is one of: - * {@code null} or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}. - * @param mbeanServerName The mbeanServerName, as returned by - * {@link #extractMBeanServerName(String)}. - * @return true if the given name corresponds to one of the forms that - * denotes an undefined MBeanServerName. - */ - public static boolean isMBeanServerNameUndefined(String mbeanServerName) { - return mbeanServerName == null || - MBeanServerFactory.DEFAULT_MBEANSERVER_NAME.equals(mbeanServerName); - } - /** - * Check that the provided mbeanServername is syntactically valid. - * @param mbeanServerName An mbeanServerName, or {@code null}. - * @return mbeanServerName, or {@value - * MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if {@code mbeanServerName} - * is {@code null}. - * @throws IllegalArgumentException if mbeanServerName contains illegal - * characters, or is empty, or is {@code "-"}. - * Illegal characters are {@link #ILLEGAL_MBEANSERVER_NAME_CHARS}. - */ - public static String checkServerName(String mbeanServerName) { - if ("".equals(mbeanServerName)) - throw new IllegalArgumentException( - "\"\" is not a valid MBean server name"); - if ("-".equals(mbeanServerName)) - throw new IllegalArgumentException( - "\"-\" is not a valid MBean server name"); - if (isMBeanServerNameUndefined(mbeanServerName)) - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME; - for (char c : ILLEGAL_MBEANSERVER_NAME_CHARS) { - if (mbeanServerName.indexOf(c) >= 0) - throw new IllegalArgumentException( - "invalid character in MBeanServer name: "+c); - } - return mbeanServerName; - } - - /** - * Get the MBeanServer name that should be put in a permission you need. - * - * @param delegate The MBeanServerDelegate - * @return The MBeanServer name - or {@value - * MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if there was no name. - */ - public static String getMBeanServerSecurityName( - MBeanServerDelegate delegate) { - try { - final String serverName = delegate.getMBeanServerName(); - if (isMBeanServerNameUndefined(serverName)) - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME; - return serverName; - } catch (Exception x) { - logshort("Failed to retrieve MBeanServerName from delegate, " + - "using \"*\"",x); - return "*"; - } - } - - // Log the exception and its causes without logging the stack trace. - // Use with care - it is usually preferable to log the whole stack trace! - // We don't want to log the whole stack trace here: logshort() is - // called in those cases where the exception might not be abnormal. - private static void logshort(String msg, Throwable t) { - if (JmxProperties.MISC_LOGGER.isLoggable(Level.FINE)) { - StringBuilder toprint = new StringBuilder(msg); - do { - toprint.append("\nCaused By: ").append(String.valueOf(t)); - } while ((t=t.getCause())!=null); - JmxProperties.MISC_LOGGER.fine(toprint.toString()); - } - } - - public static Set cloneSet(Set set) { - if (set instanceof SortedSet) { - @SuppressWarnings("unchecked") - SortedSet sset = (SortedSet) set; - set = new TreeSet(sset.comparator()); - set.addAll(sset); - } else - set = new HashSet(set); - return set; - } - - public static Set equivalentEmptySet(Set set) { - if (set instanceof SortedSet) { - @SuppressWarnings("unchecked") - SortedSet sset = (SortedSet) set; - set = new TreeSet(sset.comparator()); - } else - set = new HashSet(); - return set; - } - - // This exception is used when wrapping a class that throws IOException - // in a class that doesn't. - // The typical example for this are JMXNamespaces, when the sub - // MBeanServer can be remote. - // - public static RuntimeException newRuntimeIOException(IOException io) { - final String msg = "Communication failed with underlying resource: "+ - io.getMessage(); - return new RuntimeException(msg,io); - } } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java --- a/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,463 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.mbeanserver.Util; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Queue; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanPermission; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerNotification; -import javax.management.Notification; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.QueryExp; -import javax.management.namespace.JMXDomain; - -/** - * A DomainInterceptor wraps a JMXDomain. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class DomainInterceptor extends HandlerInterceptor { - - // TODO: Ideally DomainInterceptor should be replaced by - // something at Repository level. - // The problem there will be that we may need to - // reinstantiate the 'queryPerformedByRepos' boolean - // [or we will need to wrap the repository in - // a 'RepositoryInterceptor'?] - // Also there's no real need for a DomainInterceptor to - // extend RewritingMBeanServerConnection. - - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - private final String domainName; - private volatile ObjectName ALL; - private final String serverName; - private volatile NotificationListener mbsListener; - - private static class PatternNotificationFilter - implements NotificationFilter { - - final ObjectName pattern; - public PatternNotificationFilter(ObjectName pattern) { - this.pattern = pattern==null?ObjectName.WILDCARD:pattern; - } - - public boolean isNotificationEnabled(Notification notification) { - if (!(notification instanceof MBeanServerNotification)) - return false; - final MBeanServerNotification mbsn = - (MBeanServerNotification) notification; - if (pattern.apply(mbsn.getMBeanName())) - return true; - return false; - } - - static final long serialVersionUID = 7409950927025262111L; - } - - /** - * Creates a new instance of NamespaceInterceptor - */ - public DomainInterceptor(String serverName, - JMXDomain handler, - String domainName) { - super(handler); - this.domainName = domainName; - this.serverName = serverName; - ALL = ObjectName.valueOf(domainName+":*"); - } - - @Override - public String toString() { - return this.getClass().getName()+"(parent="+serverName+ - ", domain="+this.domainName+")"; - } - - final void connectDelegate(final MBeanServerDelegate delegate) - throws InstanceNotFoundException { - final NotificationFilter filter = - new PatternNotificationFilter(getPatternFor(null)); - synchronized (this) { - if (mbsListener == null) { - mbsListener = new NotificationListener() { - public void handleNotification(Notification notification, - Object handback) { - if (filter.isNotificationEnabled(notification)) - delegate.sendNotification(notification); - } - }; - } - } - - getHandlerInterceptorMBean(). - addMBeanServerNotificationListener(mbsListener, filter); - } - - final void disconnectDelegate() - throws InstanceNotFoundException, ListenerNotFoundException { - final NotificationListener l; - synchronized (this) { - l = mbsListener; - if (l == null) return; - mbsListener = null; - } - getHandlerInterceptorMBean().removeMBeanServerNotificationListener(l); - } - - public final void addPostRegisterTask(Queue queue, - final MBeanServerDelegate delegate) { - if (queue == null) - throw new IllegalArgumentException("task queue must not be null"); - final Runnable task1 = new Runnable() { - public void run() { - try { - connectDelegate(delegate); - } catch (Exception x) { - throw new UnsupportedOperationException( - "notification forwarding",x); - } - } - }; - queue.add(task1); - } - - public final void addPostDeregisterTask(Queue queue, - final MBeanServerDelegate delegate) { - if (queue == null) - throw new IllegalArgumentException("task queue must not be null"); - final Runnable task1 = new Runnable() { - public void run() { - try { - disconnectDelegate(); - } catch (Exception x) { - throw new UnsupportedOperationException( - "notification forwarding",x); - } - } - }; - queue.add(task1); - } - - // No name conversion for JMXDomains... - // Throws IllegalArgumentException if targetName.getDomain() is not - // in the domain handled. - // - @Override - protected ObjectName toSource(ObjectName targetName) { - if (targetName == null) return null; - if (targetName.isDomainPattern()) return targetName; - final String targetDomain = targetName.getDomain(); - - // TODO: revisit this. RuntimeOperationsException may be better? - // - if (!targetDomain.equals(domainName)) - throw new IllegalArgumentException(targetName.toString()); - return targetName; - } - - // No name conversion for JMXDomains... - @Override - protected ObjectName toTarget(ObjectName sourceName) { - return sourceName; - } - - - - /** - * No rewriting: always return sources - stripping instances for which - * the caller doesn't have permissions. - **/ - @Override - Set processOutputInstances(Set sources) { - if (sources == null || sources.isEmpty() || !checkOn()) - return sources; - final Set res = Util.equivalentEmptySet(sources); - for (ObjectInstance o : sources) { - if (checkQuery(o.getObjectName(), "queryMBeans")) - res.add(o); - } - return res; - } - - - /** - * No rewriting: always return sourceNames - stripping names for which - * the caller doesn't have permissions. - **/ - @Override - Set processOutputNames(Set sourceNames) { - if (sourceNames == null || sourceNames.isEmpty() || !checkOn()) - return sourceNames; - final Set res = Util.equivalentEmptySet(sourceNames); - for (ObjectName o : sourceNames) { - if (checkQuery(o, "queryNames")) - res.add(o); - } - return res; - } - - /** No rewriting: always return source **/ - @Override - ObjectInstance processOutputInstance(ObjectInstance source) { - return source; - } - - @Override - public Set queryNames(ObjectName name, QueryExp query) { - try { - // We don't trust the wrapped JMXDomain... - final ObjectName pattern = getPatternFor(name); - final Set res = super.queryNames(pattern,query); - return Util.filterMatchingNames(pattern,res); - } catch (Exception x) { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("Unexpected exception raised in queryNames: "+x); - LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x); - return Collections.emptySet(); - } - } - - // Compute a new pattern which is a sub pattern of 'name' but only selects - // the MBeans in domain 'domainName' - // When we reach here, it has been verified that 'name' matches our domain - // name (done by DomainDispatchInterceptor) - private ObjectName getPatternFor(final ObjectName name) { - if (name == null) return ALL; - if (name.getDomain().equals(domainName)) return name; - return name.withDomain(domainName); - } - - @Override - public Set queryMBeans(ObjectName name, QueryExp query) { - try { - // We don't trust the wrapped JMXDomain... - final ObjectName pattern = getPatternFor(name); - final Set res = super.queryMBeans(pattern,query); - return Util.filterMatchingInstances(pattern,res); - } catch (Exception x) { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("Unexpected exception raised in queryNames: "+x); - LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x); - return Collections.emptySet(); - } - } - - @Override - public String getDefaultDomain() { - return domainName; - } - - @Override - public String[] getDomains() { - return new String[] {domainName}; - } - - // We call getMBeanCount() on the namespace rather than on the - // source server in order to avoid counting MBeans which are not - // in the domain. - @Override - public Integer getMBeanCount() { - return getHandlerInterceptorMBean().getMBeanCount(); - } - - private boolean checkOn() { - final SecurityManager sm = System.getSecurityManager(); - return (sm != null); - } - - // - // Implements permission checks. - // - @Override - void check(ObjectName routingName, String member, String action) { - if (!checkOn()) return; - final String act = (action==null)?"-":action; - if("queryMBeans".equals(act) || "queryNames".equals(act)) { - // This is tricky. check with 3 parameters is called - // by queryNames/queryMBeans before performing the query. - // At this point we must check with no class name. - // Therefore we pass a className of "-". - // The filtering will be done later - processOutputNames and - // processOutputInstance will call checkQuery. - // - check(routingName, "-", "-", act); - } else { - // This is also tricky: - // passing null here will cause check to retrieve the classname, - // if needed. - check(routingName, null, member, act); - } - } - - // - // Implements permission checks. - // - @Override - void checkCreate(ObjectName routingName, String className, String action) { - if (!checkOn()) return; - check(routingName,className,"-",action); - } - - // - // Implements permission checks. - // - void check(ObjectName routingName, String className, String member, - String action) { - if (!checkOn()) return; - final MBeanPermission perm; - - final String act = (action==null)?"-":action; - if ("getDomains".equals(act)) { // ES: OK - perm = new MBeanPermission(serverName,"-",member, - routingName,act); - } else { - final String clazz = - (className==null)?getClassName(routingName):className; - perm = new MBeanPermission(serverName,clazz,member, - routingName,act); - } - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(perm); - } - - String getClassName(ObjectName routingName) { - if (routingName == null || routingName.isPattern()) return "-"; - try { - return getHandlerInterceptorMBean().getSourceServer(). - getObjectInstance(routingName).getClassName(); - } catch (InstanceNotFoundException ex) { - LOG.finest("Can't get class name for "+routingName+ - ", using \"-\". Cause is: "+ex); - return "-"; - } - } - - // - // Implements permission filters for attributes... - // - @Override - AttributeList checkAttributes(ObjectName routingName, - AttributeList attributes, String action) { - if (!checkOn()) return attributes; - final String className = getClassName(routingName); - check(routingName,className,"-",action); - if (attributes == null || attributes.isEmpty()) return attributes; - final AttributeList res = new AttributeList(); - for (Attribute at : attributes.asList()) { - try { - check(routingName,className,at.getName(),action); - res.add(at); - } catch (SecurityException x) { // DLS: OK - continue; - } - } - return res; - } - - // - // Implements permission filters for attributes... - // - @Override - String[] checkAttributes(ObjectName routingName, String[] attributes, - String action) { - if (!checkOn()) return attributes; - final String className = getClassName(routingName); - check(routingName,className,"-",action); - if (attributes == null || attributes.length==0) return attributes; - final List res = new ArrayList(attributes.length); - for (String at : attributes) { - try { - check(routingName,className,at,action); - res.add(at); - } catch (SecurityException x) { // DLS: OK - continue; - } - } - return res.toArray(new String[res.size()]); - } - - // - // Implements permission filters for domains... - // - @Override - String[] checkDomains(String[] domains, String action) { - if (domains == null || domains.length==0 || !checkOn()) - return domains; - int count=0; - for (int i=0;i - * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public abstract class HandlerInterceptor - extends RoutingMBeanServerConnection - implements MBeanServerInterceptor { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - // The wrapped JMXNamespace - private final T handler; - - /** - * Creates a new instance of HandlerInterceptor - */ - public HandlerInterceptor(T handler) { - if (handler == null) throw new IllegalArgumentException("null"); - this.handler = handler; - } - - // - // The {@code source} connection is a connection to the MBeanServer - // that contains the actual MBeans. - // In the case of cascading, that would be a connection to the sub - // agent. Practically, this is JMXNamespace.getSourceServer(); - // - @Override - protected MBeanServer source() { - return handler.getSourceServer(); - } - - // The MBeanServer on which getClassLoader / getClassLoaderFor - // will be called. - // The NamespaceInterceptor overrides this method - so that it - // getClassLoader / getClassLoaderFor don't trigger the loop - // detection mechanism. - // - MBeanServer getServerForLoading() { - return source(); - } - - // The namespace or domain handler - this either a JMXNamespace or a - // a JMXDomain - T getHandlerInterceptorMBean() { - return handler; - } - - // If the underlying JMXNamespace throws an IO, the IO will be - // wrapped in a RuntimeOperationsException. - RuntimeException handleIOException(IOException x,String fromMethodName, - Object... params) { - // Must do something here? - if (LOG.isLoggable(Level.FINEST)) { - LOG.finest("IO Exception in "+fromMethodName+": "+x+ - " - "+" rethrowing as RuntimeOperationsException."); - } - throw new RuntimeOperationsException( - Util.newRuntimeIOException(x)); - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException { - try { - final String[] authorized = - checkAttributes(name,attributes,"getAttribute"); - final AttributeList attrList = - super.getAttributes(name,authorized); - return attrList; - } catch (IOException ex) { - throw handleIOException(ex,"getAttributes",name,attributes); - } - } - - // From MBeanServer - public ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - final ObjectName sourceName = toSourceOrRuntime(mbeanName); - try { - check(mbeanName,null,"getClassLoaderFor"); - return getServerForLoading().getClassLoaderFor(sourceName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - - // From MBeanServer - public ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - final ObjectName sourceName = toSourceOrRuntime(loaderName); - try { - check(loaderName,null,"getClassLoader"); - return getServerForLoading().getClassLoader(sourceName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // From MBeanServer - public ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, MBeanRegistrationException, - NotCompliantMBeanException { - final ObjectName sourceName = newSourceMBeanName(name); - try { - checkCreate(name,object.getClass().getName(),"registerMBean"); - return processOutputInstance( - source().registerMBean(object,sourceName)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void removeNotificationListener(ObjectName name, ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - check(name,null,"removeNotificationListener"); - super.removeNotificationListener(name,listener); - } catch (IOException ex) { - throw handleIOException(ex,"removeNotificationListener",name,listener); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public String getDefaultDomain() { - try { - return super.getDefaultDomain(); - } catch (IOException ex) { - throw handleIOException(ex,"getDefaultDomain"); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public String[] getDomains() { - try { - check(null,null,"getDomains"); - final String[] domains = super.getDomains(); - return checkDomains(domains,"getDomains"); - } catch (IOException ex) { - throw handleIOException(ex,"getDomains"); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Integer getMBeanCount() { - try { - return super.getMBeanCount(); - } catch (IOException ex) { - throw handleIOException(ex,"getMBeanCount"); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException { - try { - check(name, - (attribute==null?null:attribute.getName()), - "setAttribute"); - super.setAttribute(name,attribute); - } catch (IOException ex) { - throw handleIOException(ex,"setAttribute",name, attribute); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Set queryNames(ObjectName name, QueryExp query) { - if (name == null) name=ObjectName.WILDCARD; - try { - checkPattern(name,null,"queryNames"); - return super.queryNames(name,query); - } catch (IOException ex) { - throw handleIOException(ex,"queryNames",name, query); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Set queryMBeans(ObjectName name, QueryExp query) { - if (name == null) name=ObjectName.WILDCARD; - try { - checkPattern(name,null,"queryMBeans"); - return super.queryMBeans(name,query); - } catch (IOException ex) { - throw handleIOException(ex,"queryMBeans",name, query); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - try { - check(name, null, "isInstanceOf"); - return super.isInstanceOf(name, className); - } catch (IOException ex) { - throw handleIOException(ex,"isInstanceOf",name, className); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - try { - checkCreate(name, className, "instantiate"); - checkCreate(name, className, "registerMBean"); - return super.createMBean(className, name); - } catch (IOException ex) { - throw handleIOException(ex,"createMBean",className, name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - try { - checkCreate(name, className, "instantiate"); - checkCreate(name, className, "registerMBean"); - return super.createMBean(className, name, loaderName); - } catch (IOException ex) { - throw handleIOException(ex,"createMBean",className, name, loaderName); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Object getAttribute(ObjectName name, String attribute) - throws MBeanException, AttributeNotFoundException, - InstanceNotFoundException, ReflectionException { - try { - check(name, attribute, "getAttribute"); - return super.getAttribute(name, attribute); - } catch (IOException ex) { - throw handleIOException(ex,"getAttribute",name, attribute); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void removeNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - check(name,null,"removeNotificationListener"); - super.removeNotificationListener(name, listener, filter, handback); - } catch (IOException ex) { - throw handleIOException(ex,"removeNotificationListener",name, - listener, filter, handback); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - check(name,null,"removeNotificationListener"); - super.removeNotificationListener(name, listener, filter, handback); - } catch (IOException ex) { - throw handleIOException(ex,"removeNotificationListener",name, - listener, filter, handback); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - check(name,null,"removeNotificationListener"); - super.removeNotificationListener(name, listener); - } catch (IOException ex) { - throw handleIOException(ex,"removeNotificationListener",name, - listener); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void addNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) throws InstanceNotFoundException { - try { - check(name,null,"addNotificationListener"); - super.addNotificationListener(name, listener, filter, handback); - } catch (IOException ex) { - throw handleIOException(ex,"addNotificationListener",name, - listener, filter, handback); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void addNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException { - try { - check(name,null,"addNotificationListener"); - super.addNotificationListener(name, listener, filter, handback); - } catch (IOException ex) { - throw handleIOException(ex,"addNotificationListener",name, - listener, filter, handback); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public boolean isRegistered(ObjectName name) { - try { - return super.isRegistered(name); - } catch (IOException ex) { - throw handleIOException(ex,"isRegistered",name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { - try { - check(name, null, "unregisterMBean"); - super.unregisterMBean(name); - } catch (IOException ex) { - throw handleIOException(ex,"unregisterMBean",name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException { - try { - check(name, null, "getMBeanInfo"); - return super.getMBeanInfo(name); - } catch (IOException ex) { - throw handleIOException(ex,"getMBeanInfo",name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - try { - check(name, null, "getObjectInstance"); - return super.getObjectInstance(name); - } catch (IOException ex) { - throw handleIOException(ex,"getObjectInstance",name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance createMBean(String className, ObjectName name, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - try { - checkCreate(name, className, "instantiate"); - checkCreate(name, className, "registerMBean"); - return super.createMBean(className, name, params, signature); - } catch (IOException ex) { - throw handleIOException(ex,"createMBean",className, name, - params, signature); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName, Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - try { - checkCreate(name, className, "instantiate"); - checkCreate(name, className, "registerMBean"); - return super.createMBean(className, name, loaderName, params, - signature); - } catch (IOException ex) { - throw handleIOException(ex,"createMBean",className, name,loaderName, - params, signature); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public AttributeList setAttributes(ObjectName name,AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - try { - final AttributeList authorized = - checkAttributes(name, attributes, "setAttribute"); - return super.setAttributes(name, authorized); - } catch (IOException ex) { - throw handleIOException(ex,"setAttributes",name, attributes); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Object invoke(ObjectName name, String operationName, Object[] params, - String[] signature) - throws InstanceNotFoundException, MBeanException, ReflectionException { - try { - check(name, operationName, "invoke"); - return super.invoke(name, operationName, params, signature); - } catch (IOException ex) { - throw handleIOException(ex,"invoke",name, operationName, - params, signature); - } - } - - // - // These methods are inherited from MBeanServer.... - // - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className) - throws ReflectionException, MBeanException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported instantiate method: " + - "trowing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, ObjectName loaderName) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: instantiate(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, Object[] params, - String[] signature) throws ReflectionException, MBeanException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: instantiate(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, ObjectName loaderName, - Object[] params, String[] signature) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: instantiate(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(ObjectName name, byte[] data) - throws InstanceNotFoundException, OperationsException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: deserialize(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(String className, byte[] data) - throws OperationsException, ReflectionException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: deserialize(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(String className, - ObjectName loaderName, byte[] data) - throws InstanceNotFoundException, OperationsException, - ReflectionException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: deserialize(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public ClassLoaderRepository getClassLoaderRepository() { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: getClassLoaderRepository() -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - static RuntimeException newUnsupportedException(String namespace) { - return new RuntimeOperationsException( - new UnsupportedOperationException( - "Not supported in this namespace: "+namespace)); - } - - /** - * A result might be excluded for security reasons. - */ - @Override - boolean excludesFromResult(ObjectName targetName, String queryMethod) { - return !checkQuery(targetName, queryMethod); - } - - - //---------------------------------------------------------------------- - // Hooks for checking permissions - //---------------------------------------------------------------------- - - /** - * This method is a hook to implement permission checking in subclasses. - * A subclass may override this method and throw a {@link - * SecurityException} if the permission is denied. - * - * @param routingName The name of the MBean in the enclosing context. - * This is of the form {@code //}. - * @param member The {@link - * javax.management.namespace.JMXNamespacePermission#getMember member} - * name. - * @param action The {@link - * javax.management.namespace.JMXNamespacePermission#getActions action} - * name. - * @throws SecurityException if the caller doesn't have the permission - * to perform the given action on the MBean pointed to - * by routingName. - */ - abstract void check(ObjectName routingName, - String member, String action); - - // called in createMBean and registerMBean - abstract void checkCreate(ObjectName routingName, String className, - String action); - - /** - * This is a hook to implement permission checking in subclasses. - * - * Checks that the caller has sufficient permission for returning - * information about {@code sourceName} in {@code action}. - * - * Subclass may override this method and return false if the caller - * doesn't have sufficient permissions. - * - * @param routingName The name of the MBean to include or exclude from - * the query, expressed in the enclosing context. - * This is of the form {@code //}. - * @param action one of "queryNames" or "queryMBeans" - * @return true if {@code sourceName} can be returned. - */ - abstract boolean checkQuery(ObjectName routingName, String action); - - /** - * This method is a hook to implement permission checking in subclasses. - * - * @param routingName The name of the MBean in the enclosing context. - * This is of the form {@code //}. - * @param attributes The list of attributes to check permission for. - * @param action one of "getAttribute" or "setAttribute" - * @return The list of attributes for which the callers has the - * appropriate {@link - * javax.management.namespace.JMXNamespacePermission}. - * @throws SecurityException if the caller doesn't have the permission - * to perform {@code action} on the MBean pointed to by routingName. - */ - abstract String[] checkAttributes(ObjectName routingName, - String[] attributes, String action); - - /** - * This method is a hook to implement permission checking in subclasses. - * - * @param routingName The name of the MBean in the enclosing context. - * This is of the form {@code //}. - * @param attributes The list of attributes to check permission for. - * @param action one of "getAttribute" or "setAttribute" - * @return The list of attributes for which the callers has the - * appropriate {@link - * javax.management.namespace.JMXNamespacePermission}. - * @throws SecurityException if the caller doesn't have the permission - * to perform {@code action} on the MBean pointed to by routingName. - */ - abstract AttributeList checkAttributes(ObjectName routingName, - AttributeList attributes, String action); - - /** - * This method is a hook to implement permission checking in subclasses. - * Checks that the caller as the necessary permissions to view the - * given domain. If not remove the domains for which the caller doesn't - * have permission from the list. - *

- * By default, this method always returns {@code domains} - * - * @param domains The domains to return. - * @param action "getDomains" - * @return a filtered list of domains. - */ - String[] checkDomains(String[] domains, String action) { - return domains; - } - - // A priori check for queryNames/queryMBeans/ - void checkPattern(ObjectName routingPattern, - String member, String action) { - // pattern is checked only at posteriori by checkQuery. - // checking it a priori usually doesn't work, because ObjectName.apply - // does not work between two patterns. - // We only check that we have the permission requested for 'action'. - check(null,null,action); - } - - - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java --- a/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,220 +0,0 @@ -/* - * Copyright 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. - */ -package com.sun.jmx.namespace; - -import java.util.ArrayList; -import java.util.List; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.MBeanServer; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespacePermission; - -/** - * A NamespaceInterceptor wraps a JMXNamespace, performing - * ObjectName rewriting. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class NamespaceInterceptor extends HandlerInterceptor { - - - // The target name space in which the NamepsaceHandler is mounted. - private final String targetNs; - - private final String serverName; - - private final ObjectNameRouter proc; - - /** - * Creates a new instance of NamespaceInterceptor - */ - public NamespaceInterceptor( - String serverName, - JMXNamespace handler, - String targetNamespace) { - super(handler); - this.serverName = serverName; - this.targetNs = - ObjectNameRouter.normalizeNamespacePath(targetNamespace, - true, true, false); - proc = new ObjectNameRouter(targetNamespace, ""); - } - - @Override - public String toString() { - return this.getClass().getName()+"(parent="+serverName+ - ", namespace="+this.targetNs+")"; - } - - /** - * This method will send a probe to detect self-linking name spaces. - * A self linking namespace is a namespace that links back directly - * on itslef. Calling a method on such a name space always results - * in an infinite loop going through: - * [1]MBeanServer -> [2]NamespaceDispatcher -> [3]NamespaceInterceptor - * [4]JMXNamespace -> { network // or cd // or ... } -> [5]MBeanServer - * with exactly the same request than [1]... - * - * The namespace interceptor [2] tries to detect such condition the - * *first time* that the connection is used. It does so by setting - * a flag, and sending a queryNames() through the name space. If the - * queryNames comes back, it knows that there's a loop. - * - * The DynamicProbe interface can also be used by a Sun JMXNamespace - * implementation to request the emission of a probe at any time - * (see JMXRemoteNamespace implementation). - */ - private MBeanServer connection() { - final MBeanServer c = super.source(); - if (c != null) return c; - // should not come here - throw new NullPointerException("getMBeanServerConnection"); - } - - - @Override - protected MBeanServer source() { - return connection(); - } - - @Override - protected MBeanServer getServerForLoading() { - // don't want to send probe on getClassLoader/getClassLoaderFor - return super.source(); - } - - @Override - protected ObjectName toSource(ObjectName targetName) { - return proc.toSourceContext(targetName, true); - } - - @Override - protected ObjectName toTarget(ObjectName sourceName) { - return proc.toTargetContext(sourceName, false); - } - - // - // Implements permission checks. - // - @Override - void check(ObjectName routingName, String member, String action) { - final SecurityManager sm = System.getSecurityManager(); - if (sm == null) return; - if ("getDomains".equals(action)) return; - final JMXNamespacePermission perm = - new JMXNamespacePermission(serverName,member, - routingName,action); - sm.checkPermission(perm); - } - - @Override - void checkCreate(ObjectName routingName, String className, String action) { - final SecurityManager sm = System.getSecurityManager(); - if (sm == null) return; - final JMXNamespacePermission perm = - new JMXNamespacePermission(serverName,className, - routingName,action); - sm.checkPermission(perm); - } - - // - // Implements permission filters for attributes... - // - @Override - AttributeList checkAttributes(ObjectName routingName, - AttributeList attributes, String action) { - check(routingName,null,action); - if (attributes == null || attributes.isEmpty()) return attributes; - final SecurityManager sm = System.getSecurityManager(); - if (sm == null) return attributes; - final AttributeList res = new AttributeList(); - for (Attribute at : attributes.asList()) { - try { - check(routingName,at.getName(),action); - res.add(at); - } catch (SecurityException x) { // DLS: OK - continue; - } - } - return res; - } - - // - // Implements permission filters for attributes... - // - @Override - String[] checkAttributes(ObjectName routingName, String[] attributes, - String action) { - check(routingName,null,action); - if (attributes == null || attributes.length==0) return attributes; - final SecurityManager sm = System.getSecurityManager(); - if (sm == null) return attributes; - final List res = new ArrayList(attributes.length); - for (String at : attributes) { - try { - check(routingName,at,action); - res.add(at); - } catch (SecurityException x) { // DLS: OK - continue; - } - } - return res.toArray(new String[res.size()]); - } - - // - // Implements permission filters for domains... - // - @Override - String[] checkDomains(String[] domains, String action) { - // in principle, this method is never called because - // getDomains() will never be called - since there's - // no way that MBeanServer.getDomains() can be routed - // to a NamespaceInterceptor. - // - // This is also why there's no getDomains() in a - // JMXNamespacePermission... - // - return super.checkDomains(domains, action); - } - - // - // Implements permission filters for queries... - // - @Override - boolean checkQuery(ObjectName routingName, String action) { - try { - check(routingName,null,action); - return true; - } catch (SecurityException x) { // DLS: OK - return false; - } - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java --- a/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace; - -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * The ObjectNameRouter is used to rewrite routing object names. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class ObjectNameRouter { - - private static final int NAMESPACE_SEPARATOR_LENGTH = - NAMESPACE_SEPARATOR.length(); - - final String targetPrefix; - final String sourcePrefix; - final int slen; - final int tlen; - final boolean identity; - - /** Creates a new instance of ObjectNameRouter */ - public ObjectNameRouter(final String remove, final String add) { - this.targetPrefix = (remove==null?"":remove); - this.sourcePrefix = (add==null?"":add); - tlen = targetPrefix.length(); - slen = sourcePrefix.length(); - identity = targetPrefix.equals(sourcePrefix); - } - - public final ObjectName toTargetContext(ObjectName sourceName, - boolean removeLeadingSeparators) { - if (sourceName == null) return null; - if (identity) return sourceName; - String srcDomain = sourceName.getDomain(); - - // if the ObjectName starts with // and removeLeadingSeparators is - // true, then recursively strip leading //. - // Otherwise, do not rewrite ObjectName. - // - if (srcDomain.startsWith(NAMESPACE_SEPARATOR)) { - if (!removeLeadingSeparators) return sourceName; - else srcDomain = normalizeDomain(srcDomain,true); - } - if (slen != 0) { - if (!srcDomain.startsWith(sourcePrefix) || - !srcDomain.startsWith(NAMESPACE_SEPARATOR,slen)) - throw new IllegalArgumentException( - "ObjectName does not start with expected prefix " - + sourcePrefix + ": " + - String.valueOf(sourceName)); - srcDomain = srcDomain.substring(slen+NAMESPACE_SEPARATOR_LENGTH); - } - final String targetDomain = - (tlen>0?targetPrefix+NAMESPACE_SEPARATOR+srcDomain:srcDomain); - return sourceName.withDomain(targetDomain); - } - - public final ObjectName toSourceContext(ObjectName targetName, - boolean removeLeadingSeparators) { - if (targetName == null) return null; - if (identity) return targetName; - String targetDomain = targetName.getDomain(); - if (targetDomain.startsWith(NAMESPACE_SEPARATOR)) { - if (!removeLeadingSeparators) return targetName; - else targetDomain = - normalizeDomain(targetDomain,true); - } - if (tlen != 0) { - if (!targetDomain.startsWith(targetPrefix) || - !targetDomain.startsWith(NAMESPACE_SEPARATOR,tlen)) - throw new IllegalArgumentException( - "ObjectName does not start with expected prefix " - + targetPrefix + ": " + - String.valueOf(targetName)); - targetDomain = targetDomain. - substring(tlen+NAMESPACE_SEPARATOR_LENGTH); - } - final String sourceDomain = - (slen>0?sourcePrefix+NAMESPACE_SEPARATOR+targetDomain: - targetDomain); - return targetName.withDomain(sourceDomain); - } - - public final ObjectInstance toTargetContext(ObjectInstance sourceMoi, - boolean removeLeadingSeparators) { - if (sourceMoi == null) return null; - if (identity) return sourceMoi; - return new ObjectInstance( - toTargetContext(sourceMoi.getObjectName(), - removeLeadingSeparators), - sourceMoi.getClassName()); - } - - /** - * Removes leading, trailing, or duplicate // in a name space path. - **/ - public static String normalizeDomain(String domain, - boolean removeLeadingSep) { - return normalizeNamespacePath(domain,removeLeadingSep,false,true); - } - - /** - * Removes leading, trailing, or duplicate // in a name space path. - **/ - public static String normalizeNamespacePath(String namespacePath, - boolean removeLeadingSep, - boolean removeTrailingSep, - boolean endsWithDomain) { - if (namespacePath.equals("")) - return ""; - final String[] components = namespacePath.split(NAMESPACE_SEPARATOR); - final StringBuilder b = - new StringBuilder(namespacePath.length()+NAMESPACE_SEPARATOR_LENGTH); - String sep = null; - if (!removeLeadingSep && namespacePath.startsWith(NAMESPACE_SEPARATOR)) - b.append(NAMESPACE_SEPARATOR); - int count = 0; - for (int i=0; i 0) - b.append(NAMESPACE_SEPARATOR); - return b.toString(); - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java --- a/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace; - - -import com.sun.jmx.defaults.JmxProperties; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.MBeanServerConnection; - - -/** - * A RoutingConnectionProxy is an MBeanServerConnection proxy that proxies a - * source name space in a source MBeanServerConnection. - * It wraps a source MBeanServerConnection, and rewrites routing - * ObjectNames. It is used to implement - * {@code JMXNamespaces.narrowToNamespace(MBeanServerConnection)}. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -// See class hierarchy and detailled explanations in RoutingProxy in this -// package. -// -public class RoutingConnectionProxy - extends RoutingProxy { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - - /** - * Creates a new instance of RoutingConnectionProxy - */ - public RoutingConnectionProxy(MBeanServerConnection source, - String sourceDir, - String targetDir, - boolean probe) { - super(source, sourceDir, targetDir, probe); - - if (LOG.isLoggable(Level.FINER)) - LOG.finer("RoutingConnectionProxy for " + getSourceNamespace() + - " created"); - } - - @Override - public String toString() { - final String targetNs = getTargetNamespace(); - final String sourceNs = getSourceNamespace(); - String wrapped = String.valueOf(source()); - if ("".equals(targetNs)) { - return "JMXNamespaces.narrowToNamespace("+ - wrapped+", \""+ - sourceNs+"\")"; - } - return this.getClass().getSimpleName()+"("+wrapped+", \""+ - sourceNs+"\", \""+ - targetNs+"\")"; - } - - static final RoutingProxyFactory - - FACTORY = new RoutingProxyFactory - () { - - public RoutingConnectionProxy newInstance(MBeanServerConnection source, - String sourcePath, String targetPath, boolean probe) { - return new RoutingConnectionProxy(source,sourcePath, - targetPath, probe); - } - }; - - public static MBeanServerConnection cd( - MBeanServerConnection source, String sourcePath, boolean probe) { - return RoutingProxy.cd(RoutingConnectionProxy.class, FACTORY, - source, sourcePath, probe); - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java --- a/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,556 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.mbeanserver.Util; -import java.io.IOException; -import java.lang.reflect.UndeclaredThrowableException; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.IntrospectionException; -import javax.management.InvalidAttributeValueException; -import javax.management.JMRuntimeException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServerConnection; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.RuntimeMBeanException; -import javax.management.RuntimeOperationsException; - -/** - * A RoutingMBeanServerConnection wraps a MBeanServerConnection, defining - * abstract methods that can be implemented by subclasses to rewrite - * routing ObjectNames. It is used to implement - * HandlerInterceptors (wrapping JMXNamespace instances) and routing - * proxies (used to implement cd operations). - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public abstract class RoutingMBeanServerConnection - implements MBeanServerConnection { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - /** - * Creates a new instance of RoutingMBeanServerConnection - */ - public RoutingMBeanServerConnection() { - } - - /** - * Returns the wrapped source connection. The {@code source} connection - * is a connection to the MBeanServer that contains the actual MBean. - * In the case of cascading, that would be a connection to the sub - * agent. - **/ - protected abstract T source() throws IOException; - - /** - * Converts a target ObjectName to a source ObjectName. - * The target ObjectName is the name of the MBean in the mount point - * target. In the case of cascading, that would be the name of the - * MBean in the master agent. So if a subagent S containing an MBean - * named "X" is mounted in the target namespace "foo//" of a master agent M, - * the source is S, the target is "foo//" in M, the source name is "X", and - * the target name is "foo//X". - * In the case of cascading - such as in NamespaceInterceptor, this method - * will convert "foo//X" (the targetName) into "X", the source name. - * @throws IllegalArgumentException if the name cannot be converted. - **/ - protected abstract ObjectName toSource(ObjectName targetName); - /** - * Converts a source ObjectName to a target ObjectName. - * (see description of toSource above for explanations) - * In the case of cascading - such as in NamespaceInterceptor, this method - * will convert "X" (the sourceName) into "foo//X", the target name. - * @throws IllegalArgumentException if the name cannot be converted. - **/ - protected abstract ObjectName toTarget(ObjectName sourceName); - - /** - * Can be overridden by subclasses to check the validity of a new - * ObjectName used in createMBean or registerMBean. - * This method is typically used by subclasses which might require - * special handling for "null"; - **/ - protected ObjectName newSourceMBeanName(ObjectName targetName) - throws MBeanRegistrationException { - try { - return toSource(targetName); - } catch (Exception x) { - throw new MBeanRegistrationException(x,"Illegal MBean Name"); - } - } - - // Calls toSource(), Wraps IllegalArgumentException. - ObjectName toSourceOrRuntime(ObjectName targetName) { - try { - return toSource(targetName); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - - // Wraps given exception if needed. - RuntimeException makeCompliantRuntimeException(Exception x) { - if (x instanceof SecurityException) return (SecurityException)x; - if (x instanceof JMRuntimeException) return (JMRuntimeException)x; - if (x instanceof RuntimeException) - return new RuntimeOperationsException((RuntimeException)x); - if (x instanceof IOException) - return Util.newRuntimeIOException((IOException)x); - // shouldn't come here... - final RuntimeException x2 = new UndeclaredThrowableException(x); - return new RuntimeOperationsException(x2); - } - - // from MBeanServerConnection - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().getAttributes(sourceName, attributes); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public Object invoke(ObjectName name, String operationName, Object[] params, - String[] signature) - throws InstanceNotFoundException, MBeanException, ReflectionException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - final Object result = - source().invoke(sourceName,operationName,params, - signature); - return result; - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().unregisterMBean(sourceName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().getMBeanInfo(sourceName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return processOutputInstance( - source().getObjectInstance(sourceName)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public boolean isRegistered(ObjectName name) throws IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().isRegistered(sourceName); - } catch (RuntimeMBeanException x) { - throw new RuntimeOperationsException(x.getTargetException()); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - // from MBeanServerConnection - public void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().setAttribute(sourceName,attribute); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance createMBean(String className, - ObjectName name, ObjectName loaderName, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException, IOException { - final ObjectName sourceName = newSourceMBeanName(name); - // Loader Name is already a sourceLoaderName. - final ObjectName sourceLoaderName = loaderName; - try { - final ObjectInstance instance = - source().createMBean(className,sourceName, - sourceLoaderName, - params,signature); - return processOutputInstance(instance); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance createMBean(String className, ObjectName name, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, IOException { - final ObjectName sourceName = newSourceMBeanName(name); - try { - return processOutputInstance(source().createMBean(className, - sourceName,params,signature)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException, IOException { - final ObjectName sourceName = newSourceMBeanName(name); - // Loader Name is already a source Loader Name. - final ObjectName sourceLoaderName = loaderName; - try { - return processOutputInstance(source().createMBean(className, - sourceName,sourceLoaderName)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, IOException { - final ObjectName sourceName = newSourceMBeanName(name); - try { - return processOutputInstance(source(). - createMBean(className,sourceName)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public Object getAttribute(ObjectName name, String attribute) - throws MBeanException, AttributeNotFoundException, - InstanceNotFoundException, ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().getAttribute(sourceName,attribute); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().isInstanceOf(sourceName,className); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public AttributeList setAttributes(ObjectName name, AttributeList attributes) - throws InstanceNotFoundException, ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source(). - setAttributes(sourceName,attributes); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // Return names in the target's context. - Set processOutputInstances(Set sources) { - - final Set result = Util.equivalentEmptySet(sources); - for (ObjectInstance i : sources) { - try { - final ObjectInstance target = processOutputInstance(i); - if (excludesFromResult(target.getObjectName(), "queryMBeans")) - continue; - result.add(target); - } catch (Exception x) { - if (LOG.isLoggable(Level.FINE)) { - LOG.fine("Skiping returned item: " + - "Unexpected exception while processing " + - "ObjectInstance: " + x); - } - continue; - } - } - return result; - } - - - // Return names in the target's context. - ObjectInstance processOutputInstance(ObjectInstance source) { - if (source == null) return null; - final ObjectName sourceName = source.getObjectName(); - try { - final ObjectName targetName = toTarget(sourceName); - return new ObjectInstance(targetName,source.getClassName()); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - // Returns names in the target's context. - Set processOutputNames(Set sourceNames) { - - final Set names = Util.equivalentEmptySet(sourceNames); - for (ObjectName n : sourceNames) { - try { - final ObjectName targetName = toTarget(n); - if (excludesFromResult(targetName, "queryNames")) continue; - names.add(targetName); - } catch (Exception x) { - if (LOG.isLoggable(Level.FINE)) { - LOG.fine("Skiping returned item: " + - "Unexpected exception while processing " + - "ObjectInstance: " + x); - } - continue; - } - } - return names; - } - - // from MBeanServerConnection - public Set queryMBeans(ObjectName name, - QueryExp query) throws IOException { - if (name == null) name=ObjectName.WILDCARD; - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return processOutputInstances( - source().queryMBeans(sourceName,query)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - - public Set queryNames(ObjectName name, QueryExp query) - throws IOException { - if (name == null) name=ObjectName.WILDCARD; - final ObjectName sourceName = toSourceOrRuntime(name); - try { - final Set tmp = source().queryNames(sourceName,query); - final Set out = processOutputNames(tmp); - //System.err.println("queryNames: out: "+out); - return out; - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, - ListenerNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().removeNotificationListener(sourceName,listener); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void addNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - // Listener name is already a source listener name. - try { - source().addNotificationListener(sourceName,listener, - filter,handback); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void addNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) throws InstanceNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().addNotificationListener(sourceName, listener, filter, - handback); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - - // from MBeanServerConnection - public void removeNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().removeNotificationListener(sourceName,listener,filter, - handback); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void removeNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().removeNotificationListener(sourceName,listener, - filter,handback); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void removeNotificationListener(ObjectName name, ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - // listener name is already a source name... - final ObjectName sourceListener = listener; - try { - source().removeNotificationListener(sourceName,sourceListener); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public Integer getMBeanCount() throws IOException { - try { - return source().getMBeanCount(); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public String[] getDomains() throws IOException { - try { - return source().getDomains(); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public String getDefaultDomain() throws IOException { - try { - return source().getDefaultDomain(); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - /** - * Returns true if the given targetName must be excluded from the - * query result. - * In this base class, always return {@code false}. - * By default all object names returned by the sources are - * transmitted to the caller - there is no filtering. - * - * @param name A target object name expressed in the caller's - * context. In the case of cascading, where the source - * is a sub agent mounted on e.g. namespace "foo", - * that would be a name prefixed by "foo//"... - * @param queryMethod either "queryNames" or "queryMBeans". - * @return true if the name must be excluded. - */ - boolean excludesFromResult(ObjectName targetName, String queryMethod) { - return false; - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/RoutingProxy.java --- a/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,395 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace; - -import com.sun.jmx.defaults.JmxProperties; -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.InstanceNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanRegistrationException; - -import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespaces; - - -/** - * A RoutingProxy narrows on a given name space in a - * source object implementing MBeanServerConnection. - * It is used to implement - * {@code JMXNamespaces.narrowToNamespace(...)}. - * This abstract class has two concrete subclasses: - *

{@link RoutingConnectionProxy}: to narrow down into an - * MBeanServerConnection.

- *

{@link RoutingServerProxy}: to narrow down into an MBeanServer.

- * - *

This class can also be used to "broaden" from a namespace. The same - * class is used for both purposes because in both cases all that happens - * is that ObjectNames are rewritten in one way on the way in (e.g. the - * parameter of getMBeanInfo) and another way on the way out (e.g. the - * return value of queryNames).

- * - *

Specifically, if you narrow into "a//" then you want to add the - * "a//" prefix to ObjectNames on the way in and subtract it on the way - * out. But ClientContext uses this class to subtract the - * "jmx.context//foo=bar//" prefix on the way in and add it back on the - * way out.

- * - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -// -// RoutingProxies are client side objects which are used to narrow down -// into a namespace. They are used to perform ObjectName translation, -// adding the namespace to the routing ObjectName before sending it over -// to the source connection, and removing that prefix from results of -// queries, createMBean, registerMBean, and getObjectInstance. -// This translation is the opposite to that which is performed by -// NamespaceInterceptors. -// -// There is however a special case where routing proxies are used on the -// 'server' side to remove a namespace - rather than to add it: -// This the case of ClientContext. -// When an ObjectName like "jmx.context//c1=v1,c2=v2//D:k=v" reaches the -// jmx.context namespace, a routing proxy is used to remove the prefix -// c1=v1,c2=v2// from the routing objectname. -// -// For a RoutingProxy used in a narrowDownToNamespace operation, we have: -// targetNs="" // targetNS is the namespace 'to remove' -// sourceNS= // namespace 'to add' -// -// For a RoutingProxy used in a ClientContext operation, we have: -// targetNs= // context must be removed from object name -// sourceNs="" // nothing to add... -// -// Finally, in order to avoid too many layers of wrapping, -// RoutingConnectionProxy and RoutingServerProxy can be created through a -// factory method that can concatenate namespace paths in order to -// return a single RoutingProxy - rather than wrapping a RoutingProxy inside -// another RoutingProxy. See RoutingConnectionProxy.cd and -// RoutingServerProxy.cd -// -// The class hierarchy is as follows: -// -// RoutingMBeanServerConnection -// [abstract class for all routing interceptors, -// such as RoutingProxies and HandlerInterceptors] -// / \ -// / \ -// RoutingProxy HandlerInterceptor -// [base class for [base class for server side -// client-side objects used objects, created by -// in narrowDownTo] DispatchInterceptors] -// / \ | \ -// RoutingConnectionProxy \ | NamespaceInterceptor -// [wraps MBeanServerConnection \ | [used to remove -// objects] \ | namespace prefix and -// RoutingServerProxy | wrap JMXNamespace] -// [wraps MBeanServer | -// Objects] | -// DomainInterceptor -// [used to wrap JMXDomain] -// -// RoutingProxies also differ from HandlerInterceptors in that they transform -// calls to MBeanServerConnection operations that do not have any parameters -// into a call to the underlying JMXNamespace MBean. -// So for instance a call to: -// JMXNamespaces.narrowDownToNamespace(conn,"foo").getDomains() -// is transformed into -// conn.getAttribute("foo//type=JMXNamespace","Domains"); -// -public abstract class RoutingProxy - extends RoutingMBeanServerConnection { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - // The source MBeanServerConnection - private final T source; - - // The name space we're narrowing to (usually some name space in - // the source MBeanServerConnection), e.g. "a" for the namespace - // "a//". This is empty in the case of ClientContext described above. - private final String sourceNs; - - // The name space we pretend to be mounted in. This is empty except - // in the case of ClientContext described above (where it will be - // something like "jmx.context//foo=bar". - private final String targetNs; - - // The name of the JMXNamespace that handles the source name space - private final ObjectName handlerName; - private final ObjectNameRouter router; - private volatile String defaultDomain = null; - - /** - * Creates a new instance of RoutingProxy - */ - protected RoutingProxy(T source, - String sourceNs, - String targetNs, - boolean probe) { - if (source == null) throw new IllegalArgumentException("null"); - this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs); - - // Usually sourceNs is not null, except when implementing - // Client Contexts - // - if (sourceNs.equals("")) { - this.handlerName = null; - } else { - // System.err.println("sourceNs: "+sourceNs); - this.handlerName = - JMXNamespaces.getNamespaceObjectName(this.sourceNs); - if (probe) { - try { - if (!source.isRegistered(handlerName)) { - InstanceNotFoundException infe = - new InstanceNotFoundException(handlerName); - throw new IllegalArgumentException(sourceNs + - ": no such name space", infe); - } - } catch (IOException x) { - throw new IllegalArgumentException("source stale: "+x,x); - } - } - } - this.source = source; - this.targetNs = (targetNs==null?"": - JMXNamespaces.normalizeNamespaceName(targetNs)); - this.router = - new ObjectNameRouter(this.targetNs,this.sourceNs); - - if (LOG.isLoggable(Level.FINER)) - LOG.finer("RoutingProxy for " + this.sourceNs + " created"); - } - - @Override - public T source() { return source; } - - @Override - public ObjectName toSource(ObjectName targetName) { - if (targetName == null) return null; - if (targetName.getDomain().equals("") && targetNs.equals("")) { - try { - if (defaultDomain == null) - defaultDomain = getDefaultDomain(); - } catch(Exception x) { - LOG.log(Level.FINEST,"Failed to get default domain",x); - } - if (defaultDomain != null) - targetName = targetName.withDomain(defaultDomain); - } - return router.toSourceContext(targetName,true); - } - - @Override - protected ObjectName newSourceMBeanName(ObjectName targetName) - throws MBeanRegistrationException { - if (targetName != null) return super.newSourceMBeanName(targetName); - - // OK => we can accept null if sourceNs is empty. - if (sourceNs.equals("")) return null; - - throw new MBeanRegistrationException( - new IllegalArgumentException( - "Can't use null ObjectName with namespaces")); - } - - @Override - public ObjectName toTarget(ObjectName sourceName) { - if (sourceName == null) return null; - return router.toTargetContext(sourceName,false); - } - - private Object getAttributeFromHandler(String attributeName) - throws IOException { - - try { - return source().getAttribute(handlerName,attributeName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } catch (IOException x) { - throw x; - } catch (MBeanException ex) { - throw new IOException("Failed to get "+attributeName+": "+ - ex.getCause(), - ex.getCause()); - } catch (Exception ex) { - throw new IOException("Failed to get "+attributeName+": "+ - ex,ex); - } - } - - // We cannot call getMBeanCount() on the underlying - // MBeanServerConnection, because it would return the number of - // 'top-level' MBeans, not the number of MBeans in the name space - // we are narrowing to. Instead we're calling getMBeanCount() on - // the JMXNamespace that handles the source name space. - // - // There is however one particular case when the sourceNs is empty. - // In that case, there's no handler - and the 'source' is the top - // level namespace. In that particular case, handlerName will be null, - // and we directly invoke the top level source(). - // This later complex case is only used when implementing ClientContexts. - // - @Override - public Integer getMBeanCount() throws IOException { - try { - if (handlerName == null) return source().getMBeanCount(); - return (Integer) getAttributeFromHandler("MBeanCount"); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // We cannot call getDomains() on the underlying - // MBeanServerConnection, because it would return the domains of - // 'top-level' MBeans, not the domains of MBeans in the name space - // we are narrowing to. Instead we're calling getDomains() on - // the JMXNamespace that handles the source name space. - // - // There is however one particular case when the sourceNs is empty. - // In that case, there's no handler - and the 'source' is the top - // level namespace. In that particular case, handlerName will be null, - // and we directly invoke the top level source(). - // This later complex case is only used when implementing ClientContexts. - // - @Override - public String[] getDomains() throws IOException { - try { - if (handlerName == null) return source().getDomains(); - return (String[]) getAttributeFromHandler("Domains"); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // We cannot call getDefaultDomain() on the underlying - // MBeanServerConnection, because it would return the default domain of - // 'top-level' namespace, not the default domain in the name space - // we are narrowing to. Instead we're calling getDefaultDomain() on - // the JMXNamespace that handles the source name space. - // - // There is however one particular case when the sourceNs is empty. - // In that case, there's no handler - and the 'source' is the top - // level namespace. In that particular case, handlerName will be null, - // and we directly invoke the top level source(). - // This later complex case is only used when implementing ClientContexts. - // - @Override - public String getDefaultDomain() throws IOException { - try { - if (handlerName == null) { - defaultDomain = source().getDefaultDomain(); - } else { - defaultDomain =(String) - getAttributeFromHandler("DefaultDomain"); - } - return defaultDomain; - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - public String getSourceNamespace() { - return sourceNs; - } - - public String getTargetNamespace() { - return targetNs; - } - - @Override - public String toString() { - return super.toString()+", sourceNs="+ - sourceNs + (targetNs.equals("")?"": - (" mounted on targetNs="+targetNs)); - } - - // Creates an instance of a subclass 'R' of RoutingProxy - // RoutingServerProxy and RoutingConnectionProxy have their own factory - // instance. - static interface RoutingProxyFactory> { - public R newInstance( - T source, String sourcePath, String targetPath, boolean probe); - } - - // Performs a narrowDownToNamespace operation. - // This method will attempt to merge two RoutingProxies in a single - // one if they are of the same class. - // - // This method is never called directly - it should be called only by - // subclasses of RoutingProxy. - // - // As for now it is called by: - // RoutingServerProxy.cd and RoutingConnectionProxy.cd. - // - static > - R cd(Class routingProxyClass, - RoutingProxyFactory factory, - T source, String sourcePath, boolean probe) { - if (source == null) throw new IllegalArgumentException("null"); - if (source.getClass().equals(routingProxyClass)) { - // cast is OK here, but findbugs complains unless we use class.cast - final R other = routingProxyClass.cast(source); - final String target = other.getTargetNamespace(); - - // Avoid multiple layers of serialization. - // - // We construct a new proxy from the original source instead of - // stacking a new proxy on top of the old one. - // - that is we replace - // cd ( cd ( x, dir1), dir2); - // by - // cd (x, dir1//dir2); - // - // We can do this only when the source class is exactly - // RoutingServerProxy. - // - if (target == null || target.equals("")) { - final String path = - JMXNamespaces.concat(other.getSourceNamespace(), - sourcePath); - return factory.newInstance(other.source(), path, "", probe); - } - // Note: we could do possibly something here - but it would involve - // removing part of targetDir, and possibly adding - // something to sourcePath. - // Too complex to bother! => simply default to stacking... - } - return factory.newInstance(source, sourcePath, "", probe); - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java --- a/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,576 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace; - - -import com.sun.jmx.mbeanserver.Util; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.lang.reflect.UndeclaredThrowableException; -import java.util.Collections; -import java.util.Set; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.IntrospectionException; -import javax.management.InvalidAttributeValueException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.OperationsException; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.loading.ClassLoaderRepository; - -/** - * A RoutingServerProxy is an MBeanServer proxy that proxies a - * source name space in a source MBeanServer. - * It wraps a source MBeanServer, and rewrites routing ObjectNames. - * It is typically use for implementing 'cd' operations, and - * will add the source name space to routing ObjectNames at input, - * and remove it at output. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * - * @since 1.7 - */ -// See class hierarchy and detailled explanations in RoutingProxy in this -// package. -// -public class RoutingServerProxy - extends RoutingProxy - implements MBeanServer { - - public RoutingServerProxy(MBeanServer source, - String sourceNs, - String targetNs, - boolean probe) { - super(source, sourceNs, targetNs, probe); - } - - /** - * This method is called each time an IOException is raised when - * trying to forward an operation to the underlying - * MBeanServerConnection, as a result of calling - * {@link #getMBeanServerConnection()} or as a result of invoking the - * operation on the returned connection. - * Subclasses may redefine this method if they need to perform any - * specific handling of IOException (logging etc...). - * @param x The raised IOException. - * @param method The name of the method in which the exception was - * raised. This is one of the methods of the MBeanServer - * interface. - * @return A RuntimeException that should be thrown by the caller. - * In this default implementation, this is an - * {@link UndeclaredThrowableException} wrapping x. - **/ - protected RuntimeException handleIOException(IOException x, - String method) { - return Util.newRuntimeIOException(x); - } - - - //-------------------------------------------- - //-------------------------------------------- - // - // Implementation of the MBeanServer interface - // - //-------------------------------------------- - //-------------------------------------------- - @Override - public void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - try { - super.addNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw handleIOException(x,"addNotificationListener"); - } - } - - @Override - public void addNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - try { - super.addNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw handleIOException(x,"addNotificationListener"); - } - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException { - try { - return super.createMBean(className, name); - } catch (IOException x) { - throw handleIOException(x,"createMBean"); - } - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name, - Object params[], String signature[]) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException { - try { - return super.createMBean(className, name, - params, signature); - } catch (IOException x) { - throw handleIOException(x,"createMBean"); - } - } - - @Override - public ObjectInstance createMBean(String className, - ObjectName name, - ObjectName loaderName) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - try { - return super.createMBean(className, name, loaderName); - } catch (IOException x) { - throw handleIOException(x,"createMBean"); - } - } - - @Override - public ObjectInstance createMBean(String className, - ObjectName name, - ObjectName loaderName, - Object params[], - String signature[]) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - try { - return super.createMBean(className, name, loaderName, - params, signature); - } catch (IOException x) { - throw handleIOException(x,"createMBean"); - } - } - - /** - * @deprecated see {@link MBeanServer#deserialize(ObjectName,byte[]) - * MBeanServer} - **/ - @Deprecated - public ObjectInputStream deserialize(ObjectName name, byte[] data) - throws InstanceNotFoundException, OperationsException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().deserialize(sourceName,data); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - /** - * @deprecated see {@link MBeanServer#deserialize(String,byte[]) - * MBeanServer} - */ - @Deprecated - public ObjectInputStream deserialize(String className, byte[] data) - throws OperationsException, ReflectionException { - try { - return source().deserialize(className,data); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - /** - * @deprecated see {@link MBeanServer#deserialize(String,ObjectName,byte[]) - * MBeanServer} - */ - @Deprecated - public ObjectInputStream deserialize(String className, - ObjectName loaderName, - byte[] data) - throws - InstanceNotFoundException, - OperationsException, - ReflectionException { - try { - return source().deserialize(className,loaderName,data); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - @Override - public Object getAttribute(ObjectName name, String attribute) - throws - MBeanException, - AttributeNotFoundException, - InstanceNotFoundException, - ReflectionException { - try { - return super.getAttribute(name, attribute); - } catch (IOException x) { - throw handleIOException(x,"getAttribute"); - } - } - - @Override - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException { - try { - return super.getAttributes(name, attributes); - } catch (IOException x) { - throw handleIOException(x,"getAttributes"); - } - } - - public ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - final ObjectName sourceName = toSourceOrRuntime(loaderName); - try { - return source().getClassLoader(sourceName); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - final ObjectName sourceName = toSourceOrRuntime(mbeanName); - try { - return source().getClassLoaderFor(sourceName); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public ClassLoaderRepository getClassLoaderRepository() { - try { - return source().getClassLoaderRepository(); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - @Override - public String getDefaultDomain() { - try { - return super.getDefaultDomain(); - } catch (IOException x) { - throw handleIOException(x,"getDefaultDomain"); - } - } - - @Override - public String[] getDomains() { - try { - return super.getDomains(); - } catch (IOException x) { - throw handleIOException(x,"getDomains"); - } - } - - @Override - public Integer getMBeanCount() { - try { - return super.getMBeanCount(); - } catch (IOException x) { - throw handleIOException(x,"getMBeanCount"); - } - } - - @Override - public MBeanInfo getMBeanInfo(ObjectName name) - throws - InstanceNotFoundException, - IntrospectionException, - ReflectionException { - try { - return super.getMBeanInfo(name); - } catch (IOException x) { - throw handleIOException(x,"getMBeanInfo"); - } - } - - @Override - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - try { - return super.getObjectInstance(name); - } catch (IOException x) { - throw handleIOException(x,"getObjectInstance"); - } - } - - public Object instantiate(String className) - throws ReflectionException, MBeanException { - try { - return source().instantiate(className); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public Object instantiate(String className, - Object params[], - String signature[]) - throws ReflectionException, MBeanException { - try { - return source().instantiate(className, - params,signature); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public Object instantiate(String className, ObjectName loaderName) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - final ObjectName srcLoaderName = toSourceOrRuntime(loaderName); - try { - return source().instantiate(className,srcLoaderName); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public Object instantiate(String className, ObjectName loaderName, - Object params[], String signature[]) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - final ObjectName srcLoaderName = toSourceOrRuntime(loaderName); - try { - return source().instantiate(className,srcLoaderName, - params,signature); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - @Override - public Object invoke(ObjectName name, String operationName, - Object params[], String signature[]) - throws - InstanceNotFoundException, - MBeanException, - ReflectionException { - try { - return super.invoke(name,operationName,params,signature); - } catch (IOException x) { - throw handleIOException(x,"invoke"); - } - } - - @Override - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - try { - return super.isInstanceOf(name, className); - } catch (IOException x) { - throw handleIOException(x,"isInstanceOf"); - } - } - - @Override - public boolean isRegistered(ObjectName name) { - try { - return super.isRegistered(name); - } catch (IOException x) { - throw handleIOException(x,"isRegistered"); - } - } - - @Override - public Set queryMBeans(ObjectName name, QueryExp query) { - try { - return super.queryMBeans(name, query); - } catch (IOException x) { - handleIOException(x,"queryMBeans"); - return Collections.emptySet(); - } - } - - @Override - public Set queryNames(ObjectName name, QueryExp query) { - try { - return super.queryNames(name, query); - } catch (IOException x) { - handleIOException(x,"queryNames"); - return Collections.emptySet(); - } - } - - public ObjectInstance registerMBean(Object object, ObjectName name) - throws - InstanceAlreadyExistsException, - MBeanRegistrationException, - NotCompliantMBeanException { - final ObjectName sourceName = newSourceMBeanName(name); - try { - return processOutputInstance( - source().registerMBean(object,sourceName)); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - super.removeNotificationListener(name, listener); - } catch (IOException x) { - throw handleIOException(x,"removeNotificationListener"); - } - } - - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - super.removeNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw handleIOException(x,"removeNotificationListener"); - } - } - - @Override - public void removeNotificationListener(ObjectName name, - ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - super.removeNotificationListener(name, listener); - } catch (IOException x) { - throw handleIOException(x,"removeNotificationListener"); - } - } - - @Override - public void removeNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - super.removeNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw handleIOException(x,"removeNotificationListener"); - } - } - - @Override - public void setAttribute(ObjectName name, Attribute attribute) - throws - InstanceNotFoundException, - AttributeNotFoundException, - InvalidAttributeValueException, - MBeanException, - ReflectionException { - try { - super.setAttribute(name, attribute); - } catch (IOException x) { - throw handleIOException(x,"setAttribute"); - } - } - - @Override - public AttributeList setAttributes(ObjectName name, - AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - try { - return super.setAttributes(name, attributes); - } catch (IOException x) { - throw handleIOException(x,"setAttributes"); - } - } - - @Override - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { - try { - super.unregisterMBean(name); - } catch (IOException x) { - throw handleIOException(x,"unregisterMBean"); - } - } - - static final RoutingProxyFactory - FACTORY = new RoutingProxyFactory() { - - public RoutingServerProxy newInstance(MBeanServer source, - String sourcePath, String targetPath, boolean probe) { - return new RoutingServerProxy( - source, sourcePath, targetPath, probe); - } - }; - - public static MBeanServer cd( - MBeanServer source, String sourcePath, boolean probe) { - return RoutingProxy.cd(RoutingServerProxy.class, FACTORY, - source, sourcePath, probe); - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/package.html --- a/src/share/classes/com/sun/jmx/namespace/package.html Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - The <code>com.sun.jmx.namespace</code> package - - - -

The com.sun.jmx.namespace package contains - sun specific implementation classes used to implement the - JMX namespaces. -

-

DO NOT USE THESE CLASSES DIRECTLY

-

- This API is a Sun internal API and is subject to changes without notice. -

-

The public API through wich these proprietary classes can be - invoked is located in javax.management.namespace - package. -

- - diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/serial/DefaultRewritingProcessor.java --- a/src/share/classes/com/sun/jmx/namespace/serial/DefaultRewritingProcessor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace.serial; - - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * Class DefaultRewritingProcessor. Rewrite ObjectName in input & output - * parameters. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -// We know that rewriting using serialization is costly. -// This object tries to determine whether an object needs rewriting prior -// to rewriting, and rewrites by creating a new object in those cases -// where we know how to recreate a new object (e.g. a Notification). -// Rewriting is however usually not used - so this object is just a -// skeleton that eventually uses serialization... -// -class DefaultRewritingProcessor extends RewritingProcessor { - - - private static enum RewriteMode { - INPUT, // Input from target to source (parameters) - OUTPUT // Output from source to target (results) - }; - - private final boolean identity; - - public DefaultRewritingProcessor(String targetDirName) { - this(targetDirName,null); - } - - /** Creates a new instance of SerialParamProcessor */ - public DefaultRewritingProcessor(final String remove, final String add) { - super(new SerialRewritingProcessor(remove, add)); - identity = remove.equals(add); - } - - private ObjectName rewriteObjectName(RewriteMode mode, - ObjectName name) { - return changeContext(mode, name); - } - - private ObjectInstance rewriteObjectInstance(RewriteMode mode, - ObjectInstance moi) { - final ObjectName srcName = moi.getObjectName(); - final ObjectName targetName = changeContext(mode,srcName); - if (targetName == srcName) return moi; - return new ObjectInstance(targetName,moi.getClassName()); - } - - - private Object processObject(RewriteMode mode, Object obj) { - if (obj == null) return null; - - // Some things which will always needs rewriting: - // ObjectName, ObjectInstance, and Notifications. - // Take care of those we can handle here... - // - if (obj instanceof ObjectName) - return rewriteObjectName(mode,(ObjectName) obj); - else if (obj instanceof ObjectInstance) - return rewriteObjectInstance(mode,(ObjectInstance) obj); - - // TODO: add other standard JMX classes - like e.g. MBeanInfo... - // - - // Well, the object may contain an ObjectName => pass it to - // our serial rewriting delegate... - // - return processAnyObject(mode,obj); - } - - - private Object processAnyObject(RewriteMode mode, Object obj) { - switch (mode) { - case INPUT: - return super.rewriteInput(obj); - case OUTPUT: - return super.rewriteOutput(obj); - default: // can't happen. - throw new AssertionError(); - } - } - - private ObjectName changeContext(RewriteMode mode, ObjectName name) { - switch (mode) { - case INPUT: - return toSourceContext(name); - case OUTPUT: - return toTargetContext(name); - default: // can't happen. - throw new AssertionError(); - } - } - - @Override - public ObjectName toTargetContext(ObjectName srcName) { - if (identity) return srcName; - return super.toTargetContext(srcName); - } - - @Override - public ObjectName toSourceContext(ObjectName targetName) { - if (identity) return targetName; - return super.toSourceContext(targetName); - } - - @SuppressWarnings("unchecked") - @Override - public T rewriteInput(T input) { - if (identity) return input; - return (T) processObject(RewriteMode.INPUT,input); - } - - @SuppressWarnings("unchecked") - @Override - public T rewriteOutput(T result) { - if (identity) return result; - return (T) processObject(RewriteMode.OUTPUT,result); - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/serial/IdentityProcessor.java --- a/src/share/classes/com/sun/jmx/namespace/serial/IdentityProcessor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace.serial; - - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * Class RoutingOnlyProcessor. A RewritingProcessor that uses - * Java Serialization to rewrite ObjectNames contained in - * input & results... - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * - * @since 1.7 - */ -class IdentityProcessor extends RewritingProcessor { - - - /** Creates a new instance of SerialRewritingProcessor */ - public IdentityProcessor() { - } - - @Override - public T rewriteOutput(T result) { - return result; - } - - @Override - public T rewriteInput(T input) { - return input; - } - - @Override - public final ObjectName toTargetContext(ObjectName sourceName) { - return sourceName; - } - - @Override - public final ObjectInstance toTargetContext(ObjectInstance sourceMoi) { - return sourceMoi; - } - - @Override - public final ObjectName toSourceContext(ObjectName targetName) { - return targetName; - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/serial/JMXNamespaceContext.java --- a/src/share/classes/com/sun/jmx/namespace/serial/JMXNamespaceContext.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace.serial; - -import com.sun.jmx.defaults.JmxProperties; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.logging.Level; -import java.util.logging.Logger; - - -/** - * The JMXNamespaceContext class is used to implement a thread local - * serialization / deserialization context for namespaces. - *

- * This class is consulted by {@link javax.management.ObjectName} at - * serialization / deserialization time. - * The serialization or deserialization context is established by - * by the {@link SerialRewritingProcessor} defined in this package. - *

- * These classes are Sun proprietary APIs, subject to change without - * notice. Do not use these classes directly. - * The public API to rewrite ObjectNames embedded in parameters is - * defined in {@link javax.management.namespace.JMXNamespaces}. - * - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class JMXNamespaceContext { - - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - public final String prefixToRemove; - public final String prefixToAdd; - - private JMXNamespaceContext(String add, String remove) { - prefixToRemove = (remove==null?"":remove); - prefixToAdd = (add==null?"":add); - } - - private final static class SerialContext { - private JMXNamespaceContext serializationContext; - private JMXNamespaceContext deserializationContext; - public SerialContext(){ - serializationContext = new JMXNamespaceContext("",""); - deserializationContext = new JMXNamespaceContext("",""); - } - } - - private final static ThreadLocal prefix = - new ThreadLocal() { - @Override - protected SerialContext initialValue() { - return new SerialContext(); - } - }; - - public static JMXNamespaceContext getSerializationContext() { - return prefix.get().serializationContext; - } - - public static JMXNamespaceContext getDeserializationContext() { - return prefix.get().deserializationContext; - } - - private static String[] setSerializationContext(String oldPrefix, - String newPrefix) { - final SerialContext c = prefix.get(); - JMXNamespaceContext dc = c.serializationContext; - String[] old = {dc.prefixToRemove, dc.prefixToAdd}; - c.serializationContext = new JMXNamespaceContext(newPrefix,oldPrefix); - return old; - } - - private static String[] setDeserializationContext(String oldPrefix, - String newPrefix) { - final SerialContext c = prefix.get(); - JMXNamespaceContext dc = c.deserializationContext; - String[] old = {dc.prefixToRemove, dc.prefixToAdd}; - c.deserializationContext = new JMXNamespaceContext(newPrefix,oldPrefix); - return old; - } - - static void serialize(ObjectOutputStream stream, Object obj, - String prefixToRemove, String prefixToAdd) - throws IOException { - final String[] old = - setSerializationContext(prefixToRemove,prefixToAdd); - try { - stream.writeObject(obj); - } finally { - try { - setSerializationContext(old[0],old[1]); - } catch (Exception x) { - LOG.log(Level.FINEST, - "failed to restore serialization context",x); - } - } - } - - static Object deserialize(ObjectInputStream stream, - String prefixToRemove, - String prefixToAdd) - throws IOException, ClassNotFoundException { - final String[] old = - setDeserializationContext(prefixToRemove,prefixToAdd); - try { - return stream.readObject(); - } finally { - try { - setDeserializationContext(old[0],old[1]); - } catch (Exception x) { - LOG.log(Level.FINEST, - "failed to restore serialization context",x); - } - } - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/serial/RewritingProcessor.java --- a/src/share/classes/com/sun/jmx/namespace/serial/RewritingProcessor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,362 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace.serial; - - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * An object that can rewrite ObjectNames contained in input/output - * parameters when entering/leaving a {@link javax.management.namespace - * namespace}. - *

When entering a {@link javax.management.namespace - * namespace}, the {@code namespace} prefix is stripped from - * ObjectNames contained in input parameters. When leaving a - * {@code namespace}, - * the {@code namespace} prefix is prepended to the ObjectNames contained in - * the result parameters returned from that {@code namespace}. - *

- *

Objects that need to perform these operations usually use a - * {@code RewritingProcessor} for that purpose.
- * The {@code RewritingProcessor} allows a somewhat larger - * transformation in which part of a prefix {@link #newRewritingProcessor - * remove} can be replaced by another prefix {@link #newRewritingProcessor - * add}. The transformation described above correspond to the case where - * {@code remove} is the stripped {@link javax.management.namespace - * namespace} prefix (removed when entering the {@code namespace}) and - * {@code add} is the empty String {@code ""}. - *
- * It is interesting to note that {@link - * javax.management.JMXNamespaces#narrowToNamespace narrowToNamespace} - * operations use the inverse transformation (that is, {@code remove} is - * the empty String {@code ""} and {@code add} is the {@link - * javax.management.namespace namespace} prefix). - *
- * On a more general scale, {@link #rewriteInput rewriteInput} removes - * {@link #newRewritingProcessor remove} and the prepend {@link - * #newRewritingProcessor add}, and {@link #rewriteOutput rewriteOutput} - * does the opposite, removing {@link #newRewritingProcessor add}, and - * then adding {@link #newRewritingProcessor remove}. - *
- * An implementation of {@code RewritingProcessor} should make sure that - * rewriteInput(rewriteOutput(x,clp),clp) and - * rewriteOutput(rewriteInput(x,clp),clp) always return - * {@code x} or an exact clone of {@code x}. - *

- *

A default implementation of {@code RewritingProcessor} based on - * Java Object Serialization can be - * obtained from {@link #newRewritingProcessor newRewritingProcessor}. - *

- *

- * By default, the instances of {@code RewritingProcessor} returned by - * {@link #newRewritingProcessor newRewritingProcessor} will rewrite - * ObjectNames contained in instances of classes they don't know about by - * serializing and then deserializing such object instances. This will - * happen even if such instances don't - or can't contain ObjectNames, - * because the default implementation of {@code RewritingProcessor} will - * not be able to determine whether instances of such classes can/do contain - * instance of ObjectNames before serializing/deserializing them. - *

- *

If you are using custom classes that the default implementation of - * {@code RewritingProcessor} don't know about, it can be interesting to - * prevent an instance of {@code RewritingProcessor} to serialize/deserialize - * instances of such classes for nothing. In that case, you could customize - * the behavior of such a {@code RewritingProcessor} by wrapping it in a - * custom subclass of {@code RewritingProcessor} as shown below: - *

- * public class MyRewritingProcessor extends RewritingProcessor {
- *      MyRewritingProcessor(String remove, String add) {
- *          this(RewritingProcessor.newRewritingProcessor(remove,add));
- *      }
- *      MyRewritingProcessor(RewritingProcessor delegate) {
- *          super(delegate);
- *      }
- *
- *   T rewriteInput(T input) {
- *          if (input == null) return null;
- *          if (MyClass.equals(input.getClass())) {
- *              // I know that MyClass doesn't contain any ObjectName
- *              return (T) input;
- *          }
- *          return super.rewriteInput(input);
- *      }
- *   T rewriteOutput(T result) {
- *          if (result == null) return null;
- *          if (MyClass.equals(result.getClass())) {
- *              // I know that MyClass doesn't contain any ObjectName
- *              return (T) result;
- *          }
- *          return super.rewriteOutput(result);
- *      }
- * }
- * 
- *

- *

Such a subclass may also provide an alternate way of rewriting - * custom subclasses for which rewriting is needed - for instance: - *

- * public class MyRewritingProcessor extends RewritingProcessor {
- *      MyRewritingProcessor(String remove, String add) {
- *          this(RewritingProcessor.newRewritingProcessor(remove,add));
- *      }
- *      MyRewritingProcessor(RewritingProcessor delegate) {
- *          super(delegate);
- *      }
- *
- *   T rewriteInput(T input) {
- *          if (input == null) return null;
- *          if (MyClass.equals(input.getClass())) {
- *              // I know that MyClass doesn't contain any ObjectName
- *              return (T) input;
- *          } else if (MyOtherClass.equals(input.getClass())) {
- *              // Returns a new instance in which ObjectNames have been
- *              // replaced.
- *              final ObjectName aname = ((MyOtherClass)input).getName();
- *              return (T) (new MyOtherClass(super.rewriteInput(aname)));
- *          }
- *          return super.rewriteInput(input,clp);
- *      }
- *   T rewriteOutput(T result) {
- *          if (result == null) return null;
- *          if (MyClass.equals(result.getClass())) {
- *              // I know that MyClass doesn't contain any ObjectName
- *              return (T) result;
- *          } else if (MyOtherClass.equals(result.getClass())) {
- *              // Returns a new instance in which ObjectNames have been
- *              // replaced.
- *              final ObjectName aname = ((MyOtherClass)result).getName();
- *              return (T) (new MyOtherClass(super.rewriteOutput(aname)));
- *          }
- *          return super.rewriteOutput(result,clp);
- *      }
- * }
- * 
- *

- *

If your application only uses {@link javax.management.MXBean MXBeans}, - * or MBeans using simple types, and doesn't define any custom subclass of - * {@link javax.management.Notification}, you should never write such - * such {@code RewitingProcessor} implementations. - *

- *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public abstract class RewritingProcessor { - /** - * A logger for this class. - **/ - private final RewritingProcessor delegate; - - /** - * Creates a new instance of RewritingProcessor. - *

This is equivalent to calling {@link - * #RewritingProcessor(RewritingProcessor) RewritingProcessor(null)}. - *

- **/ - protected RewritingProcessor() { - this(null); - } - - /** - * Creates a new instance of RewritingProcessor, with a delegate. - * @param delegate a {@code RewritingProcessor} to which all the - * calls will be delegated. When implementing a subclass - * of {@code RewritingProcessor}, calling {@link - * #rewriteInput super.rewriteInput} will invoke - * {@code delegate.rewriteInput} and calling {@link - * #rewriteOutput super.rewriteOutput} will invoke - * {@code delegate.rewriteOutput}. - * - **/ - protected RewritingProcessor(RewritingProcessor delegate) { - this.delegate = delegate; - } - - /** - * Rewrites ObjectNames when {@link RewritingProcessor leaving} a {@link - * javax.management.namespace namespace}. - *

- * Returns {@code obj}, if it is known that {@code obj} doesn't contain - * any ObjectName, or a new copied instance of {@code obj} in which - * ObjectNames (if any) will have been rewritten, if {@code obj} contains - * ObjectNames, or if it is not known whether {@code obj} contains - * ObjectNames or not. - *

- *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.rewriteOutput(obj)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param obj The result to be rewritten if needed. - * - * @return {@code obj}, or a clone of {@code obj} in which ObjectNames - * have been rewritten. See this class {@link RewritingProcessor - * description} for more details. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public T rewriteOutput(T obj) { - if (obj == null) return null; - if (delegate != null) - return delegate.rewriteOutput(obj); - throw new IllegalArgumentException("can't rewrite "+ - obj.getClass().getName()); - } - - /** - * Rewrites ObjectNames when {@link RewritingProcessor entering} a {@link - * javax.management.namespace namespace}. - *

- * Returns {@code obj}, if it is known that {@code obj} doesn't contain - * any ObjectName, or a new copied instance of {@code obj} in which - * ObjectNames (if any) will have been rewritten, if {@code obj} contains - * ObjectNames, or if it is not known whether {@code obj} contains - * ObjectNames or not. - *

- *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.rewriteInput(obj)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param obj The result to be rewritten if needed. - * @return {@code obj}, or a clone of {@code obj} in which ObjectNames - * have been rewritten. See this class {@link RewritingProcessor - * description} for more details. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public T rewriteInput(T obj) { - if (obj == null) return null; - if (delegate != null) - return delegate.rewriteInput(obj); - throw new IllegalArgumentException("can't rewrite "+ - obj.getClass().getName()); - } - - /** - * Translate a routing ObjectName from the target (calling) context to - * the source (called) context when {@link RewritingProcessor entering} a - * {@link javax.management.namespace namespace}. - *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.toSourceContext(targetName)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param targetName The routing target ObjectName to translate. - * @return The ObjectName translated to the source context. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public ObjectName toSourceContext(ObjectName targetName) { - if (delegate != null) - return delegate.toSourceContext(targetName); - throw new IllegalArgumentException("can't rewrite targetName: "+ - " no delegate."); - } - - /** - * Translate an ObjectName returned from the source context into - * the target (calling) context when {@link RewritingProcessor leaving} a - * {@link javax.management.namespace namespace}. - *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.toTargetContext(sourceName)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param sourceName The routing source ObjectName to translate to the - * target context. - * @return The ObjectName translated to the target context. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public ObjectName toTargetContext(ObjectName sourceName) { - if (delegate != null) - return delegate.toTargetContext(sourceName); - throw new IllegalArgumentException("can't rewrite sourceName: "+ - " no delegate."); - } - - /** - * Translate an ObjectInstance returned from the source context into - * the target (calling) context when {@link RewritingProcessor leaving} a - * {@link javax.management.namespace namespace}. - *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.toTargetContext(sourceMoi)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param sourceMoi The routing source ObjectInstance to translate. - * @return The ObjectInstance translated to the target context. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public ObjectInstance toTargetContext(ObjectInstance sourceMoi) { - if (delegate != null) - return delegate.toTargetContext(sourceMoi); - throw new IllegalArgumentException("can't rewrite sourceName: "+ - " no delegate."); - } - - /** - * Creates a new default instance of {@link RewritingProcessor}. - * @param remove The prefix to remove from {@link ObjectName ObjectNames} - * when {@link RewritingProcessor entering} the {@link - * javax.management.namespace namespace}. - * @param add The prefix to add to {@link ObjectName ObjectNames} - * when {@link RewritingProcessor entering} the {@link - * javax.management.namespace namespace} (this is performed - * after having removed the {@code remove} prefix. - * @return A new {@link RewritingProcessor} processor object that will - * perform the requested operation, using Java serialization if - * necessary. - **/ - public static RewritingProcessor newRewritingProcessor(String remove, - String add) { - return new DefaultRewritingProcessor(remove,add); - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/serial/RoutingOnlyProcessor.java --- a/src/share/classes/com/sun/jmx/namespace/serial/RoutingOnlyProcessor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace.serial; - -import com.sun.jmx.namespace.ObjectNameRouter; - - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * Class RoutingOnlyProcessor. A RewritingProcessor that uses - * Java Serialization to rewrite ObjectNames contained in - * input and results... - * - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -class RoutingOnlyProcessor extends RewritingProcessor { - - final ObjectNameRouter router; - - public RoutingOnlyProcessor(String targetDirName) { - this(targetDirName,null); - } - - /** Creates a new instance of RoutingOnlyProcessor */ - public RoutingOnlyProcessor(final String remove, final String add) { - super(new IdentityProcessor()); - if (remove == null || add == null) - throw new IllegalArgumentException("Null argument"); - router = new ObjectNameRouter(remove,add); - } - - @Override - public final ObjectName toTargetContext(ObjectName sourceName) { - return router.toTargetContext(sourceName,false); - } - - @Override - public final ObjectName toSourceContext(ObjectName targetName) { - return router.toSourceContext(targetName,false); - } - - @Override - public final ObjectInstance toTargetContext(ObjectInstance sourceMoi) { - return router.toTargetContext(sourceMoi,false); - } -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/serial/SerialRewritingProcessor.java --- a/src/share/classes/com/sun/jmx/namespace/serial/SerialRewritingProcessor.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,172 +0,0 @@ -/* - * Copyright 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. - */ - -package com.sun.jmx.namespace.serial; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InvalidClassException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.ObjectStreamClass; -import java.io.OutputStream; -import java.util.LinkedList; -import java.util.Queue; - -import javax.management.ObjectName; - -/** - * Class SerialRewritingProcessor. A RewritingProcessor that uses - * Java Serialization to rewrite ObjectNames contained in - * input & results... - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -class SerialRewritingProcessor extends RewritingProcessor { - - - private static class CloneOutput extends ObjectOutputStream { - Queue> classQueue = new LinkedList>(); - - CloneOutput(OutputStream out) throws IOException { - super(out); - } - - @Override - protected void annotateClass(Class c) { - classQueue.add(c); - } - - @Override - protected void annotateProxyClass(Class c) { - classQueue.add(c); - } - } - - private static class CloneInput extends ObjectInputStream { - private final CloneOutput output; - - CloneInput(InputStream in, CloneOutput output) throws IOException { - super(in); - this.output = output; - } - - @Override - protected Class resolveClass(ObjectStreamClass osc) - throws IOException, ClassNotFoundException { - Class c = output.classQueue.poll(); - String expected = osc.getName(); - String found = (c == null) ? null : c.getName(); - if (!expected.equals(found)) { - throw new InvalidClassException("Classes desynchronized: " + - "found " + found + " when expecting " + expected); - } - return c; - } - - @Override - protected Class resolveProxyClass(String[] interfaceNames) - throws IOException, ClassNotFoundException { - return output.classQueue.poll(); - } - } - - - final String targetPrefix; - final String sourcePrefix; - final boolean identity; - - - public SerialRewritingProcessor(String targetDirName) { - this(targetDirName,null); - } - - /** Creates a new instance of SerialRewritingProcessor */ - public SerialRewritingProcessor(final String remove, final String add) { - super(new RoutingOnlyProcessor(remove,add)); - this.targetPrefix = remove; - this.sourcePrefix = add; - identity = targetPrefix.equals(sourcePrefix); - } - - private T switchContext(T result, String from,String to) - throws IOException, ClassNotFoundException { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final CloneOutput ostream = new CloneOutput(baos); - - JMXNamespaceContext.serialize(ostream,result,from,null); - ostream.flush(); - - final byte[] bytes = baos.toByteArray(); - final ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - final CloneInput istream = new CloneInput(bais, ostream); - @SuppressWarnings("unchecked") - final T clone = (T) JMXNamespaceContext.deserialize(istream,null,to); - return clone; - } - - @Override - @SuppressWarnings("unchecked") - public T rewriteOutput(T result) { - if (identity) return result; - return (T) processOutput(result); - } - - private Object processOutput(Object result) { - try { - if (result instanceof ObjectName) - return toTargetContext((ObjectName) result); - return switchContext(result,sourcePrefix,targetPrefix); - } catch (ClassNotFoundException x) { - throw new IllegalArgumentException("Can't process result: "+x,x); - } catch (IOException x) { - throw new IllegalArgumentException("Can't process result: "+x,x); - } - } - - @Override - @SuppressWarnings("unchecked") - public T rewriteInput(T input) { - if (identity) return input; - return (T) processInput(input); - } - - private Object processInput(Object input) { - try { - if (input instanceof ObjectName) - return toSourceContext((ObjectName) input); - return switchContext(input,targetPrefix,sourcePrefix); - } catch (ClassNotFoundException x) { - throw new IllegalArgumentException("Can't process input: "+x,x); - } catch (IOException x) { - throw new IllegalArgumentException("Can't process input: "+x,x); - } - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/namespace/serial/package.html --- a/src/share/classes/com/sun/jmx/namespace/serial/package.html Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ - - - - - The <code>com.sun.jmx.namespace.serial</code> package - - - -

The com.sun.jmx.namespace.serial package contains - sun specific implementation classes used to switch namespace - prefixes in ObjectName during serialization. -

-

NEVER USE THESE CLASSES DIRECTLY

-

- This API is a Sun internal API and is subject to changes without notice. -

-

The public API through which these proprietary classes can be invoked is - located in javax.management.namespace.JMXNamespaces -

- - diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/remote/internal/IIOPHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/jmx/remote/internal/IIOPHelper.java Wed Nov 25 22:14:30 2009 -0800 @@ -0,0 +1,188 @@ +/* + * 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 com.sun.jmx.remote.internal; + +import java.util.Properties; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.NoSuchObjectException; + +import java.util.Properties; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.NoSuchObjectException; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * A helper class for RMI-IIOP and CORBA APIs. + */ + +public final class IIOPHelper { + private IIOPHelper() { } + + // loads IIOPProxy implementation class if available + private static final String IMPL_CLASS = + "com.sun.jmx.remote.protocol.iiop.IIOPProxyImpl"; + private static final IIOPProxy proxy = + AccessController.doPrivileged(new PrivilegedAction() { + public IIOPProxy run() { + try { + Class c = Class.forName(IMPL_CLASS, true, null); + return (IIOPProxy)c.newInstance(); + } catch (ClassNotFoundException cnf) { + return null; + } catch (InstantiationException e) { + throw new AssertionError(e); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + }}); + + /** + * Returns true if RMI-IIOP and CORBA is available. + */ + public static boolean isAvailable() { + return proxy != null; + } + + private static void ensureAvailable() { + if (proxy == null) + throw new AssertionError("Should not here"); + } + + /** + * Returns true if the given object is a Stub. + */ + public static boolean isStub(Object obj) { + return (proxy == null) ? false : proxy.isStub(obj); + } + + /** + * Returns the Delegate to which the given Stub delegates. + */ + public static Object getDelegate(Object stub) { + ensureAvailable(); + return proxy.getDelegate(stub); + } + + /** + * Sets the Delegate for a given Stub. + */ + public static void setDelegate(Object stub, Object delegate) { + ensureAvailable(); + proxy.setDelegate(stub, delegate); + } + + /** + * Returns the ORB associated with the given stub + * + * @throws UnsupportedOperationException + * if the object does not support the operation that + * was invoked + */ + public static Object getOrb(Object stub) { + ensureAvailable(); + return proxy.getOrb(stub); + } + + /** + * Connects the Stub to the given ORB. + */ + public static void connect(Object stub, Object orb) + throws RemoteException + { + ensureAvailable(); + proxy.connect(stub, orb); + } + + /** + * Returns true if the given object is an ORB. + */ + public static boolean isOrb(Object obj) { + ensureAvailable(); + return proxy.isOrb(obj); + } + + /** + * Creates, and returns, a new ORB instance. + */ + public static Object createOrb(String[] args, Properties props) { + ensureAvailable(); + return proxy.createOrb(args, props); + } + + /** + * Converts a string, produced by the object_to_string method, back + * to a CORBA object reference. + */ + public static Object stringToObject(Object orb, String str) { + ensureAvailable(); + return proxy.stringToObject(orb, str); + } + + /** + * Converts the given CORBA object reference to a string. + */ + public static String objectToString(Object orb, Object obj) { + ensureAvailable(); + return proxy.objectToString(orb, obj); + } + + /** + * Checks to ensure that an object of a remote or abstract interface + * type can be cast to a desired type. + */ + public static T narrow(Object narrowFrom, Class narrowTo) { + ensureAvailable(); + return proxy.narrow(narrowFrom, narrowTo); + } + + /** + * Makes a server object ready to receive remote calls + */ + public static void exportObject(Remote obj) throws RemoteException { + ensureAvailable(); + proxy.exportObject(obj); + } + + /** + * Deregisters a server object from the runtime. + */ + public static void unexportObject(Remote obj) throws NoSuchObjectException { + ensureAvailable(); + proxy.unexportObject(obj); + } + + /** + * Returns a stub for the given server object. + */ + public static Remote toStub(Remote obj) throws NoSuchObjectException { + ensureAvailable(); + return proxy.toStub(obj); + } +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/remote/internal/IIOPProxy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/jmx/remote/internal/IIOPProxy.java Wed Nov 25 22:14:30 2009 -0800 @@ -0,0 +1,110 @@ +/* + * 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 com.sun.jmx.remote.internal; + +import java.util.Properties; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.NoSuchObjectException; + +/** + * An interface to a subset of the RMI-IIOP and CORBA APIs to avoid a + * static dependencies on the types defined by these APIs. + */ + +public interface IIOPProxy { + + /** + * Returns true if the given object is a Stub. + */ + boolean isStub(Object obj); + + /** + * Returns the Delegate to which the given Stub delegates. + */ + Object getDelegate(Object stub); + + /** + * Sets the Delegate for a given Stub. + */ + void setDelegate(Object stub, Object delegate); + + /** + * Returns the ORB associated with the given stub + * + * @throws UnsupportedOperationException + * if the object does not support the operation that + * was invoked + */ + Object getOrb(Object stub); + + /** + * Connects the Stub to the given ORB. + */ + void connect(Object stub, Object orb) throws RemoteException; + + /** + * Returns true if the given object is an ORB. + */ + boolean isOrb(Object obj); + + /** + * Creates, and returns, a new ORB instance. + */ + Object createOrb(String[] args, Properties props); + + /** + * Converts a string, produced by the object_to_string method, back + * to a CORBA object reference. + */ + Object stringToObject(Object orb, String str); + + /** + * Converts the given CORBA object reference to a string. + */ + String objectToString(Object orb, Object obj); + + /** + * Checks to ensure that an object of a remote or abstract interface + * type can be cast to a desired type. + */ + T narrow(Object narrowFrom, Class narrowTo); + + /** + * Makes a server object ready to receive remote calls + */ + void exportObject(Remote obj) throws RemoteException; + + /** + * Deregisters a server object from the runtime. + */ + void unexportObject(Remote obj) throws NoSuchObjectException; + + /** + * Returns a stub for the given server object. + */ + Remote toStub(Remote obj) throws NoSuchObjectException; +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/remote/internal/ProxyInputStream.java --- a/src/share/classes/com/sun/jmx/remote/internal/ProxyInputStream.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -/* - * Copyright 2003-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. - */ - -package com.sun.jmx.remote.internal; - -import java.io.IOException; -import java.io.Serializable; -import java.math.BigDecimal; - -import org.omg.CORBA.Any; -import org.omg.CORBA.Context; -import org.omg.CORBA.NO_IMPLEMENT; -import org.omg.CORBA.ORB; -import org.omg.CORBA.TypeCode; -import org.omg.CORBA.portable.BoxedValueHelper; - -@SuppressWarnings({"deprecation", "rawtypes"}) -public class ProxyInputStream extends org.omg.CORBA_2_3.portable.InputStream { - public ProxyInputStream(org.omg.CORBA.portable.InputStream in) { - this.in = in; - } - - public boolean read_boolean() { - return in.read_boolean(); - } - - public char read_char() { - return in.read_char(); - } - - public char read_wchar() { - return in.read_wchar(); - } - - public byte read_octet() { - return in.read_octet(); - } - - public short read_short() { - return in.read_short(); - } - - public short read_ushort() { - return in.read_ushort(); - } - - public int read_long() { - return in.read_long(); - } - - public int read_ulong() { - return in.read_ulong(); - } - - public long read_longlong() { - return in.read_longlong(); - } - - public long read_ulonglong() { - return in.read_ulonglong(); - } - - public float read_float() { - return in.read_float(); - } - - public double read_double() { - return in.read_double(); - } - - public String read_string() { - return in.read_string(); - } - - public String read_wstring() { - return in.read_wstring(); - } - - public void read_boolean_array(boolean[] value, int offset, int length) { - in.read_boolean_array(value, offset, length); - } - - public void read_char_array(char[] value, int offset, int length) { - in.read_char_array(value, offset, length); - } - - public void read_wchar_array(char[] value, int offset, int length) { - in.read_wchar_array(value, offset, length); - } - - public void read_octet_array(byte[] value, int offset, int length) { - in.read_octet_array(value, offset, length); - } - - public void read_short_array(short[] value, int offset, int length) { - in.read_short_array(value, offset, length); - } - - public void read_ushort_array(short[] value, int offset, int length) { - in.read_ushort_array(value, offset, length); - } - - public void read_long_array(int[] value, int offset, int length) { - in.read_long_array(value, offset, length); - } - - public void read_ulong_array(int[] value, int offset, int length) { - in.read_ulong_array(value, offset, length); - } - - public void read_longlong_array(long[] value, int offset, int length) { - in.read_longlong_array(value, offset, length); - } - - public void read_ulonglong_array(long[] value, int offset, int length) { - in.read_ulonglong_array(value, offset, length); - } - - public void read_float_array(float[] value, int offset, int length) { - in.read_float_array(value, offset, length); - } - - public void read_double_array(double[] value, int offset, int length) { - in.read_double_array(value, offset, length); - } - - public org.omg.CORBA.Object read_Object() { - return in.read_Object(); - } - - public TypeCode read_TypeCode() { - return in.read_TypeCode(); - } - - public Any read_any() { - return in.read_any(); - } - - /** - * @deprecated - */ - @Override - @Deprecated - public org.omg.CORBA.Principal read_Principal() { - return in.read_Principal(); - } - - @Override - public int read() throws IOException { - return in.read(); - } - - @Override - public BigDecimal read_fixed() { - return in.read_fixed(); - } - - @Override - public Context read_Context() { - return in.read_Context(); - } - - @Override - public org.omg.CORBA.Object read_Object(java.lang.Class clz) { - return in.read_Object(clz); - } - - @Override - public ORB orb() { - return in.orb(); - } - - @Override - public Serializable read_value() { - return narrow().read_value(); - } - - @Override - public Serializable read_value(Class clz) { - return narrow().read_value(clz); - } - - @Override - public Serializable read_value(BoxedValueHelper factory) { - return narrow().read_value(factory); - } - - @Override - public Serializable read_value(String rep_id) { - return narrow().read_value(rep_id); - } - - @Override - public Serializable read_value(Serializable value) { - return narrow().read_value(value); - } - - @Override - public Object read_abstract_interface() { - return narrow().read_abstract_interface(); - } - - @Override - public Object read_abstract_interface(Class clz) { - return narrow().read_abstract_interface(clz); - } - - protected org.omg.CORBA_2_3.portable.InputStream narrow() { - if (in instanceof org.omg.CORBA_2_3.portable.InputStream) - return (org.omg.CORBA_2_3.portable.InputStream) in; - throw new NO_IMPLEMENT(); - } - - public org.omg.CORBA.portable.InputStream getProxiedInputStream() { - return in; - } - - protected final org.omg.CORBA.portable.InputStream in; -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java --- a/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Wed Nov 25 22:14:30 2009 -0800 @@ -86,8 +86,7 @@ // Explicitly check MBeanPermission for addNotificationListener // - checkMBeanPermission(getMBeanServerName(), - mbeanServer, name, "addNotificationListener"); + checkMBeanPermission(name, "addNotificationListener"); if (notificationAccessController != null) { notificationAccessController.addNotificationListener( connectionId, name, getSubject()); @@ -157,8 +156,7 @@ // Explicitly check MBeanPermission for removeNotificationListener // - checkMBeanPermission(getMBeanServerName(), - mbeanServer, name, "removeNotificationListener"); + checkMBeanPermission(name, "removeNotificationListener"); if (notificationAccessController != null) { notificationAccessController.removeNotificationListener( connectionId, name, getSubject()); @@ -333,8 +331,8 @@ * Explicitly check the MBeanPermission for * the current access control context. */ - public static void checkMBeanPermission(String serverName, - final MBeanServer mbs, final ObjectName name, final String actions) + public void checkMBeanPermission( + final ObjectName name, final String actions) throws InstanceNotFoundException, SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -345,7 +343,7 @@ new PrivilegedExceptionAction() { public ObjectInstance run() throws InstanceNotFoundException { - return mbs.getObjectInstance(name); + return mbeanServer.getObjectInstance(name); } }); } catch (PrivilegedActionException e) { @@ -353,7 +351,6 @@ } String classname = oi.getClassName(); MBeanPermission perm = new MBeanPermission( - serverName, classname, null, name, @@ -369,8 +366,7 @@ TargetedNotification tn) { try { if (checkNotificationEmission) { - checkMBeanPermission(getMBeanServerName(), - mbeanServer, name, "addNotificationListener"); + checkMBeanPermission(name, "addNotificationListener"); } if (notificationAccessController != null) { notificationAccessController.fetchNotification( @@ -432,27 +428,12 @@ } } - private String getMBeanServerName() { - if (mbeanServerName != null) return mbeanServerName; - else return (mbeanServerName = getMBeanServerName(mbeanServer)); - } - - private static String getMBeanServerName(final MBeanServer server) { - final PrivilegedAction action = new PrivilegedAction() { - public String run() { - return Util.getMBeanServerSecurityName(server); - } - }; - return AccessController.doPrivileged(action); - } - //------------------ // PRIVATE VARIABLES //------------------ private MBeanServer mbeanServer; - private volatile String mbeanServerName; private final String connectionId; @@ -462,7 +443,7 @@ private final static int[] listenerCounterLock = new int[0]; private NotificationBuffer notifBuffer; - private Map> listenerMap = + private final Map> listenerMap = new HashMap>(); private boolean terminated = false; diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java Wed Nov 25 22:14:30 2009 -0800 @@ -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 com.sun.jmx.remote.protocol.iiop; + +import org.omg.CORBA.ORB; +import org.omg.CORBA.portable.Delegate; +import javax.rmi.PortableRemoteObject; +import javax.rmi.CORBA.Stub; + +import java.util.Properties; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.NoSuchObjectException; + +import com.sun.jmx.remote.internal.IIOPProxy; + +/** + * An implementatin of IIOPProxy that simply delegates to the appropriate + * RMI-IIOP and CORBA APIs. + */ + +public class IIOPProxyImpl implements IIOPProxy { + public IIOPProxyImpl() { } + + @Override + public boolean isStub(Object obj) { + return (obj instanceof Stub); + } + + @Override + public Object getDelegate(Object stub) { + return ((Stub)stub)._get_delegate(); + } + + @Override + public void setDelegate(Object stub, Object delegate) { + ((Stub)stub)._set_delegate((Delegate)delegate); + } + + @Override + public Object getOrb(Object stub) { + try { + return ((Stub)stub)._orb(); + } catch (org.omg.CORBA.BAD_OPERATION x) { + throw new UnsupportedOperationException(x); + } + } + + @Override + public void connect(Object stub, Object orb) + throws RemoteException + { + ((Stub)stub).connect((ORB)orb); + } + + @Override + public boolean isOrb(Object obj) { + return (obj instanceof ORB); + } + + @Override + public Object createOrb(String[] args, Properties props) { + return ORB.init(args, props); + } + + @Override + public Object stringToObject(Object orb, String str) { + return ((ORB)orb).string_to_object(str); + } + + @Override + public String objectToString(Object orb, Object obj) { + return ((ORB)orb).object_to_string((org.omg.CORBA.Object)obj); + } + + @Override + @SuppressWarnings("unchecked") + public T narrow(Object narrowFrom, Class narrowTo) { + return (T)PortableRemoteObject.narrow(narrowFrom, narrowTo); + } + + @Override + public void exportObject(Remote obj) throws RemoteException { + PortableRemoteObject.exportObject(obj); + } + + @Override + public void unexportObject(Remote obj) throws NoSuchObjectException { + PortableRemoteObject.unexportObject(obj); + } + + @Override + public Remote toStub(Remote obj) throws NoSuchObjectException { + return PortableRemoteObject.toStub(obj); + } +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/remote/protocol/iiop/ProxyInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/jmx/remote/protocol/iiop/ProxyInputStream.java Wed Nov 25 22:14:30 2009 -0800 @@ -0,0 +1,241 @@ +/* + * Copyright 2003-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. + */ + +package com.sun.jmx.remote.protocol.iiop; + +import java.io.IOException; +import java.io.Serializable; +import java.math.BigDecimal; + +import org.omg.CORBA.Any; +import org.omg.CORBA.Context; +import org.omg.CORBA.NO_IMPLEMENT; +import org.omg.CORBA.ORB; +import org.omg.CORBA.TypeCode; +import org.omg.CORBA.portable.BoxedValueHelper; + +@SuppressWarnings({"deprecation", "rawtypes"}) +public class ProxyInputStream extends org.omg.CORBA_2_3.portable.InputStream { + public ProxyInputStream(org.omg.CORBA.portable.InputStream in) { + this.in = in; + } + + public boolean read_boolean() { + return in.read_boolean(); + } + + public char read_char() { + return in.read_char(); + } + + public char read_wchar() { + return in.read_wchar(); + } + + public byte read_octet() { + return in.read_octet(); + } + + public short read_short() { + return in.read_short(); + } + + public short read_ushort() { + return in.read_ushort(); + } + + public int read_long() { + return in.read_long(); + } + + public int read_ulong() { + return in.read_ulong(); + } + + public long read_longlong() { + return in.read_longlong(); + } + + public long read_ulonglong() { + return in.read_ulonglong(); + } + + public float read_float() { + return in.read_float(); + } + + public double read_double() { + return in.read_double(); + } + + public String read_string() { + return in.read_string(); + } + + public String read_wstring() { + return in.read_wstring(); + } + + public void read_boolean_array(boolean[] value, int offset, int length) { + in.read_boolean_array(value, offset, length); + } + + public void read_char_array(char[] value, int offset, int length) { + in.read_char_array(value, offset, length); + } + + public void read_wchar_array(char[] value, int offset, int length) { + in.read_wchar_array(value, offset, length); + } + + public void read_octet_array(byte[] value, int offset, int length) { + in.read_octet_array(value, offset, length); + } + + public void read_short_array(short[] value, int offset, int length) { + in.read_short_array(value, offset, length); + } + + public void read_ushort_array(short[] value, int offset, int length) { + in.read_ushort_array(value, offset, length); + } + + public void read_long_array(int[] value, int offset, int length) { + in.read_long_array(value, offset, length); + } + + public void read_ulong_array(int[] value, int offset, int length) { + in.read_ulong_array(value, offset, length); + } + + public void read_longlong_array(long[] value, int offset, int length) { + in.read_longlong_array(value, offset, length); + } + + public void read_ulonglong_array(long[] value, int offset, int length) { + in.read_ulonglong_array(value, offset, length); + } + + public void read_float_array(float[] value, int offset, int length) { + in.read_float_array(value, offset, length); + } + + public void read_double_array(double[] value, int offset, int length) { + in.read_double_array(value, offset, length); + } + + public org.omg.CORBA.Object read_Object() { + return in.read_Object(); + } + + public TypeCode read_TypeCode() { + return in.read_TypeCode(); + } + + public Any read_any() { + return in.read_any(); + } + + /** + * @deprecated + */ + @Override + @Deprecated + public org.omg.CORBA.Principal read_Principal() { + return in.read_Principal(); + } + + @Override + public int read() throws IOException { + return in.read(); + } + + @Override + public BigDecimal read_fixed() { + return in.read_fixed(); + } + + @Override + public Context read_Context() { + return in.read_Context(); + } + + @Override + public org.omg.CORBA.Object read_Object(java.lang.Class clz) { + return in.read_Object(clz); + } + + @Override + public ORB orb() { + return in.orb(); + } + + @Override + public Serializable read_value() { + return narrow().read_value(); + } + + @Override + public Serializable read_value(Class clz) { + return narrow().read_value(clz); + } + + @Override + public Serializable read_value(BoxedValueHelper factory) { + return narrow().read_value(factory); + } + + @Override + public Serializable read_value(String rep_id) { + return narrow().read_value(rep_id); + } + + @Override + public Serializable read_value(Serializable value) { + return narrow().read_value(value); + } + + @Override + public Object read_abstract_interface() { + return narrow().read_abstract_interface(); + } + + @Override + public Object read_abstract_interface(Class clz) { + return narrow().read_abstract_interface(clz); + } + + protected org.omg.CORBA_2_3.portable.InputStream narrow() { + if (in instanceof org.omg.CORBA_2_3.portable.InputStream) + return (org.omg.CORBA_2_3.portable.InputStream) in; + throw new NO_IMPLEMENT(); + } + + public org.omg.CORBA.portable.InputStream getProxiedInputStream() { + return in; + } + + protected final org.omg.CORBA.portable.InputStream in; +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/remote/util/EnvHelp.java --- a/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java Wed Nov 25 22:14:30 2009 -0800 @@ -781,25 +781,6 @@ } /** - * Returns true if the parameter JMXConnector.USE_EVENT_SERVICE is set to a - * String equals "true" by ignoring case in the map or in the System. - */ - public static boolean eventServiceEnabled(Map env) { - return computeBooleanFromString(env, JMXConnector.USE_EVENT_SERVICE, true); - } - - /** - * Returns true if the parameter JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE - * is set to a String equals "true" (ignores case). - * If the property DELEGATE_TO_EVENT_SERVICE is not set, returns - * a default value of "true". - */ - public static boolean delegateToEventService(Map env) { - return computeBooleanFromString(env, - JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE, true, true); - } - - /** *

Name of the attribute that specifies whether a connector server * should not prevent the VM from exiting */ @@ -817,46 +798,6 @@ ("true".equalsIgnoreCase((String)env.get(JMX_SERVER_DAEMON))); } -// /** -// *

Name of the attribute that specifies an EventRelay object to use. -// */ -// public static final String EVENT_RELAY = -// "jmx.remote.x.event.relay"; -// -// -// /** -// * Returns an EventRelay object. The default one is FetchingEventRelay. -// * If {@code EVENT_RELAY} is specified in {@code env} as a key, -// * its value will be returned as an EventRelay object, if the value is -// * not of type {@code EventRelay}, the default {@code FetchingEventRelay} -// * will be returned. -// * If {@code EVENT_RELAY} is not specified but {@code ENABLE_EVENT_RELAY} -// * is specified as a key and its value is , the default {@code FetchingEventRelay} -// * will be returned. -// */ -// public static EventRelay getEventRelay(Map env) { -// Map info = env == null ? -// Collections.EMPTY_MAP : env; -// -// Object o = env.get(EVENT_RELAY); -// if (o instanceof EventRelay) { -// return (EventRelay)o; -// } else if (o != null) { -// logger.warning("getEventRelay", -// "The user specified object is not an EventRelay object, " + -// "using the default class FetchingEventRelay."); -// -// return new FetchingEventRelay(); -// } -// -// if (enableEventRelay(env)) { -// return new FetchingEventRelay(); -// } -// -// return null; -// } - - private static final class SinkOutputStream extends OutputStream { public void write(byte[] b, int off, int len) {} public void write(int b) {} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java --- a/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java Wed Nov 25 21:27:06 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,469 +0,0 @@ -/* - * Copyright 2007-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. - */ - -package com.sun.jmx.remote.util; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.event.EventClientFactory; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Arrays; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.MBeanServerConnection; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.namespace.JMXNamespaces; - -/** - * Class EventClientConnection - a {@link Proxy} that wraps an - * {@link MBeanServerConnection} and an {@link EventClient}. - * All methods are routed to the underlying {@code MBeanServerConnection}, - * except add/remove notification listeners which are routed to the - * {@code EventClient}. - * The caller only sees an {@code MBeanServerConnection} which uses an - * {@code EventClient} behind the scenes. - * - * @author Sun Microsystems, Inc. - */ -public class EventClientConnection implements InvocationHandler, - EventClientFactory { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NOTIFICATION_LOGGER; - - private static final int NAMESPACE_SEPARATOR_LENGTH = - JMXNamespaces.NAMESPACE_SEPARATOR.length(); - - /** - * Creates a new {@code EventClientConnection}. - * @param connection The underlying MBeanServerConnection. - */ - public EventClientConnection(MBeanServerConnection connection) { - this(connection,null); - } - - /** - * Creates a new {@code EventClientConnection}. - * @param connection The underlying MBeanServerConnection. - * @param eventClientFactory a factory object that will be invoked - * to create an {@link EventClient} when needed. - * The {@code EventClient} is created lazily, when it is needed - * for the first time. If null, a default factory will be used - * (see {@link #createEventClient}). - */ - public EventClientConnection(MBeanServerConnection connection, - Callable eventClientFactory) { - - if (connection == null) { - throw new IllegalArgumentException("Null connection"); - } - this.connection = connection; - if (eventClientFactory == null) { - eventClientFactory = new Callable() { - public final EventClient call() throws Exception { - return createEventClient(EventClientConnection.this.connection); - } - }; - } - this.eventClientFactory = eventClientFactory; - this.lock = new ReentrantLock(); - } - - /** - *

The MBean server connection through which the methods of - * a proxy using this handler are forwarded.

- * - * @return the MBean server connection. - * - * @since 1.6 - */ - public MBeanServerConnection getMBeanServerConnection() { - return connection; - } - - - - - /** - * Creates a new EventClientConnection proxy instance. - * - * @param The underlying {@code MBeanServerConnection} - which should - * not be using the Event Service itself. - * @param interfaceClass {@code MBeanServerConnection.class}, or a subclass. - * @param eventClientFactory a factory used to create the EventClient. - * If null, a default factory is used (see {@link - * #createEventClient}). - * @return the new proxy instance, which will route add/remove notification - * listener calls through an {@code EventClient}. - * - */ - private static T - newProxyInstance(T connection, - Class interfaceClass, Callable eventClientFactory) { - final InvocationHandler handler = - new EventClientConnection(connection,eventClientFactory); - final Class[] interfaces = - new Class[] {interfaceClass, EventClientFactory.class}; - - Object proxy = - Proxy.newProxyInstance(interfaceClass.getClassLoader(), - interfaces, - handler); - return interfaceClass.cast(proxy); - } - - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - final String methodName = method.getName(); - - // add/remove notification listener are routed to the EventClient - if (methodName.equals("addNotificationListener") - || methodName.equals("removeNotificationListener")) { - final Class[] sig = method.getParameterTypes(); - if (sig.length>1 && - NotificationListener.class.isAssignableFrom(sig[1])) { - return invokeBroadcasterMethod(proxy,method,args); - } - } - - // subscribe/unsubscribe are also routed to the EventClient. - final Class clazz = method.getDeclaringClass(); - if (clazz.equals(EventClientFactory.class)) { - return invokeEventClientSubscriberMethod(proxy,method,args); - } - - // local or not: equals, toString, hashCode - if (shouldDoLocally(proxy, method)) - return doLocally(proxy, method, args); - - return call(connection,method,args); - } - - // The purpose of this method is to unwrap InvocationTargetException, - // in order to avoid throwing UndeclaredThrowableException for - // declared exceptions. - // - // When calling method.invoke(), any exception thrown by the invoked - // method will be wrapped in InvocationTargetException. If we don't - // unwrap this exception, the proxy will always throw - // UndeclaredThrowableException, even for runtime exceptions. - // - private Object call(final Object obj, final Method m, - final Object[] args) - throws Throwable { - try { - return m.invoke(obj,args); - } catch (InvocationTargetException x) { - final Throwable xx = x.getTargetException(); - if (xx == null) throw x; - else throw xx; - } - } - - /** - * Route add/remove notification listener to the event client. - **/ - private Object invokeBroadcasterMethod(Object proxy, Method method, - Object[] args) throws Exception { - final String methodName = method.getName(); - final int nargs = (args == null) ? 0 : args.length; - - if (nargs < 1) { - final String msg = - "Bad arg count: " + nargs; - throw new IllegalArgumentException(msg); - } - - final ObjectName mbean = (ObjectName) args[0]; - final EventClient evtClient = getEventClient(); - - // Fails if evtClient is null AND the MBean we try to listen to is - // in a subnamespace. We fail here because we know this will not - // work. - // - // Note that if the wrapped MBeanServerConnection points to a an - // earlier agent (JDK 1.6 or earlier), then the EventClient will - // be null (we can't use the event service with earlier JDKs). - // - // In principle a null evtClient indicates that the remote VM is of - // an earlier version, in which case it shouldn't contain any namespace. - // - // So having a null evtClient AND an MBean contained in a namespace is - // clearly an error case. - // - if (evtClient == null) { - final String domain = mbean.getDomain(); - final int index = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR); - if (index > -1 && index < - (domain.length()-NAMESPACE_SEPARATOR_LENGTH)) { - throw new UnsupportedOperationException(method.getName()+ - " on namespace "+domain.substring(0,index+ - NAMESPACE_SEPARATOR_LENGTH)); - } - } - - if (methodName.equals("addNotificationListener")) { - /* The various throws of IllegalArgumentException here - should not happen, since we know what the methods in - NotificationBroadcaster and NotificationEmitter - are. */ - if (nargs != 4) { - final String msg = - "Bad arg count to addNotificationListener: " + nargs; - throw new IllegalArgumentException(msg); - } - /* Other inconsistencies will produce ClassCastException - below. */ - - final NotificationListener listener = (NotificationListener) args[1]; - final NotificationFilter filter = (NotificationFilter) args[2]; - final Object handback = args[3]; - - if (evtClient != null) { - // general case - evtClient.addNotificationListener(mbean,listener,filter,handback); - } else { - // deprecated case. Only works for mbean in local namespace. - connection.addNotificationListener(mbean,listener,filter, - handback); - } - return null; - - } else if (methodName.equals("removeNotificationListener")) { - - /* NullPointerException if method with no args, but that - shouldn't happen because removeNL does have args. */ - NotificationListener listener = (NotificationListener) args[1]; - - switch (nargs) { - case 2: - if (evtClient != null) { - // general case - evtClient.removeNotificationListener(mbean,listener); - } else { - // deprecated case. Only works for mbean in local namespace. - connection.removeNotificationListener(mbean, listener); - } - return null; - - case 4: - NotificationFilter filter = (NotificationFilter) args[2]; - Object handback = args[3]; - if (evtClient != null) { - evtClient.removeNotificationListener(mbean, - listener, - filter, - handback); - } else { - connection.removeNotificationListener(mbean, - listener, - filter, - handback); - } - return null; - - default: - final String msg = - "Bad arg count to removeNotificationListener: " + nargs; - throw new IllegalArgumentException(msg); - } - - } else { - throw new IllegalArgumentException("Bad method name: " + - methodName); - } - } - - private boolean shouldDoLocally(Object proxy, Method method) { - final String methodName = method.getName(); - if ((methodName.equals("hashCode") || methodName.equals("toString")) - && method.getParameterTypes().length == 0 - && isLocal(proxy, method)) - return true; - if (methodName.equals("equals") - && Arrays.equals(method.getParameterTypes(), - new Class[] {Object.class}) - && isLocal(proxy, method)) - return true; - return false; - } - - private Object doLocally(Object proxy, Method method, Object[] args) { - final String methodName = method.getName(); - - if (methodName.equals("equals")) { - - if (this == args[0]) { - return true; - } - - if (!(args[0] instanceof Proxy)) { - return false; - } - - final InvocationHandler ihandler = - Proxy.getInvocationHandler(args[0]); - - if (ihandler == null || - !(ihandler instanceof EventClientConnection)) { - return false; - } - - final EventClientConnection handler = - (EventClientConnection)ihandler; - - return connection.equals(handler.connection) && - proxy.getClass().equals(args[0].getClass()); - } else if (methodName.equals("hashCode")) { - return connection.hashCode(); - } - - throw new RuntimeException("Unexpected method name: " + methodName); - } - - private static boolean isLocal(Object proxy, Method method) { - final Class[] interfaces = proxy.getClass().getInterfaces(); - if(interfaces == null) { - return true; - } - - final String methodName = method.getName(); - final Class[] params = method.getParameterTypes(); - for (Class intf : interfaces) { - try { - intf.getMethod(methodName, params); - return false; // found method in one of our interfaces - } catch (NoSuchMethodException nsme) { - // OK. - } - } - - return true; // did not find in any interface - } - - /** - * Return the EventClient used by this object. Can be null if the - * remote VM is of an earlier JDK version which doesn't have the - * event service.
- * This method will invoke the event client factory the first time - * it is called. - **/ - public final EventClient getEventClient() { - if (initialized) return client; - try { - if (!lock.tryLock(TRYLOCK_TIMEOUT,TimeUnit.SECONDS)) - throw new IllegalStateException("can't acquire lock"); - try { - client = eventClientFactory.call(); - initialized = true; - } finally { - lock.unlock(); - } - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new IllegalStateException("Can't create EventClient: "+x,x); - } - return client; - } - - /** - * Returns an event client for the wrapped {@code MBeanServerConnection}. - * This is the method invoked by the default event client factory. - * @param connection the wrapped {@code MBeanServerConnection}. - **/ - protected EventClient createEventClient(MBeanServerConnection connection) - throws Exception { - final ObjectName name = - EventClientDelegate.OBJECT_NAME; - if (connection.isRegistered(name)) { - return new EventClient(connection); - } - return null; - } - - /** - * Creates a new {@link MBeanServerConnection} that goes through an - * {@link EventClient} to receive/subscribe to notifications. - * @param connection the underlying {@link MBeanServerConnection}. - * The given connection shouldn't be already - * using an {@code EventClient}. - * @param eventClientFactory a factory object that will be invoked - * to create an {@link EventClient} when needed. - * The {@code EventClient} is created lazily, when it is needed - * for the first time. If null, a default factory will be used - * (see {@link #createEventClient}). - * @return the MBeanServerConnection. - **/ - public static MBeanServerConnection getEventConnectionFor( - MBeanServerConnection connection, - Callable eventClientFactory) { - if (connection instanceof EventClientFactory - && eventClientFactory != null) - throw new IllegalArgumentException("connection already uses EventClient"); - - if (connection instanceof EventClientFactory) - return connection; - - // create a new proxy using an event client. - // - if (LOG.isLoggable(Level.FINE)) - LOG.fine("Creating EventClient for: "+connection); - return newProxyInstance(connection, - MBeanServerConnection.class, - eventClientFactory); - } - - private Object invokeEventClientSubscriberMethod(Object proxy, - Method method, Object[] args) throws Throwable { - return call(this,method,args); - } - - // Maximum lock timeout in seconds. Obviously arbitrary. - // - private final static short TRYLOCK_TIMEOUT = 3; - - private final MBeanServerConnection connection; - private final Callable eventClientFactory; - private final Lock lock; - private volatile EventClient client = null; - private volatile boolean initialized = false; - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jndi/ldap/Connection.java --- a/src/share/classes/com/sun/jndi/ldap/Connection.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jndi/ldap/Connection.java Wed Nov 25 22:14:30 2009 -0800 @@ -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); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java --- a/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Wed Nov 25 22:14:30 2009 -0800 @@ -40,7 +40,6 @@ import java.security.Principal; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; -import javax.security.auth.kerberos.KerberosPrincipal; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; @@ -413,14 +412,15 @@ try { HostnameChecker checker = HostnameChecker.getInstance( HostnameChecker.TYPE_LDAP); - Principal principal = getPeerPrincipal(session); - if (principal instanceof KerberosPrincipal) { - if (!checker.match(hostname, (KerberosPrincipal) principal)) { + // Use ciphersuite to determine whether Kerberos is active. + if (session.getCipherSuite().startsWith("TLS_KRB5")) { + Principal principal = getPeerPrincipal(session); + if (!checker.match(hostname, principal)) { throw new SSLPeerUnverifiedException( "hostname of the kerberos principal:" + principal + " does not match the hostname:" + hostname); } - } else { + } else { // X.509 // get the subject's certificate certs = session.getPeerCertificates(); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/naming/internal/ResourceManager.java --- a/src/share/classes/com/sun/naming/internal/ResourceManager.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/naming/internal/ResourceManager.java Wed Nov 25 22:14:30 2009 -0800 @@ -25,11 +25,12 @@ package com.sun.naming.internal; -import java.applet.Applet; import java.io.InputStream; import java.io.IOException; import java.net.URL; import java.lang.ref.WeakReference; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; @@ -112,6 +113,52 @@ private static final WeakHashMap urlFactoryCache = new WeakHashMap(11); private static final WeakReference NO_FACTORY = new WeakReference(null); + /** + * A class to allow JNDI properties be specified as applet parameters + * without creating a static dependency on java.applet. + */ + private static class AppletParameter { + private static final Class clazz = getClass("java.applet.Applet"); + private static final Method getMethod = + getMethod(clazz, "getParameter", String.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; + } + } + + /** + * Returns the value of the applet's named parameter. + */ + static Object get(Object applet, String name) { + // if clazz is null then applet cannot be an Applet. + if (clazz == null || !clazz.isInstance(applet)) + throw new ClassCastException(applet.getClass().getName()); + try { + return getMethod.invoke(applet, name); + } catch (InvocationTargetException e) { + throw new AssertionError(e); + } catch (IllegalAccessException iae) { + throw new AssertionError(iae); + } + } + } // There should be no instances of this class. private ResourceManager() { @@ -143,7 +190,7 @@ if (env == null) { env = new Hashtable(11); } - Applet applet = (Applet)env.get(Context.APPLET); + Object applet = env.get(Context.APPLET); // Merge property values from env param, applet params, and system // properties. The first value wins: there's no concatenation of @@ -157,7 +204,7 @@ Object val = env.get(props[i]); if (val == null) { if (applet != null) { - val = applet.getParameter(props[i]); + val = AppletParameter.get(applet, props[i]); } if (val == null) { // Read system property. diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java --- a/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java Wed Nov 25 22:14:30 2009 -0800 @@ -36,7 +36,6 @@ import java.security.cert.*; import javax.security.auth.x500.X500Principal; -import javax.security.auth.kerberos.KerberosPrincipal; import sun.security.util.HostnameChecker; import sun.security.util.DerValue; @@ -109,20 +108,18 @@ /* * In com.sun.net.ssl.HostnameVerifier the method is defined * as verify(String urlHostname, String certHostname). - * This means we need to extract the hostname from the certificate - * in this wrapper + * This means we need to extract the hostname from the X.509 certificate + * or from the Kerberos principal name, in this wrapper. */ public boolean verify(String hostname, javax.net.ssl.SSLSession session) { try { String serverName; - Principal principal = getPeerPrincipal(session); - // X.500 principal or Kerberos principal. - // (Use ciphersuite check to determine whether Kerberos is present.) - if (session.getCipherSuite().startsWith("TLS_KRB5") && - principal instanceof KerberosPrincipal) { + // Use ciphersuite to determine whether Kerberos is active. + if (session.getCipherSuite().startsWith("TLS_KRB5")) { serverName = - HostnameChecker.getServerName((KerberosPrincipal)principal); - } else { + HostnameChecker.getServerName(getPeerPrincipal(session)); + + } else { // X.509 Certificate[] serverChain = session.getPeerCertificates(); if ((serverChain == null) || (serverChain.length == 0)) { return false; diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/awt/KeyboardFocusManager.java --- a/src/share/classes/java/awt/KeyboardFocusManager.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/awt/KeyboardFocusManager.java Wed Nov 25 22:14:30 2009 -0800 @@ -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"); } } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/awt/color/ICC_Profile.java --- a/src/share/classes/java/awt/color/ICC_Profile.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/awt/color/ICC_Profile.java Wed Nov 25 22:14:30 2009 -0800 @@ -865,7 +865,9 @@ case ColorSpace.CS_PYCC: synchronized(ICC_Profile.class) { if (PYCCprofile == null) { - if (getProfileFile("PYCC.pf") != null) { + if (BootClassLoaderHook.getHook() != null || + 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 pa = new PrivilegedAction() { + 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,85 +1799,104 @@ * 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 == 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 == null) || (!f.isFile()))) { dir = st.nextToken(); fullPath = dir + File.separatorChar + fileName; f = new File(fullPath); } } - if ((!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())) { - dir = st.nextToken(); - fullPath = dir + File.separatorChar + fileName; - f = new File(fullPath); - } - } - - if (!f.isFile()) { /* try the directory of built-in profiles */ - dir = System.getProperty("java.home") + - File.separatorChar + "lib" + File.separatorChar + "cmm"; - fullPath = dir + File.separatorChar + fileName; - f = new File(fullPath); - if (!f.isFile()) { - //make sure file was installed in the kernel mode - BootClassLoaderHook hook = BootClassLoaderHook.getHook(); - if (hook.getHook() != null) { - hook.prefetchFile("lib/cmm/"+fileName); - } - } - } - - 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 + BootClassLoaderHook hook = BootClassLoaderHook.getHook(); + if (hook != null) { + hook.prefetchFile("lib/cmm/"+fileName); + } + } + 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() { + public Boolean run() { + return getStandardProfileFile(fileName) != null; + } + }); + } + /* * Serialization support. diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/awt/font/NumericShaper.java --- a/src/share/classes/java/awt/font/NumericShaper.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/awt/font/NumericShaper.java Wed Nov 25 22:14:30 2009 -0800 @@ -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 @@ -25,6 +25,13 @@ package java.awt.font; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.Set; + /** * The NumericShaper class is used to convert Latin-1 (European) * digits to other Unicode decimal digits. Users of this class will @@ -64,13 +71,261 @@ * NumericShaper.getContextualShaper(NumericShaper.ARABIC | * NumericShaper.TAMIL, * NumericShaper.EUROPEAN); - * shaper.shape(text. start, count); + * shaper.shape(text, start, count); * * + *

Bit mask- and enum-based Unicode ranges

+ * + *

This class supports two different programming interfaces to + * represent Unicode ranges for script-specific digits: bit + * mask-based ones, such as {@link #ARABIC NumericShaper.ARABIC}, and + * enum-based ones, such as {@link NumericShaper.Range#ARABIC}. + * Multiple ranges can be specified by ORing bit mask-based constants, + * such as: + *

+ * NumericShaper.ARABIC | NumericShaper.TAMIL
+ * 
+ * or creating a {@code Set} with the {@link NumericShaper.Range} + * constants, such as: + *
+ * EnumSet.of(NumericShaper.Scirpt.ARABIC, NumericShaper.Range.TAMIL)
+ * 
+ * The enum-based ranges are a super set of the bit mask-based ones. + * + *

If the two interfaces are mixed (including serialization), + * Unicode range values are mapped to their counterparts where such + * mapping is possible, such as {@code NumericShaper.Range.ARABIC} + * from/to {@code NumericShaper.ARABIC}. If any unmappable range + * values are specified, such as {@code NumericShaper.Range.BALINESE}, + * those ranges are ignored. + * * @since 1.4 */ public final class NumericShaper implements java.io.Serializable { + /** + * A {@code NumericShaper.Range} represents a Unicode range of a + * script having its own decimal digits. For example, the {@link + * NumericShaper.Range#THAI} range has the Thai digits, THAI DIGIT + * ZERO (U+0E50) to THAI DIGIT NINE (U+0E59). + * + *

The Range enum replaces the traditional bit + * mask-based values (e.g., {@link NumericShaper#ARABIC}), and + * supports more Unicode ranges than the bit mask-based ones. For + * example, the following code using the bit mask: + *

+     * NumericShaper.getContextualShaper(NumericShaper.ARABIC |
+     *                                     NumericShaper.TAMIL,
+     *                                   NumericShaper.EUROPEAN);
+     * 
+ * can be written using this enum as: + *
+     * NumericShaper.getContextualShaper(EnumSet.of(
+     *                                     NumericShaper.Range.ARABIC,
+     *                                     NumericShaper.Range.TAMIL),
+     *                                   NumericShaper.Range.EUROPEAN);
+     * 
+ * + * @since 1.7 + */ + public static enum Range { + /** + * The Latin (European) range with the Latin (ASCII) digits. + */ + EUROPEAN ('\u0030', '\u0000', '\u0300'), + /** + * The Arabic range with the Arabic-Indic digits. + */ + ARABIC ('\u0660', '\u0600', '\u0780'), + /** + * The Arabic range with the Eastern Arabic-Indic digits. + */ + EASTERN_ARABIC ('\u06f0', '\u0600', '\u0780'), + /** + * The Devanagari range with the Devanagari digits. + */ + DEVANAGARI ('\u0966', '\u0900', '\u0980'), + /** + * The Bengali range with the Bengali digits. + */ + BENGALI ('\u09e6', '\u0980', '\u0a00'), + /** + * The Gurmukhi range with the Gurmukhi digits. + */ + GURMUKHI ('\u0a66', '\u0a00', '\u0a80'), + /** + * The Gujarati range with the Gujarati digits. + */ + GUJARATI ('\u0ae6', '\u0b00', '\u0b80'), + /** + * The Oriya range with the Oriya digits. + */ + ORIYA ('\u0b66', '\u0b00', '\u0b80'), + /** + * The Tamil range with the Tamil digits. + */ + TAMIL ('\u0be6', '\u0b80', '\u0c00'), + /** + * The Telugu range with the Telugu digits. + */ + TELUGU ('\u0c66', '\u0c00', '\u0c80'), + /** + * The Kannada range with the Kannada digits. + */ + KANNADA ('\u0ce6', '\u0c80', '\u0d00'), + /** + * The Malayalam range with the Malayalam digits. + */ + MALAYALAM ('\u0d66', '\u0d00', '\u0d80'), + /** + * The Thai range with the Thai digits. + */ + THAI ('\u0e50', '\u0e00', '\u0e80'), + /** + * The Lao range with the Lao digits. + */ + LAO ('\u0ed0', '\u0e80', '\u0f00'), + /** + * The Tibetan range with the Tibetan digits. + */ + TIBETAN ('\u0f20', '\u0f00', '\u1000'), + /** + * The Myanmar range with the Myanmar digits. + */ + MYANMAR ('\u1040', '\u1000', '\u1080'), + /** + * The Ethiopic range with the Ethiopic digits. Ethiopic + * does not have a decimal digit 0 so Latin (European) 0 is + * used. + */ + ETHIOPIC ('\u1369', '\u1200', '\u1380') { + @Override + char getNumericBase() { return 1; } + }, + /** + * The Khmer range with the Khmer digits. + */ + KHMER ('\u17e0', '\u1780', '\u1800'), + /** + * The Mongolian range with the Mongolian digits. + */ + MONGOLIAN ('\u1810', '\u1800', '\u1900'), + /** + * The N'Ko range with the N'Ko digits. + */ + NKO ('\u07c0', '\u07c0', '\u0800'), + /** + * The Myanmar range with the Myanmar Shan digits. + */ + MYANMAR_SHAN ('\u1090', '\u1000', '\u10a0'), + /** + * The Limbu range with the Limbu digits. + */ + LIMBU ('\u1946', '\u1900', '\u1950'), + /** + * The New Tai Lue range with the New Tai Lue digits. + */ + NEW_TAI_LUE ('\u19d0', '\u1980', '\u19e0'), + /** + * The Balinese range with the Balinese digits. + */ + BALINESE ('\u1b50', '\u1b00', '\u1b80'), + /** + * The Sundanese range with the Sundanese digits. + */ + SUNDANESE ('\u1bb0', '\u1b80', '\u1bc0'), + /** + * The Lepcha range with the Lepcha digits. + */ + LEPCHA ('\u1c40', '\u1c00', '\u1c50'), + /** + * The Ol Chiki range with the Ol Chiki digits. + */ + OL_CHIKI ('\u1c50', '\u1c50', '\u1c80'), + /** + * The Vai range with the Vai digits. + */ + VAI ('\ua620', '\ua500', '\ua640'), + /** + * The Saurashtra range with the Saurashtra digits. + */ + SAURASHTRA ('\ua8d0', '\ua880', '\ua8e0'), + /** + * The Kayah Li range with the Kayah Li digits. + */ + KAYAH_LI ('\ua900', '\ua900', '\ua930'), + /** + * The Cham range with the Cham digits. + */ + CHAM ('\uaa50', '\uaa00', '\uaa60'); + + private static final Range[] ranges = Range.class.getEnumConstants(); + static { + // sort ranges[] by base for binary search + Arrays.sort(ranges, + new Comparator() { + public int compare(Range s1, Range s2) { + return s1.base > s2.base ? 1 : s1.base == s2.base ? 0 : -1; + } + }); + } + + private static int toRangeIndex(Range script) { + int index = script.ordinal(); + return index < NUM_KEYS ? index : -1; + } + + private static Range indexToRange(int index) { + return index < NUM_KEYS ? Range.values()[index] : null; + } + + private static int toRangeMask(Set ranges) { + int m = 0; + for (Range range : ranges) { + int index = range.ordinal(); + if (index < NUM_KEYS) { + m |= 1 << index; + } + } + return m; + } + + private static Set maskToRangeSet(int mask) { + Set set = EnumSet.noneOf(Range.class); + Range[] a = Range.values(); + for (int i = 0; i < NUM_KEYS; i++) { + if ((mask & (1 << i)) != 0) { + set.add(a[i]); + } + } + return set; + } + + // base character of range digits + private final int base; + // Unicode range + private final int start, // inclusive + end; // exclusive + + private Range(int base, int start, int end) { + this.base = base - ('0' + getNumericBase()); + this.start = start; + this.end = end; + } + + private int getDigitBase() { + return base; + } + + char getNumericBase() { + return 0; + } + + private boolean inRange(int c) { + return start <= c && c < end; + } + } + /** index of context for contextual shaping - values range from 0 to 18 */ private int key; @@ -79,6 +334,25 @@ */ private int mask; + /** + * The context {@code Range} for contextual shaping or the {@code + * Range} for non-contextual shaping. {@code null} for the bit + * mask-based API. + * + * @since 1.7 + */ + private Range shapingRange; + + /** + * {@code Set} indicating which Unicode ranges to + * shape. {@code null} for the bit mask-based API. + * + * @since 1.7 + */ + private transient Set rangeSet; + + private static final long serialVersionUID = -8022764705923730308L; + /** Identifies the Latin-1 (European) and extended range, and * Latin-1 (European) decimal base. */ @@ -105,9 +379,8 @@ /** Identifies the ORIYA range and decimal base. */ public static final int ORIYA = 1<<7; - /** Identifies the TAMIL range and decimal base. Tamil does not have a - * decimal digit 0 so Latin-1 (European) 0 is used. - */ + /** Identifies the TAMIL range and decimal base. */ + // TAMIL DIGIT ZERO was added in Unicode 4.1 public static final int TAMIL = 1<<8; /** Identifies the TELUGU range and decimal base. */ @@ -140,7 +413,12 @@ /** Identifies the MONGOLIAN range and decimal base. */ public static final int MONGOLIAN = 1<<18; - /** Identifies all ranges, for full contextual shaping. */ + /** Identifies all ranges, for full contextual shaping. + * + *

This constant specifies all of the bit mask-based + * ranges. Use {@code EmunSet.allOf(NumericShaper.Range.class)} to + * specify all of the enum-based ranges. + */ public static final int ALL_RANGES = 0x0007ffff; private static final int EUROPEAN_KEY = 0; @@ -163,42 +441,20 @@ private static final int KHMER_KEY = 17; private static final int MONGOLIAN_KEY = 18; - private static final int NUM_KEYS = 19; - - private static final String[] keyNames = { - "EUROPEAN", - "ARABIC", - "EASTERN_ARABIC", - "DEVANAGARI", - "BENGALI", - "GURMUKHI", - "GUJARATI", - "ORIYA", - "TAMIL", - "TELUGU", - "KANNADA", - "MALAYALAM", - "THAI", - "LAO", - "TIBETAN", - "MYANMAR", - "ETHIOPIC", - "KHMER", - "MONGOLIAN" - }; + private static final int NUM_KEYS = MONGOLIAN_KEY + 1; // fixed private static final int CONTEXTUAL_MASK = 1<<31; private static final char[] bases = { '\u0030' - '\u0030', // EUROPEAN - '\u0660' - '\u0030', // ARABIC - '\u06f0' - '\u0030', // EASTERN_ARABIC + '\u0660' - '\u0030', // ARABIC-INDIC + '\u06f0' - '\u0030', // EXTENDED ARABIC-INDIC (EASTERN_ARABIC) '\u0966' - '\u0030', // DEVANAGARI '\u09e6' - '\u0030', // BENGALI '\u0a66' - '\u0030', // GURMUKHI '\u0ae6' - '\u0030', // GUJARATI '\u0b66' - '\u0030', // ORIYA - '\u0be7' - '\u0030', // TAMIL - note missing zero + '\u0be6' - '\u0030', // TAMIL - zero was added in Unicode 4.1 '\u0c66' - '\u0030', // TELUGU '\u0ce6' - '\u0030', // KANNADA '\u0d66' - '\u0030', // MALAYALAM @@ -206,7 +462,7 @@ '\u0ed0' - '\u0030', // LAO '\u0f20' - '\u0030', // TIBETAN '\u1040' - '\u0030', // MYANMAR - '\u1369' - '\u0030', // ETHIOPIC + '\u1369' - '\u0031', // ETHIOPIC - no zero '\u17e0' - '\u0030', // KHMER '\u1810' - '\u0030', // MONGOLIAN }; @@ -215,14 +471,14 @@ private static final char[] contexts = { '\u0000', '\u0300', // 'EUROPEAN' (really latin-1 and extended) - '\u0600', '\u0700', // ARABIC - '\u0600', '\u0700', // EASTERN_ARABIC -- note overlap with arabic + '\u0600', '\u0780', // ARABIC + '\u0600', '\u0780', // EASTERN_ARABIC -- note overlap with arabic '\u0900', '\u0980', // DEVANAGARI '\u0980', '\u0a00', // BENGALI '\u0a00', '\u0a80', // GURMUKHI '\u0a80', '\u0b00', // GUJARATI '\u0b00', '\u0b80', // ORIYA - '\u0b80', '\u0c00', // TAMIL - note missing zero + '\u0b80', '\u0c00', // TAMIL '\u0c00', '\u0c80', // TELUGU '\u0c80', '\u0d00', // KANNADA '\u0d00', '\u0d80', // MALAYALAM @@ -230,7 +486,7 @@ '\u0e80', '\u0f00', // LAO '\u0f00', '\u1000', // TIBETAN '\u1000', '\u1080', // MYANMAR - '\u1200', '\u1380', // ETHIOPIC + '\u1200', '\u1380', // ETHIOPIC - note missing zero '\u1780', '\u1800', // KHMER '\u1800', '\u1900', // MONGOLIAN '\uffff', @@ -254,378 +510,290 @@ return (ctCache & 0x1) == 0 ? (ctCache / 2) : EUROPEAN_KEY; } + // cache for the NumericShaper.Range version + private transient volatile Range currentRange = Range.EUROPEAN; + + private Range rangeForCodePoint(int codepoint) { + Range range = currentRange; + if (range.inRange(codepoint)) { + return range; + } + + final Range[] ranges = Range.ranges; + int lo = 0; + int hi = ranges.length - 1; + while (lo <= hi) { + int mid = (lo + hi) / 2; + range = ranges[mid]; + if (codepoint < range.start) { + hi = mid - 1; + } else if (codepoint >= range.end) { + lo = mid + 1; + } else { + currentRange = range; + return range; + } + } + return Range.EUROPEAN; + } + /* * A range table of strong directional characters (types L, R, AL). * Even (left) indexes are starts of ranges of non-strong-directional (or undefined) * characters, odd (right) indexes are starts of ranges of strong directional * characters. */ - private static char[] strongTable = { - '\u0000', '\u0041', - '\u005b', '\u0061', - '\u007b', '\u00aa', - '\u00ab', '\u00b5', - '\u00b6', '\u00ba', - '\u00bb', '\u00c0', - '\u00d7', '\u00d8', - '\u00f7', '\u00f8', - '\u0220', '\u0222', - '\u0234', '\u0250', - '\u02ae', '\u02b0', - '\u02b9', '\u02bb', - '\u02c2', '\u02d0', - '\u02d2', '\u02e0', - '\u02e5', '\u02ee', - '\u02ef', '\u037a', - '\u037b', '\u0386', - '\u0387', '\u0388', - '\u038b', '\u038c', - '\u038d', '\u038e', - '\u03a2', '\u03a3', - '\u03cf', '\u03d0', - '\u03d8', '\u03da', - '\u03f4', '\u0400', - '\u0483', '\u048c', - '\u04c5', '\u04c7', - '\u04c9', '\u04cb', - '\u04cd', '\u04d0', - '\u04f6', '\u04f8', - '\u04fa', '\u0531', - '\u0557', '\u0559', - '\u0560', '\u0561', - '\u0588', '\u0589', - '\u058a', '\u05be', - '\u05bf', '\u05c0', - '\u05c1', '\u05c3', - '\u05c4', '\u05d0', - '\u05eb', '\u05f0', - '\u05f5', '\u061b', - '\u061c', '\u061f', - '\u0620', '\u0621', - '\u063b', '\u0640', - '\u064b', '\u066d', - '\u066e', '\u0671', - '\u06d6', '\u06e5', - '\u06e7', '\u06fa', - '\u06ff', '\u0700', - '\u070e', '\u0710', - '\u0711', '\u0712', - '\u072d', '\u0780', - '\u07a6', '\u0903', - '\u0904', '\u0905', - '\u093a', '\u093d', - '\u0941', '\u0949', - '\u094d', '\u0950', - '\u0951', '\u0958', - '\u0962', '\u0964', - '\u0971', '\u0982', - '\u0984', '\u0985', - '\u098d', '\u098f', - '\u0991', '\u0993', - '\u09a9', '\u09aa', - '\u09b1', '\u09b2', - '\u09b3', '\u09b6', - '\u09ba', '\u09be', - '\u09c1', '\u09c7', - '\u09c9', '\u09cb', - '\u09cd', '\u09d7', - '\u09d8', '\u09dc', - '\u09de', '\u09df', - '\u09e2', '\u09e6', - '\u09f2', '\u09f4', - '\u09fb', '\u0a05', - '\u0a0b', '\u0a0f', - '\u0a11', '\u0a13', - '\u0a29', '\u0a2a', - '\u0a31', '\u0a32', - '\u0a34', '\u0a35', - '\u0a37', '\u0a38', - '\u0a3a', '\u0a3e', - '\u0a41', '\u0a59', - '\u0a5d', '\u0a5e', - '\u0a5f', '\u0a66', - '\u0a70', '\u0a72', - '\u0a75', '\u0a83', - '\u0a84', '\u0a85', - '\u0a8c', '\u0a8d', - '\u0a8e', '\u0a8f', - '\u0a92', '\u0a93', - '\u0aa9', '\u0aaa', - '\u0ab1', '\u0ab2', - '\u0ab4', '\u0ab5', - '\u0aba', '\u0abd', - '\u0ac1', '\u0ac9', - '\u0aca', '\u0acb', - '\u0acd', '\u0ad0', - '\u0ad1', '\u0ae0', - '\u0ae1', '\u0ae6', - '\u0af0', '\u0b02', - '\u0b04', '\u0b05', - '\u0b0d', '\u0b0f', - '\u0b11', '\u0b13', - '\u0b29', '\u0b2a', - '\u0b31', '\u0b32', - '\u0b34', '\u0b36', - '\u0b3a', '\u0b3d', - '\u0b3f', '\u0b40', - '\u0b41', '\u0b47', - '\u0b49', '\u0b4b', - '\u0b4d', '\u0b57', - '\u0b58', '\u0b5c', - '\u0b5e', '\u0b5f', - '\u0b62', '\u0b66', - '\u0b71', '\u0b83', - '\u0b84', '\u0b85', - '\u0b8b', '\u0b8e', - '\u0b91', '\u0b92', - '\u0b96', '\u0b99', - '\u0b9b', '\u0b9c', - '\u0b9d', '\u0b9e', - '\u0ba0', '\u0ba3', - '\u0ba5', '\u0ba8', - '\u0bab', '\u0bae', - '\u0bb6', '\u0bb7', - '\u0bba', '\u0bbe', - '\u0bc0', '\u0bc1', - '\u0bc3', '\u0bc6', - '\u0bc9', '\u0bca', - '\u0bcd', '\u0bd7', - '\u0bd8', '\u0be7', - '\u0bf3', '\u0c01', - '\u0c04', '\u0c05', - '\u0c0d', '\u0c0e', - '\u0c11', '\u0c12', - '\u0c29', '\u0c2a', - '\u0c34', '\u0c35', - '\u0c3a', '\u0c41', - '\u0c45', '\u0c60', - '\u0c62', '\u0c66', - '\u0c70', '\u0c82', - '\u0c84', '\u0c85', - '\u0c8d', '\u0c8e', - '\u0c91', '\u0c92', - '\u0ca9', '\u0caa', - '\u0cb4', '\u0cb5', - '\u0cba', '\u0cbe', - '\u0cbf', '\u0cc0', - '\u0cc5', '\u0cc7', - '\u0cc9', '\u0cca', - '\u0ccc', '\u0cd5', - '\u0cd7', '\u0cde', - '\u0cdf', '\u0ce0', - '\u0ce2', '\u0ce6', - '\u0cf0', '\u0d02', - '\u0d04', '\u0d05', - '\u0d0d', '\u0d0e', - '\u0d11', '\u0d12', - '\u0d29', '\u0d2a', - '\u0d3a', '\u0d3e', - '\u0d41', '\u0d46', - '\u0d49', '\u0d4a', - '\u0d4d', '\u0d57', - '\u0d58', '\u0d60', - '\u0d62', '\u0d66', - '\u0d70', '\u0d82', - '\u0d84', '\u0d85', - '\u0d97', '\u0d9a', - '\u0db2', '\u0db3', - '\u0dbc', '\u0dbd', - '\u0dbe', '\u0dc0', - '\u0dc7', '\u0dcf', - '\u0dd2', '\u0dd8', - '\u0de0', '\u0df2', - '\u0df5', '\u0e01', - '\u0e31', '\u0e32', - '\u0e34', '\u0e40', - '\u0e47', '\u0e4f', - '\u0e5c', '\u0e81', - '\u0e83', '\u0e84', - '\u0e85', '\u0e87', - '\u0e89', '\u0e8a', - '\u0e8b', '\u0e8d', - '\u0e8e', '\u0e94', - '\u0e98', '\u0e99', - '\u0ea0', '\u0ea1', - '\u0ea4', '\u0ea5', - '\u0ea6', '\u0ea7', - '\u0ea8', '\u0eaa', - '\u0eac', '\u0ead', - '\u0eb1', '\u0eb2', - '\u0eb4', '\u0ebd', - '\u0ebe', '\u0ec0', - '\u0ec5', '\u0ec6', - '\u0ec7', '\u0ed0', - '\u0eda', '\u0edc', - '\u0ede', '\u0f00', - '\u0f18', '\u0f1a', - '\u0f35', '\u0f36', - '\u0f37', '\u0f38', - '\u0f39', '\u0f3e', - '\u0f48', '\u0f49', - '\u0f6b', '\u0f7f', - '\u0f80', '\u0f85', - '\u0f86', '\u0f88', - '\u0f8c', '\u0fbe', - '\u0fc6', '\u0fc7', - '\u0fcd', '\u0fcf', - '\u0fd0', '\u1000', - '\u1022', '\u1023', - '\u1028', '\u1029', - '\u102b', '\u102c', - '\u102d', '\u1031', - '\u1032', '\u1038', - '\u1039', '\u1040', - '\u1058', '\u10a0', - '\u10c6', '\u10d0', - '\u10f7', '\u10fb', - '\u10fc', '\u1100', - '\u115a', '\u115f', - '\u11a3', '\u11a8', - '\u11fa', '\u1200', - '\u1207', '\u1208', - '\u1247', '\u1248', - '\u1249', '\u124a', - '\u124e', '\u1250', - '\u1257', '\u1258', - '\u1259', '\u125a', - '\u125e', '\u1260', - '\u1287', '\u1288', - '\u1289', '\u128a', - '\u128e', '\u1290', - '\u12af', '\u12b0', - '\u12b1', '\u12b2', - '\u12b6', '\u12b8', - '\u12bf', '\u12c0', - '\u12c1', '\u12c2', - '\u12c6', '\u12c8', - '\u12cf', '\u12d0', - '\u12d7', '\u12d8', - '\u12ef', '\u12f0', - '\u130f', '\u1310', - '\u1311', '\u1312', - '\u1316', '\u1318', - '\u131f', '\u1320', - '\u1347', '\u1348', - '\u135b', '\u1361', - '\u137d', '\u13a0', - '\u13f5', '\u1401', - '\u1677', '\u1681', - '\u169b', '\u16a0', - '\u16f1', '\u1780', - '\u17b7', '\u17be', - '\u17c6', '\u17c7', - '\u17c9', '\u17d4', - '\u17db', '\u17dc', - '\u17dd', '\u17e0', - '\u17ea', '\u1810', - '\u181a', '\u1820', - '\u1878', '\u1880', - '\u18a9', '\u1e00', - '\u1e9c', '\u1ea0', - '\u1efa', '\u1f00', - '\u1f16', '\u1f18', - '\u1f1e', '\u1f20', - '\u1f46', '\u1f48', - '\u1f4e', '\u1f50', - '\u1f58', '\u1f59', - '\u1f5a', '\u1f5b', - '\u1f5c', '\u1f5d', - '\u1f5e', '\u1f5f', - '\u1f7e', '\u1f80', - '\u1fb5', '\u1fb6', - '\u1fbd', '\u1fbe', - '\u1fbf', '\u1fc2', - '\u1fc5', '\u1fc6', - '\u1fcd', '\u1fd0', - '\u1fd4', '\u1fd6', - '\u1fdc', '\u1fe0', - '\u1fed', '\u1ff2', - '\u1ff5', '\u1ff6', - '\u1ffd', '\u200e', - '\u2010', '\u207f', - '\u2080', '\u2102', - '\u2103', '\u2107', - '\u2108', '\u210a', - '\u2114', '\u2115', - '\u2116', '\u2119', - '\u211e', '\u2124', - '\u2125', '\u2126', - '\u2127', '\u2128', - '\u2129', '\u212a', - '\u212e', '\u212f', - '\u2132', '\u2133', - '\u213a', '\u2160', - '\u2184', '\u2336', - '\u237b', '\u2395', - '\u2396', '\u249c', - '\u24ea', '\u3005', - '\u3008', '\u3021', - '\u302a', '\u3031', - '\u3036', '\u3038', - '\u303b', '\u3041', - '\u3095', '\u309d', - '\u309f', '\u30a1', - '\u30fb', '\u30fc', - '\u30ff', '\u3105', - '\u312d', '\u3131', - '\u318f', '\u3190', - '\u31b8', '\u3200', - '\u321d', '\u3220', - '\u3244', '\u3260', - '\u327c', '\u327f', - '\u32b1', '\u32c0', - '\u32cc', '\u32d0', - '\u32ff', '\u3300', - '\u3377', '\u337b', - '\u33de', '\u33e0', - '\u33ff', '\u3400', - '\u4db6', '\u4e00', - '\u9fa6', '\ua000', - '\ua48d', '\uac00', - '\ud7a4', '\uf900', - '\ufa2e', '\ufb00', - '\ufb07', '\ufb13', - '\ufb18', '\ufb1d', - '\ufb1e', '\ufb1f', - '\ufb29', '\ufb2a', - '\ufb37', '\ufb38', - '\ufb3d', '\ufb3e', - '\ufb3f', '\ufb40', - '\ufb42', '\ufb43', - '\ufb45', '\ufb46', - '\ufbb2', '\ufbd3', - '\ufd3e', '\ufd50', - '\ufd90', '\ufd92', - '\ufdc8', '\ufdf0', - '\ufdfc', '\ufe70', - '\ufe73', '\ufe74', - '\ufe75', '\ufe76', - '\ufefd', '\uff21', - '\uff3b', '\uff41', - '\uff5b', '\uff66', - '\uffbf', '\uffc2', - '\uffc8', '\uffca', - '\uffd0', '\uffd2', - '\uffd8', '\uffda', - '\uffdd', '\uffff' // last entry is sentinel, actually never checked + private static int[] strongTable = { + 0x0000, 0x0041, + 0x005b, 0x0061, + 0x007b, 0x00aa, + 0x00ab, 0x00b5, + 0x00b6, 0x00ba, + 0x00bb, 0x00c0, + 0x00d7, 0x00d8, + 0x00f7, 0x00f8, + 0x02b9, 0x02bb, + 0x02c2, 0x02d0, + 0x02d2, 0x02e0, + 0x02e5, 0x02ee, + 0x02ef, 0x0370, + 0x0374, 0x0376, + 0x037e, 0x0386, + 0x0387, 0x0388, + 0x03f6, 0x03f7, + 0x0483, 0x048a, + 0x058a, 0x05be, + 0x05bf, 0x05c0, + 0x05c1, 0x05c3, + 0x05c4, 0x05c6, + 0x05c7, 0x05d0, + 0x0600, 0x0608, + 0x0609, 0x060b, + 0x060c, 0x060d, + 0x060e, 0x061b, + 0x064b, 0x066d, + 0x0670, 0x0671, + 0x06d6, 0x06e5, + 0x06e7, 0x06ee, + 0x06f0, 0x06fa, + 0x070f, 0x0710, + 0x0711, 0x0712, + 0x0730, 0x074d, + 0x07a6, 0x07b1, + 0x07eb, 0x07f4, + 0x07f6, 0x07fa, + 0x0901, 0x0903, + 0x093c, 0x093d, + 0x0941, 0x0949, + 0x094d, 0x0950, + 0x0951, 0x0958, + 0x0962, 0x0964, + 0x0981, 0x0982, + 0x09bc, 0x09bd, + 0x09c1, 0x09c7, + 0x09cd, 0x09ce, + 0x09e2, 0x09e6, + 0x09f2, 0x09f4, + 0x0a01, 0x0a03, + 0x0a3c, 0x0a3e, + 0x0a41, 0x0a59, + 0x0a70, 0x0a72, + 0x0a75, 0x0a83, + 0x0abc, 0x0abd, + 0x0ac1, 0x0ac9, + 0x0acd, 0x0ad0, + 0x0ae2, 0x0ae6, + 0x0af1, 0x0b02, + 0x0b3c, 0x0b3d, + 0x0b3f, 0x0b40, + 0x0b41, 0x0b47, + 0x0b4d, 0x0b57, + 0x0b62, 0x0b66, + 0x0b82, 0x0b83, + 0x0bc0, 0x0bc1, + 0x0bcd, 0x0bd0, + 0x0bf3, 0x0c01, + 0x0c3e, 0x0c41, + 0x0c46, 0x0c58, + 0x0c62, 0x0c66, + 0x0c78, 0x0c7f, + 0x0cbc, 0x0cbd, + 0x0ccc, 0x0cd5, + 0x0ce2, 0x0ce6, + 0x0cf1, 0x0d02, + 0x0d41, 0x0d46, + 0x0d4d, 0x0d57, + 0x0d62, 0x0d66, + 0x0dca, 0x0dcf, + 0x0dd2, 0x0dd8, + 0x0e31, 0x0e32, + 0x0e34, 0x0e40, + 0x0e47, 0x0e4f, + 0x0eb1, 0x0eb2, + 0x0eb4, 0x0ebd, + 0x0ec8, 0x0ed0, + 0x0f18, 0x0f1a, + 0x0f35, 0x0f36, + 0x0f37, 0x0f38, + 0x0f39, 0x0f3e, + 0x0f71, 0x0f7f, + 0x0f80, 0x0f85, + 0x0f86, 0x0f88, + 0x0f90, 0x0fbe, + 0x0fc6, 0x0fc7, + 0x102d, 0x1031, + 0x1032, 0x1038, + 0x1039, 0x103b, + 0x103d, 0x103f, + 0x1058, 0x105a, + 0x105e, 0x1061, + 0x1071, 0x1075, + 0x1082, 0x1083, + 0x1085, 0x1087, + 0x108d, 0x108e, + 0x135f, 0x1360, + 0x1390, 0x13a0, + 0x1680, 0x1681, + 0x169b, 0x16a0, + 0x1712, 0x1720, + 0x1732, 0x1735, + 0x1752, 0x1760, + 0x1772, 0x1780, + 0x17b7, 0x17be, + 0x17c6, 0x17c7, + 0x17c9, 0x17d4, + 0x17db, 0x17dc, + 0x17dd, 0x17e0, + 0x17f0, 0x1810, + 0x18a9, 0x18aa, + 0x1920, 0x1923, + 0x1927, 0x1929, + 0x1932, 0x1933, + 0x1939, 0x1946, + 0x19de, 0x1a00, + 0x1a17, 0x1a19, + 0x1b00, 0x1b04, + 0x1b34, 0x1b35, + 0x1b36, 0x1b3b, + 0x1b3c, 0x1b3d, + 0x1b42, 0x1b43, + 0x1b6b, 0x1b74, + 0x1b80, 0x1b82, + 0x1ba2, 0x1ba6, + 0x1ba8, 0x1baa, + 0x1c2c, 0x1c34, + 0x1c36, 0x1c3b, + 0x1dc0, 0x1e00, + 0x1fbd, 0x1fbe, + 0x1fbf, 0x1fc2, + 0x1fcd, 0x1fd0, + 0x1fdd, 0x1fe0, + 0x1fed, 0x1ff2, + 0x1ffd, 0x200e, + 0x2010, 0x2071, + 0x2074, 0x207f, + 0x2080, 0x2090, + 0x20a0, 0x2102, + 0x2103, 0x2107, + 0x2108, 0x210a, + 0x2114, 0x2115, + 0x2116, 0x2119, + 0x211e, 0x2124, + 0x2125, 0x2126, + 0x2127, 0x2128, + 0x2129, 0x212a, + 0x212e, 0x212f, + 0x213a, 0x213c, + 0x2140, 0x2145, + 0x214a, 0x214e, + 0x2153, 0x2160, + 0x2190, 0x2336, + 0x237b, 0x2395, + 0x2396, 0x249c, + 0x24ea, 0x26ac, + 0x26ad, 0x2800, + 0x2900, 0x2c00, + 0x2ce5, 0x2d00, + 0x2de0, 0x3005, + 0x3008, 0x3021, + 0x302a, 0x3031, + 0x3036, 0x3038, + 0x303d, 0x3041, + 0x3099, 0x309d, + 0x30a0, 0x30a1, + 0x30fb, 0x30fc, + 0x31c0, 0x31f0, + 0x321d, 0x3220, + 0x3250, 0x3260, + 0x327c, 0x327f, + 0x32b1, 0x32c0, + 0x32cc, 0x32d0, + 0x3377, 0x337b, + 0x33de, 0x33e0, + 0x33ff, 0x3400, + 0x4dc0, 0x4e00, + 0xa490, 0xa500, + 0xa60d, 0xa610, + 0xa66f, 0xa680, + 0xa700, 0xa722, + 0xa788, 0xa789, + 0xa802, 0xa803, + 0xa806, 0xa807, + 0xa80b, 0xa80c, + 0xa825, 0xa827, + 0xa828, 0xa840, + 0xa874, 0xa880, + 0xa8c4, 0xa8ce, + 0xa926, 0xa92e, + 0xa947, 0xa952, + 0xaa29, 0xaa2f, + 0xaa31, 0xaa33, + 0xaa35, 0xaa40, + 0xaa43, 0xaa44, + 0xaa4c, 0xaa4d, + 0xfb1e, 0xfb1f, + 0xfb29, 0xfb2a, + 0xfd3e, 0xfd50, + 0xfdfd, 0xfe70, + 0xfeff, 0xff21, + 0xff3b, 0xff41, + 0xff5b, 0xff66, + 0xffe0, 0x10000, + 0x10101, 0x10102, + 0x10140, 0x101d0, + 0x101fd, 0x10280, + 0x1091f, 0x10920, + 0x10a01, 0x10a10, + 0x10a38, 0x10a40, + 0x1d167, 0x1d16a, + 0x1d173, 0x1d183, + 0x1d185, 0x1d18c, + 0x1d1aa, 0x1d1ae, + 0x1d200, 0x1d360, + 0x1d7ce, 0x20000, + 0xe0001, 0xf0000, + 0x10fffe, 0x10ffff // sentinel }; // use a binary search with a cache - private static int stCache = 0; + private transient volatile int stCache = 0; - // warning, synchronize access to this as it modifies state - private static boolean isStrongDirectional(char c) { - if (c < strongTable[stCache]) { - stCache = search(c, strongTable, 0, stCache); - } else if (c >= strongTable[stCache + 1]) { - stCache = search(c, strongTable, stCache + 1, strongTable.length - stCache - 1); + private boolean isStrongDirectional(char c) { + int cachedIndex = stCache; + if (c < strongTable[cachedIndex]) { + cachedIndex = search(c, strongTable, 0, cachedIndex); + } else if (c >= strongTable[cachedIndex + 1]) { + cachedIndex = search(c, strongTable, cachedIndex + 1, + strongTable.length - cachedIndex - 1); } - return (stCache & 0x1) == 1; + boolean val = (cachedIndex & 0x1) == 1; + stCache = cachedIndex; + return val; } - static private int getKeyFromMask(int mask) { + private static int getKeyFromMask(int mask) { int key = 0; while (key < NUM_KEYS && ((mask & (1<The shaper assumes EUROPEAN as the starting context, that + * is, if EUROPEAN digits are encountered before any strong + * directional text in the string, the context is presumed to be + * EUROPEAN, and so the digits will not shape. + * + * @param ranges the specified Unicode ranges + * @return a contextual shaper for the specified ranges + * @throws NullPointerException if {@code ranges} is {@code null}. + * @since 1.7 + */ + public static NumericShaper getContextualShaper(Set ranges) { + NumericShaper shaper = new NumericShaper(Range.EUROPEAN, ranges); + shaper.mask = CONTEXTUAL_MASK; + return shaper; + } + + /** * Returns a contextual shaper for the provided unicode range(s). * Latin-1 (EUROPEAN) digits will be converted to the decimal digits * corresponding to the range of the preceding text, if the @@ -683,13 +888,38 @@ * @throws IllegalArgumentException if the specified * defaultContext is not a single valid range. */ - static public NumericShaper getContextualShaper(int ranges, int defaultContext) { + public static NumericShaper getContextualShaper(int ranges, int defaultContext) { int key = getKeyFromMask(defaultContext); ranges |= CONTEXTUAL_MASK; return new NumericShaper(key, ranges); } /** + * Returns a contextual shaper for the provided Unicode range(s). + * The Latin-1 (EUROPEAN) digits will be converted to the decimal + * digits corresponding to the range of the preceding text, if the + * range is one of the provided ranges. The shaper uses {@code + * defaultContext} as the starting context. + * + * @param ranges the specified Unicode ranges + * @param defaultContext the starting context, such as + * {@code NumericShaper.Range.EUROPEAN} + * @return a contextual shaper for the specified Unicode ranges. + * @throws NullPointerException + * if {@code ranges} or {@code defaultContext} is {@code null} + * @since 1.7 + */ + public static NumericShaper getContextualShaper(Set ranges, + Range defaultContext) { + if (defaultContext == null) { + throw new NullPointerException(); + } + NumericShaper shaper = new NumericShaper(defaultContext, ranges); + shaper.mask = CONTEXTUAL_MASK; + return shaper; + } + + /** * Private constructor. */ private NumericShaper(int key, int mask) { @@ -697,6 +927,11 @@ this.mask = mask; } + private NumericShaper(Range defaultContext, Set ranges) { + this.shapingRange = defaultContext; + this.rangeSet = EnumSet.copyOf(ranges); // throws NPE if ranges is null. + } + /** * Converts the digits in the text that occur between start and * start + count. @@ -710,19 +945,13 @@ * @throws NullPointerException if text is null */ public void shape(char[] text, int start, int count) { - if (text == null) { - throw new NullPointerException("text is null"); - } - if ((start < 0) - || (start > text.length) - || ((start + count) < 0) - || ((start + count) > text.length)) { - throw new IndexOutOfBoundsException( - "bad start or count for text of length " + text.length); - } - + checkParams(text, start, count); if (isContextual()) { - shapeContextually(text, start, count, key); + if (rangeSet == null) { + shapeContextually(text, start, count, key); + } else { + shapeContextually(text, start, count, shapingRange); + } } else { shapeNonContextually(text, start, count); } @@ -747,6 +976,60 @@ * range. */ public void shape(char[] text, int start, int count, int context) { + checkParams(text, start, count); + if (isContextual()) { + int ctxKey = getKeyFromMask(context); + if (rangeSet == null) { + shapeContextually(text, start, count, ctxKey); + } else { + shapeContextually(text, start, count, Range.values()[ctxKey]); + } + } else { + shapeNonContextually(text, start, count); + } + } + + /** + * Converts the digits in the text that occur between {@code + * start} and {@code start + count}, using the provided {@code + * context}. {@code Context} is ignored if the shaper is not a + * contextual shaper. + * + * @param text a {@code char} array + * @param start the index into {@code text} to start converting + * @param count the number of {@code char}s in {@code text} + * to convert + * @param context the context to which to convert the characters, + * such as {@code NumericShaper.Range.EUROPEAN} + * @throws IndexOutOfBoundsException + * if {@code start} or {@code start + count} is out of bounds + * @throws NullPointerException + * if {@code text} or {@code context} is null + * @since 1.7 + */ + public void shape(char[] text, int start, int count, Range context) { + checkParams(text, start, count); + if (context == null) { + throw new NullPointerException("context is null"); + } + + if (isContextual()) { + if (rangeSet != null) { + shapeContextually(text, start, count, context); + } else { + int key = Range.toRangeIndex(context); + if (key >= 0) { + shapeContextually(text, start, count, key); + } else { + shapeContextually(text, start, count, shapingRange); + } + } + } else { + shapeNonContextually(text, start, count); + } + } + + private void checkParams(char[] text, int start, int count) { if (text == null) { throw new NullPointerException("text is null"); } @@ -757,13 +1040,6 @@ throw new IndexOutOfBoundsException( "bad start or count for text of length " + text.length); } - - if (isContextual()) { - int ctxKey = getKeyFromMask(context); - shapeContextually(text, start, count, ctxKey); - } else { - shapeNonContextually(text, start, count); - } } /** @@ -785,6 +1061,10 @@ *

* if ((shaper.getRanges() & shaper.ARABIC) != 0) { ... *
+ * + *

Note that this method supports only the bit mask-based + * ranges. Call {@link #getRangeSet()} for the enum-based ranges. + * * @return the values for all the ranges to be shaped. */ public int getRanges() { @@ -792,11 +1072,34 @@ } /** + * Returns a {@code Set} representing all the Unicode ranges in + * this {@code NumericShaper} that will be shaped. + * + * @return all the Unicode ranges to be shaped. + * @since 1.7 + */ + public Set getRangeSet() { + if (rangeSet != null) { + return EnumSet.copyOf(rangeSet); + } + return Range.maskToRangeSet(mask); + } + + /** * Perform non-contextual shaping. */ private void shapeNonContextually(char[] text, int start, int count) { - int base = bases[key]; - char minDigit = key == TAMIL_KEY ? '\u0031' : '\u0030'; // Tamil doesn't use decimal zero + int base; + char minDigit = '0'; + if (shapingRange != null) { + base = shapingRange.getDigitBase(); + minDigit += shapingRange.getNumericBase(); + } else { + base = bases[key]; + if (key == ETHIOPIC_KEY) { + minDigit++; // Ethiopic doesn't use decimal zero + } + } for (int i = start, e = start + count; i < e; ++i) { char c = text[i]; if (c >= minDigit && c <= '\u0039') { @@ -807,7 +1110,7 @@ /** * Perform contextual shaping. - * Synchronized to protect caches used in getContextKey and isStrongDirectional. + * Synchronized to protect caches used in getContextKey. */ private synchronized void shapeContextually(char[] text, int start, int count, int ctxKey) { @@ -818,29 +1121,64 @@ int lastkey = ctxKey; int base = bases[ctxKey]; - char minDigit = ctxKey == TAMIL_KEY ? '\u0031' : '\u0030'; // Tamil doesn't use decimal zero + char minDigit = ctxKey == ETHIOPIC_KEY ? '1' : '0'; // Ethiopic doesn't use decimal zero - for (int i = start, e = start + count; i < e; ++i) { + synchronized (NumericShaper.class) { + for (int i = start, e = start + count; i < e; ++i) { + char c = text[i]; + if (c >= minDigit && c <= '\u0039') { + text[i] = (char)(c + base); + } + + if (isStrongDirectional(c)) { + int newkey = getContextKey(c); + if (newkey != lastkey) { + lastkey = newkey; + + ctxKey = newkey; + if (((mask & EASTERN_ARABIC) != 0) && (ctxKey == ARABIC_KEY || ctxKey == EASTERN_ARABIC_KEY)) { + ctxKey = EASTERN_ARABIC_KEY; + } else if ((mask & (1<= minDigit && c <= '\u0039') { + if (c >= minDigit && c <= '9') { text[i] = (char)(c + base); + continue; } - if (isStrongDirectional(c)) { - int newkey = getContextKey(c); - if (newkey != lastkey) { - lastkey = newkey; - - ctxKey = newkey; - if (((mask & EASTERN_ARABIC) != 0) && (ctxKey == ARABIC_KEY || ctxKey == EASTERN_ARABIC_KEY)) { - ctxKey = EASTERN_ARABIC_KEY; - } else if ((mask & (1<NumericShaper and shapes identically to this one. + * Returns {@code true} if the specified object is an instance of + * NumericShaper and shapes identically to this one, + * regardless of the range representations, the bit mask or the + * enum. For example, the following code produces {@code "true"}. + *

+     * NumericShaper ns1 = NumericShaper.getShaper(NumericShaper.ARABIC);
+     * NumericShaper ns2 = NumericShaper.getShaper(NumericShaper.Range.ARABIC);
+     * System.out.println(ns1.equals(ns2));
+     * 
+ * * @param o the specified object to compare to this * NumericShaper * @return true if o is an instance @@ -869,6 +1223,22 @@ if (o != null) { try { NumericShaper rhs = (NumericShaper)o; + if (rangeSet != null) { + if (rhs.rangeSet != null) { + return isContextual() == rhs.isContextual() + && rangeSet.equals(rhs.rangeSet) + && shapingRange == rhs.shapingRange; + } + return isContextual() == rhs.isContextual() + && rangeSet.equals(Range.maskToRangeSet(rhs.mask)) + && shapingRange == Range.indexToRange(rhs.key); + } else if (rhs.rangeSet != null) { + Set rset = Range.maskToRangeSet(mask); + Range srange = Range.indexToRange(key); + return isContextual() == rhs.isContextual() + && rset.equals(rhs.rangeSet) + && srange == rhs.shapingRange; + } return rhs.mask == mask && rhs.key == key; } catch (ClassCastException e) { @@ -885,23 +1255,29 @@ public String toString() { StringBuilder buf = new StringBuilder(super.toString()); - buf.append("[contextual:" + isContextual()); + buf.append("[contextual:").append(isContextual()); + String[] keyNames = null; if (isContextual()) { - buf.append(", context:" + keyNames[key]); + buf.append(", context:"); + buf.append(shapingRange == null ? Range.values()[key] : shapingRange); } - buf.append(", range(s): "); - boolean first = true; - for (int i = 0; i < NUM_KEYS; ++i) { - if ((mask & (1 << i)) != 0) { - if (first) { - first = false; - } else { - buf.append(", "); + if (rangeSet == null) { + buf.append(", range(s): "); + boolean first = true; + for (int i = 0; i < NUM_KEYS; ++i) { + if ((mask & (1 << i)) != 0) { + if (first) { + first = false; + } else { + buf.append(", "); + } + buf.append(Range.values()[i]); } - buf.append(keyNames[i]); } + } else { + buf.append(", range set: ").append(rangeSet); } buf.append(']'); @@ -940,7 +1316,6 @@ } if (value >= 1 << 1) { - value >>= 1; bit += 1; } @@ -950,7 +1325,7 @@ /** * fast binary search over subrange of array. */ - private static int search(char value, char[] array, int start, int length) + private static int search(int value, int[] array, int start, int length) { int power = 1 << getHighBit(length); int extra = length - power; @@ -971,4 +1346,27 @@ return index; } + + /** + * Converts the {@code NumericShaper.Range} enum-based parameters, + * if any, to the bit mask-based counterparts and writes this + * object to the {@code stream}. Any enum constants that have no + * bit mask-based counterparts are ignored in the conversion. + * + * @param stream the output stream to write to + * @throws IOException if an I/O error occurs while writing to {@code stream} + * @since 1.7 + */ + private void writeObject(ObjectOutputStream stream) throws IOException { + if (shapingRange != null) { + int index = Range.toRangeIndex(shapingRange); + if (index >= 0) { + key = index; + } + } + if (rangeSet != null) { + mask |= Range.toRangeMask(rangeSet); + } + stream.defaultWriteObject(); + } } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/beans/MetaData.java --- a/src/share/classes/java/beans/MetaData.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/beans/MetaData.java Wed Nov 25 22:14:30 2009 -0800 @@ -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 { + 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); + } + } + + /** + * 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) { - Timestamp oldTime = (Timestamp)oldInstance; - Timestamp newTime = (Timestamp)newInstance; - - int nanos = oldTime.getNanos(); - if (nanos != newTime.getNanos()) { - out.writeStatement(new Statement(oldTime, "setNanos", new Object[] {nanos})); + // assumes oldInstance and newInstance are Timestamps + int nanos = getNanos(oldInstance); + if (nanos != getNanos(newInstance)) { + out.writeStatement(new Statement(oldInstance, "setNanos", new Object[] {nanos})); } } } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/io/FilePermission.java --- a/src/share/classes/java/io/FilePermission.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/io/FilePermission.java Wed Nov 25 22:14:30 2009 -0800 @@ -209,7 +209,17 @@ cpath = AccessController.doPrivileged(new PrivilegedAction() { public String run() { try { - return sun.security.provider.PolicyFile.canonPath(cpath); + String path = cpath; + if (cpath.endsWith("*")) { + // call getCanonicalPath with a path with wildcard character + // replaced to avoid calling it with paths that are + // intended to match all entries in a directory + path = path.substring(0, path.length()-1) + "-"; + path = new File(path).getCanonicalPath(); + return path.substring(0, path.length()-1) + "*"; + } else { + return new File(path).getCanonicalPath(); + } } catch (IOException ioe) { return cpath; } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/io/ObjectStreamClass.java --- a/src/share/classes/java/io/ObjectStreamClass.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/io/ObjectStreamClass.java Wed Nov 25 22:14:30 2009 -0800 @@ -99,7 +99,7 @@ } /** class associated with this descriptor (if any) */ - private Class cl; + private Class cl; /** name of class represented by this descriptor */ private String name; /** serialVersionUID of represented class (null if not computed yet) */ @@ -276,7 +276,7 @@ * @param all if true, return descriptors for all classes; if false, only * return descriptors for serializable classes */ - static ObjectStreamClass lookup(Class cl, boolean all) { + static ObjectStreamClass lookup(Class cl, boolean all) { if (!(all || Serializable.class.isAssignableFrom(cl))) { return null; } @@ -414,7 +414,7 @@ /** * Creates local class descriptor representing given class. */ - private ObjectStreamClass(final Class cl) { + private ObjectStreamClass(final Class cl) { this.cl = cl; name = cl.getName(); isProxy = Proxy.isProxyClass(cl); @@ -422,7 +422,7 @@ serializable = Serializable.class.isAssignableFrom(cl); externalizable = Externalizable.class.isAssignableFrom(cl); - Class superCl = cl.getSuperclass(); + Class superCl = cl.getSuperclass(); superDesc = (superCl != null) ? lookup(superCl, false) : null; localDesc = this; @@ -453,10 +453,10 @@ } else { cons = getSerializableConstructor(cl); writeObjectMethod = getPrivateMethod(cl, "writeObject", - new Class[] { ObjectOutputStream.class }, + new Class[] { ObjectOutputStream.class }, Void.TYPE); readObjectMethod = getPrivateMethod(cl, "readObject", - new Class[] { ObjectInputStream.class }, + new Class[] { ObjectInputStream.class }, Void.TYPE); readObjectNoDataMethod = getPrivateMethod( cl, "readObjectNoData", null, Void.TYPE); @@ -507,7 +507,7 @@ /** * Initializes class descriptor representing a proxy class. */ - void initProxy(Class cl, + void initProxy(Class cl, ClassNotFoundException resolveEx, ObjectStreamClass superDesc) throws InvalidClassException @@ -540,7 +540,7 @@ * Initializes class descriptor representing a non-proxy class. */ void initNonProxy(ObjectStreamClass model, - Class cl, + Class cl, ClassNotFoundException resolveEx, ObjectStreamClass superDesc) throws InvalidClassException @@ -1131,7 +1131,7 @@ throws InvalidClassException { ArrayList slots = new ArrayList(); - Class start = cl, end = cl; + Class start = cl, end = cl; // locate closest non-serializable superclass while (end != null && Serializable.class.isAssignableFrom(end)) { @@ -1142,8 +1142,8 @@ // search up inheritance hierarchy for class with matching name String searchName = (d.cl != null) ? d.cl.getName() : d.name; - Class match = null; - for (Class c = start; c != end; c = c.getSuperclass()) { + Class match = null; + for (Class c = start; c != end; c = c.getSuperclass()) { if (searchName.equals(c.getName())) { match = c; break; @@ -1152,7 +1152,7 @@ // add "no data" slot for each unmatched class below match if (match != null) { - for (Class c = start; c != match; c = c.getSuperclass()) { + for (Class c = start; c != match; c = c.getSuperclass()) { slots.add(new ClassDataSlot( ObjectStreamClass.lookup(c, true), false)); } @@ -1164,7 +1164,7 @@ } // add "no data" slot for any leftover unmatched classes - for (Class c = start; c != end; c = c.getSuperclass()) { + for (Class c = start; c != end; c = c.getSuperclass()) { slots.add(new ClassDataSlot( ObjectStreamClass.lookup(c, true), false)); } @@ -1288,7 +1288,7 @@ * descriptor, returns reference to this class descriptor. Otherwise, * returns variant of this class descriptor bound to given class. */ - private ObjectStreamClass getVariantFor(Class cl) + private ObjectStreamClass getVariantFor(Class cl) throws InvalidClassException { if (this.cl == cl) { @@ -1355,8 +1355,8 @@ * method (if any). */ private static Method getInheritableMethod(Class cl, String name, - Class[] argTypes, - Class returnType) + Class[] argTypes, + Class returnType) { Method meth = null; Class defCl = cl; @@ -1410,7 +1410,7 @@ * Returns true if classes are defined in the same runtime package, false * otherwise. */ - private static boolean packageEquals(Class cl1, Class cl2) { + private static boolean packageEquals(Class cl1, Class cl2) { return (cl1.getClassLoader() == cl2.getClassLoader() && getPackageName(cl1).equals(getPackageName(cl2))); } @@ -1418,7 +1418,7 @@ /** * Returns package name of given class. */ - private static String getPackageName(Class cl) { + private static String getPackageName(Class cl) { String s = cl.getName(); int i = s.lastIndexOf('['); if (i >= 0) { @@ -1441,7 +1441,7 @@ /** * Returns JVM type signature for given class. */ - static String getClassSignature(Class cl) { + private static String getClassSignature(Class cl) { StringBuilder sbuf = new StringBuilder(); while (cl.isArray()) { sbuf.append('['); @@ -1478,8 +1478,8 @@ /** * Returns JVM type signature for given list of parameters and return type. */ - private static String getMethodSignature(Class[] paramTypes, - Class retType) + private static String getMethodSignature(Class[] paramTypes, + Class retType) { StringBuilder sbuf = new StringBuilder(); sbuf.append('('); @@ -1515,7 +1515,7 @@ * Field objects. Throws InvalidClassException if the (explicitly * declared) serializable fields are invalid. */ - private static ObjectStreamField[] getSerialFields(Class cl) + private static ObjectStreamField[] getSerialFields(Class cl) throws InvalidClassException { ObjectStreamField[] fields; @@ -1545,7 +1545,7 @@ * InvalidClassException if the declared serializable fields are * invalid--e.g., if multiple fields share the same name. */ - private static ObjectStreamField[] getDeclaredSerialFields(Class cl) + private static ObjectStreamField[] getDeclaredSerialFields(Class cl) throws InvalidClassException { ObjectStreamField[] serialPersistentFields = null; @@ -1602,7 +1602,7 @@ * contains a Field object for the field it represents. If no default * serializable fields exist, NO_FIELDS is returned. */ - private static ObjectStreamField[] getDefaultSerialFields(Class cl) { + private static ObjectStreamField[] getDefaultSerialFields(Class cl) { Field[] clFields = cl.getDeclaredFields(); ArrayList list = new ArrayList(); int mask = Modifier.STATIC | Modifier.TRANSIENT; @@ -1621,7 +1621,7 @@ * Returns explicit serial version UID value declared by given class, or * null if none. */ - private static Long getDeclaredSUID(Class cl) { + private static Long getDeclaredSUID(Class cl) { try { Field f = cl.getDeclaredField("serialVersionUID"); int mask = Modifier.STATIC | Modifier.FINAL; @@ -1637,7 +1637,7 @@ /** * Computes the default serial version UID value for the given class. */ - private static long computeDefaultSUID(Class cl) { + private static long computeDefaultSUID(Class cl) { if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl)) { return 0L; @@ -1671,7 +1671,7 @@ * Class.getInterfaces() was modified to return Cloneable and * Serializable for array classes. */ - Class[] interfaces = cl.getInterfaces(); + Class[] interfaces = cl.getInterfaces(); String[] ifaceNames = new String[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { ifaceNames[i] = interfaces[i].getName(); @@ -1784,7 +1784,7 @@ * Returns true if the given class defines a static initializer method, * false otherwise. */ - private native static boolean hasStaticInitializer(Class cl); + private native static boolean hasStaticInitializer(Class cl); /** * Class for computing and caching field/constructor/method signatures @@ -1837,7 +1837,7 @@ /** field type codes */ private final char[] typeCodes; /** field types */ - private final Class[] types; + private final Class[] types; /** * Constructs FieldReflector capable of setting/getting values from the @@ -2071,7 +2071,7 @@ throws InvalidClassException { // class irrelevant if no fields - Class cl = (localDesc != null && fields.length > 0) ? + Class cl = (localDesc != null && fields.length > 0) ? localDesc.cl : null; processQueue(Caches.reflectorsQueue, Caches.reflectors); FieldReflectorKey key = new FieldReflectorKey(cl, fields, @@ -2136,7 +2136,7 @@ private final int hash; private final boolean nullClass; - FieldReflectorKey(Class cl, ObjectStreamField[] fields, + FieldReflectorKey(Class cl, ObjectStreamField[] fields, ReferenceQueue> queue) { super(cl, queue); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/io/ObjectStreamField.java --- a/src/share/classes/java/io/ObjectStreamField.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/io/ObjectStreamField.java Wed Nov 25 22:14:30 2009 -0800 @@ -45,7 +45,7 @@ /** canonical JVM signature of field type */ private final String signature; /** field type (Object.class if unknown non-primitive type) */ - private final Class type; + private final Class type; /** whether or not to (de)serialize field values as unshared */ private final boolean unshared; /** corresponding reflective field object, if any */ @@ -88,7 +88,7 @@ this.name = name; this.type = type; this.unshared = unshared; - signature = ObjectStreamClass.getClassSignature(type).intern(); + signature = getClassSignature(type).intern(); field = null; } @@ -132,9 +132,9 @@ this.field = field; this.unshared = unshared; name = field.getName(); - Class ftype = field.getType(); + Class ftype = field.getType(); type = (showType || ftype.isPrimitive()) ? ftype : Object.class; - signature = ObjectStreamClass.getClassSignature(ftype).intern(); + signature = getClassSignature(ftype).intern(); } /** @@ -274,4 +274,41 @@ String getSignature() { return signature; } + + /** + * Returns JVM type signature for given class. + */ + private static String getClassSignature(Class cl) { + StringBuilder sbuf = new StringBuilder(); + while (cl.isArray()) { + sbuf.append('['); + cl = cl.getComponentType(); + } + if (cl.isPrimitive()) { + if (cl == Integer.TYPE) { + sbuf.append('I'); + } else if (cl == Byte.TYPE) { + sbuf.append('B'); + } else if (cl == Long.TYPE) { + sbuf.append('J'); + } else if (cl == Float.TYPE) { + sbuf.append('F'); + } else if (cl == Double.TYPE) { + sbuf.append('D'); + } else if (cl == Short.TYPE) { + sbuf.append('S'); + } else if (cl == Character.TYPE) { + sbuf.append('C'); + } else if (cl == Boolean.TYPE) { + sbuf.append('Z'); + } else if (cl == Void.TYPE) { + sbuf.append('V'); + } else { + throw new InternalError(); + } + } else { + sbuf.append('L' + cl.getName().replace('.', '/') + ';'); + } + return sbuf.toString(); + } } diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/lang/ClassLoader.java --- a/src/share/classes/java/lang/ClassLoader.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/lang/ClassLoader.java Wed Nov 25 22:14:30 2009 -0800 @@ -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 packages = new HashMap(); + 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(); + package2certs = new ConcurrentHashMap(); + domains = + Collections.synchronizedSet(new HashSet()); + assertionLock = new Object(); + } else { + // no finer-grained lock; lock on the classloader instance + parallelLockMap = null; + package2certs = new Hashtable(); + domains = new HashSet(); + 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(); - package2certs = new ConcurrentHashMap(); - domains = - Collections.synchronizedSet(new HashSet()); - assertionLock = new Object(); - } else { - // no finer-grained lock; lock on the classloader instance - parallelLockMap = null; - package2certs = new Hashtable(); - domains = new HashSet(); - 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(); - package2certs = new ConcurrentHashMap(); - domains = - Collections.synchronizedSet(new HashSet()); - assertionLock = new Object(); - } else { - // no finer-grained lock; lock on the classloader instance - parallelLockMap = null; - package2certs = new Hashtable(); - domains = new HashSet(); - 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 binary name 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; } } + diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/lang/Enum.java --- a/src/share/classes/java/lang/Enum.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/lang/Enum.java Wed Nov 25 22:14:30 2009 -0800 @@ -40,10 +40,17 @@ * Edition, §8.9. * + *

Note that when using an enumeration type as the type of a set + * or as the type of the keys in a map, specialized and efficient + * {@linkplain java.util.EnumSet set} and {@linkplain + * java.util.EnumMap map} implementations are available. + * * @param The enum type subclass * @author Josh Bloch * @author Neal Gafter * @see Class#getEnumConstants() + * @see java.util.EnumSet + * @see java.util.EnumMap * @since 1.5 */ public abstract class Enum> diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/lang/management/PlatformComponent.java --- a/src/share/classes/java/lang/management/PlatformComponent.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/lang/management/PlatformComponent.java Wed Nov 25 22:14:30 2009 -0800 @@ -30,8 +30,7 @@ import java.util.List; import java.util.HashSet; import java.util.Set; -import java.util.logging.LoggingMXBean; -import java.util.logging.LogManager; +import java.util.logging.PlatformLoggingMXBean; import java.nio.BufferPoolMXBean; import javax.management.MBeanServerConnection; import javax.management.ObjectName; @@ -40,6 +39,7 @@ import com.sun.management.UnixOperatingSystemMXBean; import sun.management.ManagementFactoryHelper; +import sun.management.Util; /** * This enum class defines the list of platform components @@ -180,15 +180,14 @@ * Logging facility. */ LOGGING( - "java.util.logging.LoggingMXBean", + "java.util.logging.PlatformLoggingMXBean", "java.util.logging", "Logging", defaultKeyProperties(), - new MXBeanFetcher() { - public List getMXBeans() { - return Collections.singletonList(LogManager.getLoggingMXBean()); + new MXBeanFetcher() { + public List getMXBeans() { + return ManagementFactoryHelper.getLoggingMXBean(); } }), - /** * Buffer pools. */ @@ -384,7 +383,7 @@ // if there are more than 1 key properties (i.e. other than "type") domainAndType += ",*"; } - ObjectName on = ObjectName.valueOf(domainAndType); + ObjectName on = Util.newObjectName(domainAndType); Set set = mbs.queryNames(on, null); for (PlatformComponent pc : subComponents) { set.addAll(pc.getObjectNames(mbs)); diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/lang/reflect/AccessibleObject.java --- a/src/share/classes/java/lang/reflect/AccessibleObject.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/lang/reflect/AccessibleObject.java Wed Nov 25 22:14:30 2009 -0800 @@ -44,6 +44,8 @@ * as Java Object Serialization or other persistence mechanisms, to * manipulate objects in a manner that would normally be prohibited. * + *

By default, a reflected object is not accessible. + * * @see Field * @see Method * @see Constructor diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/math/BigInteger.java --- a/src/share/classes/java/math/BigInteger.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/math/BigInteger.java Wed Nov 25 22:14:30 2009 -0800 @@ -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) @@ -478,7 +478,7 @@ /** * Constructs a randomly generated BigInteger, uniformly distributed over - * the range {@code 0} to (2{@code numBits} - 1), inclusive. + * the range 0 to (2{@code numBits} - 1), inclusive. * The uniformity of the distribution assumes that a fair source of random * bits is provided in {@code rnd}. Note that this constructor always * constructs a non-negative BigInteger. @@ -1332,7 +1332,7 @@ * * @param val value by which this BigInteger is to be divided. * @return {@code this / val} - * @throws ArithmeticException {@code val==0} + * @throws ArithmeticException if {@code val} is zero. */ public BigInteger divide(BigInteger val) { MutableBigInteger q = new MutableBigInteger(), @@ -1352,7 +1352,7 @@ * @return an array of two BigIntegers: the quotient {@code (this / val)} * is the initial element, and the remainder {@code (this % val)} * is the final element. - * @throws ArithmeticException {@code val==0} + * @throws ArithmeticException if {@code val} is zero. */ public BigInteger[] divideAndRemainder(BigInteger val) { BigInteger[] result = new BigInteger[2]; @@ -1371,7 +1371,7 @@ * @param val value by which this BigInteger is to be divided, and the * remainder computed. * @return {@code this % val} - * @throws ArithmeticException {@code val==0} + * @throws ArithmeticException if {@code val} is zero. */ public BigInteger remainder(BigInteger val) { MutableBigInteger q = new MutableBigInteger(), @@ -1547,7 +1547,7 @@ * * @param m the modulus. * @return {@code this mod m} - * @throws ArithmeticException {@code m <= 0} + * @throws ArithmeticException {@code m} ≤ 0 * @see #remainder */ public BigInteger mod(BigInteger m) { @@ -1566,7 +1566,9 @@ * @param exponent the exponent. * @param m the modulus. * @return thisexponent mod m - * @throws ArithmeticException {@code m <= 0} + * @throws ArithmeticException {@code m} ≤ 0 or the exponent is + * negative and this BigInteger is not relatively + * prime to {@code m}. * @see #modInverse */ public BigInteger modPow(BigInteger exponent, BigInteger m) { @@ -2015,7 +2017,7 @@ * * @param m the modulus. * @return {@code this}-1 {@code mod m}. - * @throws ArithmeticException {@code m <= 0}, or this BigInteger + * @throws ArithmeticException {@code m} ≤ 0, or this BigInteger * has no multiplicative inverse mod m (that is, this BigInteger * is not relatively prime to m). */ @@ -2051,6 +2053,8 @@ * * @param n shift distance, in bits. * @return {@code this << n} + * @throws ArithmeticException if the shift distance is {@code + * Integer.MIN_VALUE}. * @see #shiftRight */ public BigInteger shiftLeft(int n) { @@ -2058,8 +2062,13 @@ return ZERO; if (n==0) return this; - if (n<0) - return shiftRight(-n); + if (n<0) { + if (n == Integer.MIN_VALUE) { + throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported."); + } else { + return shiftRight(-n); + } + } int nInts = n >>> 5; int nBits = n & 0x1f; @@ -2097,13 +2106,20 @@ * * @param n shift distance, in bits. * @return {@code this >> n} + * @throws ArithmeticException if the shift distance is {@code + * Integer.MIN_VALUE}. * @see #shiftLeft */ public BigInteger shiftRight(int n) { if (n==0) return this; - if (n<0) - return shiftLeft(-n); + if (n<0) { + if (n == Integer.MIN_VALUE) { + throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported."); + } else { + return shiftLeft(-n); + } + } int nInts = n >>> 5; int nBits = n & 0x1f; @@ -2435,7 +2451,7 @@ /** * Returns {@code true} if this BigInteger is probably prime, * {@code false} if it's definitely composite. If - * {@code certainty} is {@code <= 0}, {@code true} is + * {@code certainty} is ≤ 0, {@code true} is * returned. * * @param certainty a measure of the uncertainty that the caller is diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/net/CookieHandler.java --- a/src/share/classes/java/net/CookieHandler.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/net/CookieHandler.java Wed Nov 25 22:14:30 2009 -0800 @@ -101,11 +101,21 @@ * Gets all the applicable cookies from a cookie cache for the * specified uri in the request header. * - * HTTP protocol implementers should make sure that this method is + *

The {@code URI} passed as an argument specifies the intended use for + * the cookies. In particular the scheme should reflect whether the cookies + * will be sent over http, https or used in another context like javascript. + * The host part should reflect either the destination of the cookies or + * their origin in the case of javascript.

+ *

It is up to the implementation to take into account the {@code URI} and + * the cookies attributes and security settings to determine which ones + * should be returned.

+ * + *

HTTP protocol implementers should make sure that this method is * called after all request headers related to choosing cookies - * are added, and before the request is sent. + * are added, and before the request is sent.

* - * @param uri a URI to send cookies to in a request + * @param uri a URI representing the intended use for the + * cookies * @param requestHeaders - a Map from request header * field names to lists of field values representing * the current request headers diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/net/CookieManager.java --- a/src/share/classes/java/net/CookieManager.java Wed Nov 25 21:27:06 2009 +0300 +++ b/src/share/classes/java/net/CookieManager.java Wed Nov 25 22:14:30 2009 -0800 @@ -218,6 +218,13 @@ // 'secure' cookies over unsecure links) if (pathMatches(path, cookie.getPath()) && (secureLink || !cookie.getSecure())) { + // Enforce httponly attribute + if (cookie.isHttpOnly()) { + String s = uri.getScheme(); + if (!"http".equalsIgnoreCase(s) && !"https".equalsIgnoreCase(s)) { + continue; + } + } // Let's check the authorize port list if it exists String ports = cookie.getPortlist(); if (ports != null && !ports.isEmpty()) { diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/ByteBufferAs-X-Buffer.java --- a/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java Wed Nov 25 21:27:06 2009 +0300 +++ /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] - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template Wed Nov 25 22:14:30 2009 -0800 @@ -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] + } + +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/Direct-X-Buffer-bin.java --- a/src/share/classes/java/nio/Direct-X-Buffer-bin.java Wed Nov 25 21:27:06 2009 +0300 +++ /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 - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/Direct-X-Buffer-bin.java.template --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/nio/Direct-X-Buffer-bin.java.template Wed Nov 25 22:14:30 2009 -0800 @@ -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 + +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/Direct-X-Buffer.java --- a/src/share/classes/java/nio/Direct-X-Buffer.java Wed Nov 25 21:27:06 2009 +0300 +++ /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] - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/Direct-X-Buffer.java.template --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/nio/Direct-X-Buffer.java.template Wed Nov 25 22:14:30 2009 -0800 @@ -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] + +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/Heap-X-Buffer.java --- a/src/share/classes/java/nio/Heap-X-Buffer.java Wed Nov 25 21:27:06 2009 +0300 +++ /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] - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/Heap-X-Buffer.java.template --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/nio/Heap-X-Buffer.java.template Wed Nov 25 22:14:30 2009 -0800 @@ -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] + +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/X-Buffer-bin.java --- a/src/share/classes/java/nio/X-Buffer-bin.java Wed Nov 25 21:27:06 2009 +0300 +++ /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 get method for reading $a$ $type$ value. - * - *

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$.

- * - * @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 put method for writing $a$ $type$ - * value  (optional operation). - * - *

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$.

- * - * @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 get method for reading $a$ $type$ value. - * - *

Reads $nbytes$ bytes at the given index, composing them into a - * $type$ value according to the current byte order.

- * - * @param index - * The index from which the bytes will be read - * - * @return The $type$ value at the given index - * - * @throws IndexOutOfBoundsException - * If index is negative - * or not smaller than the buffer's limit, - * minus $nbytesButOne$ - */ - public abstract $type$ get$Type$(int index); - - /** - * Absolute put method for writing $a$ $type$ - * value  (optional operation). - * - *

Writes $nbytes$ bytes containing the given $type$ value, in the - * current byte order, into this buffer at the given index.

- * - * @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 index 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. - * - *

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. - * - *

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.

- * - * @return A new $type$ buffer - */ - public abstract $Type$Buffer as$Type$Buffer(); - -#end - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/X-Buffer-bin.java.template --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/nio/X-Buffer-bin.java.template Wed Nov 25 22:14:30 2009 -0800 @@ -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 get method for reading $a$ $type$ value. + * + *

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$.

+ * + * @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 put method for writing $a$ $type$ + * value  (optional operation). + * + *

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$.

+ * + * @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 get method for reading $a$ $type$ value. + * + *

Reads $nbytes$ bytes at the given index, composing them into a + * $type$ value according to the current byte order.

+ * + * @param index + * The index from which the bytes will be read + * + * @return The $type$ value at the given index + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus $nbytesButOne$ + */ + public abstract $type$ get$Type$(int index); + + /** + * Absolute put method for writing $a$ $type$ + * value  (optional operation). + * + *

Writes $nbytes$ bytes containing the given $type$ value, in the + * current byte order, into this buffer at the given index.

+ * + * @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 index 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. + * + *

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. + * + *

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.

+ * + * @return A new $type$ buffer + */ + public abstract $Type$Buffer as$Type$Buffer(); + +#end + +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/X-Buffer.java --- a/src/share/classes/java/nio/X-Buffer.java Wed Nov 25 21:27:06 2009 +0300 +++ /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. - * - *

This class defines {#if[byte]?six:four} categories of operations upon - * $fulltype$ buffers: - * - *

    - * - *
  • Absolute and relative {@link #get() get} and - * {@link #put($type$) put} methods that read and write - * single $fulltype$s;

  • - * - *
  • Relative {@link #get($type$[]) bulk get} - * methods that transfer contiguous sequences of $fulltype$s from this buffer - * into an array; {#if[!byte]?and}

  • - * - *
  • Relative {@link #put($type$[]) bulk put} - * 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}

  • - * -#if[byte] - * - *
  • Absolute and relative {@link #getChar() get} - * and {@link #putChar(char) put} methods that read and - * write values of other primitive types, translating them to and from - * sequences of bytes in a particular byte order;

  • - * - *
  • Methods for creating view buffers, - * which allow a byte buffer to be viewed as a buffer containing values of - * some other primitive type; and

  • - * -#end[byte] - * - *
  • Methods for {@link #compact compacting}, {@link - * #duplicate duplicating}, and {@link #slice - * slicing} $a$ $fulltype$ buffer.

  • - * - *
- * - *

$Fulltype$ buffers can be created either by {@link #allocate - * allocation}, which allocates space for the buffer's - * -#if[byte] - * - * content, or by {@link #wrap($type$[]) wrapping} an - * existing $fulltype$ array {#if[char]?or string} into a buffer. - * -#else[byte] - * - * content, by {@link #wrap($type$[]) wrapping} an existing - * $fulltype$ array {#if[char]?or string} into a buffer, or by creating a - * view of an existing byte buffer. - * -#end[byte] - * -#if[byte] - * - * - *

Direct vs. non-direct buffers

- * - *

A byte buffer is either direct or non-direct. 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. - * - *

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. - * - *

A direct byte buffer may also be created by {@link - * java.nio.channels.FileChannel#map mapping} 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. - * - *

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. - * - * - * - *

Access to binary data

- * - *

This class defines methods for reading and writing values of all other - * primitive types, except boolean. 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}. - * - *

For access to heterogeneous binary data, that is, sequences of values of - * different types, this class defines a family of absolute and relative - * get and put methods for each type. For 32-bit floating-point - * values, for example, this class defines: - * - *

- * 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)}
- * - *

Corresponding methods are defined for the types char, - * short, int, long, and double. The index - * parameters of the absolute get and put methods are in terms of - * bytes rather than of the type being read or written. - * - * - * - *

For access to homogeneous binary data, that is, sequences of values of - * the same type, this class defines methods that can create views of a - * given byte buffer. A view buffer 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 char, short, int, long, and - * double. - * - *

View buffers have three important advantages over the families of - * type-specific get and put methods described above: - * - *

- * - *

The byte order of a view buffer is fixed to be that of its byte buffer - * at the time that the view is created.

- * -#end[byte] -* -#if[!byte] - * - *

Like a byte buffer, $a$ $fulltype$ buffer is either direct or non-direct. A - * $fulltype$ buffer created via the wrap 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.

- * -#end[!byte] -* -#if[char] - * - *

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 {@link java.util.regex}. - *

- * -#end[char] - * -#if[byte] - *

Invocation chaining

-#end[byte] - * - *

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 - * - *

- * bb.putInt(0xCAFEBABE);
- * bb.putShort(3);
- * bb.putShort(45);
- * - * can, for example, be replaced by the single statement - * - *
- * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);
- * -#end[byte] -#if[char] - * - * The sequence of statements - * - *
- * cb.put("text/");
- * cb.put(subtype);
- * cb.put("; charset=");
- * cb.put(enc);
- * - * can, for example, be replaced by the single statement - * - *
- * cb.put("text/").put(subtype).put("; charset=").put(enc);
- * -#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. - * - *

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 backing array} is unspecified. - * - * @param capacity - * The new buffer's capacity, in $fulltype$s - * - * @return The new $fulltype$ buffer - * - * @throws IllegalArgumentException - * If the capacity is a negative integer - */ - public static $Type$Buffer allocateDirect(int capacity) { - return new Direct$Type$Buffer(capacity); - } - -#end[byte] - - /** - * Allocates a new $fulltype$ buffer. - * - *

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 - * backing array}, and its {@link #arrayOffset array - * offset} will be zero. - * - * @param capacity - * The new buffer's capacity, in $fulltype$s - * - * @return The new $fulltype$ buffer - * - * @throws IllegalArgumentException - * If the capacity 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. - * - *

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 - * array.length, its position will be offset, its limit - * will be offset + length, and its mark will be undefined. Its - * {@link #array backing array} will be the given array, and - * its {@link #arrayOffset array offset} will be zero.

- * - * @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 array.length. 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 - * array.length - offset. - * The new buffer's limit will be set to offset + length. - * - * @return The new $fulltype$ buffer - * - * @throws IndexOutOfBoundsException - * If the preconditions on the offset and length - * 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. - * - *

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 - * array.length, its position will be zero, and its mark will be - * undefined. Its {@link #array backing array} will be the - * given array, and its {@link #arrayOffset array offset} will - * be zero.

- * - * @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. - * - *

The content of the new, read-only buffer will be the content of the - * given character sequence. The buffer's capacity will be - * csq.length(), its position will be start, its limit - * will be end, and its mark will be undefined.

- * - * @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 csq.length(). - * 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 start and no larger - * than csq.length(). - * The new buffer's limit will be set to this value. - * - * @return The new character buffer - * - * @throws IndexOutOfBoundsException - * If the preconditions on the start and end - * 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. - * - *

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 - * csq.length(), its position will be zero, and its mark will be - * undefined.

- * - * @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. - * - *

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. - * - *

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.

- * - * @return The new $fulltype$ buffer - */ - public abstract $Type$Buffer slice(); - - /** - * Creates a new $fulltype$ buffer that shares this buffer's content. - * - *

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. - * - *

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.

- * - * @return The new $fulltype$ buffer - */ - public abstract $Type$Buffer duplicate(); - - /** - * Creates a new, read-only $fulltype$ buffer that shares this buffer's - * content. - * - *

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. - * - *

The new buffer's capacity, limit, position, and mark values will be - * identical to those of this buffer. - * - *

If this buffer is itself read-only then this method behaves in - * exactly the same way as the {@link #duplicate duplicate} method.

- * - * @return The new, read-only $fulltype$ buffer - */ - public abstract $Type$Buffer asReadOnlyBuffer(); - - - // -- Singleton get/put methods -- - - /** - * Relative get method. Reads the $fulltype$ at this buffer's - * current position, and then increments the position.

- * - * @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 put method  (optional operation). - * - *

Writes the given $fulltype$ into this buffer at the current - * position, and then increments the position.

- * - * @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 get method. Reads the $fulltype$ at the given - * index.

- * - * @param index - * The index from which the $fulltype$ will be read - * - * @return The $fulltype$ at the given index - * - * @throws IndexOutOfBoundsException - * If index is negative - * or not smaller than the buffer's limit - */ - public abstract $type$ get(int index); - - /** - * Absolute put method  (optional operation). - * - *

Writes the given $fulltype$ into this buffer at the given - * index.

- * - * @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 index 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 get method. - * - *

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 - * length > remaining(), then no - * $fulltype$s are transferred and a {@link BufferUnderflowException} is - * thrown. - * - *

Otherwise, this method copies length $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 length. - * - *

In other words, an invocation of this method of the form - * src.get(dst, off, len) has exactly the same effect as - * the loop - * - *

-     *     for (int i = off; i < off + len; i++)
-     *         dst[i] = src.get(); 
- * - * except that it first checks that there are sufficient $fulltype$s in - * this buffer and it is potentially much more efficient.

- * - * @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 - * dst.length - * - * @param length - * The maximum number of $fulltype$s to be written to the given - * array; must be non-negative and no larger than - * dst.length - offset - * - * @return This buffer - * - * @throws BufferUnderflowException - * If there are fewer than length $fulltype$s - * remaining in this buffer - * - * @throws IndexOutOfBoundsException - * If the preconditions on the offset and length - * 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 get method. - * - *

This method transfers $fulltype$s from this buffer into the given - * destination array. An invocation of this method of the form - * src.get(a) behaves in exactly the same way as the invocation - * - *

-     *     src.get(a, 0, a.length) 
- * - * @return This buffer - * - * @throws BufferUnderflowException - * If there are fewer than length $fulltype$s - * remaining in this buffer - */ - public $Type$Buffer get($type$[] dst) { - return get(dst, 0, dst.length); - } - - - // -- Bulk put operations -- - - /** - * Relative bulk put method  (optional operation). - * - *

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 - * src.remaining() > remaining(), - * then no $fulltype$s are transferred and a {@link - * BufferOverflowException} is thrown. - * - *

Otherwise, this method copies - * n = src.remaining() $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 n. - * - *

In other words, an invocation of this method of the form - * dst.put(src) has exactly the same effect as the loop - * - *

-     *     while (src.hasRemaining())
-     *         dst.put(src.get()); 
- * - * except that it first checks that there is sufficient space in this - * buffer and it is potentially much more efficient.

- * - * @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 put method  (optional operation). - * - *

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 - * length > remaining(), then no - * $fulltype$s are transferred and a {@link BufferOverflowException} is - * thrown. - * - *

Otherwise, this method copies length $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 length. - * - *

In other words, an invocation of this method of the form - * dst.put(src, off, len) has exactly the same effect as - * the loop - * - *

-     *     for (int i = off; i < off + len; i++)
-     *         dst.put(a[i]); 
- * - * except that it first checks that there is sufficient space in this - * buffer and it is potentially much more efficient.

- * - * @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 array.length - * - * @param length - * The number of $fulltype$s to be read from the given array; - * must be non-negative and no larger than - * array.length - offset - * - * @return This buffer - * - * @throws BufferOverflowException - * If there is insufficient space in this buffer - * - * @throws IndexOutOfBoundsException - * If the preconditions on the offset and length - * 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 put method  (optional operation). - * - *

This method transfers the entire content of the given source - * $fulltype$ array into this buffer. An invocation of this method of the - * form dst.put(a) behaves in exactly the same way as the - * invocation - * - *

-     *     dst.put(a, 0, a.length) 
- * - * @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 put method  (optional operation). - * - *

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 - * end - start > remaining(), - * then no $fulltype$s are transferred and a {@link - * BufferOverflowException} is thrown. - * - *

Otherwise, this method copies - * n = end - start $fulltype$s - * from the given string into this buffer, starting at the given - * start index and at the current position of this buffer. The - * position of this buffer is then incremented by n. - * - *

In other words, an invocation of this method of the form - * dst.put(src, start, end) has exactly the same effect - * as the loop - * - *

-     *     for (int i = start; i < end; i++)
-     *         dst.put(src.charAt(i)); 
- * - * except that it first checks that there is sufficient space in this - * buffer and it is potentially much more efficient.

- * - * @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 - * string.length() - * - * @param end - * The offset within the string of the last $fulltype$ to be read, - * plus one; must be non-negative and no larger than - * string.length() - * - * @return This buffer - * - * @throws BufferOverflowException - * If there is insufficient space in this buffer - * - * @throws IndexOutOfBoundsException - * If the preconditions on the start and end - * 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 put method  (optional operation). - * - *

This method transfers the entire content of the given source string - * into this buffer. An invocation of this method of the form - * dst.put(s) behaves in exactly the same way as the invocation - * - *

-     *     dst.put(s, 0, s.length()) 
- * - * @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. - * - *

If this method returns true then the {@link #array() array} - * and {@link #arrayOffset() arrayOffset} methods may safely be invoked. - *

- * - * @return true 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  (optional operation). - * - *

Modifications to this buffer's content will cause the returned - * array's content to be modified, and vice versa. - * - *

Invoke the {@link #hasArray hasArray} method before invoking this - * method in order to ensure that this buffer has an accessible backing - * array.

- * - * @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  (optional operation). - * - *

If this buffer is backed by an array then buffer position p - * corresponds to array index p + arrayOffset(). - * - *

Invoke the {@link #hasArray hasArray} method before invoking this - * method in order to ensure that this buffer has an accessible backing - * array.

- * - * @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  (optional operation). - * - *

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 p = position() is copied - * to index zero, the $fulltype$ at index p + 1 is copied - * to index one, and so forth until the $fulltype$ at index - * limit() - 1 is copied to index - * n = limit() - 1 - p. - * The buffer's position is then set to n+1 and its limit is set to - * its capacity. The mark, if defined, is discarded. - * - *

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 put - * method.

- * -#if[byte] - * - *

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 buf: - * - *

-     * 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
-     * }
- * -#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.

- * - * @return true if, and only if, this buffer is direct - */ - public abstract boolean isDirect(); - -#if[!char] - - /** - * Returns a string summarizing the state of this buffer.

- * - * @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. - * - *

The hash code of a $type$ buffer depends only upon its remaining - * elements; that is, upon the elements from position() up to, and - * including, the element at limit() - 1. - * - *

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.

- * - * @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. - * - *

Two $type$ buffers are equal if, and only if, - * - *

    - * - *
  1. They have the same element type,

  2. - * - *
  3. They have the same number of remaining elements, and - *

  4. - * - *
  5. The two sequences of remaining elements, considered - * independently of their starting positions, are pointwise equal. - *

  6. - * - *
- * - *

A $type$ buffer is not equal to any other type of object.

- * - * @param ob The object to which this buffer is to be compared - * - * @return true 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. - * - *

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. - * - *

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. - * - *

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 limit() - 1. Invoking this method does not - * change the buffer's position.

- * - * @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. - * - *

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 - * remaining().

- * - * @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.

- * - * @param index - * The index of the character to be read, relative to the position; - * must be non-negative and smaller than remaining() - * - * @return The character at index - * position() + index - * - * @throws IndexOutOfBoundsException - * If the preconditions on index 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. - * - *

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 - * position() + start, and its limit will be - * position() + end. 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.

- * - * @param start - * The index, relative to the current position, of the first - * character in the subsequence; must be non-negative and no larger - * than remaining() - * - * @param end - * The index, relative to the current position, of the character - * following the last character in the subsequence; must be no - * smaller than start and no larger than - * remaining() - * - * @return The new character buffer - * - * @throws IndexOutOfBoundsException - * If the preconditions on start and end - * do not hold - */ - public abstract CharBuffer subSequence(int start, int end); - - - // --- Methods to support Appendable --- - - /** - * Appends the specified character sequence to this - * buffer  (optional operation). - * - *

An invocation of this method of the form dst.append(csq) - * behaves in exactly the same way as the invocation - * - *

-     *     dst.put(csq.toString()) 
- * - *

Depending on the specification of toString for the - * character sequence csq, 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 csq is - * null, then the four characters "null" 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  (optional operation). - * - *

An invocation of this method of the form dst.append(csq, start, - * end) when csq is not null, behaves in exactly the - * same way as the invocation - * - *

-     *     dst.put(csq.subSequence(start, end).toString()) 
- * - * @param csq - * The character sequence from which a subsequence will be - * appended. If csq is null, then characters - * will be appended as if csq contained the four - * characters "null". - * - * @return This buffer - * - * @throws BufferOverflowException - * If there is insufficient space in this buffer - * - * @throws IndexOutOfBoundsException - * If start or end are negative, start - * is greater than end, or end is greater than - * csq.length() - * - * @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  (optional operation). - * - *

An invocation of this method of the form dst.append($x$) - * behaves in exactly the same way as the invocation - * - *

-     *     dst.put($x$) 
- * - * @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. - * - *

The byte order of $a$ $fulltype$ buffer created by allocation or by - * wrapping an existing $type$ array is the {@link - * ByteOrder#nativeOrder native order} of the underlying - * hardware. The byte order of $a$ $fulltype$ buffer created as a view of a byte buffer is that of the - * byte buffer at the moment that the view is created.

- * - * @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. - * - *

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}.

- * - * @return This buffer's byte order - */ - public final ByteOrder order() { - return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; - } - - /** - * Modifies this buffer's byte order.

- * - * @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] - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/X-Buffer.java.template --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/nio/X-Buffer.java.template Wed Nov 25 22:14:30 2009 -0800 @@ -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. + * + *

This class defines {#if[byte]?six:four} categories of operations upon + * $fulltype$ buffers: + * + *

    + * + *
  • Absolute and relative {@link #get() get} and + * {@link #put($type$) put} methods that read and write + * single $fulltype$s;

  • + * + *
  • Relative {@link #get($type$[]) bulk get} + * methods that transfer contiguous sequences of $fulltype$s from this buffer + * into an array; {#if[!byte]?and}

  • + * + *
  • Relative {@link #put($type$[]) bulk put} + * 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}

  • + * +#if[byte] + * + *
  • Absolute and relative {@link #getChar() get} + * and {@link #putChar(char) put} methods that read and + * write values of other primitive types, translating them to and from + * sequences of bytes in a particular byte order;

  • + * + *
  • Methods for creating view buffers, + * which allow a byte buffer to be viewed as a buffer containing values of + * some other primitive type; and

  • + * +#end[byte] + * + *
  • Methods for {@link #compact compacting}, {@link + * #duplicate duplicating}, and {@link #slice + * slicing} $a$ $fulltype$ buffer.

  • + * + *
+ * + *

$Fulltype$ buffers can be created either by {@link #allocate + * allocation}, which allocates space for the buffer's + * +#if[byte] + * + * content, or by {@link #wrap($type$[]) wrapping} an + * existing $fulltype$ array {#if[char]?or string} into a buffer. + * +#else[byte] + * + * content, by {@link #wrap($type$[]) wrapping} an existing + * $fulltype$ array {#if[char]?or string} into a buffer, or by creating a + * view of an existing byte buffer. + * +#end[byte] + * +#if[byte] + * + * + *

Direct vs. non-direct buffers

+ * + *

A byte buffer is either direct or non-direct. 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. + * + *

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. + * + *

A direct byte buffer may also be created by {@link + * java.nio.channels.FileChannel#map mapping} 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. + * + *

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. + * + * + * + *

Access to binary data

+ * + *

This class defines methods for reading and writing values of all other + * primitive types, except boolean. 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}. + * + *

For access to heterogeneous binary data, that is, sequences of values of + * different types, this class defines a family of absolute and relative + * get and put methods for each type. For 32-bit floating-point + * values, for example, this class defines: + * + *

+ * 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)}
+ * + *

Corresponding methods are defined for the types char, + * short, int, long, and double. The index + * parameters of the absolute get and put methods are in terms of + * bytes rather than of the type being read or written. + * + * + * + *

For access to homogeneous binary data, that is, sequences of values of + * the same type, this class defines methods that can create views of a + * given byte buffer. A view buffer 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 char, short, int, long, and + * double. + * + *

View buffers have three important advantages over the families of + * type-specific get and put methods described above: + * + *

+ * + *

The byte order of a view buffer is fixed to be that of its byte buffer + * at the time that the view is created.

+ * +#end[byte] +* +#if[!byte] + * + *

Like a byte buffer, $a$ $fulltype$ buffer is either direct or non-direct. A + * $fulltype$ buffer created via the wrap 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.

+ * +#end[!byte] +* +#if[char] + * + *

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 {@link java.util.regex}. + *

+ * +#end[char] + * +#if[byte] + *

Invocation chaining

+#end[byte] + * + *

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 + * + *

+ * bb.putInt(0xCAFEBABE);
+ * bb.putShort(3);
+ * bb.putShort(45);
+ * + * can, for example, be replaced by the single statement + * + *
+ * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);
+ * +#end[byte] +#if[char] + * + * The sequence of statements + * + *
+ * cb.put("text/");
+ * cb.put(subtype);
+ * cb.put("; charset=");
+ * cb.put(enc);
+ * + * can, for example, be replaced by the single statement + * + *
+ * cb.put("text/").put(subtype).put("; charset=").put(enc);
+ * +#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. + * + *

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 backing array} is unspecified. + * + * @param capacity + * The new buffer's capacity, in $fulltype$s + * + * @return The new $fulltype$ buffer + * + * @throws IllegalArgumentException + * If the capacity is a negative integer + */ + public static $Type$Buffer allocateDirect(int capacity) { + return new Direct$Type$Buffer(capacity); + } + +#end[byte] + + /** + * Allocates a new $fulltype$ buffer. + * + *

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 + * backing array}, and its {@link #arrayOffset array + * offset} will be zero. + * + * @param capacity + * The new buffer's capacity, in $fulltype$s + * + * @return The new $fulltype$ buffer + * + * @throws IllegalArgumentException + * If the capacity 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. + * + *

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 + * array.length, its position will be offset, its limit + * will be offset + length, and its mark will be undefined. Its + * {@link #array backing array} will be the given array, and + * its {@link #arrayOffset array offset} will be zero.

+ * + * @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 array.length. 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 + * array.length - offset. + * The new buffer's limit will be set to offset + length. + * + * @return The new $fulltype$ buffer + * + * @throws IndexOutOfBoundsException + * If the preconditions on the offset and length + * 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. + * + *

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 + * array.length, its position will be zero, and its mark will be + * undefined. Its {@link #array backing array} will be the + * given array, and its {@link #arrayOffset array offset} will + * be zero.

+ * + * @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. + * + *

The content of the new, read-only buffer will be the content of the + * given character sequence. The buffer's capacity will be + * csq.length(), its position will be start, its limit + * will be end, and its mark will be undefined.

+ * + * @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 csq.length(). + * 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 start and no larger + * than csq.length(). + * The new buffer's limit will be set to this value. + * + * @return The new character buffer + * + * @throws IndexOutOfBoundsException + * If the preconditions on the start and end + * 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. + * + *

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 + * csq.length(), its position will be zero, and its mark will be + * undefined.

+ * + * @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. + * + *

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. + * + *

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.

+ * + * @return The new $fulltype$ buffer + */ + public abstract $Type$Buffer slice(); + + /** + * Creates a new $fulltype$ buffer that shares this buffer's content. + * + *

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. + * + *

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.

+ * + * @return The new $fulltype$ buffer + */ + public abstract $Type$Buffer duplicate(); + + /** + * Creates a new, read-only $fulltype$ buffer that shares this buffer's + * content. + * + *

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. + * + *

The new buffer's capacity, limit, position, and mark values will be + * identical to those of this buffer. + * + *

If this buffer is itself read-only then this method behaves in + * exactly the same way as the {@link #duplicate duplicate} method.

+ * + * @return The new, read-only $fulltype$ buffer + */ + public abstract $Type$Buffer asReadOnlyBuffer(); + + + // -- Singleton get/put methods -- + + /** + * Relative get method. Reads the $fulltype$ at this buffer's + * current position, and then increments the position.

+ * + * @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 put method  (optional operation). + * + *

Writes the given $fulltype$ into this buffer at the current + * position, and then increments the position.

+ * + * @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 get method. Reads the $fulltype$ at the given + * index.

+ * + * @param index + * The index from which the $fulltype$ will be read + * + * @return The $fulltype$ at the given index + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit + */ + public abstract $type$ get(int index); + + /** + * Absolute put method  (optional operation). + * + *

Writes the given $fulltype$ into this buffer at the given + * index.

+ * + * @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 index 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 get method. + * + *

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 + * length > remaining(), then no + * $fulltype$s are transferred and a {@link BufferUnderflowException} is + * thrown. + * + *

Otherwise, this method copies length $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 length. + * + *

In other words, an invocation of this method of the form + * src.get(dst, off, len) has exactly the same effect as + * the loop + * + *

+     *     for (int i = off; i < off + len; i++)
+     *         dst[i] = src.get(); 
+ * + * except that it first checks that there are sufficient $fulltype$s in + * this buffer and it is potentially much more efficient.

+ * + * @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 + * dst.length + * + * @param length + * The maximum number of $fulltype$s to be written to the given + * array; must be non-negative and no larger than + * dst.length - offset + * + * @return This buffer + * + * @throws BufferUnderflowException + * If there are fewer than length $fulltype$s + * remaining in this buffer + * + * @throws IndexOutOfBoundsException + * If the preconditions on the offset and length + * 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 get method. + * + *

This method transfers $fulltype$s from this buffer into the given + * destination array. An invocation of this method of the form + * src.get(a) behaves in exactly the same way as the invocation + * + *

+     *     src.get(a, 0, a.length) 
+ * + * @return This buffer + * + * @throws BufferUnderflowException + * If there are fewer than length $fulltype$s + * remaining in this buffer + */ + public $Type$Buffer get($type$[] dst) { + return get(dst, 0, dst.length); + } + + + // -- Bulk put operations -- + + /** + * Relative bulk put method  (optional operation). + * + *

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 + * src.remaining() > remaining(), + * then no $fulltype$s are transferred and a {@link + * BufferOverflowException} is thrown. + * + *

Otherwise, this method copies + * n = src.remaining() $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 n. + * + *

In other words, an invocation of this method of the form + * dst.put(src) has exactly the same effect as the loop + * + *

+     *     while (src.hasRemaining())
+     *         dst.put(src.get()); 
+ * + * except that it first checks that there is sufficient space in this + * buffer and it is potentially much more efficient.

+ * + * @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 put method  (optional operation). + * + *

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 + * length > remaining(), then no + * $fulltype$s are transferred and a {@link BufferOverflowException} is + * thrown. + * + *

Otherwise, this method copies length $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 length. + * + *

In other words, an invocation of this method of the form + * dst.put(src, off, len) has exactly the same effect as + * the loop + * + *

+     *     for (int i = off; i < off + len; i++)
+     *         dst.put(a[i]); 
+ * + * except that it first checks that there is sufficient space in this + * buffer and it is potentially much more efficient.

+ * + * @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 array.length + * + * @param length + * The number of $fulltype$s to be read from the given array; + * must be non-negative and no larger than + * array.length - offset + * + * @return This buffer + * + * @throws BufferOverflowException + * If there is insufficient space in this buffer + * + * @throws IndexOutOfBoundsException + * If the preconditions on the offset and length + * 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 put method  (optional operation). + * + *

This method transfers the entire content of the given source + * $fulltype$ array into this buffer. An invocation of this method of the + * form dst.put(a) behaves in exactly the same way as the + * invocation + * + *

+     *     dst.put(a, 0, a.length) 
+ * + * @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 put method  (optional operation). + * + *

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 + * end - start > remaining(), + * then no $fulltype$s are transferred and a {@link + * BufferOverflowException} is thrown. + * + *

Otherwise, this method copies + * n = end - start $fulltype$s + * from the given string into this buffer, starting at the given + * start index and at the current position of this buffer. The + * position of this buffer is then incremented by n. + * + *

In other words, an invocation of this method of the form + * dst.put(src, start, end) has exactly the same effect + * as the loop + * + *

+     *     for (int i = start; i < end; i++)
+     *         dst.put(src.charAt(i)); 
+ * + * except that it first checks that there is sufficient space in this + * buffer and it is potentially much more efficient.

+ * + * @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 + * string.length() + * + * @param end + * The offset within the string of the last $fulltype$ to be read, + * plus one; must be non-negative and no larger than + * string.length() + * + * @return This buffer + * + * @throws BufferOverflowException + * If there is insufficient space in this buffer + * + * @throws IndexOutOfBoundsException + * If the preconditions on the start and end + * 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 put method  (optional operation). + * + *

This method transfers the entire content of the given source string + * into this buffer. An invocation of this method of the form + * dst.put(s) behaves in exactly the same way as the invocation + * + *

+     *     dst.put(s, 0, s.length()) 
+ * + * @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. + * + *

If this method returns true then the {@link #array() array} + * and {@link #arrayOffset() arrayOffset} methods may safely be invoked. + *

+ * + * @return true 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  (optional operation). + * + *

Modifications to this buffer's content will cause the returned + * array's content to be modified, and vice versa. + * + *

Invoke the {@link #hasArray hasArray} method before invoking this + * method in order to ensure that this buffer has an accessible backing + * array.

+ * + * @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  (optional operation). + * + *

If this buffer is backed by an array then buffer position p + * corresponds to array index p + arrayOffset(). + * + *

Invoke the {@link #hasArray hasArray} method before invoking this + * method in order to ensure that this buffer has an accessible backing + * array.

+ * + * @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  (optional operation). + * + *

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 p = position() is copied + * to index zero, the $fulltype$ at index p + 1 is copied + * to index one, and so forth until the $fulltype$ at index + * limit() - 1 is copied to index + * n = limit() - 1 - p. + * The buffer's position is then set to n+1 and its limit is set to + * its capacity. The mark, if defined, is discarded. + * + *

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 put + * method.

+ * +#if[byte] + * + *

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 buf: + * + *

+     * 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
+     * }
+ * +#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.

+ * + * @return true if, and only if, this buffer is direct + */ + public abstract boolean isDirect(); + +#if[!char] + + /** + * Returns a string summarizing the state of this buffer.

+ * + * @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. + * + *

The hash code of a $type$ buffer depends only upon its remaining + * elements; that is, upon the elements from position() up to, and + * including, the element at limit() - 1. + * + *

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.

+ * + * @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. + * + *

Two $type$ buffers are equal if, and only if, + * + *

    + * + *
  1. They have the same element type,

  2. + * + *
  3. They have the same number of remaining elements, and + *

  4. + * + *
  5. The two sequences of remaining elements, considered + * independently of their starting positions, are pointwise equal. + *

  6. + * + *
+ * + *

A $type$ buffer is not equal to any other type of object.

+ * + * @param ob The object to which this buffer is to be compared + * + * @return true 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. + * + *

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. + * + *

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. + * + *

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 limit() - 1. Invoking this method does not + * change the buffer's position.

+ * + * @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. + * + *

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 + * remaining().

+ * + * @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.

+ * + * @param index + * The index of the character to be read, relative to the position; + * must be non-negative and smaller than remaining() + * + * @return The character at index + * position() + index + * + * @throws IndexOutOfBoundsException + * If the preconditions on index 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. + * + *

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 + * position() + start, and its limit will be + * position() + end. 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.

+ * + * @param start + * The index, relative to the current position, of the first + * character in the subsequence; must be non-negative and no larger + * than remaining() + * + * @param end + * The index, relative to the current position, of the character + * following the last character in the subsequence; must be no + * smaller than start and no larger than + * remaining() + * + * @return The new character buffer + * + * @throws IndexOutOfBoundsException + * If the preconditions on start and end + * do not hold + */ + public abstract CharBuffer subSequence(int start, int end); + + + // --- Methods to support Appendable --- + + /** + * Appends the specified character sequence to this + * buffer  (optional operation). + * + *

An invocation of this method of the form dst.append(csq) + * behaves in exactly the same way as the invocation + * + *

+     *     dst.put(csq.toString()) 
+ * + *

Depending on the specification of toString for the + * character sequence csq, 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 csq is + * null, then the four characters "null" 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  (optional operation). + * + *

An invocation of this method of the form dst.append(csq, start, + * end) when csq is not null, behaves in exactly the + * same way as the invocation + * + *

+     *     dst.put(csq.subSequence(start, end).toString()) 
+ * + * @param csq + * The character sequence from which a subsequence will be + * appended. If csq is null, then characters + * will be appended as if csq contained the four + * characters "null". + * + * @return This buffer + * + * @throws BufferOverflowException + * If there is insufficient space in this buffer + * + * @throws IndexOutOfBoundsException + * If start or end are negative, start + * is greater than end, or end is greater than + * csq.length() + * + * @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  (optional operation). + * + *

An invocation of this method of the form dst.append($x$) + * behaves in exactly the same way as the invocation + * + *

+     *     dst.put($x$) 
+ * + * @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. + * + *

The byte order of $a$ $fulltype$ buffer created by allocation or by + * wrapping an existing $type$ array is the {@link + * ByteOrder#nativeOrder native order} of the underlying + * hardware. The byte order of $a$ $fulltype$ buffer created as a view of a byte buffer is that of the + * byte buffer at the moment that the view is created.

+ * + * @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. + * + *

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}.

+ * + * @return This buffer's byte order + */ + public final ByteOrder order() { + return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; + } + + /** + * Modifies this buffer's byte order.

+ * + * @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] + +} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/charset/Charset-X-Coder.java --- a/src/share/classes/java/nio/charset/Charset-X-Coder.java Wed Nov 25 21:27:06 2009 +0300 +++ /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$. - * - * - * - *

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$ - * $coding$ operation: - * - *

    - * - *
  1. Reset the $coder$ via the {@link #reset reset} method, unless it - * has not been used before;

  2. - * - *
  3. Invoke the {@link #$code$ $code$} method zero or more times, as - * long as additional input may be available, passing false for the - * endOfInput argument and filling the input buffer and flushing the - * output buffer between invocations;

  4. - * - *
  5. Invoke the {@link #$code$ $code$} method one final time, passing - * true for the endOfInput argument; and then

  6. - * - *
  7. Invoke the {@link #flush flush} method so that the $coder$ can - * flush any internal state to the output buffer.

  8. - * - *
- * - * 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. - * - *
- * - *

There are two general types of $coding$ errors. If the input $itype$ - * sequence is $notLegal$ then the input is considered malformed. If - * the input $itype$ sequence is legal but cannot be mapped to a valid - * $outSequence$ then an unmappable character has been encountered. - * - * - * - *

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 ignore} the erroneous input, {@link - * CodingErrorAction#REPORT report} the error to the invoker via - * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE - * replace} 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. - * - *

The default action for malformed-input and unmappable-character errors - * is to {@link CodingErrorAction#REPORT report} 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. - * - *

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. - * - *

Instances of this class are not safe for use by multiple concurrent - * threads.

- * - * - * @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.

- * - * @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 null, must have - * non-zero length, must not be longer than max$ItypesPerOtype$, - * and must be {@link #isLegalReplacement
legal} - * - * @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$.

- * - * @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$.

- * - * @return This $coder$'s charset - */ - public final Charset charset() { - return charset; - } - - /** - * Returns this $coder$'s replacement value.

- * - * @return This $coder$'s current replacement, - * which is never null and is never empty - */ - public final $replType$ replacement() { - return replacement; - } - - /** - * Changes this $coder$'s replacement value. - * - *

This method invokes the {@link #implReplaceWith implReplaceWith} - * method, passing the new replacement, after checking that the new - * replacement is acceptable.

- * - * @param newReplacement - * -#if[decoder] - * The new replacement; must not be null - * and must have non-zero length -#end[decoder] -#if[encoder] - * The new replacement; must not be null, 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
legal} -#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. - * - *

The default implementation of this method does nothing. This method - * should be overridden by $coder$s that require notification of changes to - * the replacement.

- * - * @param newReplacement - */ - protected void implReplaceWith($replType$ newReplacement) { - } - -#if[encoder] - - private WeakReference cachedDecoder = null; - - /** - * Tells whether or not the given byte array is a legal replacement value - * for this encoder. - * - *

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. - * - *

The default implementation of this method is not very efficient; it - * should generally be overridden to improve performance.

- * - * @param repl The byte array to be tested - * - * @return true if, and only if, the given byte array - * is a legal replacement value for this encoder - */ - public boolean isLegalReplacement(byte[] repl) { - WeakReference 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(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.

- * - * @return The current malformed-input action, which is never null - */ - public CodingErrorAction malformedInputAction() { - return malformedInputAction; - } - - /** - * Changes this $coder$'s action for malformed-input errors.

- * - *

This method invokes the {@link #implOnMalformedInput - * implOnMalformedInput} method, passing the new action.

- * - * @param newAction The new action; must not be null - * - * @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. - * - *

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.

- */ - protected void implOnMalformedInput(CodingErrorAction newAction) { } - - /** - * Returns this $coder$'s current action for unmappable-character errors. - *

- * - * @return The current unmappable-character action, which is never - * null - */ - public CodingErrorAction unmappableCharacterAction() { - return unmappableCharacterAction; - } - - /** - * Changes this $coder$'s action for unmappable-character errors. - * - *

This method invokes the {@link #implOnUnmappableCharacter - * implOnUnmappableCharacter} method, passing the new action.

- * - * @param newAction The new action; must not be null - * - * @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. - * - *

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.

- */ - 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.

- * - * @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.

- * - * @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. - * - *

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. - * - *

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: - * - *

- * - * 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. - * - *

The endOfInput 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 false for this parameter; if there - * is no possibility of providing further input then the invoker should - * pass true. It is not erroneous, and in fact it is quite - * common, to pass false 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 true so that any remaining un$code$d input will be treated - * as being malformed. - * - *

This method works by invoking the {@link #$code$Loop $code$Loop} - * method, interpreting its results, handling error conditions, and - * reinvoking it as necessary.

- * - * - * @param in - * The input $itype$ buffer - * - * @param out - * The output $otype$ buffer - * - * @param endOfInput - * true 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 false for - * the endOfInput parameter, nor of this method with a - * value of true for the endOfInput 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$. - * - *

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. - * - *

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. - * - *

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 $coding$ - * operation. - * - *

If this $coder$ has already been flushed then invoking this method - * has no effect. - * - *

This method invokes the {@link #implFlush implFlush} method to - * perform the actual flushing operation.

- * - * @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 true for the endOfInput - * 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$. - * - *

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.

- * - * @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. - * - *

This method resets charset-independent state and also invokes the - * {@link #implReset() implReset} method in order to perform any - * charset-specific reset actions.

- * - * @return This $coder$ - * - */ - public final Charset$Coder$ reset() { - implReset(); - state = ST_RESET; - return this; - } - - /** - * Resets this $coder$, clearing any charset-specific internal state. - * - *

The default implementation of this method does nothing. This method - * should be overridden by $coder$s that maintain internal state.

- */ - protected void implReset() { } - - /** - * $Code$s one or more $itype$s into one or more $otype$s. - * - *

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. - * - *

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. - * - *

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. - * - *

An implementation of this method may perform arbitrary lookahead by - * returning {@link CoderResult#UNDERFLOW} until it receives sufficient - * input.

- * - * @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. - * - *

This method implements an entire $coding$ - * operation; 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.

- * - * @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. - * - *

The default implementation of this method always returns - * false; it should be overridden by auto-detecting decoders to - * return true.

- * - * @return true 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  (optional operation). - * - *

If this decoder implements an auto-detecting charset then at a - * single point during a decoding operation this method may start returning - * true 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. - * - *

That this method returns false 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. - * - *

The default implementation of this method always throws an {@link - * UnsupportedOperationException}; it should be overridden by - * auto-detecting decoders to return true once the input charset - * has been determined.

- * - * @return true 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  (optional operation). - * - *

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}. - * - *

The default implementation of this method always throws an {@link - * UnsupportedOperationException}; it should be overridden by - * auto-detecting decoders to return the appropriate value.

- * - * @return The charset detected by this auto-detecting decoder, - * or null 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. - * - *

This method returns false 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. - * - *

This method may modify this encoder's state; it should therefore not - * be invoked if an encoding operation is already in - * progress. - * - *

The default implementation of this method is not very efficient; it - * should generally be overridden to improve performance.

- * - * @return true 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. - * - *

If this method returns false for a particular character - * sequence then more information about why the sequence cannot be encoded - * may be obtained by performing a full encoding - * operation. - * - *

This method may modify this encoder's state; it should therefore not - * be invoked if an encoding operation is already in progress. - * - *

The default implementation of this method is not very efficient; it - * should generally be overridden to improve performance.

- * - * @return true 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]); - } - -} diff -r b62c74b1772e -r 6fd07b903478 src/share/classes/java/nio/charset/Charset-X-Coder.java.template --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/nio/charset/Charset-X-Coder.java.template Wed Nov 25 22:14:30 2009 -0800 @@ -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$. + * + * + * + *

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$ + * $coding$ operation: + * + *

    + * + *
  1. Reset the $coder$ via the {@link #reset reset} method, unless it + * has not been used before;

  2. + * + *
  3. Invoke the {@link #$code$ $code$} method zero or more times, as + * long as additional input may be available, passing false for the + * endOfInput argument and filling the input buffer and flushing the + * output buffer between invocations;

  4. + * + *
  5. Invoke the {@link #$code$ $code$} method one final time, passing + * true for the endOfInput argument; and then

  6. + * + *
  7. Invoke the {@link #flush flush} method so that the $coder$ can + * flush any internal state to the output buffer.

  8. + * + *
+ * + * 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. + * + *
+ * + *

There are two general types of $coding$ errors. If the input $itype$ + * sequence is $notLegal$ then the input is considered malformed. If + * the input $itype$ sequence is legal but cannot be mapped to a valid + * $outSequence$ then an unmappable character has been encountered. + * + * + * + *

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 ignore} the erroneous input, {@link + * CodingErrorAction#REPORT report} the error to the invoker via + * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE + * replace} 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. + * + *

The default action for malformed-input and unmappable-character errors + * is to {@link CodingErrorAction#REPORT report} 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. + * + *

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. + * + *

Instances of this class are not safe for use by multiple concurrent + * threads.

+ * + * + * @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.

+ * + * @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 null, must have + * non-zero length, must not be longer than max$ItypesPerOtype$, + * and must be {@link #isLegalReplacement
legal} + * + * @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$.

+ * + * @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$.

+ * + * @return This $coder$'s charset + */ + public final Charset charset() { + return charset; + } + + /** + * Returns this $coder$'s replacement value.

+ * + * @return This $coder$'s current replacement, + * which is never null and is never empty + */ + public final $replType$ replacement() { + return replacement; + } + + /** + * Changes this $coder$'s replacement value. + * + *

This method invokes the {@link #implReplaceWith implReplaceWith} + * method, passing the new replacement, after checking that the new + * replacement is acceptable.

+ * + * @param newReplacement + * +#if[decoder] + * The new replacement; must not be null + * and must have non-zero length +#end[decoder] +#if[encoder] + * The new replacement; must not be null, 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
legal} +#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. + * + *

The default implementation of this method does nothing. This method + * should be overridden by $coder$s that require notification of changes to + * the replacement.

+ * + * @param newReplacement + */ + protected void implReplaceWith($replType$ newReplacement) { + } + +#if[encoder] + + private WeakReference cachedDecoder = null; + + /** + * Tells whether or not the given byte array is a legal replacement value + * for this encoder. + * + *

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. + * + *

The default implementation of this method is not very efficient; it + * should generally be overridden to improve performance.

+ * + * @param repl The byte array to be tested + * + * @return true if, and only if, the given byte array + * is a legal replacement value for this encoder + */ + public boolean isLegalReplacement(byte[] repl) { + WeakReference 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(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.

+ * + * @return The current malformed-input action, which is never null + */ + public CodingErrorAction malformedInputAction() { + return malformedInputAction; + } + + /** + * Changes this $coder$'s action for malformed-input errors.

+ * + *

This method invokes the {@link #implOnMalformedInput + * implOnMalformedInput} method, passing the new action.

+ * + * @param newAction The new action; must not be null + * + * @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. + * + *

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.

+ */ + protected void implOnMalformedInput(CodingErrorAction newAction) { } + + /** + * Returns this $coder$'s current action for unmappable-character errors. + *

+ * + * @return The current unmappable-character action, which is never + * null + */ + public CodingErrorAction unmappableCharacterAction() { + return unmappableCharacterAction; + } + + /** + * Changes this $coder$'s action for unmappable-character errors. + * + *

This method invokes the {@link #implOnUnmappableCharacter + * implOnUnmappableCharacter} method, passing the new action.

+ * + * @param newAction The new action; must not be null + * + * @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. + * + *

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.

+ */ + 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.

+ * + * @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.

+ * + * @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. + * + *

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. + * + *

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: + * + *

+ * + * 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. + * + *

The endOfInput 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 false for this parameter; if there + * is no possibility of providing further input then the invoker should + * pass true. It is not erroneous, and in fact it is quite + * common, to pass false 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 true so that any remaining un$code$d input will be treated + * as being malformed. + * + *

This method works by invoking the {@link #$code$Loop $code$Loop} + * method, interpreting its results, handling error conditions, and + * reinvoking it as necessary.

+ * + * + * @param in + * The input $itype$ buffer + * + * @param out + * The output $otype$ buffer + * + * @param endOfInput + * true 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 false for + * the endOfInput parameter, nor of this method with a + * value of true for the endOfInput 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$. + * + *

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. + * + *

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. + * + *

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 $coding$ + * operation. + * + *

If this $coder$ has already been flushed then invoking this method + * has no effect. + * + *

This method invokes the {@link #implFlush implFlush} method to + * perform the actual flushing operation.

+ * + * @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 true for the endOfInput + * 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$. + * + *

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.

+ * + * @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. + * + *

This method resets charset-independent state and also invokes the + * {@link #implReset() implReset} method in order to perform any + * charset-specific reset actions.

+ * + * @return This $coder$ + * + */ + public final Charset$Coder$ reset() { + implReset(); + state = ST_RESET; + return this; + } + + /** + * Resets this $coder$, clearing any charset-specific internal state. + * + *

The default implementation of this method does nothing. This method + * should be overridden by $coder$s that maintain internal state.

+ */ + protected void implReset() { } + + /** + * $Code$s one or more $itype$s into one or more $otype$s. + * + *

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. + * + *

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. + * + *

This

    + * + *
  • {@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 + * $coding$ operation. Otherwise this method + * should be invoked again with further input.

  • + * + *
  • {@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.

  • + * + *
  • A {@link CoderResult#malformedForLength + * malformed-input} 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 malformed action} of this $coder$ + * is {@link CodingErrorAction#REPORT}; otherwise the malformed input + * will be ignored or replaced, as requested.

  • + * + *
  • An {@link CoderResult#unmappableForLength + * unmappable-character} 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 + * unmappable action} of this $coder$ is {@link + * CodingErrorAction#REPORT}; otherwise the unmappable character will be + * ignored or replaced, as requested.

  • + * + *
    - * - *
  • {@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 - * $coding$ operation. Otherwise this method - * should be invoked again with further input.

  • - * - *
  • {@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.

  • - * - *
  • A {@link CoderResult#malformedForLength - * malformed-input} 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 malformed action} of this $coder$ - * is {@link CodingErrorAction#REPORT}; otherwise the malformed input - * will be ignored or replaced, as requested.

  • - * - *
  • An {@link CoderResult#unmappableForLength - * unmappable-character} 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 - * unmappable action} of this $coder$ is {@link - * CodingErrorAction#REPORT}; otherwise the unmappable character will be - * ignored or replaced, as requested.

  • - * - *