Merge
authorxdono
Wed Sep 17 13:45:37 2008 -0700 (18 months ago)
changeset 56816818689f727
parent 567da5513a6af53
parent 5448484e830666e
child 594134fd1a656ea
Merge
src/share/classes/com/sun/jmx/interceptor/MBeanServerSupport.java
src/share/classes/java/nio/channels/package.html
src/share/classes/sun/nio/ch/OptionAdaptor.java
src/share/classes/sun/nio/ch/SocketOpts.java
src/share/classes/sun/nio/ch/SocketOptsImpl.java
src/share/classes/sun/nio/ch/exceptions
--- a/.hgtags Thu Sep 11 11:27:16 2008 -0700
+++ b/.hgtags Wed Sep 17 13:45:37 2008 -0700
@@ -9,3 +9,4 @@ c51121419e30eac5f0fbbce45ff1711c4ce0de28
c51121419e30eac5f0fbbce45ff1711c4ce0de28 jdk7-b32
fa4c0a6cdd25d97d4e6f5d7aa180bcbb0e0d56af jdk7-b33
434055a0716ee44bca712ebca02fc04b20e6e288 jdk7-b34
+cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35
--- a/make/docs/CORE_PKGS.gmk Thu Sep 11 11:27:16 2008 -0700
+++ b/make/docs/CORE_PKGS.gmk Wed Sep 17 13:45:37 2008 -0700
@@ -158,6 +158,7 @@ CORE_PKGS =
javax.management.event \
javax.management.loading \
javax.management.monitor \
+ javax.management.namespace \
javax.management.relation \
javax.management.openmbean \
javax.management.timer \
--- a/make/java/java/FILES_java.gmk Thu Sep 11 11:27:16 2008 -0700
+++ b/make/java/java/FILES_java.gmk Wed Sep 17 13:45:37 2008 -0700
@@ -449,6 +449,7 @@ JAVA_JAVA_java = \
sun/misc/JavaLangAccess.java \
sun/misc/JavaIOAccess.java \
sun/misc/JavaIODeleteOnExitAccess.java \
- sun/misc/JavaIOFileDescriptorAccess.java
+ sun/misc/JavaIOFileDescriptorAccess.java \
+ sun/misc/JavaNioAccess.java
FILES_java = $(JAVA_JAVA_java)
--- a/make/java/java/mapfile-vers Thu Sep 11 11:27:16 2008 -0700
+++ b/make/java/java/mapfile-vers Wed Sep 17 13:45:37 2008 -0700
@@ -222,8 +222,6 @@ SUNWprivate_1.1 {
Java_java_lang_UNIXProcess_waitForProcessExit;
Java_java_lang_UNIXProcess_forkAndExec;
Java_java_lang_UNIXProcess_destroyProcess;
- Java_java_nio_Bits_copyFromByteArray;
- Java_java_nio_Bits_copyToByteArray;
Java_java_nio_Bits_copyFromShortArray;
Java_java_nio_Bits_copyToShortArray;
Java_java_nio_Bits_copyFromIntArray;
--- a/make/java/jli/Makefile Thu Sep 11 11:27:16 2008 -0700
+++ b/make/java/jli/Makefile Wed Sep 17 13:45:37 2008 -0700
@@ -113,7 +113,11 @@ ifeq ($(PLATFORM), windows)
JAVALIB =
OTHER_LCF = -export:JLI_Launch \
-export:JLI_ManifestIterate \
- -export:JLI_SetTraceLauncher
+ -export:JLI_SetTraceLauncher \
+ -export:JLI_ReportErrorMessage \
+ -export:JLI_ReportErrorMessageSys \
+ -export:JLI_ReportMessage \
+ -export:JLI_ReportExceptionDescription
endif
--- a/make/java/jli/mapfile-vers Thu Sep 11 11:27:16 2008 -0700
+++ b/make/java/jli/mapfile-vers Wed Sep 17 13:45:37 2008 -0700
@@ -1,5 +1,5 @@
#
-# Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 2005-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
@@ -30,6 +30,10 @@ SUNWprivate_1.1 {
JLI_Launch;
JLI_ManifestIterate;
JLI_SetTraceLauncher;
+ JLI_ReportErrorMessage;
+ JLI_ReportErrorMessageSys;
+ JLI_ReportMessage;
+ JLI_ReportExceptionDescription;
local:
*;
};
--- a/make/java/nio/FILES_java.gmk Thu Sep 11 11:27:16 2008 -0700
+++ b/make/java/nio/FILES_java.gmk Wed Sep 17 13:45:37 2008 -0700
@@ -26,6 +26,7 @@ FILES_src = \
FILES_src = \
java/nio/Bits.java \
java/nio/Buffer.java \
+ java/nio/BufferPoolMXBean.java \
java/nio/ByteOrder.java \
java/nio/MappedByteBuffer.java \
java/nio/StringCharBuffer.java \
@@ -38,6 +39,9 @@ FILES_src = \
java/nio/channels/FileLock.java \
java/nio/channels/GatheringByteChannel.java \
java/nio/channels/InterruptibleChannel.java \
+ java/nio/channels/MembershipKey.java \
+ java/nio/channels/MulticastChannel.java \
+ java/nio/channels/NetworkChannel.java \
java/nio/channels/ReadableByteChannel.java \
java/nio/channels/ScatteringByteChannel.java \
java/nio/channels/SelectableChannel.java \
@@ -72,6 +76,7 @@ FILES_src = \
sun/nio/ch/DatagramSocketAdaptor.java \
sun/nio/ch/DefaultSelectorProvider.java \
sun/nio/ch/DirectBuffer.java \
+ sun/nio/ch/ExtendedSocketOption.java \
sun/nio/ch/FileChannelImpl.java \
sun/nio/ch/FileDispatcher.java \
sun/nio/ch/FileKey.java \
@@ -79,12 +84,14 @@ FILES_src = \
sun/nio/ch/IOUtil.java \
sun/nio/ch/IOStatus.java \
sun/nio/ch/IOVecWrapper.java \
+ sun/nio/ch/MembershipKeyImpl.java \
+ sun/nio/ch/MembershipRegistry.java \
sun/nio/ch/NativeDispatcher.java \
sun/nio/ch/NativeObject.java \
sun/nio/ch/NativeThread.java \
sun/nio/ch/NativeThreadSet.java \
sun/nio/ch/Net.java \
- sun/nio/ch/OptionAdaptor.java \
+ sun/nio/ch/OptionKey.java \
sun/nio/ch/PipeImpl.java \
sun/nio/ch/PollArrayWrapper.java \
sun/nio/ch/Reflect.java \
@@ -98,8 +105,7 @@ FILES_src = \
sun/nio/ch/SocketAdaptor.java \
sun/nio/ch/SocketChannelImpl.java \
sun/nio/ch/SocketDispatcher.java \
- sun/nio/ch/SocketOpts.java \
- sun/nio/ch/SocketOptsImpl.java \
+ sun/nio/ch/SocketOptionRegistry.java \
sun/nio/ch/SourceChannelImpl.java \
sun/nio/ch/Util.java \
\
@@ -239,6 +245,7 @@ FILES_gen_ex = \
java/nio/InvalidMarkException.java \
java/nio/ReadOnlyBufferException.java \
\
+ java/nio/channels/AlreadyBoundException.java \
java/nio/channels/AlreadyConnectedException.java \
java/nio/channels/AsynchronousCloseException.java \
java/nio/channels/ClosedByInterruptException.java \
@@ -257,14 +264,15 @@ FILES_gen_ex = \
java/nio/channels/UnresolvedAddressException.java \
java/nio/channels/UnsupportedAddressTypeException.java \
\
- sun/nio/ch/AlreadyBoundException.java \
- \
java/nio/charset/CharacterCodingException.java \
java/nio/charset/IllegalCharsetNameException.java \
java/nio/charset/UnsupportedCharsetException.java
FILES_gen_csp = sun/nio/cs/StandardCharsets.java
-FILES_gen = $(FILES_gen_coder) $(FILES_gen_buffer) $(FILES_gen_ex) $(FILES_gen_csp)
+FILES_gen_sor = sun/nio/ch/SocketOptionRegistry.java
+
+FILES_gen = $(FILES_gen_coder) $(FILES_gen_buffer) $(FILES_gen_ex) \
+ $(FILES_gen_csp) $(FILES_gen_sor)
FILES_java = $(FILES_src) $(FILES_gen)
--- a/make/java/nio/Makefile Thu Sep 11 11:27:16 2008 -0700
+++ b/make/java/nio/Makefile Wed Sep 17 13:45:37 2008 -0700
@@ -56,18 +56,18 @@ FILES_java += \
sun/nio/ch/DevPollSelectorProvider.java \
sun/nio/ch/InheritedChannel.java \
sun/nio/ch/PollSelectorProvider.java \
- sun/nio/ch/PollSelectorImpl.java
+ sun/nio/ch/PollSelectorImpl.java
FILES_c += \
DevPollArrayWrapper.c \
InheritedChannel.c \
- PollArrayWrapper.c \
- NativeThread.c
+ NativeThread.c \
+ PollArrayWrapper.c
FILES_export += \
sun/nio/ch/DevPollArrayWrapper.java \
sun/nio/ch/InheritedChannel.java \
- sun/nio/ch/NativeThread.java
+ sun/nio/ch/NativeThread.java
endif # PLATFORM = solaris
ifeq ($(PLATFORM), windows)
@@ -94,14 +94,14 @@ FILES_java += \
FILES_c += \
EPollArrayWrapper.c \
- PollArrayWrapper.c \
InheritedChannel.c \
- NativeThread.c
+ NativeThread.c \
+ PollArrayWrapper.c
FILES_export += \
sun/nio/ch/EPollArrayWrapper.java \
sun/nio/ch/InheritedChannel.java \
- sun/nio/ch/NativeThread.java
+ sun/nio/ch/NativeThread.java
endif # PLATFORM = linux
# Find platform-specific C source files
@@ -618,12 +618,6 @@ GEN_EX_CMD = NAWK="$(NAWK)" SH="$(SH)" $
@$(RM) $@.temp
$(GEN_EX_CMD) $(BUF_SRC)/exceptions $(BUF_GEN)
-$(SCH_GEN)/%Exception.java: genExceptions.sh $(SCH_SRC)/exceptions
- $(prep-target)
- @$(RM) $@.temp
- $(GEN_EX_CMD) $(SCH_SRC)/exceptions $(SCH_GEN)
-
-
#
# Generated charset-provider classes
#
@@ -638,4 +632,29 @@ HASHER_JARFILE = $(BUILDTOOLJARDIR)/hash
HASHER="$(BOOT_JAVA_CMD) -jar $(HASHER_JARFILE)" \
$(SH) -e genCharsetProvider.sh $(SCS_SRC)/standard-charsets $(SCS_GEN)
+#
+# Generated channel implementation classes.
+# C source is compiled in TEMPDIR to avoid turds left by Windows compilers.
+#
+
+GENSOR_SRC = $(SHARE_SRC)/native/sun/nio/ch/genSocketOptionRegistry.c
+
+GENSOR_EXE = $(TEMPDIR)/genSocketOptionRegistry$(EXE_SUFFIX)
+
+SOR_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSOR_SRC) | \
+ $(NAWK) '/^.*Copyright.*Sun/ { print $$3 }')
+
+$(TEMPDIR)/$(GENSOR_SRC) : $(GENSOR_SRC)
+ $(install-file)
+
+$(GENSOR_EXE) : $(TEMPDIR)/$(GENSOR_SRC)
+ $(prep-target)
+ ($(CD) $(TEMPDIR); $(CC) $(CPPFLAGS) $(LDDFLAGS) \
+ -o genSocketOptionRegistry$(EXE_SUFFIX) $(GENSOR_SRC))
+
+$(SCH_GEN)/SocketOptionRegistry.java: $(GENSOR_EXE)
+ $(prep-target)
+ NAWK="$(NAWK)" SH="$(SH)" $(SH) -e addNotices.sh $(SOR_COPYRIGHT_YEARS) > $@
+ $(GENSOR_EXE) >> $@
+
.PHONY: sources
--- a/make/java/nio/mapfile-linux Thu Sep 11 11:27:16 2008 -0700
+++ b/make/java/nio/mapfile-linux Wed Sep 17 13:45:37 2008 -0700
@@ -1,3 +1,27 @@
+#
+# Copyright 2001-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.
+#
SUNWprivate_1.1 {
global:
@@ -18,6 +42,8 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_EPollArrayWrapper_fdLimit;
Java_sun_nio_ch_EPollArrayWrapper_init;
Java_sun_nio_ch_EPollArrayWrapper_interrupt;
+ Java_sun_nio_ch_EPollArrayWrapper_offsetofData;
+ Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent;
Java_sun_nio_ch_FileChannelImpl_close0;
Java_sun_nio_ch_FileChannelImpl_force0;
Java_sun_nio_ch_FileChannelImpl_initIDs;
@@ -59,20 +85,29 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
Java_sun_nio_ch_Net_socket0;
- Java_sun_nio_ch_Net_bind;
- Java_sun_nio_ch_Net_connect;
+ Java_sun_nio_ch_Net_bind0;
+ Java_sun_nio_ch_Net_connect0;
+ Java_sun_nio_ch_Net_listen;
Java_sun_nio_ch_Net_localPort;
Java_sun_nio_ch_Net_localInetAddress;
Java_sun_nio_ch_Net_getIntOption0;
Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_Net_initIDs;
+ Java_sun_nio_ch_Net_isIPv6Available0;
+ Java_sun_nio_ch_Net_joinOrDrop4;
+ Java_sun_nio_ch_Net_blockOrUnblock4;
+ Java_sun_nio_ch_Net_joinOrDrop6;
+ Java_sun_nio_ch_Net_blockOrUnblock6;
+ Java_sun_nio_ch_Net_setInterface4;
+ Java_sun_nio_ch_Net_getInterface4;
+ Java_sun_nio_ch_Net_setInterface6;
+ Java_sun_nio_ch_Net_getInterface6;
+ Java_sun_nio_ch_Net_shutdown;
Java_sun_nio_ch_PollArrayWrapper_interrupt;
Java_sun_nio_ch_PollArrayWrapper_poll0;
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
- Java_sun_nio_ch_ServerSocketChannelImpl_listen;
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
- Java_sun_nio_ch_SocketChannelImpl_shutdown;
local:
*;
--- a/make/java/nio/mapfile-solaris Thu Sep 11 11:27:16 2008 -0700
+++ b/make/java/nio/mapfile-solaris Wed Sep 17 13:45:37 2008 -0700
@@ -1,3 +1,27 @@
+#
+# Copyright 2001-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.
+#
SUNWprivate_1.1 {
global:
@@ -59,20 +83,29 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
Java_sun_nio_ch_Net_socket0;
- Java_sun_nio_ch_Net_bind;
- Java_sun_nio_ch_Net_connect;
+ Java_sun_nio_ch_Net_bind0;
+ Java_sun_nio_ch_Net_connect0;
+ Java_sun_nio_ch_Net_listen;
Java_sun_nio_ch_Net_localPort;
Java_sun_nio_ch_Net_localInetAddress;
Java_sun_nio_ch_Net_getIntOption0;
Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_Net_initIDs;
+ Java_sun_nio_ch_Net_isIPv6Available0;
+ Java_sun_nio_ch_Net_joinOrDrop4;
+ Java_sun_nio_ch_Net_blockOrUnblock4;
+ Java_sun_nio_ch_Net_joinOrDrop6;
+ Java_sun_nio_ch_Net_blockOrUnblock6;
+ Java_sun_nio_ch_Net_setInterface4;
+ Java_sun_nio_ch_Net_getInterface4;
+ Java_sun_nio_ch_Net_setInterface6;
+ Java_sun_nio_ch_Net_getInterface6;
+ Java_sun_nio_ch_Net_shutdown;
Java_sun_nio_ch_PollArrayWrapper_interrupt;
Java_sun_nio_ch_PollArrayWrapper_poll0;
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
- Java_sun_nio_ch_ServerSocketChannelImpl_listen;
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
- Java_sun_nio_ch_SocketChannelImpl_shutdown;
local:
*;
--- a/make/mksample/nio/Makefile Thu Sep 11 11:27:16 2008 -0700
+++ b/make/mksample/nio/Makefile Wed Sep 17 13:45:37 2008 -0700
@@ -31,7 +31,7 @@ PRODUCT = java
PRODUCT = java
include $(BUILDDIR)/common/Defs.gmk
-SUBDIRS = server
+SUBDIRS = multicast server
all build clean clobber::
$(SUBDIRS-loop)
--- a/src/share/bin/emessages.h Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/bin/emessages.h Wed Sep 17 13:45:37 2008 -0700
@@ -25,8 +25,8 @@
/*
* This file primarily consists of all the error and warning messages, that
- * are used in ReportErrorMessage. All message must be defined here, in order
- * to help in I18N/L10N the messages.
+ * are used in JLI_ReportErrorMessage. All message must be defined here, in
+ * order to help with localizing the messages.
*/
#ifndef _EMESSAGES_H
--- a/src/share/bin/java.c Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/bin/java.c Wed Sep 17 13:45:37 2008 -0700
@@ -148,7 +148,7 @@ static jboolean IsWildCardEnabled();
static jboolean IsWildCardEnabled();
#define ARG_CHECK(n, f, a) if (n < 1) { \
- ReportErrorMessage(f, a); \
+ JLI_ReportErrorMessage(f, a); \
printUsage = JNI_TRUE; \
*pret = 1; \
return JNI_TRUE; \
@@ -326,15 +326,15 @@ JavaMain(void * _args)
start = CounterGet();
if (!InitializeJVM(&vm, &env, &ifn)) {
- ReportErrorMessage(JVM_ERROR1);
+ JLI_ReportErrorMessage(JVM_ERROR1);
exit(1);
}
if (printVersion || showVersion) {
PrintJavaVersion(env, showVersion);
if ((*env)->ExceptionOccurred(env)) {
- ReportExceptionDescription(env);
- ReportErrorMessage(JNI_ERROR);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(JNI_ERROR);
goto leave;
}
if (printVersion) {
@@ -347,8 +347,8 @@ JavaMain(void * _args)
if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) {
PrintUsage(env, printXUsage);
if ((*env)->ExceptionOccurred(env)) {
- ReportExceptionDescription(env);
- ReportErrorMessage(JNI_ERROR);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(JNI_ERROR);
ret=1;
}
goto leave;
@@ -397,43 +397,43 @@ JavaMain(void * _args)
if (jarfile != 0) {
mainClassName = GetMainClassName(env, jarfile);
if ((*env)->ExceptionOccurred(env)) {
- ReportExceptionDescription(env);
- ReportErrorMessage(JNI_ERROR);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(JNI_ERROR);
goto leave;
}
if (mainClassName == NULL) {
- ReportErrorMessage(JAR_ERROR1,jarfile, GEN_ERROR);
+ JLI_ReportErrorMessage(JAR_ERROR1,jarfile, GEN_ERROR);
goto leave;
}
classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
if (classname == NULL) {
- ReportExceptionDescription(env);
- ReportErrorMessage(JNI_ERROR);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(JNI_ERROR);
goto leave;
}
mainClass = LoadClass(env, classname);
if(mainClass == NULL) { /* exception occured */
- ReportExceptionDescription(env);
- ReportErrorMessage(CLS_ERROR1, classname);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(CLS_ERROR1, classname);
goto leave;
}
(*env)->ReleaseStringUTFChars(env, mainClassName, classname);
} else {
mainClassName = NewPlatformString(env, classname);
if (mainClassName == NULL) {
- ReportErrorMessage(CLS_ERROR2, classname, GEN_ERROR);
+ JLI_ReportErrorMessage(CLS_ERROR2, classname, GEN_ERROR);
goto leave;
}
classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
if (classname == NULL) {
- ReportExceptionDescription(env);
- ReportErrorMessage(JNI_ERROR);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(JNI_ERROR);
goto leave;
}
mainClass = LoadClass(env, classname);
if(mainClass == NULL) { /* exception occured */
- ReportExceptionDescription(env);
- ReportErrorMessage(CLS_ERROR1, classname);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(CLS_ERROR1, classname);
goto leave;
}
(*env)->ReleaseStringUTFChars(env, mainClassName, classname);
@@ -444,10 +444,10 @@ JavaMain(void * _args)
"([Ljava/lang/String;)V");
if (mainID == NULL) {
if ((*env)->ExceptionOccurred(env)) {
- ReportExceptionDescription(env);
- ReportErrorMessage(JNI_ERROR);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(JNI_ERROR);
} else {
- ReportErrorMessage(CLS_ERROR3);
+ JLI_ReportErrorMessage(CLS_ERROR3);
}
goto leave;
}
@@ -459,8 +459,8 @@ JavaMain(void * _args)
mainID, JNI_TRUE);
if( obj == NULL) { /* exception occurred */
- ReportExceptionDescription(env);
- ReportErrorMessage(JNI_ERROR);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(JNI_ERROR);
goto leave;
}
@@ -469,14 +469,14 @@ JavaMain(void * _args)
(*env)->GetObjectClass(env, obj),
"getModifiers", "()I");
if ((*env)->ExceptionOccurred(env)) {
- ReportExceptionDescription(env);
- ReportErrorMessage(JNI_ERROR);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(JNI_ERROR);
goto leave;
}
mods = (*env)->CallIntMethod(env, obj, mid);
if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */
- ReportErrorMessage(CLS_ERROR4);
+ JLI_ReportErrorMessage(CLS_ERROR4);
goto leave;
}
}
@@ -484,8 +484,8 @@ JavaMain(void * _args)
/* Build argument array */
mainArgs = NewPlatformStringArray(env, argv, argc);
if (mainArgs == NULL) {
- ReportExceptionDescription(env);
- ReportErrorMessage(JNI_ERROR);
+ JLI_ReportExceptionDescription(env);
+ JLI_ReportErrorMessage(JNI_ERROR);
goto leave;
}
@@ -506,7 +506,7 @@ JavaMain(void * _args)
* launcher's return code except by calling System.exit.
*/
if ((*vm)->DetachCurrentThread(vm) != 0) {
- ReportErrorMessage(JVM_ERROR2);
+ JLI_ReportErrorMessage(JVM_ERROR2);
ret = 1;
goto leave;
}
@@ -635,7 +635,7 @@ CheckJvmType(int *pargc, char ***argv, j
if (loopCount > knownVMsCount) {
if (!speculative) {
- ReportErrorMessage(CFG_ERROR1);
+ JLI_ReportErrorMessage(CFG_ERROR1);
exit(1);
} else {
return "ERROR";
@@ -645,7 +645,7 @@ CheckJvmType(int *pargc, char ***argv, j
if (nextIdx < 0) {
if (!speculative) {
- ReportErrorMessage(CFG_ERROR2, knownVMs[jvmidx].alias);
+ JLI_ReportErrorMessage(CFG_ERROR2, knownVMs[jvmidx].alias);
exit(1);
} else {
return "ERROR";
@@ -660,7 +660,7 @@ CheckJvmType(int *pargc, char ***argv, j
switch (knownVMs[jvmidx].flag) {
case VM_WARN:
if (!speculative) {
- ReportErrorMessage(CFG_WARN1, jvmtype, knownVMs[0].name + 1);
+ JLI_ReportErrorMessage(CFG_WARN1, jvmtype, knownVMs[0].name + 1);
}
/* fall through */
case VM_IGNORE:
@@ -670,7 +670,7 @@ CheckJvmType(int *pargc, char ***argv, j
break;
case VM_ERROR:
if (!speculative) {
- ReportErrorMessage(CFG_ERROR3, jvmtype);
+ JLI_ReportErrorMessage(CFG_ERROR3, jvmtype);
exit(1);
} else {
return "ERROR";
@@ -879,9 +879,9 @@ SelectVersion(int argc, char **argv, cha
if (jarflag && operand) {
if ((res = JLI_ParseManifest(operand, &info)) != 0) {
if (res == -1)
- ReportErrorMessage(JAR_ERROR2, operand);
+ JLI_ReportErrorMessage(JAR_ERROR2, operand);
else
- ReportErrorMessage(JAR_ERROR3, operand);
+ JLI_ReportErrorMessage(JAR_ERROR3, operand);
exit(1);
}
@@ -948,7 +948,7 @@ SelectVersion(int argc, char **argv, cha
* Check for correct syntax of the version specification (JSR 56).
*/
if (!JLI_ValidVersionString(info.jre_version)) {
- ReportErrorMessage(SPC_ERROR1, info.jre_version);
+ JLI_ReportErrorMessage(SPC_ERROR1, info.jre_version);
exit(1);
}
@@ -970,7 +970,7 @@ SelectVersion(int argc, char **argv, cha
JLI_MemFree(new_argv);
return;
} else {
- ReportErrorMessage(CFG_ERROR4, info.jre_version);
+ JLI_ReportErrorMessage(CFG_ERROR4, info.jre_version);
exit(1);
}
}
@@ -1040,7 +1040,7 @@ ParseArguments(int *pargc, char ***pargv
* command line options.
*/
} else if (JLI_StrCmp(arg, "-fullversion") == 0) {
- ReportMessage("%s full version \"%s\"", _launcher_name, GetFullVersion());
+ JLI_ReportMessage("%s full version \"%s\"", _launcher_name, GetFullVersion());
return JNI_FALSE;
} else if (JLI_StrCmp(arg, "-verbosegc") == 0) {
AddOption("-verbose:gc", NULL);
@@ -1080,7 +1080,7 @@ ParseArguments(int *pargc, char ***pargv
JLI_StrCmp(arg, "-cs") == 0 ||
JLI_StrCmp(arg, "-noasyncgc") == 0) {
/* No longer supported */
- ReportErrorMessage(ARG_WARN, arg);
+ JLI_ReportErrorMessage(ARG_WARN, arg);
} else if (JLI_StrCCmp(arg, "-version:") == 0 ||
JLI_StrCmp(arg, "-no-jre-restrict-search") == 0 ||
JLI_StrCmp(arg, "-jre-restrict-search") == 0 ||
@@ -1143,12 +1143,12 @@ InitializeJVM(JavaVM **pvm, JNIEnv **pen
#define NULL_CHECK0(e) if ((e) == 0) { \
- ReportErrorMessage(JNI_ERROR); \
+ JLI_ReportErrorMessage(JNI_ERROR); \
return 0; \
}
#define NULL_CHECK(e) if ((e) == 0) { \
- ReportErrorMessage(JNI_ERROR); \
+ JLI_ReportErrorMessage(JNI_ERROR); \
return; \
}
@@ -1351,7 +1351,7 @@ TranslateApplicationArgs(int jargc, cons
char *arg = argv[i];
if (arg[0] == '-' && arg[1] == 'J') {
if (arg[2] == '\0') {
- ReportErrorMessage(ARG_ERROR3);
+ JLI_ReportErrorMessage(ARG_ERROR3);
exit(1);
}
*nargv++ = arg + 2;
@@ -1418,7 +1418,7 @@ AddApplicationOptions(int cpathc, const
}
if (!GetApplicationHome(home, sizeof(home))) {
- ReportErrorMessage(CFG_ERROR5);
+ JLI_ReportErrorMessage(CFG_ERROR5);
return JNI_FALSE;
}
@@ -1691,7 +1691,7 @@ ReadKnownVMs(const char *jrepath, const
jvmCfg = fopen(jvmCfgName, "r");
if (jvmCfg == NULL) {
if (!speculative) {
- ReportErrorMessage(CFG_ERROR6, jvmCfgName);
+ JLI_ReportErrorMessage(CFG_ERROR6, jvmCfgName);
exit(1);
} else {
return -1;
@@ -1703,7 +1703,7 @@ ReadKnownVMs(const char *jrepath, const
if (line[0] == '#')
continue;
if (line[0] != '-') {
- ReportErrorMessage(CFG_WARN2, lineno, jvmCfgName);
+ JLI_ReportErrorMessage(CFG_WARN2, lineno, jvmCfgName);
}
if (cnt >= knownVMsLimit) {
GrowKnownVMs(cnt);
@@ -1711,13 +1711,13 @@ ReadKnownVMs(const char *jrepath, const
line[JLI_StrLen(line)-1] = '\0'; /* remove trailing newline */
tmpPtr = line + JLI_StrCSpn(line, whiteSpace);
if (*tmpPtr == 0) {
- ReportErrorMessage(CFG_WARN3, lineno, jvmCfgName);
+ JLI_ReportErrorMessage(CFG_WARN3, lineno, jvmCfgName);
} else {
/* Null-terminate this string for JLI_StringDup below */
*tmpPtr++ = 0;
tmpPtr += JLI_StrSpn(tmpPtr, whiteSpace);
if (*tmpPtr == 0) {
- ReportErrorMessage(CFG_WARN3, lineno, jvmCfgName);
+ JLI_ReportErrorMessage(CFG_WARN3, lineno, jvmCfgName);
} else {
if (!JLI_StrCCmp(tmpPtr, "KNOWN")) {
vmType = VM_KNOWN;
@@ -1727,7 +1727,7 @@ ReadKnownVMs(const char *jrepath, const
tmpPtr += JLI_StrSpn(tmpPtr, whiteSpace);
}
if (*tmpPtr == 0) {
- ReportErrorMessage(CFG_WARN3, lineno, jvmCfgName);
+ JLI_ReportErrorMessage(CFG_WARN3, lineno, jvmCfgName);
} else {
/* Null terminate altVMName */
altVMName = tmpPtr;
@@ -1747,7 +1747,7 @@ ReadKnownVMs(const char *jrepath, const
tmpPtr += JLI_StrSpn(tmpPtr, whiteSpace);
}
if (*tmpPtr == 0) {
- ReportErrorMessage(CFG_WARN4, lineno, jvmCfgName);
+ JLI_ReportErrorMessage(CFG_WARN4, lineno, jvmCfgName);
} else {
/* Null terminate server class VM name */
serverClassVMName = tmpPtr;
@@ -1756,7 +1756,7 @@ ReadKnownVMs(const char *jrepath, const
vmType = VM_IF_SERVER_CLASS;
}
} else {
- ReportErrorMessage(CFG_WARN5, lineno, &jvmCfgName[0]);
+ JLI_ReportErrorMessage(CFG_WARN5, lineno, &jvmCfgName[0]);
vmType = VM_KNOWN;
}
}
@@ -2019,7 +2019,7 @@ RemovableOption(char * option)
* A utility procedure to always print to stderr
*/
void
-ReportMessage(const char* fmt, ...)
+JLI_ReportMessage(const char* fmt, ...)
{
va_list vl;
va_start(vl, fmt);
--- a/src/share/bin/java.h Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/bin/java.h Wed Sep 17 13:45:37 2008 -0700
@@ -121,24 +121,20 @@ void CreateExecutionEnvironment(int *_ar
char jvmpath[],
jint so_jvmpath,
char **original_argv);
+/* Reports an error message to stderr or a window as appropriate. */
+void JLI_ReportErrorMessage(const char * message, ...);
+
+/* Reports a system error message to stderr or a window */
+void JLI_ReportErrorMessageSys(const char * message, ...);
+
+/* Reports an error message only to stderr. */
+void JLI_ReportMessage(const char * message, ...);
/*
- * Report an error message to stderr or a window as appropriate.
- */
-void ReportErrorMessage(const char * message, ...);
-void ReportErrorMessageSys(const char * format, ...);
-
-/*
- * Report an error message only to stderr.
- */
-void ReportMessage(const char * message, ...);
-
-/*
- * Report an exception which terminates the vm to stderr or a window
+ * Reports an exception which terminates the vm to stderr or a window
* as appropriate.
*/
-void ReportExceptionDescription(JNIEnv * env);
-
+void JLI_ReportExceptionDescription(JNIEnv * env);
void PrintMachineDependentOptions();
const char *jlong_format_specifier();
--- a/src/share/classes/com/sun/jmx/defaults/JmxProperties.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/defaults/JmxProperties.java Wed Sep 17 13:45:37 2008 -0700
@@ -177,6 +177,18 @@ public class JmxProperties {
"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 =
--- a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Wed Sep 17 13:45:37 2008 -0700
@@ -25,33 +25,49 @@
package com.sun.jmx.interceptor;
-// java import
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.WeakHashMap;
+
+// JMX RI
+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.lang.ref.WeakReference;
import java.security.AccessControlContext;
+import java.security.AccessController;
import java.security.Permission;
+import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+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;
// JMX import
import javax.management.Attribute;
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;
import javax.management.InvalidAttributeValueException;
import javax.management.JMRuntimeException;
import javax.management.ListenerNotFoundException;
-import javax.management.MalformedObjectNameException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanPermission;
@@ -64,6 +80,7 @@ import javax.management.NotCompliantMBea
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;
@@ -75,22 +92,7 @@ import javax.management.RuntimeErrorExce
import javax.management.RuntimeErrorException;
import javax.management.RuntimeMBeanException;
import javax.management.RuntimeOperationsException;
-
-// JMX RI
-import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
-import com.sun.jmx.mbeanserver.DynamicMBean2;
-import com.sun.jmx.mbeanserver.ModifiableClassLoaderRepository;
-import com.sun.jmx.mbeanserver.MBeanInstantiator;
-import com.sun.jmx.mbeanserver.Repository;
-import com.sun.jmx.mbeanserver.NamedObject;
-import com.sun.jmx.mbeanserver.Introspector;
-import com.sun.jmx.mbeanserver.MBeanInjector;
-import com.sun.jmx.mbeanserver.NotifySupport;
-import com.sun.jmx.mbeanserver.Repository.RegistrationContext;
-import com.sun.jmx.mbeanserver.Util;
-import com.sun.jmx.remote.util.EnvHelp;
-import javax.management.DynamicWrapperMBean;
-import javax.management.NotificationBroadcasterSupport;
+import javax.management.namespace.JMXNamespace;
/**
* This is the default class for MBean manipulation on the agent side. It
@@ -113,7 +115,8 @@ import javax.management.NotificationBroa
*
* @since 1.5
*/
-public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
+public class DefaultMBeanServerInterceptor
+ extends MBeanServerInterceptorSupport {
/** The MBeanInstantiator object used by the
* DefaultMBeanServerInterceptor */
@@ -123,7 +126,7 @@ public class DefaultMBeanServerIntercept
* DefaultMBeanServerInterceptor */
private transient MBeanServer server = null;
- /** The MBean server object taht associated to the
+ /** The MBean server delegate object that is associated to the
* DefaultMBeanServerInterceptor */
private final transient MBeanServerDelegate delegate;
@@ -138,13 +141,15 @@ public class DefaultMBeanServerIntercept
new WeakHashMap<ListenerWrapper,
WeakReference<ListenerWrapper>>();
+ private final NamespaceDispatchInterceptor dispatcher;
+
/** The default domain of the object names */
private final String domain;
- /** True if the repository perform queries, false otherwise */
- private boolean queryByRepo;
-
- /** The sequence number identifyng the notifications sent */
+ /** The mbeanServerName */
+ private final String mbeanServerName;
+
+ /** The sequence number identifying the notifications sent */
// Now sequence number is handled by MBeanServerDelegate.
// private int sequenceNumber=0;
@@ -162,11 +167,13 @@ public class DefaultMBeanServerIntercept
* @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) {
+ Repository repository,
+ NamespaceDispatchInterceptor dispatcher) {
if (outer == null) throw new
IllegalArgumentException("outer MBeanServer cannot be null");
if (delegate == null) throw new
@@ -181,6 +188,8 @@ public class DefaultMBeanServerIntercept
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)
@@ -259,8 +268,8 @@ public class DefaultMBeanServerIntercept
name = nonDefaultDomain(name);
}
- checkMBeanPermission(className, null, null, "instantiate");
- checkMBeanPermission(className, null, name, "registerMBean");
+ checkMBeanPermission(mbeanServerName,className, null, null, "instantiate");
+ checkMBeanPermission(mbeanServerName,className, null, name, "registerMBean");
/* Load the appropriate class. */
if (withDefaultLoaderRepository) {
@@ -324,7 +333,7 @@ public class DefaultMBeanServerIntercept
final String infoClassName = getNewMBeanClassName(object);
- checkMBeanPermission(infoClassName, null, name, "registerMBean");
+ checkMBeanPermission(mbeanServerName,infoClassName, null, name, "registerMBean");
checkMBeanTrustPermission(theClass);
return registerObject(infoClassName, object, name);
@@ -433,7 +442,8 @@ public class DefaultMBeanServerIntercept
DynamicMBean instance = getMBean(name);
// may throw InstanceNotFoundException
- checkMBeanPermission(instance, null, name, "unregisterMBean");
+ checkMBeanPermission(mbeanServerName, instance, null, name,
+ "unregisterMBean");
if (instance instanceof MBeanRegistration)
preDeregisterInvoke((MBeanRegistration) instance);
@@ -467,7 +477,8 @@ public class DefaultMBeanServerIntercept
name = nonDefaultDomain(name);
DynamicMBean instance = getMBean(name);
- checkMBeanPermission(instance, null, name, "getObjectInstance");
+ checkMBeanPermission(mbeanServerName,
+ instance, null, name, "getObjectInstance");
final String className = getClassName(instance);
@@ -479,7 +490,7 @@ public class DefaultMBeanServerIntercept
if (sm != null) {
// Check if the caller has the right to invoke 'queryMBeans'
//
- checkMBeanPermission((String) null, null, null, "queryMBeans");
+ checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryMBeans");
// Perform query without "query".
//
@@ -492,7 +503,7 @@ public class DefaultMBeanServerIntercept
new HashSet<ObjectInstance>(list.size());
for (ObjectInstance oi : list) {
try {
- checkMBeanPermission(oi.getClassName(), null,
+ checkMBeanPermission(mbeanServerName,oi.getClassName(), null,
oi.getObjectName(), "queryMBeans");
allowedList.add(oi);
} catch (SecurityException e) {
@@ -516,11 +527,6 @@ public class DefaultMBeanServerIntercept
//
Set<NamedObject> list = repository.query(name, query);
- if (queryByRepo) {
- // The repository performs the filtering
- query = null;
- }
-
return (objectInstancesFromFilteredNamedObjects(list, query));
}
@@ -530,7 +536,7 @@ public class DefaultMBeanServerIntercept
if (sm != null) {
// Check if the caller has the right to invoke 'queryNames'
//
- checkMBeanPermission((String) null, null, null, "queryNames");
+ checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryNames");
// Perform query without "query".
//
@@ -543,7 +549,7 @@ public class DefaultMBeanServerIntercept
new HashSet<ObjectInstance>(list.size());
for (ObjectInstance oi : list) {
try {
- checkMBeanPermission(oi.getClassName(), null,
+ checkMBeanPermission(mbeanServerName, oi.getClassName(), null,
oi.getObjectName(), "queryNames");
allowedList.add(oi);
} catch (SecurityException e) {
@@ -572,11 +578,6 @@ public class DefaultMBeanServerIntercept
//
Set<NamedObject> list = repository.query(name, query);
- if (queryByRepo) {
- // The repository performs the filtering
- query = null;
- }
-
return (objectNamesFromFilteredNamedObjects(list, query));
}
@@ -589,8 +590,8 @@ public class DefaultMBeanServerIntercept
name = nonDefaultDomain(name);
-// /* Permission check */
-// checkMBeanPermission(null, null, name, "isRegistered");
+ /* No Permission check */
+ // isRegistered is always unchecked as per JMX spec.
return (repository.contains(name));
}
@@ -600,7 +601,7 @@ public class DefaultMBeanServerIntercept
if (sm != null) {
// Check if the caller has the right to invoke 'getDomains'
//
- checkMBeanPermission((String) null, null, null, "getDomains");
+ checkMBeanPermission(mbeanServerName, (String) null, null, null, "getDomains");
// Return domains
//
@@ -612,8 +613,9 @@ public class DefaultMBeanServerIntercept
List<String> result = new ArrayList<String>(domains.length);
for (int i = 0; i < domains.length; i++) {
try {
- ObjectName domain = Util.newObjectName(domains[i] + ":x=x");
- checkMBeanPermission((String) null, null, domain, "getDomains");
+ ObjectName dom =
+ Util.newObjectName(domains[i] + ":x=x");
+ checkMBeanPermission(mbeanServerName, (String) null, null, dom, "getDomains");
result.add(domains[i]);
} catch (SecurityException e) {
// OK: Do not add this domain to the list
@@ -657,7 +659,8 @@ public class DefaultMBeanServerIntercept
}
final DynamicMBean instance = getMBean(name);
- checkMBeanPermission(instance, attribute, name, "getAttribute");
+ checkMBeanPermission(mbeanServerName, instance, attribute,
+ name, "getAttribute");
try {
return instance.getAttribute(attribute);
@@ -702,7 +705,7 @@ public class DefaultMBeanServerIntercept
// Check if the caller has the right to invoke 'getAttribute'
//
- checkMBeanPermission(classname, null, name, "getAttribute");
+ checkMBeanPermission(mbeanServerName, classname, null, name, "getAttribute");
// Check if the caller has the right to invoke 'getAttribute'
// on each specific attribute
@@ -711,14 +714,15 @@ public class DefaultMBeanServerIntercept
new ArrayList<String>(attributes.length);
for (String attr : attributes) {
try {
- checkMBeanPermission(classname, attr,
+ checkMBeanPermission(mbeanServerName, classname, attr,
name, "getAttribute");
allowedList.add(attr);
} catch (SecurityException e) {
// OK: Do not add this attribute to the list
}
}
- allowedAttributes = allowedList.toArray(new String[0]);
+ allowedAttributes =
+ allowedList.toArray(new String[allowedList.size()]);
}
try {
@@ -756,7 +760,7 @@ public class DefaultMBeanServerIntercept
}
DynamicMBean instance = getMBean(name);
- checkMBeanPermission(instance, attribute.getName(),
+ checkMBeanPermission(mbeanServerName, instance, attribute.getName(),
name, "setAttribute");
try {
@@ -799,7 +803,7 @@ public class DefaultMBeanServerIntercept
// Check if the caller has the right to invoke 'setAttribute'
//
- checkMBeanPermission(classname, null, name, "setAttribute");
+ checkMBeanPermission(mbeanServerName, classname, null, name, "setAttribute");
// Check if the caller has the right to invoke 'setAttribute'
// on each specific attribute
@@ -808,7 +812,7 @@ public class DefaultMBeanServerIntercept
for (Iterator i = attributes.iterator(); i.hasNext();) {
try {
Attribute attribute = (Attribute) i.next();
- checkMBeanPermission(classname, attribute.getName(),
+ checkMBeanPermission(mbeanServerName, classname, attribute.getName(),
name, "setAttribute");
allowedAttributes.add(attribute);
} catch (SecurityException e) {
@@ -832,7 +836,8 @@ public class DefaultMBeanServerIntercept
name = nonDefaultDomain(name);
DynamicMBean instance = getMBean(name);
- checkMBeanPermission(instance, operationName, name, "invoke");
+ checkMBeanPermission(mbeanServerName, instance, operationName,
+ name, "invoke");
try {
return instance.invoke(operationName, params, signature);
} catch (Throwable t) {
@@ -934,8 +939,7 @@ public class DefaultMBeanServerIntercept
"registerMBean", "ObjectName = " + name);
}
- ObjectName logicalName = name;
- logicalName = preRegister(mbean, server, name);
+ ObjectName logicalName = preRegister(mbean, server, name);
// preRegister returned successfully, so from this point on we
// must call postRegister(false) if there is any problem.
@@ -961,16 +965,17 @@ public class DefaultMBeanServerIntercept
if (logicalName != name && logicalName != null) {
logicalName =
- ObjectName.getInstance(nonDefaultDomain(logicalName));
- }
-
- checkMBeanPermission(classname, null, logicalName, "registerMBean");
+ ObjectName.getInstance(nonDefaultDomain(logicalName));
+ }
+
+ checkMBeanPermission(mbeanServerName, classname, null, logicalName,
+ "registerMBean");
if (logicalName == null) {
final RuntimeException wrapped =
- new IllegalArgumentException("No object name specified");
+ new IllegalArgumentException("No object name specified");
throw new RuntimeOperationsException(wrapped,
- "Exception occurred trying to register the MBean");
+ "Exception occurred trying to register the MBean");
}
final Object resource = getResource(mbean);
@@ -987,13 +992,15 @@ public class DefaultMBeanServerIntercept
//
context = registerWithRepository(resource, mbean, logicalName);
+
registerFailed = false;
registered = true;
+
} finally {
try {
postRegister(logicalName, mbean, registered, registerFailed);
} finally {
- if (registered) context.done();
+ if (registered && context!=null) context.done();
}
}
return new ObjectInstance(logicalName, classname);
@@ -1001,20 +1008,19 @@ public class DefaultMBeanServerIntercept
private static void throwMBeanRegistrationException(Throwable t, String where)
throws MBeanRegistrationException {
- try {
- throw t;
- } catch (RuntimeException e) {
- throw new RuntimeMBeanException(
- e, "RuntimeException thrown " + where);
- } catch (Error er) {
- throw new RuntimeErrorException(er, "Error thrown " + where);
- } catch (MBeanRegistrationException r) {
- throw r;
- } catch (Exception ex) {
- throw new MBeanRegistrationException(ex, "Exception thrown " + where);
- } catch (Throwable t1) {
- throw new RuntimeException(t); // neither Error nor Exception??
- }
+ if (t instanceof RuntimeException) {
+ throw new RuntimeMBeanException((RuntimeException)t,
+ "RuntimeException thrown " + where);
+ } else if (t instanceof Error) {
+ throw new RuntimeErrorException((Error)t,
+ "Error thrown " + where);
+ } else if (t instanceof MBeanRegistrationException) {
+ throw (MBeanRegistrationException)t;
+ } else if (t instanceof Exception) {
+ throw new MBeanRegistrationException((Exception)t,
+ "Exception thrown " + where);
+ } else // neither Error nor Exception??
+ throw new RuntimeException(t);
}
private static ObjectName preRegister(
@@ -1230,7 +1236,8 @@ public class DefaultMBeanServerIntercept
}
DynamicMBean instance = getMBean(name);
- checkMBeanPermission(instance, null, name, "addNotificationListener");
+ checkMBeanPermission(mbeanServerName, instance, null,
+ name, "addNotificationListener");
NotificationBroadcaster broadcaster =
getNotificationBroadcaster(name, instance,
@@ -1367,7 +1374,7 @@ public class DefaultMBeanServerIntercept
}
DynamicMBean instance = getMBean(name);
- checkMBeanPermission(instance, null, name,
+ checkMBeanPermission(mbeanServerName, instance, null, name,
"removeNotificationListener");
/* We could simplify the code by assigning broadcaster after
@@ -1438,7 +1445,7 @@ public class DefaultMBeanServerIntercept
throw new JMRuntimeException("MBean " + name +
"has no MBeanInfo");
- checkMBeanPermission(mbi.getClassName(), null, name, "getMBeanInfo");
+ checkMBeanPermission(mbeanServerName, mbi.getClassName(), null, name, "getMBeanInfo");
return mbi;
}
@@ -1446,8 +1453,9 @@ public class DefaultMBeanServerIntercept
public boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException {
- DynamicMBean instance = getMBean(name);
- checkMBeanPermission(instance, null, name, "isInstanceOf");
+ final DynamicMBean instance = getMBean(name);
+ checkMBeanPermission(mbeanServerName,
+ instance, null, name, "isInstanceOf");
try {
Object resource = getResource(instance);
@@ -1498,7 +1506,8 @@ public class DefaultMBeanServerIntercept
throws InstanceNotFoundException {
DynamicMBean instance = getMBean(mbeanName);
- checkMBeanPermission(instance, null, mbeanName, "getClassLoaderFor");
+ checkMBeanPermission(mbeanServerName, instance, null, mbeanName,
+ "getClassLoaderFor");
return getResourceLoader(instance);
}
@@ -1513,12 +1522,13 @@ public class DefaultMBeanServerIntercept
throws InstanceNotFoundException {
if (loaderName == null) {
- checkMBeanPermission((String) null, null, null, "getClassLoader");
+ checkMBeanPermission(mbeanServerName, (String) null, null, null, "getClassLoader");
return server.getClass().getClassLoader();
}
DynamicMBean instance = getMBean(loaderName);
- checkMBeanPermission(instance, null, loaderName, "getClassLoader");
+ checkMBeanPermission(mbeanServerName, instance, null, loaderName,
+ "getClassLoader");
Object resource = getResource(instance);
@@ -1568,7 +1578,7 @@ public class DefaultMBeanServerIntercept
}
} else {
// Access the filter
- MBeanServer oldServer = QueryEval.getMBeanServer();
+ final MBeanServer oldServer = QueryEval.getMBeanServer();
query.setMBeanServer(server);
try {
for (NamedObject no : list) {
@@ -1817,26 +1827,30 @@ public class DefaultMBeanServerIntercept
return mbean.getMBeanInfo().getClassName();
}
- private static void checkMBeanPermission(DynamicMBean mbean,
+ private static void checkMBeanPermission(String mbeanServerName,
+ DynamicMBean mbean,
String member,
ObjectName objectName,
String actions) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- checkMBeanPermission(safeGetClassName(mbean),
+ checkMBeanPermission(mbeanServerName,
+ safeGetClassName(mbean),
member,
objectName,
actions);
}
}
- private static void checkMBeanPermission(String classname,
+ private static void checkMBeanPermission(String mbeanServerName,
+ String classname,
String member,
ObjectName objectName,
String actions) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- Permission perm = new MBeanPermission(classname,
+ Permission perm = new MBeanPermission(mbeanServerName,
+ classname,
member,
objectName,
actions);
@@ -1902,6 +1916,12 @@ public class DefaultMBeanServerIntercept
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 =
@@ -1965,6 +1985,57 @@ public class DefaultMBeanServerIntercept
sendNotification(MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
logicalName);
return context;
+ }
+
+
+ /**
+ * 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<Runnable> postQueue) {
+ dispatcher.addNamespace(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<Runnable> postQueue) {
+ dispatcher.removeNamespace(logicalName, namespace, postQueue);
}
/**
@@ -2020,6 +2091,52 @@ public class DefaultMBeanServerIntercept
}
}
+
+ /**
+ * 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<Runnable> doneTaskQueue = new LinkedList<Runnable>();
+ 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
@@ -2065,10 +2182,16 @@ public class DefaultMBeanServerIntercept
*/
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);
}
return ResourceContext.NONE;
}
+
+
}
--- a/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptor.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptor.java Wed Sep 17 13:45:37 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * 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
@@ -25,35 +25,14 @@
package com.sun.jmx.interceptor;
-import java.util.Set;
-// RI import
-import javax.management.DynamicMBean;
-import javax.management.AttributeNotFoundException;
+import java.io.ObjectInputStream;
+import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.OperationsException;
import javax.management.ReflectionException;
-import javax.management.MBeanAttributeInfo;
-import javax.management.MBeanInfo;
-import javax.management.QueryExp;
-import javax.management.NotificationListener;
-import javax.management.NotificationFilter;
-import javax.management.ListenerNotFoundException;
-import javax.management.IntrospectionException;
-import javax.management.OperationsException;
-import javax.management.MBeanNotificationInfo;
-import javax.management.JMRuntimeException;
-import javax.management.InstanceNotFoundException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.MBeanRegistrationException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InvalidAttributeValueException;
-import javax.management.ObjectName;
-import javax.management.ObjectInstance;
-import javax.management.Attribute;
-import javax.management.AttributeList;
-import javax.management.RuntimeOperationsException;
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerDelegate;
import javax.management.loading.ClassLoaderRepository;
/**
@@ -85,618 +64,67 @@ import javax.management.loading.ClassLoa
*
* @since 1.5
*/
-public interface MBeanServerInterceptor extends MBeanServerConnection {
+public interface MBeanServerInterceptor extends MBeanServer {
/**
- * Instantiates and registers an MBean in the MBean server. The
- * MBean server will use its {@link
- * javax.management.loading.ClassLoaderRepository Default Loader
- * Repository} to load the class of the MBean. An object name is
- * associated to the MBean. If the object name given is null, the
- * MBean must provide its own name by implementing the {@link
- * javax.management.MBeanRegistration MBeanRegistration} interface
- * and returning the name from the {@link
- * javax.management.MBeanRegistration#preRegister preRegister} method.
- *
- * @param className The class name of the MBean to be instantiated.
- * @param name The object name of the MBean. May be null.
- * @param params An array containing the parameters of the
- * constructor to be invoked.
- * @param signature An array containing the signature of the
- * constructor to be invoked.
- *
- * @return An <CODE>ObjectInstance</CODE>, containing the
- * <CODE>ObjectName</CODE> and the Java class name of the newly
- * instantiated MBean.
- *
- * @exception ReflectionException Wraps a
- * <CODE>java.lang.ClassNotFoundException</CODE> or a
- * <CODE>java.lang.Exception</CODE> that occurred when trying to
- * invoke the MBean's constructor.
- * @exception InstanceAlreadyExistsException The MBean is already
- * under the control of the MBean server.
- * @exception MBeanRegistrationException The
- * <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
- * interface) method of the MBean has thrown an exception. The
- * MBean will not be registered.
- * @exception MBeanException The constructor of the MBean has
- * thrown an exception
- * @exception RuntimeOperationsException Wraps a
- * <CODE>java.lang.IllegalArgumentException</CODE>: The className
- * passed in parameter is null, the <CODE>ObjectName</CODE> passed
- * in parameter contains a pattern or no <CODE>ObjectName</CODE>
- * is specified for the MBean.
+ * This method should never be called.
+ * Usually hrows UnsupportedOperationException.
*/
- public ObjectInstance createMBean(String className, ObjectName name,
- Object params[], String signature[])
- throws ReflectionException, InstanceAlreadyExistsException,
- MBeanRegistrationException, MBeanException,
- NotCompliantMBeanException;
+ public Object instantiate(String className)
+ throws ReflectionException, MBeanException;
+ /**
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
+ */
+ public Object instantiate(String className, ObjectName loaderName)
+ throws ReflectionException, MBeanException,
+ InstanceNotFoundException;
+ /**
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
+ */
+ public Object instantiate(String className, Object[] params,
+ String[] signature) throws ReflectionException, MBeanException;
/**
- * Instantiates and registers an MBean in the MBean server. The
- * class loader to be used is identified by its object name. An
- * object name is associated to the MBean. If the object name of
- * the loader is not specified, the ClassLoader that loaded the
- * MBean server will be used. If the MBean object name given is
- * null, the MBean must provide its own name by implementing the
- * {@link javax.management.MBeanRegistration MBeanRegistration}
- * interface and returning the name from the {@link
- * javax.management.MBeanRegistration#preRegister preRegister} method.
- *
- * @param className The class name of the MBean to be instantiated.
- * @param name The object name of the MBean. May be null.
- * @param params An array containing the parameters of the
- * constructor to be invoked.
- * @param signature An array containing the signature of the
- * constructor to be invoked.
- * @param loaderName The object name of the class loader to be used.
- *
- * @return An <CODE>ObjectInstance</CODE>, containing the
- * <CODE>ObjectName</CODE> and the Java class name of the newly
- * instantiated MBean.
- *
- * @exception ReflectionException Wraps a
- * <CODE>java.lang.ClassNotFoundException</CODE> or a
- * <CODE>java.lang.Exception</CODE> that occurred when trying to
- * invoke the MBean's constructor.
- * @exception InstanceAlreadyExistsException The MBean is already
- * under the control of the MBean server.
- * @exception MBeanRegistrationException The
- * <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
- * interface) method of the MBean has thrown an exception. The
- * MBean will not be registered.
- * @exception MBeanException The constructor of the MBean has
- * thrown an exception
- * @exception InstanceNotFoundException The specified class loader
- * is not registered in the MBean server.
- * @exception RuntimeOperationsException Wraps a
- * <CODE>java.lang.IllegalArgumentException</CODE>: The className
- * passed in parameter is null, the <CODE>ObjectName</CODE> passed
- * in parameter contains a pattern or no <CODE>ObjectName</CODE>
- * is specified for the MBean.
- *
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
*/
- public ObjectInstance createMBean(String className, ObjectName name,
- ObjectName loaderName, Object params[],
- String signature[])
- throws ReflectionException, InstanceAlreadyExistsException,
- MBeanRegistrationException, MBeanException,
- NotCompliantMBeanException, InstanceNotFoundException;
+ public Object instantiate(String className, ObjectName loaderName,
+ Object[] params, String[] signature)
+ throws ReflectionException, MBeanException,
+ InstanceNotFoundException;
/**
- * Registers a pre-existing object as an MBean with the MBean
- * server. If the object name given is null, the MBean must
- * provide its own name by implementing the {@link
- * javax.management.MBeanRegistration MBeanRegistration} interface
- * and returning the name from the {@link
- * javax.management.MBeanRegistration#preRegister preRegister} method.
- *
- * @param object The MBean to be registered as an MBean.
- * @param name The object name of the MBean. May be null.
- *
- * @return The <CODE>ObjectInstance</CODE> for the MBean that has
- * been registered.
- *
- * @exception InstanceAlreadyExistsException The MBean is already
- * under the control of the MBean server.
- * @exception MBeanRegistrationException The
- * <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
- * interface) method of the MBean has thrown an exception. The
- * MBean will not be registered.
- * @exception NotCompliantMBeanException This object is not a JMX
- * compliant MBean
- * @exception RuntimeOperationsException Wraps a
- * <CODE>java.lang.IllegalArgumentException</CODE>: The object
- * passed in parameter is null or no object name is specified.
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
*/
- public ObjectInstance registerMBean(Object object, ObjectName name)
- throws InstanceAlreadyExistsException, MBeanRegistrationException,
- NotCompliantMBeanException;
+ @Deprecated
+ public ObjectInputStream deserialize(ObjectName name, byte[] data)
+ throws InstanceNotFoundException, OperationsException;
/**
- * Unregisters an MBean from the MBean server. The MBean is
- * identified by its object name. Once the method has been
- * invoked, the MBean may no longer be accessed by its object
- * name.
- *
- * @param name The object name of the MBean to be unregistered.
- *
- * @exception InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @exception MBeanRegistrationException The preDeregister
- * ((<CODE>MBeanRegistration</CODE> interface) method of the MBean
- * has thrown an exception.
- * @exception RuntimeOperationsException Wraps a
- * <CODE>java.lang.IllegalArgumentException</CODE>: The object
- * name in parameter is null or the MBean you are when trying to
- * unregister is the {@link javax.management.MBeanServerDelegate
- * MBeanServerDelegate} MBean.
- *
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
*/
- public void unregisterMBean(ObjectName name)
- throws InstanceNotFoundException, MBeanRegistrationException;
+ @Deprecated
+ public ObjectInputStream deserialize(String className, byte[] data)
+ throws OperationsException, ReflectionException;
/**
- * Gets the <CODE>ObjectInstance</CODE> for a given MBean
- * registered with the MBean server.
- *
- * @param name The object name of the MBean.
- *
- * @return The <CODE>ObjectInstance</CODE> associated to the MBean
- * specified by <VAR>name</VAR>.
- *
- * @exception InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
+ * This method should never be called.
+ * Usually hrows UnsupportedOperationException.
*/
- public ObjectInstance getObjectInstance(ObjectName name)
- throws InstanceNotFoundException;
+ @Deprecated
+ public ObjectInputStream deserialize(String className,
+ ObjectName loaderName, byte[] data)
+ throws InstanceNotFoundException, OperationsException,
+ ReflectionException;
/**
- * Gets MBeans controlled by the MBean server. This method allows
- * any of the following to be obtained: All MBeans, a set of
- * MBeans specified by pattern matching on the
- * <CODE>ObjectName</CODE> and/or a Query expression, a specific
- * MBean. When the object name is null or no domain and key
- * properties are specified, all objects are to be selected (and
- * filtered if a query is specified). It returns the set of
- * <CODE>ObjectInstance</CODE> objects (containing the
- * <CODE>ObjectName</CODE> and the Java Class name) for the
- * selected MBeans.
- *
- * @param name The object name pattern identifying the MBeans to
- * be retrieved. If null or no domain and key properties are
- * specified, all the MBeans registered will be retrieved.
- * @param query The query expression to be applied for selecting
- * MBeans. If null no query expression will be applied for
- * selecting MBeans.
- *
- * @return A set containing the <CODE>ObjectInstance</CODE>
- * objects for the selected MBeans. If no MBean satisfies the
- * query an empty list is returned.
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
*/
- public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query);
-
- /**
- * Gets the names of MBeans controlled by the MBean server. This
- * method enables any of the following to be obtained: The names
- * of all MBeans, the names of a set of MBeans specified by
- * pattern matching on the <CODE>ObjectName</CODE> and/or a Query
- * expression, a specific MBean name (equivalent to testing
- * whether an MBean is registered). When the object name is null
- * or no domain and key properties are specified, all objects are
- * selected (and filtered if a query is specified). It returns the
- * set of ObjectNames for the MBeans selected.
- *
- * @param name The object name pattern identifying the MBean names
- * to be retrieved. If null oror no domain and key properties are
- * specified, the name of all registered MBeans will be retrieved.
- * @param query The query expression to be applied for selecting
- * MBeans. If null no query expression will be applied for
- * selecting MBeans.
- *
- * @return A set containing the ObjectNames for the MBeans
- * selected. If no MBean satisfies the query, an empty list is
- * returned.
- */
- public Set<ObjectName> queryNames(ObjectName name, QueryExp query);
-
- /**
- * Checks whether an MBean, identified by its object name, is
- * already registered with the MBean server.
- *
- * @param name The object name of the MBean to be checked.
- *
- * @return True if the MBean is already registered in the MBean
- * server, false otherwise.
- *
- * @exception RuntimeOperationsException Wraps a
- * <CODE>java.lang.IllegalArgumentException</CODE>: The object
- * name in parameter is null.
- */
- public boolean isRegistered(ObjectName name);
-
- /**
- * Returns the number of MBeans registered in the MBean server.
- */
- public Integer getMBeanCount();
-
- /**
- * Gets the value of a specific attribute of a named MBean. The MBean
- * is identified by its object name.
- *
- * @param name The object name of the MBean from which the
- * attribute is to be retrieved.
- * @param attribute A String specifying the name of the attribute
- * to be retrieved.
- *
- * @return The value of the retrieved attribute.
- *
- * @exception AttributeNotFoundException The attribute specified
- * is not accessible in the MBean.
- * @exception MBeanException Wraps an exception thrown by the
- * MBean's getter.
- * @exception InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @exception ReflectionException Wraps a
- * <CODE>java.lang.Exception</CODE> thrown when trying to invoke
- * the setter.
- * @exception RuntimeOperationsException Wraps a
- * <CODE>java.lang.IllegalArgumentException</CODE>: The object
- * name in parameter is null or the attribute in parameter is
- * null.
- */
- public Object getAttribute(ObjectName name, String attribute)
- throws MBeanException, AttributeNotFoundException,
- InstanceNotFoundException, ReflectionException;
-
- /**
- * Enables the values of several attributes of a named MBean. The MBean
- * is identified by its object name.
- *
- * @param name The object name of the MBean from which the
- * attributes are retrieved.
- * @param attributes A list of the attributes to be retrieved.
- *
- * @return The list of the retrieved attributes.
- *
- * @exception InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @exception ReflectionException An exception occurred when
- * trying to invoke the getAttributes method of a Dynamic MBean.
- * @exception RuntimeOperationsException Wrap a
- * <CODE>java.lang.IllegalArgumentException</CODE>: The object
- * name in parameter is null or attributes in parameter is null.
- */
- public AttributeList getAttributes(ObjectName name, String[] attributes)
- throws InstanceNotFoundException, ReflectionException;
-
- /**
- * Sets the value of a specific attribute of a named MBean. The MBean
- * is identified by its object name.
- *
- * @param name The name of the MBean within which the attribute is
- * to be set.
- * @param attribute The identification of the attribute to be set
- * and the value it is to be set to.
- *
- * @exception InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @exception AttributeNotFoundException The attribute specified
- * is not accessible in the MBean.
- * @exception InvalidAttributeValueException The value specified
- * for the attribute is not valid.
- * @exception MBeanException Wraps an exception thrown by the
- * MBean's setter.
- * @exception ReflectionException Wraps a
- * <CODE>java.lang.Exception</CODE> thrown when trying to invoke
- * the setter.
- * @exception RuntimeOperationsException Wraps a
- * <CODE>java.lang.IllegalArgumentException</CODE>: The object
- * name in parameter is null or the attribute in parameter is
- * null.
- */
- public void setAttribute(ObjectName name, Attribute attribute)
- throws InstanceNotFoundException, AttributeNotFoundException,
- InvalidAttributeValueException, MBeanException,
- ReflectionException;
-
-
-
- /**
- * Sets the values of several attributes of a named MBean. The MBean is
- * identified by its object name.
- *
- * @param name The object name of the MBean within which the
- * attributes are to be set.
- * @param attributes A list of attributes: The identification of
- * the attributes to be set and the values they are to be set to.
- *
- * @return The list of attributes that were set, with their new
- * values.
- *
- * @exception InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @exception ReflectionException An exception occurred when
- * trying to invoke the getAttributes method of a Dynamic MBean.
- * @exception RuntimeOperationsException Wraps a
- * <CODE>java.lang.IllegalArgumentException</CODE>: The object
- * name in parameter is null or attributes in parameter is null.
- */
- public AttributeList setAttributes(ObjectName name,
- AttributeList attributes)
- throws InstanceNotFoundException, ReflectionException;
-
- /**
- * Invokes an operation on an MBean.
- *
- * @param name The object name of the MBean on which the method is
- * to be invoked.
- * @param operationName The name of the operation to be invoked.
- * @param params An array containing the parameters to be set when
- * the operation is invoked
- * @param signature An array containing the signature of the
- * operation. The class objects will be loaded using the same
- * class loader as the one used for loading the MBean on which the
- * operation was invoked.
- *
- * @return The object returned by the operation, which represents
- * the result ofinvoking the operation on the MBean specified.
- *
- * @exception InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @exception MBeanException Wraps an exception thrown by the
- * MBean's invoked method.
- * @exception ReflectionException Wraps a
- * <CODE>java.lang.Exception</CODE> thrown while trying to invoke
- * the method.
- */
- public Object invoke(ObjectName name, String operationName,
- Object params[], String signature[])
- throws InstanceNotFoundException, MBeanException,
- ReflectionException;
-
- /**
- * Returns the default domain used for naming the MBean.
- * The default domain name is used as the domain part in the ObjectName
- * of MBeans if no domain is specified by the user.
- */
- public String getDefaultDomain();
-
- /**
- * Returns the list of domains in which any MBean is currently
- * registered.
- */
- public String[] getDomains();
-
- /**
- * <p>Adds a listener to a registered MBean.</p>
- *
- * <P> A notification emitted by an MBean will be forwarded by the
- * MBeanServer to the listener. If the source of the notification
- * is a reference to an MBean object, the MBean server will replace it
- * by that MBean's ObjectName. Otherwise the source is unchanged.
- *
- * @param name The name of the MBean on which the listener should
- * be added.
- * @param listener The listener object which will handle the
- * notifications emitted by the registered MBean.
- * @param filter The filter object. If filter is null, no
- * filtering will be performed before handling notifications.
- * @param handback The context to be sent to the listener when a
- * notification is emitted.
- *
- * @exception InstanceNotFoundException The MBean name provided
- * does not match any of the registered MBeans.
- */
- public void addNotificationListener(ObjectName name,
- NotificationListener listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException;
-
-
- /**
- * <p>Adds a listener to a registered MBean.</p>
- *
- * <p>A notification emitted by an MBean will be forwarded by the
- * MBeanServer to the listener. If the source of the notification
- * is a reference to an MBean object, the MBean server will
- * replace it by that MBean's ObjectName. Otherwise the source is
- * unchanged.</p>
- *
- * <p>The listener object that receives notifications is the one
- * that is registered with the given name at the time this method
- * is called. Even if it is subsequently unregistered, it will
- * continue to receive notifications.</p>
- *
- * @param name The name of the MBean on which the listener should
- * be added.
- * @param listener The object name of the listener which will
- * handle the notifications emitted by the registered MBean.
- * @param filter The filter object. If filter is null, no
- * filtering will be performed before handling notifications.
- * @param handback The context to be sent to the listener when a
- * notification is emitted.
- *
- * @exception InstanceNotFoundException The MBean name of the
- * notification listener or of the notification broadcaster does
- * not match any of the registered MBeans.
- * @exception RuntimeOperationsException Wraps an {@link
- * IllegalArgumentException}. The MBean named by
- * <code>listener</code> exists but does not implement the {@link
- * NotificationListener} interface.
- * @exception IOException A communication problem occurred when
- * talking to the MBean server.
- */
- public void addNotificationListener(ObjectName name,
- ObjectName listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException;
-
- /**
- * Removes a listener from a registered MBean.
- *
- * <P> If the listener is registered more than once, perhaps with
- * different filters or callbacks, this method will remove all
- * those registrations.
- *
- * @param name The name of the MBean on which the listener should
- * be removed.
- * @param listener The object name of the listener to be removed.
- *
- * @exception InstanceNotFoundException The MBean name provided
- * does not match any of the registered MBeans.
- * @exception ListenerNotFoundException The listener is not
- * registered in the MBean.
- */
- public void removeNotificationListener(ObjectName name,
- ObjectName listener)
- throws InstanceNotFoundException, ListenerNotFoundException;
-
- /**
- * <p>Removes a listener from a registered MBean.</p>
- *
- * <p>The MBean must have a listener that exactly matches the
- * given <code>listener</code>, <code>filter</code>, and
- * <code>handback</code> parameters. If there is more than one
- * such listener, only one is removed.</p>
- *
- * <p>The <code>filter</code> and <code>handback</code> parameters
- * may be null if and only if they are null in a listener to be
- * removed.</p>
- *
- * @param name The name of the MBean on which the listener should
- * be removed.
- * @param listener A listener that was previously added to this
- * MBean.
- * @param filter The filter that was specified when the listener
- * was added.
- * @param handback The handback that was specified when the
- * listener was added.
- *
- * @exception InstanceNotFoundException The MBean name provided
- * does not match any of the registered MBeans.
- * @exception ListenerNotFoundException The listener is not
- * registered in the MBean, or it is not registered with the given
- * filter and handback.
- */
- public void removeNotificationListener(ObjectName name,
- ObjectName listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException, ListenerNotFoundException;
-
-
- /**
- * <p>Removes a listener from a registered MBean.</p>
- *
- * <P> If the listener is registered more than once, perhaps with
- * different filters or callbacks, this method will remove all
- * those registrations.
- *
- * @param name The name of the MBean on which the listener should
- * be removed.
- * @param listener The listener object which will handle the
- * notifications emitted by the registered MBean.
- *
- * @exception InstanceNotFoundException The MBean name provided
- * does not match any of the registered MBeans.
- * @exception ListenerNotFoundException The listener is not
- * registered in the MBean.
- */
- public void removeNotificationListener(ObjectName name,
- NotificationListener listener)
- throws InstanceNotFoundException, ListenerNotFoundException;
-
- /**
- * <p>Removes a listener from a registered MBean.</p>
- *
- * <p>The MBean must have a listener that exactly matches the
- * given <code>listener</code>, <code>filter</code>, and
- * <code>handback</code> parameters. If there is more than one
- * such listener, only one is removed.</p>
- *
- * <p>The <code>filter</code> and <code>handback</code> parameters
- * may be null if and only if they are null in a listener to be
- * removed.</p>
- *
- * @param name The name of the MBean on which the listener should
- * be removed.
- * @param listener A listener that was previously added to this
- * MBean.
- * @param filter The filter that was specified when the listener
- * was added.
- * @param handback The handback that was specified when the
- * listener was added.
- *
- * @exception InstanceNotFoundException The MBean name provided
- * does not match any of the registered MBeans.
- * @exception ListenerNotFoundException The listener is not
- * registered in the MBean, or it is not registered with the given
- * filter and handback.
- */
- public void removeNotificationListener(ObjectName name,
- NotificationListener listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException, ListenerNotFoundException;
-
- /**
- * This method discovers the attributes and operations that an
- * MBean exposes for management.
- *
- * @param name The name of the MBean to analyze
- *
- * @return An instance of <CODE>MBeanInfo</CODE> allowing the
- * retrieval of all attributes and operations of this MBean.
- *
- * @exception IntrospectionException An exception occurred during
- * introspection.
- * @exception InstanceNotFoundException The MBean specified was
- * not found.
- * @exception ReflectionException An exception occurred when
- * trying to invoke the getMBeanInfo of a Dynamic MBean.
- */
- public MBeanInfo getMBeanInfo(ObjectName name)
- throws InstanceNotFoundException, IntrospectionException,
- ReflectionException;
-
-
- /**
- * Returns true if the MBean specified is an instance of the
- * specified class, false otherwise.
- *
- * @param name The <CODE>ObjectName</CODE> of the MBean.
- * @param className The name of the class.
- *
- * @return true if the MBean specified is an instance of the
- * specified class, false otherwise.
- *
- * @exception InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- */
- public boolean isInstanceOf(ObjectName name, String className)
- throws InstanceNotFoundException;
-
- /**
- * <p>Return the {@link java.lang.ClassLoader} that was used for
- * loading the class of the named MBean.
- * @param mbeanName The ObjectName of the MBean.
- * @return The ClassLoader used for that MBean.
- * @exception InstanceNotFoundException if the named MBean is not found.
- */
- public ClassLoader getClassLoaderFor(ObjectName mbeanName)
- throws InstanceNotFoundException;
-
- /**
- * <p>Return the named {@link java.lang.ClassLoader}.
- * @param loaderName The ObjectName of the ClassLoader.
- * @return The named ClassLoader.
- * @exception InstanceNotFoundException if the named ClassLoader is
- * not found.
- */
- public ClassLoader getClassLoader(ObjectName loaderName)
- throws InstanceNotFoundException;
+ public ClassLoaderRepository getClassLoaderRepository();
}
+
--- a/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java Wed Sep 17 13:45:37 2008 -0700
@@ -51,6 +51,8 @@ import javax.management.ObjectName;
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;
public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@@ -285,14 +287,14 @@ public class SingleMBeanForwarder extend
if (!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);
-// }
+ 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.
--- a/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Wed Sep 17 13:45:37 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * 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
@@ -25,43 +25,41 @@
package com.sun.jmx.mbeanserver;
-import java.util.Iterator;
-import java.util.logging.Level;
-import java.util.Set;
+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;
-
-// RI import
-import javax.management.MBeanPermission;
-import javax.management.AttributeNotFoundException;
-import javax.management.MBeanException;
-import javax.management.ReflectionException;
-import javax.management.MBeanInfo;
-import javax.management.QueryExp;
-import javax.management.NotificationListener;
-import javax.management.NotificationFilter;
-import javax.management.ListenerNotFoundException;
-import javax.management.IntrospectionException;
-import javax.management.OperationsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.MBeanRegistrationException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InvalidAttributeValueException;
-import javax.management.ObjectName;
-import javax.management.ObjectInstance;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.logging.Level;
+
import javax.management.Attribute;
import javax.management.AttributeList;
-import javax.management.RuntimeOperationsException;
+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.MBeanPermission;
+import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerDelegate;
+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.RuntimeOperationsException;
import javax.management.loading.ClassLoaderRepository;
-
-import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
-import com.sun.jmx.interceptor.DefaultMBeanServerInterceptor;
-import com.sun.jmx.interceptor.MBeanServerInterceptor;
/**
* This is the base class for MBean manipulation on the agent side. It
@@ -102,15 +100,14 @@ public final class JmxMBeanServer
/** true if interceptors are enabled **/
private final boolean interceptorsEnabled;
- /** Revisit: transient ??? **/
- private final transient MBeanServer outerShell;
-
- /** Revisit: transient ??? **/
- private transient MBeanServerInterceptor mbsInterceptor = null;
-
- /** Revisit: transient ??? **/
+ private final MBeanServer outerShell;
+
+ private volatile MBeanServer mbsInterceptor = null;
+
/** The MBeanServerDelegate object representing the MBean Server */
- private final transient MBeanServerDelegate mBeanServerDelegateObject;
+ private final MBeanServerDelegate mBeanServerDelegateObject;
+
+ private final String mbeanServerName;
/**
* <b>Package:</b> Creates an MBeanServer with the
@@ -243,9 +240,10 @@ public final class JmxMBeanServer
final Repository repository = new Repository(domain,fairLock);
this.mbsInterceptor =
- new DefaultMBeanServerInterceptor(outer, delegate, instantiator,
+ new NamespaceDispatchInterceptor(outer, delegate, instantiator,
repository);
this.interceptorsEnabled = interceptors;
+ this.mbeanServerName = Util.getMBeanServerSecurityName(delegate);
initialize();
}
@@ -941,7 +939,8 @@ public final class JmxMBeanServer
throws ReflectionException, MBeanException {
/* Permission check */
- checkMBeanPermission(className, null, null, "instantiate");
+ checkMBeanPermission(mbeanServerName, className, null, null,
+ "instantiate");
return instantiator.instantiate(className);
}
@@ -978,7 +977,8 @@ public final class JmxMBeanServer
InstanceNotFoundException {
/* Permission check */
- checkMBeanPermission(className, null, null, "instantiate");
+ checkMBeanPermission(mbeanServerName, className, null,
+ null, "instantiate");
ClassLoader myLoader = outerShell.getClass().getClassLoader();
return instantiator.instantiate(className, loaderName, myLoader);
@@ -1016,7 +1016,8 @@ public final class JmxMBeanServer
throws ReflectionException, MBeanException {
/* Permission check */
- checkMBeanPermission(className, null, null, "instantiate");
+ checkMBeanPermission(mbeanServerName, className, null, null,
+ "instantiate");
ClassLoader myLoader = outerShell.getClass().getClassLoader();
return instantiator.instantiate(className, params, signature,
@@ -1059,7 +1060,8 @@ public final class JmxMBeanServer
InstanceNotFoundException {
/* Permission check */
- checkMBeanPermission(className, null, null, "instantiate");
+ checkMBeanPermission(mbeanServerName, className, null,
+ null, "instantiate");
ClassLoader myLoader = outerShell.getClass().getClassLoader();
return instantiator.instantiate(className,loaderName,params,signature,
@@ -1236,7 +1238,7 @@ public final class JmxMBeanServer
"Unexpected exception occurred", e);
}
throw new
- IllegalStateException("Can't register delegate.");
+ IllegalStateException("Can't register delegate.",e);
}
@@ -1278,7 +1280,7 @@ public final class JmxMBeanServer
* are not enabled on this object.
* @see #interceptorsEnabled
**/
- public synchronized MBeanServerInterceptor getMBeanServerInterceptor() {
+ public synchronized MBeanServer getMBeanServerInterceptor() {
if (interceptorsEnabled) return mbsInterceptor;
else throw new UnsupportedOperationException(
"MBeanServerInterceptors are disabled.");
@@ -1292,7 +1294,7 @@ public final class JmxMBeanServer
* @see #interceptorsEnabled
**/
public synchronized void
- setMBeanServerInterceptor(MBeanServerInterceptor interceptor) {
+ setMBeanServerInterceptor(MBeanServer interceptor) {
if (!interceptorsEnabled) throw new UnsupportedOperationException(
"MBeanServerInterceptors are disabled.");
if (interceptor == null) throw new
@@ -1330,7 +1332,8 @@ public final class JmxMBeanServer
**/
public ClassLoaderRepository getClassLoaderRepository() {
/* Permission check */
- checkMBeanPermission(null, null, null, "getClassLoaderRepository");
+ checkMBeanPermission(mbeanServerName, null, null,
+ null, "getClassLoaderRepository");
return secureClr;
}
@@ -1484,14 +1487,16 @@ public final class JmxMBeanServer
// SECURITY CHECKS
//----------------
- private static void checkMBeanPermission(String classname,
+ private static void checkMBeanPermission(String serverName,
+ String classname,
String member,
ObjectName objectName,
String actions)
throws SecurityException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- Permission perm = new MBeanPermission(classname,
+ Permission perm = new MBeanPermission(serverName,
+ classname,
member,
objectName,
actions);
--- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java Wed Sep 17 13:45:37 2008 -0700
@@ -224,7 +224,7 @@ public abstract class MXBeanLookup {
throws InvalidObjectException {
String domain = prefix + name.getDomain();
try {
- name = switchDomain(domain, name);
+ name = name.withDomain(domain);
} catch (MalformedObjectNameException e) {
throw EnvHelp.initCause(
new InvalidObjectException(e.getMessage()), e);
@@ -242,7 +242,7 @@ public abstract class MXBeanLookup {
"Proxy's name does not start with " + prefix + ": " + name);
}
try {
- name = switchDomain(domain.substring(prefix.length()), name);
+ name = name.withDomain(domain.substring(prefix.length()));
} catch (MalformedObjectNameException e) {
throw EnvHelp.initCause(new OpenDataException(e.getMessage()), e);
}
@@ -269,14 +269,6 @@ public abstract class MXBeanLookup {
currentLookup.set(lookup);
}
- // Method temporarily added until we have ObjectName.switchDomain in the
- // public API. Note that this method DOES NOT PRESERVE the order of
- // keys in the ObjectName so it must not be used in the final release.
- static ObjectName switchDomain(String domain, ObjectName name)
- throws MalformedObjectNameException {
- return new ObjectName(domain, name.getKeyPropertyList());
- }
-
private static final ThreadLocal<MXBeanLookup> currentLookup =
new ThreadLocal<MXBeanLookup>();
--- a/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Wed Sep 17 13:45:37 2008 -0700
@@ -45,7 +45,6 @@ import javax.management.RuntimeOperation
import javax.management.RuntimeOperationsException;
/**
- * The RepositorySupport implements the Repository interface.
* This repository does not support persistency.
*
* @since 1.5
@@ -197,9 +196,9 @@ public class Repository {
if (isPropertyValuePattern &&
pattern.isPropertyValuePattern(keys[i])) {
// wildmatch key property values
- final char[] val_pattern = values[i].toCharArray();
- final char[] val_string = v.toCharArray();
- if (wildmatch(val_string,val_pattern))
+ // values[i] is the pattern;
+ // v is the string
+ if (Util.wildmatch(v,values[i]))
continue;
else
return false;
@@ -236,86 +235,6 @@ public class Repository {
}
}
- /** Match a string against a shell-style pattern. The only pattern
- characters recognised are <code>?</code>, standing for any one
- character, and <code>*</code>, standing for any string of
- characters, including the empty string.
-
- @param str the string to match, as a character array.
- @param pat the pattern to match the string against, as a
- character array.
-
- @return true if and only if the string matches the pattern.
- */
- /* The algorithm is a classical one. We advance pointers in
- parallel through str and pat. If we encounter a star in pat,
- we remember its position and continue advancing. If at any
- stage we get a mismatch between str and pat, we look to see if
- there is a remembered star. If not, we fail. If so, we
- retreat pat to just past that star and str to the position
- after the last one we tried, and we let the match advance
- again.
-
- Even though there is only one remembered star position, the
- algorithm works when there are several stars in the pattern.
- When we encounter the second star, we forget the first one.
- This is OK, because if we get to the second star in A*B*C
- (where A etc are arbitrary strings), we have already seen AXB.
- We're therefore setting up a match of *C against the remainder
- of the string, which will match if that remainder looks like
- YC, so the whole string looks like AXBYC.
- */
- public static boolean wildmatch(char[] str, char[] pat) {
- int stri; // index in str
- int pati; // index in pat
- int starstri; // index for backtrack if "*" attempt fails
- int starpati; // index for backtrack if "*" attempt fails, +1
- final int strlen = str.length;
- final int patlen = pat.length;
-
- stri = pati = 0;
- starstri = starpati = -1;
-
- /* On each pass through this loop, we either advance pati,
- or we backtrack pati and advance starstri. Since starstri
- is only ever assigned from pati, the loop must terminate. */
- while (true) {
- if (pati < patlen) {
- final char patc = pat[pati];
- switch (patc) {
- case '?':
- if (stri == strlen)
- break;
- stri++;
- pati++;
- continue;
- case '*':
- pati++;
- starpati = pati;
- starstri = stri;
- continue;
- default:
- if (stri < strlen && str[stri] == patc) {
- stri++;
- pati++;
- continue;
- }
- break;
- }
- } else if (stri == strlen)
- return true;
-
- // Mismatched, can we backtrack to a "*"?
- if (starpati < 0 || starstri == strlen)
- return false;
-
- // Retry the match one position later in str
- pati = starpati;
- starstri++;
- stri = starstri;
- }
- }
-
private void addNewDomMoi(final DynamicMBean object,
final String dom,
final ObjectName name,
@@ -370,7 +289,7 @@ public class Repository {
if (name.isPattern()) return null;
// Extract the domain name.
- String dom= name.getDomain().intern();
+ String dom = name.getDomain().intern();
// Default domain case
if (dom.length() == 0) {
@@ -480,7 +399,7 @@ public class Repository {
name = Util.newObjectName(domain + name.toString());
// Do we have default domain ?
- if (dom == domain) {
+ if (dom == domain) { // ES: OK (dom & domain are interned)
to_default_domain = true;
dom = domain;
} else {
@@ -652,10 +571,9 @@ public class Repository {
}
// Pattern matching in the domain name (*, ?)
- char[] dom2Match = name.getDomain().toCharArray();
+ final String dom2Match = name.getDomain();
for (String dom : domainTb.keySet()) {
- char[] theDom = dom.toCharArray();
- if (wildmatch(theDom, dom2Match)) {
+ if (Util.wildpathmatch(dom, dom2Match)) {
final Map<String,NamedObject> moiTb = domainTb.get(dom);
if (allNames)
result.addAll(moiTb.values());
@@ -726,7 +644,7 @@ public class Repository {
// need to reinstantiate a hashtable because of possible
// big buckets array size inside table, never cleared,
// thus the new !
- if (dom == domain)
+ if (dom == domain) // ES: OK dom and domain are interned.
domainTb.put(domain, new HashMap<String,NamedObject>());
}
--- a/src/share/classes/com/sun/jmx/mbeanserver/SunJmxMBeanServer.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/SunJmxMBeanServer.java Wed Sep 17 13:45:37 2008 -0700
@@ -28,17 +28,16 @@ import javax.management.MBeanServer;
import javax.management.MBeanServer;
import javax.management.MBeanServerDelegate;
-import com.sun.jmx.interceptor.MBeanServerInterceptor;
/**
- * Extends the MBeanServer and MBeanServerInterceptor interface to
+ * Extends the MBeanServer interface to
* provide methods for getting the MetaData and MBeanServerInstantiator
* objects associated with an MBeanServer.
*
* @since 1.5
*/
public interface SunJmxMBeanServer
- extends MBeanServerInterceptor, MBeanServer {
+ extends MBeanServer {
/**
* Return the MBeanInstantiator associated to this MBeanServer.
@@ -68,7 +67,7 @@ public interface SunJmxMBeanServer
* are not enabled on this object.
* @see #interceptorsEnabled
**/
- public MBeanServerInterceptor getMBeanServerInterceptor();
+ public MBeanServer getMBeanServerInterceptor();
/**
* Set the MBeanServerInterceptor.
@@ -77,7 +76,7 @@ public interface SunJmxMBeanServer
* are not enabled on this object.
* @see #interceptorsEnabled
**/
- public void setMBeanServerInterceptor(MBeanServerInterceptor interceptor);
+ public void setMBeanServerInterceptor(MBeanServer interceptor);
/**
* <p>Return the MBeanServerDelegate representing the MBeanServer.
--- a/src/share/classes/com/sun/jmx/mbeanserver/Util.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/mbeanserver/Util.java Wed Sep 17 13:45:37 2008 -0700
@@ -25,6 +25,8 @@
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;
@@ -42,11 +44,22 @@ import java.util.TreeMap;
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.MalformedObjectNameException;
+import javax.management.ObjectInstance;
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 String ILLEGAL_MBEANSERVER_NAME_CHARS=";:*?";
+
+
static <K, V> Map<K, V> newMap() {
return new HashMap<K, V>();
}
@@ -145,6 +158,270 @@ public class Util {
return hash;
}
+ /** Match a part of a string against a shell-style pattern.
+ The only pattern characters recognized are <code>?</code>,
+ standing for any one character,
+ and <code>*</code>, standing for any string of
+ characters, including the empty string. For instance,
+ {@code wildmatch("sandwich","sa?d*ch",1,4,1,4)} will match
+ {@code "and"} against {@code "a?d"}.
+
+ @param str the string containing the sequence to match.
+ @param pat a string containing a pattern to match the sub string
+ against.
+ @param stri the index in the string at which matching should begin.
+ @param strend the index in the string at which the matching should
+ end.
+ @param pati the index in the pattern at which matching should begin.
+ @param patend the index in the pattern at which the matching should
+ end.
+
+ @return true if and only if the string matches the pattern.
+ */
+ /* The algorithm is a classical one. We advance pointers in
+ parallel through str and pat. If we encounter a star in pat,
+ we remember its position and continue advancing. If at any
+ stage we get a mismatch between str and pat, we look to see if
+ there is a remembered star. If not, we fail. If so, we
+ retreat pat to just past that star and str to the position
+ after the last one we tried, and we let the match advance
+ again.
+
+ Even though there is only one remembered star position, the
+ algorithm works when there are several stars in the pattern.
+ When we encounter the second star, we forget the first one.
+ This is OK, because if we get to the second star in A*B*C
+ (where A etc are arbitrary strings), we have already seen AXB.
+ We're therefore setting up a match of *C against the remainder
+ of the string, which will match if that remainder looks like
+ YC, so the whole string looks like AXBYC.
+ */
+ private static boolean wildmatch(final String str, final String pat,
+ int stri, final int strend, int pati, final int patend) {
+
+ // System.out.println("matching "+pat.substring(pati,patend)+
+ // " against "+str.substring(stri, strend));
+ int starstri; // index for backtrack if "*" attempt fails
+ int starpati; // index for backtrack if "*" attempt fails, +1
+
+ starstri = starpati = -1;
+
+ /* On each pass through this loop, we either advance pati,
+ or we backtrack pati and advance starstri. Since starstri
+ is only ever assigned from pati, the loop must terminate. */
+ while (true) {
+ if (pati < patend) {
+ final char patc = pat.charAt(pati);
+ switch (patc) {
+ case '?':
+ if (stri == strend)
+ break;
+ stri++;
+ pati++;
+ continue;
+ case '*':
+ pati++;
+ starpati = pati;
+ starstri = stri;
+ continue;
+ default:
+ if (stri < strend && str.charAt(stri) == patc) {
+ stri++;
+ pati++;
+ continue;
+ }
+ break;
+ }
+ } else if (stri == strend)
+ return true;
+
+ // Mismatched, can we backtrack to a "*"?
+ if (starpati < 0 || starstri == strend)
+ return false;
+
+ // Retry the match one position later in str
+ pati = starpati;
+ starstri++;
+ stri = starstri;
+ }
+ }
+
+ /** Match a string against a shell-style pattern. The only pattern
+ characters recognized are <code>?</code>, standing for any one
+ character, and <code>*</code>, standing for any string of
+ characters, including the empty string.
+
+ @param str the string to match.
+ @param pat the pattern to match the string against.
+
+ @return true if and only if the string matches the pattern.
+ */
+ 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 <elt-1>//<elt2>//...//<elt-n> matches <pat-1>//<pat-2>//...//<pat-q>
+ * 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.
*
@@ -167,6 +444,34 @@ public class Util {
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<ObjectInstance>
+ filterMatchingInstances(ObjectName pattern,
+ Set<ObjectInstance> 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<ObjectInstance> 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.
**/
@@ -214,6 +519,160 @@ public class Util {
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=<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=<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 {@value #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.toCharArray()) {
+ 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 usally 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);
+ toprint.append("\nCaused By: ").append(String.valueOf(t));
+ while ((t=t.getCause())!=null)
+ toprint.append("\nCaused By: ").append(String.valueOf(t));
+ JmxProperties.MISC_LOGGER.fine(toprint.toString());
+ }
}
public static <T> Set<T> cloneSet(Set<T> set) {
@@ -232,10 +691,19 @@ public class Util {
@SuppressWarnings("unchecked")
SortedSet<T> sset = (SortedSet<T>) set;
set = new TreeSet<T>(sset.comparator());
- } else if (set != null) {
- set = new HashSet<T>(set.size());
} else
set = new HashSet<T>();
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);
+ }
}
--- a/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Wed Sep 17 13:45:37 2008 -0700
@@ -57,6 +57,7 @@ import javax.security.auth.Subject;
public class ServerNotifForwarder {
+
public ServerNotifForwarder(MBeanServer mbeanServer,
Map env,
NotificationBuffer notifBuffer,
@@ -85,7 +86,8 @@ public class ServerNotifForwarder {
// Explicitly check MBeanPermission for addNotificationListener
//
- checkMBeanPermission(name, "addNotificationListener");
+ checkMBeanPermission(getMBeanServerName(),
+ mbeanServer, name, "addNotificationListener");
if (notificationAccessController != null) {
notificationAccessController.addNotificationListener(
connectionId, name, getSubject());
@@ -155,7 +157,8 @@ public class ServerNotifForwarder {
// Explicitly check MBeanPermission for removeNotificationListener
//
- checkMBeanPermission(name, "removeNotificationListener");
+ checkMBeanPermission(getMBeanServerName(),
+ mbeanServer, name, "removeNotificationListener");
if (notificationAccessController != null) {
notificationAccessController.removeNotificationListener(
connectionId, name, getSubject());
@@ -330,13 +333,7 @@ public class ServerNotifForwarder {
* Explicitly check the MBeanPermission for
* the current access control context.
*/
- private void checkMBeanPermission(final ObjectName name,
- final String actions)
- throws InstanceNotFoundException, SecurityException {
- checkMBeanPermission(mbeanServer, name, actions);
- }
-
- public static void checkMBeanPermission(
+ public static void checkMBeanPermission(String serverName,
final MBeanServer mbs, final ObjectName name, final String actions)
throws InstanceNotFoundException, SecurityException {
SecurityManager sm = System.getSecurityManager();
@@ -355,7 +352,9 @@ public class ServerNotifForwarder {
throw (InstanceNotFoundException) extractException(e);
}
String classname = oi.getClassName();
- MBeanPermission perm = new MBeanPermission(classname,
+ MBeanPermission perm = new MBeanPermission(
+ serverName,
+ classname,
null,
name,
actions);
@@ -370,8 +369,8 @@ public class ServerNotifForwarder {
TargetedNotification tn) {
try {
if (checkNotificationEmission) {
- checkMBeanPermission(
- name, "addNotificationListener");
+ checkMBeanPermission(getMBeanServerName(),
+ mbeanServer, name, "addNotificationListener");
}
if (notificationAccessController != null) {
notificationAccessController.fetchNotification(
@@ -433,11 +432,27 @@ public class ServerNotifForwarder {
}
}
+ private String getMBeanServerName() {
+ if (mbeanServerName != null) return mbeanServerName;
+ else return (mbeanServerName = getMBeanServerName(mbeanServer));
+ }
+
+ private static String getMBeanServerName(final MBeanServer server) {
+ final PrivilegedAction<String> action = new PrivilegedAction<String>() {
+ public String run() {
+ return Util.getMBeanServerSecurityName(server);
+ }
+ };
+ return AccessController.doPrivileged(action);
+ }
+
+
//------------------
// PRIVATE VARIABLES
//------------------
private MBeanServer mbeanServer;
+ private volatile String mbeanServerName;
private final String connectionId;
--- a/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java Wed Sep 17 13:45:37 2008 -0700
@@ -25,6 +25,7 @@
package com.sun.jmx.remote.util;
+import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.event.EventClientFactory;
import java.lang.reflect.InvocationHandler;
@@ -45,6 +46,7 @@ import javax.management.ObjectName;
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
@@ -63,12 +65,10 @@ public class EventClientConnection imple
/**
* A logger for this class.
**/
- private static final Logger LOG =
- Logger.getLogger(EventClientConnection.class.getName());
-
- private static final String NAMESPACE_SEPARATOR = "//";
+ private static final Logger LOG = JmxProperties.NOTIFICATION_LOGGER;
+
private static final int NAMESPACE_SEPARATOR_LENGTH =
- NAMESPACE_SEPARATOR.length();
+ JMXNamespaces.NAMESPACE_SEPARATOR.length();
/**
* Creates a new {@code EventClientConnection}.
@@ -212,9 +212,9 @@ public class EventClientConnection imple
}
final ObjectName mbean = (ObjectName) args[0];
- final EventClient client = getEventClient();
-
- // Fails if client is null AND the MBean we try to listen to is
+ 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.
//
@@ -222,15 +222,15 @@ public class EventClientConnection imple
// 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 client indicates that the remote VM is of
+ // 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 client AND an MBean contained in a namespace is
+ // So having a null evtClient AND an MBean contained in a namespace is
// clearly an error case.
//
- if (client == null) {
+ if (evtClient == null) {
final String domain = mbean.getDomain();
- final int index = domain.indexOf(NAMESPACE_SEPARATOR);
+ final int index = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
if (index > -1 && index <
(domain.length()-NAMESPACE_SEPARATOR_LENGTH)) {
throw new UnsupportedOperationException(method.getName()+
@@ -256,9 +256,9 @@ public class EventClientConnection imple
final NotificationFilter filter = (NotificationFilter) args[2];
final Object handback = args[3];
- if (client != null) {
+ if (evtClient != null) {
// general case
- client.addNotificationListener(mbean,listener,filter,handback);
+ evtClient.addNotificationListener(mbean,listener,filter,handback);
} else {
// deprecated case. Only works for mbean in local namespace.
connection.addNotificationListener(mbean,listener,filter,
@@ -274,9 +274,9 @@ public class EventClientConnection imple
switch (nargs) {
case 2:
- if (client != null) {
+ if (evtClient != null) {
// general case
- client.removeNotificationListener(mbean,listener);
+ evtClient.removeNotificationListener(mbean,listener);
} else {
// deprecated case. Only works for mbean in local namespace.
connection.removeNotificationListener(mbean, listener);
@@ -286,8 +286,8 @@ public class EventClientConnection imple
case 4:
NotificationFilter filter = (NotificationFilter) args[2];
Object handback = args[3];
- if (client != null) {
- client.removeNotificationListener(mbean,
+ if (evtClient != null) {
+ evtClient.removeNotificationListener(mbean,
listener,
filter,
handback);
--- a/src/share/classes/com/sun/tools/extcheck/ExtCheck.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/extcheck/ExtCheck.java Wed Sep 17 13:45:37 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1998-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
@@ -256,13 +256,13 @@ public class ExtCheck {
private boolean isNotOlderThan(String already,String target)
throws NumberFormatException
{
- if (already == null || already.length() < 1) {
+ if (already == null || already.length() < 1) {
throw new NumberFormatException("Empty version string");
}
- // Until it matches scan and compare numbers
- StringTokenizer dtok = new StringTokenizer(target, ".", true);
- StringTokenizer stok = new StringTokenizer(already, ".", true);
+ // Until it matches scan and compare numbers
+ StringTokenizer dtok = new StringTokenizer(target, ".", true);
+ StringTokenizer stok = new StringTokenizer(already, ".", true);
while (dtok.hasMoreTokens() || stok.hasMoreTokens()) {
int dver;
int sver;
@@ -276,19 +276,19 @@ public class ExtCheck {
} else
sver = 0;
- if (sver < dver)
- return false; // Known to be incompatible
- if (sver > dver)
- return true; // Known to be compatible
-
- // Check for and absorb separators
- if (dtok.hasMoreTokens())
- dtok.nextToken();
- if (stok.hasMoreTokens())
- stok.nextToken();
- // Compare next component
- }
- // All components numerically equal
+ if (sver < dver)
+ return false; // Known to be incompatible
+ if (sver > dver)
+ return true; // Known to be compatible
+
+ // Check for and absorb separators
+ if (dtok.hasMoreTokens())
+ dtok.nextToken();
+ if (stok.hasMoreTokens())
+ stok.nextToken();
+ // Compare next component
+ }
+ // All components numerically equal
return true;
}
@@ -307,11 +307,10 @@ public class ExtCheck {
}
/**
- * Print out the error message and exit from the program
- */
- static void error(String message){
- System.err.println(message);
- System.exit(-1);
+ * Throws a RuntimeException with a message describing the error.
+ */
+ static void error(String message) throws RuntimeException {
+ throw new RuntimeException(message);
}
@@ -356,19 +355,19 @@ public class ExtCheck {
}
private JarFile findJarFile(URL url) throws IOException {
- // Optimize case where url refers to a local jar file
- if ("file".equals(url.getProtocol())) {
- String path = url.getFile().replace('/', File.separatorChar);
- File file = new File(path);
- if (!file.exists()) {
- throw new FileNotFoundException(path);
- }
- return new JarFile(path);
- }
- URLConnection uc = getBaseURL().openConnection();
- //uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
- return ((JarURLConnection)uc).getJarFile();
- }
+ // Optimize case where url refers to a local jar file
+ if ("file".equals(url.getProtocol())) {
+ String path = url.getFile().replace('/', File.separatorChar);
+ File file = new File(path);
+ if (!file.exists()) {
+ throw new FileNotFoundException(path);
+ }
+ return new JarFile(path);
+ }
+ URLConnection uc = getBaseURL().openConnection();
+ //uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
+ return ((JarURLConnection)uc).getJarFile();
+ }
/*
--- a/src/share/classes/com/sun/tools/extcheck/Main.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/extcheck/Main.java Wed Sep 17 13:45:37 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1998-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
@@ -32,7 +32,10 @@ import java.io.*;
*/
public final class Main {
-
+ public static final String INSUFFICIENT = "Insufficient number of arguments";
+ public static final String MISSING = "Missing <jar file> argument";
+ public static final String DOES_NOT_EXIST = "Jarfile does not exist: ";
+ public static final String EXTRA = "Extra command line argument: ";
/**
* Terminates with one of the following codes
@@ -40,26 +43,36 @@ public final class Main {
* 0 No newer jar file was found
* -1 An internal error occurred
*/
- public static void main(String args[]){
+ public static void main(String args[]) {
+ try {
+ realMain(args);
+ } catch (Exception ex) {
+ System.err.println(ex.getMessage());
+ System.exit(-1);
+ }
+ }
- if (args.length < 1){
- System.err.println("Usage: extcheck [-verbose] <jar file>");
- System.exit(-1);
+ public static void realMain(String[] args) throws Exception {
+ if (args.length < 1) {
+ usage(INSUFFICIENT);
}
int argIndex = 0;
boolean verboseFlag = false;
- if (args[argIndex].equals("-verbose")){
+ if (args[argIndex].equals("-verbose")) {
verboseFlag = true;
argIndex++;
+ if (argIndex >= args.length) {
+ usage(MISSING);
+ }
}
String jarName = args[argIndex];
argIndex++;
File jarFile = new File(jarName);
if (!jarFile.exists()){
- ExtCheck.error("Jarfile " + jarName + " does not exist");
+ usage(DOES_NOT_EXIST + jarName);
}
if (argIndex < args.length) {
- ExtCheck.error("Extra command line argument :"+args[argIndex]);
+ usage(EXTRA + args[argIndex]);
}
ExtCheck jt = ExtCheck.create(jarFile,verboseFlag);
boolean result = jt.checkInstalledAgainstTarget();
@@ -68,7 +81,10 @@ public final class Main {
} else {
System.exit(1);
}
-
}
+ private static void usage(String msg) throws Exception {
+ throw new Exception(msg + "\nUsage: extcheck [-verbose] <jar file>");
+ }
}
+
--- a/src/share/classes/com/sun/tools/hat/internal/parser/HprofReader.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/com/sun/tools/hat/internal/parser/HprofReader.java Wed Sep 17 13:45:37 2008 -0700
@@ -120,7 +120,7 @@ public class HprofReader extends Reader
private int version; // The version of .hprof being read
private int debugLevel;
- private int currPos; // Current position in the file
+ private long currPos; // Current position in the file
private int dumpsToSkip;
private boolean callStack; // If true, read the call stack of objects
@@ -196,7 +196,9 @@ public class HprofReader extends Reader
break;
}
in.readInt(); // Timestamp of this record
- int length = in.readInt();
+ // Length of record: readInt() will return negative value for record
+ // length >2GB. so store 32bit value in long to keep it unsigned.
+ long length = in.readInt() & 0xffffffffL;
if (debugLevel > 0) {
System.out.println("Read record type " + type
+ ", length " + length
@@ -211,7 +213,7 @@ public class HprofReader extends Reader
switch (type) {
case HPROF_UTF8: {
long id = readID();
- byte[] chars = new byte[length - identifierSize];
+ byte[] chars = new byte[(int)length - identifierSize];
in.readFully(chars);
names.put(new Long(id), new String(chars));
break;
@@ -351,8 +353,8 @@ public class HprofReader extends Reader
return snapshot;
}
- private void skipBytes(int length) throws IOException {
- in.skipBytes(length);
+ private void skipBytes(long length) throws IOException {
+ in.skipBytes((int)length);
}
private int readVersionHeader() throws IOException {
@@ -381,7 +383,7 @@ public class HprofReader extends Reader
throw new IOException("Version string not recognized at byte " + (pos+3));
}
- private void readHeapDump(int bytesLeft, int posAtEnd) throws IOException {
+ private void readHeapDump(long bytesLeft, long posAtEnd) throws IOException {
while (bytesLeft > 0) {
int type = in.readUnsignedByte();
if (debugLevel > 0) {
--- a/src/share/classes/java/lang/Thread.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/lang/Thread.java Wed Sep 17 13:45:37 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1994-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1994-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
@@ -30,7 +30,6 @@ import java.security.PrivilegedAction;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.HashMap;
-import java.util.Collections;
import java.util.concurrent.locks.LockSupport;
import sun.misc.SoftCache;
import sun.nio.ch.Interruptible;
@@ -120,6 +119,10 @@ import sun.security.util.SecurityConstan
* Every thread has a name for identification purposes. More than
* one thread may have the same name. If a name is not specified when
* a thread is created, a new name is generated for it.
+ * <p>
+ * Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
*
* @author unascribed
* @see Runnable
@@ -348,6 +351,10 @@ class Thread implements Runnable {
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
+ if (name == null) {
+ throw new NullPointerException("name cannot be null");
+ }
+
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
@@ -378,7 +385,6 @@ class Thread implements Runnable {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
-
g.addUnstarted();
@@ -403,160 +409,175 @@ class Thread implements Runnable {
tid = nextThreadID();
}
- /**
- * Allocates a new <code>Thread</code> object. This constructor has
- * the same effect as <code>Thread(null, null,</code>
- * <i>gname</i><code>)</code>, where <b><i>gname</i></b> is
- * a newly generated name. Automatically generated names are of the
- * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer.
- *
- * @see #Thread(ThreadGroup, Runnable, String)
+ /**
+ * Allocates a new {@code Thread} object. This constructor has the same
+ * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
+ * {@code (null, null, gname)}, where {@code gname} is a newly generated
+ * name. Automatically generated names are of the form
+ * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
*/
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
/**
- * Allocates a new <code>Thread</code> object. This constructor has
- * the same effect as <code>Thread(null, target,</code>
- * <i>gname</i><code>)</code>, where <i>gname</i> is
- * a newly generated name. Automatically generated names are of the
- * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer.
- *
- * @param target the object whose <code>run</code> method is called.
- * @see #Thread(ThreadGroup, Runnable, String)
+ * Allocates a new {@code Thread} object. This constructor has the same
+ * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
+ * {@code (null, target, gname)}, where {@code gname} is a newly generated
+ * name. Automatically generated names are of the form
+ * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
+ *
+ * @param target
+ * the object whose {@code run} method is invoked when this thread
+ * is started. If {@code null}, this classes {@code run} method does
+ * nothing.
*/
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
/**
- * Allocates a new <code>Thread</code> object. This constructor has
- * the same effect as <code>Thread(group, target,</code>
- * <i>gname</i><code>)</code>, where <i>gname</i> is
- * a newly generated name. Automatically generated names are of the
- * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer.
- *
- * @param group the thread group.
- * @param target the object whose <code>run</code> method is called.
- * @exception SecurityException if the current thread cannot create a
- * thread in the specified thread group.
- * @see #Thread(ThreadGroup, Runnable, String)
+ * Allocates a new {@code Thread} object. This constructor has the same
+ * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
+ * {@code (group, target, gname)} ,where {@code gname} is a newly generated
+ * name. Automatically generated names are of the form
+ * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
+ *
+ * @param group
+ * the thread group. If {@code null} and there is a security
+ * manager, the group is determined by {@linkplain
+ * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
+ * If there is not a security manager or {@code
+ * SecurityManager.getThreadGroup()} returns {@code null}, the group
+ * is set to the current thread's thread group.
+ *
+ * @param target
+ * the object whose {@code run} method is invoked when this thread
+ * is started. If {@code null}, this thread's run method is invoked.
+ *
+ * @throws SecurityException
+ * if the current thread cannot create a thread in the specified
+ * thread group
*/
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
/**
- * Allocates a new <code>Thread</code> object. This constructor has
- * the same effect as <code>Thread(null, null, name)</code>.
- *
- * @param name the name of the new thread.
- * @see #Thread(ThreadGroup, Runnable, String)
+ * Allocates a new {@code Thread} object. This constructor has the same
+ * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
+ * {@code (null, null, name)}.
+ *
+ * @param name
+ * the name of the new thread
*/
public Thread(String name) {
init(null, null, name, 0);
}
/**
- * Allocates a new <code>Thread</code> object. This constructor has
- * the same effect as <code>Thread(group, null, name)</code>
- *
- * @param group the thread group.
- * @param name the name of the new thread.
- * @exception SecurityException if the current thread cannot create a
- * thread in the specified thread group.
- * @see #Thread(ThreadGroup, Runnable, String)
+ * Allocates a new {@code Thread} object. This constructor has the same
+ * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
+ * {@code (group, null, name)}.
+ *
+ * @param group
+ * the thread group. If {@code null} and there is a security
+ * manager, the group is determined by {@linkplain
+ * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
+ * If there is not a security manager or {@code
+ * SecurityManager.getThreadGroup()} returns {@code null}, the group
+ * is set to the current thread's thread group.
+ *
+ * @param name
+ * the name of the new thread
+ *
+ * @throws SecurityException
+ * if the current thread cannot create a thread in the specified
+ * thread group
*/
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
/**
- * Allocates a new <code>Thread</code> object. This constructor has
- * the same effect as <code>Thread(null, target, name)</code>.
- *
- * @param target the object whose <code>run</code> method is called.
- * @param name the name of the new thread.
- * @see #Thread(ThreadGroup, Runnable, String)
+ * Allocates a new {@code Thread} object. This constructor has the same
+ * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
+ * {@code (null, target, name)}.
+ *
+ * @param target
+ * the object whose {@code run} method is invoked when this thread
+ * is started. If {@code null}, this thread's run method is invoked.
+ *
+ * @param name
+ * the name of the new thread
*/
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
/**
- * Allocates a new <code>Thread</code> object so that it has
- * <code>target</code> as its run object, has the specified
- * <code>name</code> as its name, and belongs to the thread group
- * referred to by <code>group</code>.
- * <p>
- * If <code>group</code> is <code>null</code> and there is a
- * security manager, the group is determined by the security manager's
- * <code>getThreadGroup</code> method. If <code>group</code> is
- * <code>null</code> and there is not a security manager, or the
- * security manager's <code>getThreadGroup</code> method returns
- * <code>null</code>, the group is set to be the same ThreadGroup
- * as the thread that is creating the new thread.
- *
- * <p>If there is a security manager, its <code>checkAccess</code>
- * method is called with the ThreadGroup as its argument.
- * <p>In addition, its <code>checkPermission</code>
- * method is called with the
- * <code>RuntimePermission("enableContextClassLoaderOverride")</code>
+ * Allocates a new {@code Thread} object so that it has {@code target}
+ * as its run object, has the specified {@code name} as its name,
+ * and belongs to the thread group referred to by {@code group}.
+ *
+ * <p>If there is a security manager, its
+ * {@link SecurityManager#checkAccess(ThreadGroup) checkAccess}
+ * method is invoked with the ThreadGroup as its argument.
+ *
+ * <p>In addition, its {@code checkPermission} method is invoked with
+ * the {@code RuntimePermission("enableContextClassLoaderOverride")}
* permission when invoked directly or indirectly by the constructor
- * of a subclass which overrides the <code>getContextClassLoader</code>
- * or <code>setContextClassLoader</code> methods.
- * This may result in a SecurityException.
-
- * <p>
- * If the <code>target</code> argument is not <code>null</code>, the
- * <code>run</code> method of the <code>target</code> is called when
- * this thread is started. If the target argument is
- * <code>null</code>, this thread's <code>run</code> method is called
- * when this thread is started.
- * <p>
- * The priority of the newly created thread is set equal to the
+ * of a subclass which overrides the {@code getContextClassLoader}
+ * or {@code setContextClassLoader} methods.
+ *
+ * <p>The priority of the newly created thread is set equal to the
* priority of the thread creating it, that is, the currently running
- * thread. The method <code>setPriority</code> may be used to
- * change the priority to a new value.
- * <p>
- * The newly created thread is initially marked as being a daemon
+ * thread. The method {@linkplain #setPriority setPriority} may be
+ * used to change the priority to a new value.
+ *
+ * <p>The newly created thread is initially marked as being a daemon
* thread if and only if the thread creating it is currently marked
- * as a daemon thread. The method <code>setDaemon </code> may be used
- * to change whether or not a thread is a daemon.
- *
- * @param group the thread group.
- * @param target the object whose <code>run</code> method is called.
- * @param name the name of the new thread.
- * @exception SecurityException if the current thread cannot create a
- * thread in the specified thread group or cannot
- * override the context class loader methods.
- * @see Runnable#run()
- * @see #run()
- * @see #setDaemon(boolean)
- * @see #setPriority(int)
- * @see ThreadGroup#checkAccess()
- * @see SecurityManager#checkAccess
+ * as a daemon thread. The method {@linkplain #setDaemon setDaemon}
+ * may be used to change whether or not a thread is a daemon.
+ *
+ * @param group
+ * the thread group. If {@code null} and there is a security
+ * manager, the group is determined by {@linkplain
+ * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
+ * If there is not a security manager or {@code
+ * SecurityManager.getThreadGroup()} returns {@code null}, the group
+ * is set to the current thread's thread group.
+ *
+ * @param target
+ * the object whose {@code run} method is invoked when this thread
+ * is started. If {@code null}, this thread's run method is invoked.
+ *
+ * @param name
+ * the name of the new thread
+ *
+ * @throws SecurityException
+ * if the current thread cannot create a thread in the specified
+ * thread group or cannot override the context class loader methods.
*/
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
/**
- * Allocates a new <code>Thread</code> object so that it has
- * <code>target</code> as its run object, has the specified
- * <code>name</code> as its name, belongs to the thread group referred to
- * by <code>group</code>, and has the specified <i>stack size</i>.
+ * Allocates a new {@code Thread} object so that it has {@code target}
+ * as its run object, has the specified {@code name} as its name,
+ * and belongs to the thread group referred to by {@code group}, and has
+ * the specified <i>stack size</i>.
*
* <p>This constructor is identical to {@link
* #Thread(ThreadGroup,Runnable,String)} with the exception of the fact
* that it allows the thread stack size to be specified. The stack size
* is the approximate number of bytes of address space that the virtual
* machine is to allocate for this thread's stack. <b>The effect of the
- * <tt>stackSize</tt> parameter, if any, is highly platform dependent.</b>
+ * {@code stackSize} parameter, if any, is highly platform dependent.</b>
*
* <p>On some platforms, specifying a higher value for the
- * <tt>stackSize</tt> parameter may allow a thread to achieve greater
+ * {@code stackSize} parameter may allow a thread to achieve greater
* recursion depth before throwing a {@link StackOverflowError}.
* Similarly, specifying a lower value may allow a greater number of
* threads to exist concurrently without throwing an {@link
@@ -564,9 +585,9 @@ class Thread implements Runnable {
* the relationship between the value of the <tt>stackSize</tt> parameter
* and the maximum recursion depth and concurrency level are
* platform-dependent. <b>On some platforms, the value of the
- * <tt>stackSize</tt> parameter may have no effect whatsoever.</b>
- *
- * <p>The virtual machine is free to treat the <tt>stackSize</tt>
+ * {@code stackSize} parameter may have no effect whatsoever.</b>
+ *
+ * <p>The virtual machine is free to treat the {@code stackSize}
* parameter as a suggestion. If the specified value is unreasonably low
* for the platform, the virtual machine may instead use some
* platform-specific minimum value; if the specified value is unreasonably
@@ -574,9 +595,9 @@ class Thread implements Runnable {
* maximum. Likewise, the virtual machine is free to round the specified
* value up or down as it sees fit (or to ignore it completely).
*
- * <p>Specifying a value of zero for the <tt>stackSize</tt> parameter will
+ * <p>Specifying a value of zero for the {@code stackSize} parameter will
* cause this constructor to behave exactly like the
- * <tt>Thread(ThreadGroup, Runnable, String)</tt> constructor.
+ * {@code Thread(ThreadGroup, Runnable, String)} constructor.
*
* <p><i>Due to the platform-dependent nature of the behavior of this
* constructor, extreme care should be exercised in its use.
@@ -588,15 +609,32 @@ class Thread implements Runnable {
*
* <p>Implementation note: Java platform implementers are encouraged to
* document their implementation's behavior with respect to the
- * <tt>stackSize parameter</tt>.
- *
- * @param group the thread group.
- * @param target the object whose <code>run</code> method is called.
- * @param name the name of the new thread.
- * @param stackSize the desired stack size for the new thread, or
- * zero to indicate that this parameter is to be ignored.
- * @exception SecurityException if the current thread cannot create a
- * thread in the specified thread group.
+ * {@code stackSize} parameter.
+ *
+ *
+ * @param group
+ * the thread group. If {@code null} and there is a security
+ * manager, the group is determined by {@linkplain
+ * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
+ * If there is not a security manager or {@code
+ * SecurityManager.getThreadGroup()} returns {@code null}, the group
+ * is set to the current thread's thread group.
+ *
+ * @param target
+ * the object whose {@code run} method is invoked when this thread
+ * is started. If {@code null}, this thread's run method is invoked.
+ *
+ * @param name
+ * the name of the new thread
+ *
+ * @param stackSize
+ * the desired stack size for the new thread, or zero to indicate
+ * that this parameter is to be ignored.
+ *
+ * @throws SecurityException
+ * if the current thread cannot create a thread in the specified
+ * thread group
+ *
* @since 1.4
*/
public Thread(ThreadGroup group, Runnable target, String name,
@@ -669,6 +707,7 @@ class Thread implements Runnable {
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
+ @Override
public void run() {
if (target != null) {
target.run();
@@ -1386,28 +1425,25 @@ class Thread implements Runnable {
* Returns the context ClassLoader for this Thread. The context
* ClassLoader is provided by the creator of the thread for use
* by code running in this thread when loading classes and resources.
- * If not set, the default is the ClassLoader context of the parent
- * Thread. The context ClassLoader of the primordial thread is
- * typically set to the class loader used to load the application.
- *
- * <p>First, if there is a security manager, and the caller's class
- * loader is not null and the caller's class loader is not the same as or
- * an ancestor of the context class loader for the thread whose
- * context class loader is being requested, then the security manager's
- * <code>checkPermission</code>
- * method is called with a
- * <code>RuntimePermission("getClassLoader")</code> permission
- * to see if it's ok to get the context ClassLoader..
- *
- * @return the context ClassLoader for this Thread
- *
- * @throws SecurityException
- * if a security manager exists and its
- * <code>checkPermission</code> method doesn't allow
- * getting the context ClassLoader.
- * @see #setContextClassLoader
- * @see SecurityManager#checkPermission
- * @see RuntimePermission
+ * If not {@linkplain #setContextClassLoader set}, the default is the
+ * ClassLoader context of the parent Thread. The context ClassLoader of the
+ * primordial thread is typically set to the class loader used to load the
+ * application.
+ *
+ * <p>If a security manager is present, and the invoker's class loader is not
+ * {@code null} and is not the same as or an ancestor of the context class
+ * loader, then this method invokes the security manager's {@link
+ * SecurityManager#checkPermission(java.security.Permission) checkPermission}
+ * method with a {@link RuntimePermission RuntimePermission}{@code
+ * ("getClassLoader")} permission to verify that retrieval of the context
+ * class loader is permitted.
+ *
+ * @return the context ClassLoader for this Thread, or {@code null}
+ * indicating the system class loader (or, failing that, the
+ * bootstrap class loader)
+ *
+ * @throws SecurityException
+ * if the current thread cannot get the context ClassLoader
*
* @since 1.2
*/
@@ -1428,21 +1464,22 @@ class Thread implements Runnable {
/**
* Sets the context ClassLoader for this Thread. The context
* ClassLoader can be set when a thread is created, and allows
- * the creator of the thread to provide the appropriate class loader
- * to code running in the thread when loading classes and resources.
- *
- * <p>First, if there is a security manager, its <code>checkPermission</code>
- * method is called with a
- * <code>RuntimePermission("setContextClassLoader")</code> permission
- * to see if it's ok to set the context ClassLoader..
- *
- * @param cl the context ClassLoader for this Thread
- *
- * @exception SecurityException if the current thread cannot set the
- * context ClassLoader.
- * @see #getContextClassLoader
- * @see SecurityManager#checkPermission
- * @see RuntimePermission
+ * the creator of the thread to provide the appropriate class loader,
+ * through {@code getContextClassLoader}, to code running in the thread
+ * when loading classes and resources.
+ *
+ * <p>If a security manager is present, its {@link
+ * SecurityManager#checkPermission(java.security.Permission) checkPermission}
+ * method is invoked with a {@link RuntimePermission RuntimePermission}{@code
+ * ("setContextClassLoader")} permission to see if setting the context
+ * ClassLoader is permitted.
+ *
+ * @param cl
+ * the context ClassLoader for this Thread, or null indicating the
+ * system class loader (or, failing that, the bootstrap class loader)
+ *
+ * @throws SecurityException
+ * if the current thread cannot set the context ClassLoader
*
* @since 1.2
*/
--- a/src/share/classes/java/lang/management/PlatformComponent.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/lang/management/PlatformComponent.java Wed Sep 17 13:45:37 2008 -0700
@@ -32,6 +32,7 @@ import java.util.Set;
import java.util.Set;
import java.util.logging.LoggingMXBean;
import java.util.logging.LogManager;
+import java.nio.BufferPoolMXBean;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
@@ -188,6 +189,23 @@ enum PlatformComponent {
}
}),
+
+ /**
+ * Buffer pools.
+ */
+ BUFFER_POOL(
+ "java.nio.BufferPoolMXBean",
+ "java.nio", "BufferPool", keyProperties("name"),
+ new MXBeanFetcher<BufferPoolMXBean>() {
+ public List<BufferPoolMXBean> getMXBeans() {
+ List<BufferPoolMXBean> pools = new ArrayList<BufferPoolMXBean>(2);
+ pools.add( sun.misc.SharedSecrets.getJavaNioAccess().getDirectBufferPoolMXBean() );
+ pools.add( sun.nio.ch.FileChannelImpl.getMappedBufferPoolMXBean() );
+ return pools;
+ }
+ }),
+
+
// Sun Platform Extension
/**
--- a/src/share/classes/java/net/NetworkInterface.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/net/NetworkInterface.java Wed Sep 17 13:45:37 2008 -0700
@@ -25,7 +25,6 @@
package java.net;
-import java.net.SocketException;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import sun.security.action.*;
--- a/src/share/classes/java/nio/Bits.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/nio/Bits.java Wed Sep 17 13:45:37 2008 -0700
@@ -29,6 +29,8 @@ import java.security.PrivilegedAction;
import java.security.PrivilegedAction;
import sun.misc.Unsafe;
import sun.misc.VM;
+import javax.management.ObjectName;
+import javax.management.MalformedObjectNameException;
/**
* Access to bits, native and otherwise.
@@ -625,13 +627,15 @@ class Bits {
// direct buffer memory. This value may be changed during VM
// initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
private static volatile long maxMemory = VM.maxDirectMemory();
- private static volatile long reservedMemory = 0;
+ private static volatile long reservedMemory;
+ private static volatile long usedMemory;
+ private static volatile long count;
private static boolean memoryLimitSet = false;
// These methods should be called whenever direct memory is allocated or
// freed. They allow the user to control the amount of direct memory
// which a process may access. All sizes are specified in bytes.
- static void reserveMemory(long size) {
+ static void reserveMemory(long size, int cap) {
synchronized (Bits.class) {
if (!memoryLimitSet && VM.isBooted()) {
@@ -640,6 +644,8 @@ class Bits {
}
if (size <= maxMemory - reservedMemory) {
reservedMemory += size;
+ usedMemory += cap;
+ count++;
return;
}
}
@@ -655,17 +661,71 @@ class Bits {
if (reservedMemory + size > maxMemory)
throw new OutOfMemoryError("Direct buffer memory");
reservedMemory += size;
+ usedMemory += cap;
+ count++;
}
}
- static synchronized void unreserveMemory(long size) {
+ static synchronized void unreserveMemory(long size, int cap) {
if (reservedMemory > 0) {
reservedMemory -= size;
+ usedMemory -= cap;
+ count--;
assert (reservedMemory > -1);
}
}
+ // -- Management interface for monitoring of direct buffer usage --
+
+ static {
+ // setup access to this package in SharedSecrets
+ sun.misc.SharedSecrets.setJavaNioAccess(
+ new sun.misc.JavaNioAccess() {
+ @Override
+ public BufferPoolMXBean getDirectBufferPoolMXBean() {
+ return LazyInitialization.directBufferPoolMXBean;
+ }
+ }
+ );
+ }
+
+ // Lazy initialization of management interface
+ private static class LazyInitialization {
+ static final BufferPoolMXBean directBufferPoolMXBean = directBufferPoolMXBean();
+
+ private static BufferPoolMXBean directBufferPoolMXBean() {
+ final String pool = "direct";
+ final ObjectName obj;
+ try {
+ obj = new ObjectName("java.nio:type=BufferPool,name=" + pool);
+ } catch (MalformedObjectNameException x) {
+ throw new AssertionError(x);
+ }
+ return new BufferPoolMXBean() {
+ @Override
+ public ObjectName getObjectName() {
+ return obj;
+ }
+ @Override
+ public String getName() {
+ return pool;
+ }
+ @Override
+ public long getCount() {
+ return Bits.count;
+ }
+ @Override
+ public long getTotalCapacity() {
+ return Bits.usedMemory;
+ }
+ @Override
+ public long getMemoryUsed() {
+ return Bits.reservedMemory;
+ }
+ };
+ }
+ }
// -- Bulk get/put acceleration --
@@ -675,14 +735,68 @@ class Bits {
static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;
static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
+ // This number limits the number of bytes to copy per call to Unsafe's
+ // copyMemory method. A limit is imposed to allow for safepoint polling
+ // during a large copy
+ static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
+
// These methods do no bounds checking. Verification that the copy will not
// result in memory corruption should be done prior to invocation.
// All positions and lengths are specified in bytes.
- static native void copyFromByteArray(Object src, long srcPos, long dstAddr,
- long length);
- static native void copyToByteArray(long srcAddr, Object dst, long dstPos,
- long length);
+ /**
+ * Copy from given source array to destination address.
+ *
+ * @param src
+ * source array
+ * @param srcBaseOffset
+ * offset of first element of storage in source array
+ * @param srcPos
+ * offset within source array of the first element to read
+ * @param dstAddr
+ * destination address
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyFromArray(Object src, long srcBaseOffset, long srcPos,
+ long dstAddr, long length)
+ {
+ long offset = srcBaseOffset + srcPos;
+ while (length > 0) {
+ long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
+ unsafe.copyMemory(src, offset, null, dstAddr, size);
+ length -= size;
+ offset += size;
+ dstAddr += size;
+ }
+ }
+
+ /**
+ * Copy from source address into given destination array.
+ *
+ * @param srcAddr
+ * source address
+ * @param dst
+ * destination array
+ * @param dstBaseOffset
+ * offset of first element of storage in destination array
+ * @param dstPos
+ * offset within destination array of the first element to write
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos,
+ long length)
+ {
+ long offset = dstBaseOffset + dstPos;
+ while (length > 0) {
+ long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
+ unsafe.copyMemory(null, srcAddr, dst, offset, size);
+ length -= size;
+ srcAddr += size;
+ offset += size;
+ }
+ }
static void copyFromCharArray(Object src, long srcPos, long dstAddr,
long length)
--- a/src/share/classes/java/nio/Direct-X-Buffer.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/nio/Direct-X-Buffer.java Wed Sep 17 13:45:37 2008 -0700
@@ -47,6 +47,9 @@ class Direct$Type$Buffer$RW$$BO$
// 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();
@@ -71,11 +74,13 @@ class Direct$Type$Buffer$RW$$BO$
private static Unsafe unsafe = Unsafe.getUnsafe();
private long address;
+ private long size;
private int capacity;
- private Deallocator(long address, int capacity) {
+ private Deallocator(long address, long size, int capacity) {
assert (address != 0);
this.address = address;
+ this.size = size;
this.capacity = capacity;
}
@@ -86,7 +91,7 @@ class Direct$Type$Buffer$RW$$BO$
}
unsafe.freeMemory(address);
address = 0;
- Bits.unreserveMemory(capacity);
+ Bits.unreserveMemory(size, capacity);
}
}
@@ -110,23 +115,25 @@ class Direct$Type$Buffer$RW$$BO$
Direct$Type$Buffer$RW$(int cap) { // package-private
#if[rw]
super(-1, 0, cap, cap, false);
- Bits.reserveMemory(cap);
int ps = Bits.pageSize();
+ int size = cap + ps;
+ Bits.reserveMemory(size, cap);
+
long base = 0;
try {
- base = unsafe.allocateMemory(cap + ps);
+ base = unsafe.allocateMemory(size);
} catch (OutOfMemoryError x) {
- Bits.unreserveMemory(cap);
+ Bits.unreserveMemory(size, cap);
throw x;
}
- unsafe.setMemory(base, cap + ps, (byte) 0);
+ 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, cap));
+ cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
#else[rw]
super(cap);
#end[rw]
@@ -238,14 +245,16 @@ class Direct$Type$Buffer$RW$$BO$
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
- Bits.copyToByteArray(ix(pos), dst,
- offset << $LG_BYTES_PER_VALUE$,
- length << $LG_BYTES_PER_VALUE$);
+#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);
@@ -328,12 +337,14 @@ class Direct$Type$Buffer$RW$$BO$
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
- Bits.copyFromByteArray(src, offset << $LG_BYTES_PER_VALUE$,
- ix(pos), length << $LG_BYTES_PER_VALUE$);
+#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);
--- a/src/share/classes/java/nio/channels/DatagramChannel.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/nio/channels/DatagramChannel.java Wed Sep 17 13:45:37 2008 -0700
@@ -26,28 +26,21 @@ package java.nio.channels;
package java.nio.channels;
import java.io.IOException;
+import java.net.ProtocolFamily;
import java.net.DatagramSocket;
+import java.net.SocketOption;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.spi.*;
-
/**
* A selectable channel for datagram-oriented sockets.
*
- *
- * <p> Datagram channels are not a complete abstraction of network datagram
- * sockets. Binding and the manipulation of socket options must be done
- * through an associated {@link java.net.DatagramSocket} object obtained by
- * invoking the {@link #socket() socket} method. It is not possible to create
- * a channel for an arbitrary, pre-existing datagram socket, nor is it possible
- * to specify the {@link java.net.DatagramSocketImpl} object to be used by a
- * datagram socket associated with a datagram channel.
- *
- * <p> A datagram channel is created by invoking the {@link #open open} method
- * of this class. A newly-created datagram channel is open but not connected.
- * A datagram channel need not be connected in order for the {@link #send send}
- * and {@link #receive receive} methods to be used. A datagram channel may be
+ * <p> A datagram channel is created by invoking one of the {@link #open open} methods
+ * of this class. It is not possible to create a channel for an arbitrary,
+ * pre-existing datagram socket. A newly-created datagram channel is open but not
+ * connected. A datagram channel need not be connected in order for the {@link #send
+ * send} and {@link #receive receive} methods to be used. A datagram channel may be
* connected, by invoking its {@link #connect connect} method, in order to
* avoid the overhead of the security checks are otherwise performed as part of
* every send and receive operation. A datagram channel must be connected in
@@ -59,10 +52,56 @@ import java.nio.channels.spi.*;
* disconnected or closed. Whether or not a datagram channel is connected may
* be determined by invoking its {@link #isConnected isConnected} method.
*
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. Datagram channels support the following options:
+ * <blockquote>
+ * <table border>
+ * <tr>
+ * <th>Option Name</th>
+ * <th>Description</th>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
+ * <td> The size of the socket send buffer </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
+ * <td> The size of the socket receive buffer </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
+ * <td> Re-use address </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_BROADCAST SO_BROADCAST} </td>
+ * <td> Allow transmission of broadcast datagrams </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#IP_TOS IP_TOS} </td>
+ * <td> The Type of Service (ToS) octet in the Internet Protocol (IP) header </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#IP_MULTICAST_IF IP_MULTICAST_IF} </td>
+ * <td> The network interface for Internet Protocol (IP) multicast datagrams </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#IP_MULTICAST_TTL
+ * IP_MULTICAST_TTL} </td>
+ * <td> The <em>time-to-live</em> for Internet Protocol (IP) multicast
+ * datagrams </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#IP_MULTICAST_LOOP
+ * IP_MULTICAST_LOOP} </td>
+ * <td> Loopback for Internet Protocol (IP) multicast datagrams </td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ * Additional (implementation specific) options may also be supported.
+ *
* <p> Datagram channels are safe for use by multiple concurrent threads. They
* support concurrent reading and writing, though at most one thread may be
* reading and at most one thread may be writing at any given time. </p>
- *
*
* @author Mark Reinhold
* @author JSR-51 Expert Group
@@ -71,7 +110,7 @@ import java.nio.channels.spi.*;
public abstract class DatagramChannel
extends AbstractSelectableChannel
- implements ByteChannel, ScatteringByteChannel, GatheringByteChannel
+ implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, MulticastChannel
{
/**
@@ -88,7 +127,13 @@ public abstract class DatagramChannel
* java.nio.channels.spi.SelectorProvider#openDatagramChannel()
* openDatagramChannel} method of the system-wide default {@link
* java.nio.channels.spi.SelectorProvider} object. The channel will not be
- * connected. </p>
+ * connected.
+ *
+ * <p> The {@link ProtocolFamily ProtocolFamily} of the channel's socket
+ * is platform (and possibly configuration) dependent and therefore unspecified.
+ * The {@link #open(ProtocolFamily) open} allows the protocol family to be
+ * selected when opening a datagram channel, and should be used to open
+ * datagram channels that are intended for Internet Protocol multicasting.
*
* @return A new datagram channel
*
@@ -97,6 +142,39 @@ public abstract class DatagramChannel
*/
public static DatagramChannel open() throws IOException {
return SelectorProvider.provider().openDatagramChannel();
+ }
+
+ /**
+ * Opens a datagram channel.
+ *
+ * <p> The {@code family} parameter is used to specify the {@link
+ * ProtocolFamily}. If the datagram channel is to be used for IP multicasing
+ * then this should correspond to the address type of the multicast groups
+ * that this channel will join.
+ *
+ * <p> The new channel is created by invoking the {@link
+ * java.nio.channels.spi.SelectorProvider#openDatagramChannel(ProtocolFamily)
+ * openDatagramChannel} method of the system-wide default {@link
+ * java.nio.channels.spi.SelectorProvider} object. The channel will not be
+ * connected.
+ *
+ * @param family
+ * The protocol family
+ *
+ * @return A new datagram channel
+ *
+ * @throws UnsupportedOperationException
+ * If the specified protocol family is not supported. For example,
+ * suppose the parameter is specified as {@link
+ * java.net.StandardProtocolFamily#INET6 StandardProtocolFamily.INET6}
+ * but IPv6 is not enabled on the platform.
+ * @throws IOException
+ * If an I/O error occurs
+ *
+ * @since 1.7
+ */
+ public static DatagramChannel open(ProtocolFamily family) throws IOException {
+ return SelectorProvider.provider().openDatagramChannel(family);
}
/**
@@ -118,6 +196,32 @@ public abstract class DatagramChannel
// -- Socket-specific operations --
/**
+ * @throws AlreadyBoundException {@inheritDoc}
+ * @throws UnsupportedAddressTypeException {@inheritDoc}
+ * @throws ClosedChannelException {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ * @throws SecurityException
+ * If a security manager has been installed and its {@link
+ * SecurityManager#checkListen checkListen} method denies the
+ * operation
+ *
+ * @since 1.7
+ */
+ public abstract DatagramChannel bind(SocketAddress local)
+ throws IOException;
+
+ /**
+ * @throws IllegalArgumentException {@inheritDoc}
+ * @throws ClosedChannelException {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ *
+ * @since 1.7
+ */
+ public abstract <T> DatagramChannel setOption(SocketOption<T> name, T value)
+ throws IOException;
+
+
+ /**
* Retrieves a datagram socket associated with this channel.
*
* <p> The returned object will not declare any public methods that are not
@@ -128,10 +232,10 @@ public abstract class DatagramChannel
public abstract DatagramSocket socket();
/**
- * Tells whether or not this channel's socket is connected. </p>
- *
- * @return <tt>true</tt> if, and only if, this channel's socket
- * is connected
+ * Tells whether or not this channel's socket is connected.
+ *
+ * @return {@code true} if, and only if, this channel's socket
+ * is {@link #isOpen open} and connected
*/
public abstract boolean isConnected();
@@ -205,6 +309,19 @@ public abstract class DatagramChannel
* If some other I/O error occurs
*/
public abstract DatagramChannel disconnect() throws IOException;
+
+ /**
+ * Returns the remote address to which this channel's socket is connected.
+ *
+ * @return The remote address; {@code null} if the channel is not {@link
+ * #isOpen open} or the channel's socket is not connected
+ *
+ * @throws IOException
+ * If an I/O error occurs
+ *
+ * @since 1.7
+ */
+ public abstract SocketAddress getConnectedAddress() throws IOException;
/**
* Receives a datagram via this channel.
--- a/src/share/classes/java/nio/channels/ServerSocketChannel.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/nio/channels/ServerSocketChannel.java Wed Sep 17 13:45:37 2008 -0700
@@ -27,32 +27,43 @@ package java.nio.channels;
import java.io.IOException;
import java.net.ServerSocket;
+import java.net.SocketOption;
import java.net.SocketAddress;
import java.nio.channels.spi.*;
-
/**
* A selectable channel for stream-oriented listening sockets.
*
- * <p> Server-socket channels are not a complete abstraction of listening
- * network sockets. Binding and the manipulation of socket options must be
- * done through an associated {@link java.net.ServerSocket} object obtained by
- * invoking the {@link #socket() socket} method. It is not possible to create
- * a channel for an arbitrary, pre-existing server socket, nor is it possible
- * to specify the {@link java.net.SocketImpl} object to be used by a server
- * socket associated with a server-socket channel.
- *
* <p> A server-socket channel is created by invoking the {@link #open() open}
- * method of this class. A newly-created server-socket channel is open but not
- * yet bound. An attempt to invoke the {@link #accept() accept} method of an
- * unbound server-socket channel will cause a {@link NotYetBoundException} to
- * be thrown. A server-socket channel can be bound by invoking one of the
- * {@link java.net.ServerSocket#bind(java.net.SocketAddress,int) bind} methods
- * of an associated server socket.
+ * method of this class. It is not possible to create a channel for an arbitrary,
+ * pre-existing {@link ServerSocket}. A newly-created server-socket channel is
+ * open but not yet bound. An attempt to invoke the {@link #accept() accept}
+ * method of an unbound server-socket channel will cause a {@link NotYetBoundException}
+ * to be thrown. A server-socket channel can be bound by invoking one of the
+ * {@link #bind(java.net.SocketAddress,int) bind} methods defined by this class.
+ *
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. Server-socket channels support the following options:
+ * <blockquote>
+ * <table border>
+ * <tr>
+ * <th>Option Name</th>
+ * <th>Description</th>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
+ * <td> The size of the socket receive buffer </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
+ * <td> Re-use address </td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ * Additional (implementation specific) options may also be supported.
*
* <p> Server-socket channels are safe for use by multiple concurrent threads.
* </p>
- *
*
* @author Mark Reinhold
* @author JSR-51 Expert Group
@@ -61,6 +72,7 @@ import java.nio.channels.spi.*;
public abstract class ServerSocketChannel
extends AbstractSelectableChannel
+ implements NetworkChannel
{
/**
@@ -108,6 +120,89 @@ public abstract class ServerSocketChanne
// -- ServerSocket-specific operations --
+
+ /**
+ * Binds the channel's socket to a local address and configures the socket
+ * to listen for connections.
+ *
+ * <p> An invocation of this method is equivalent to the following:
+ * <blockquote><pre>
+ * bind(local, 0);
+ * </pre></blockquote>
+ *
+ * @param local
+ * The local address to bind the socket, or {@code null} to bind
+ * to an automatically assigned socket address
+ *
+ * @return This channel
+ *
+ * @throws AlreadyBoundException {@inheritDoc}
+ * @throws UnsupportedAddressTypeException {@inheritDoc}
+ * @throws ClosedChannelException {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ * @throws SecurityException
+ * If a security manager has been installed and its {@link
+ * SecurityManager#checkListen checkListen} method denies the
+ * operation
+ *
+ * @since 1.7
+ */
+ public final ServerSocketChannel bind(SocketAddress local)
+ throws IOException
+ {
+ return bind(local, 0);
+ }
+
+ /**
+ * Binds the channel's socket to a local address and configures the socket to
+ * listen for connections.
+ *
+ * <p> This method is used to establish an association between the socket and
+ * a local address. Once an association is established then the socket remains
+ * bound until the channel is closed.
+ *
+ * <p> The {@code backlog} parameter is the maximum number of pending
+ * connections on the socket. Its exact semantics are implementation specific.
+ * In particular, an implementation may impose a maximum length or may choose
+ * to ignore the parameter altogther. If the {@code backlog} parameter has
+ * the value {@code 0}, or a negative value, then an implementation specific
+ * default is used.
+ *
+ * @param local
+ * The address to bind the socket, or {@code null} to bind to an
+ * automatically assigned socket address
+ * @param backlog
+ * The maximum number of pending connections
+ *
+ * @return This channel
+ *
+ * @throws AlreadyBoundException
+ * If the socket is already bound
+ * @throws UnsupportedAddressTypeException
+ * If the type of the given address is not supported
+ * @throws ClosedChannelException
+ * If this channel is closed
+ * @throws IOException
+ * If some other I/O error occurs
+ * @throws SecurityException
+ * If a security manager has been installed and its {@link
+ * SecurityManager#checkListen checkListen} method denies the
+ * operation
+ *
+ * @since 1.7
+ */
+ public abstract ServerSocketChannel bind(SocketAddress local, int backlog)
+ throws IOException;
+
+ /**
+ * @throws IllegalArgumentException {@inheritDoc}
+ * @throws ClosedChannelException {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ *
+ * @since 1.7
+ */
+ public abstract <T> ServerSocketChannel setOption(SocketOption<T> name, T value)
+ throws IOException;
/**
* Retrieves a server socket associated with this channel.
--- a/src/share/classes/java/nio/channels/SocketChannel.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/nio/channels/SocketChannel.java Wed Sep 17 13:45:37 2008 -0700
@@ -27,24 +27,17 @@ package java.nio.channels;
import java.io.IOException;
import java.net.Socket;
+import java.net.SocketOption;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.spi.*;
-
/**
* A selectable channel for stream-oriented connecting sockets.
*
- * <p> Socket channels are not a complete abstraction of connecting network
- * sockets. Binding, shutdown, and the manipulation of socket options must be
- * done through an associated {@link java.net.Socket} object obtained by
- * invoking the {@link #socket() socket} method. It is not possible to create
- * a channel for an arbitrary, pre-existing socket, nor is it possible to
- * specify the {@link java.net.SocketImpl} object to be used by a socket
- * associated with a socket channel.
- *
* <p> A socket channel is created by invoking one of the {@link #open open}
- * methods of this class. A newly-created socket channel is open but not yet
+ * methods of this class. It is not possible to create a channel for an arbitrary,
+ * pre-existing socket. A newly-created socket channel is open but not yet
* connected. An attempt to invoke an I/O operation upon an unconnected
* channel will cause a {@link NotYetConnectedException} to be thrown. A
* socket channel can be connected by invoking its {@link #connect connect}
@@ -58,16 +51,6 @@ import java.nio.channels.spi.*;
* later completion by the {@link #finishConnect finishConnect} method.
* Whether or not a connection operation is in progress may be determined by
* invoking the {@link #isConnectionPending isConnectionPending} method.
- *
- * <p> The input and output sides of a socket channel may independently be
- * <i>shut down</i> without actually closing the channel. Shutting down the
- * input side of a channel by invoking the {@link java.net.Socket#shutdownInput
- * shutdownInput} method of an associated socket object will cause further
- * reads on the channel to return <tt>-1</tt>, the end-of-stream indication.
- * Shutting down the output side of the channel by invoking the {@link
- * java.net.Socket#shutdownOutput shutdownOutput} method of an associated
- * socket object will cause further writes on the channel to throw a {@link
- * ClosedChannelException}.
*
* <p> Socket channels support <i>asynchronous shutdown,</i> which is similar
* to the asynchronous close operation specified in the {@link Channel} class.
@@ -79,6 +62,43 @@ import java.nio.channels.spi.*;
* channel, then the blocked thread will receive an {@link
* AsynchronousCloseException}.
*
+ * <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
+ * setOption} method. Socket channels support the following options:
+ * <blockquote>
+ * <table border>
+ * <tr>
+ * <th>Option Name</th>
+ * <th>Description</th>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
+ * <td> The size of the socket send buffer </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
+ * <td> The size of the socket receive buffer </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_KEEPALIVE SO_KEEPALIVE} </td>
+ * <td> Keep connection alive </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
+ * <td> Re-use address </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#SO_LINGER SO_LINGER} </td>
+ * <td> Linger on close if data is present (when configured in blocking mode
+ * only) </td>
+ * </tr>
+ * <tr>
+ * <td> {@link java.net.StandardSocketOption#TCP_NODELAY TCP_NODELAY} </td>
+ * <td> Disable the Nagle algorithm </td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ * Additional (implementation specific) options may also be supported.
+ *
* <p> Socket channels are safe for use by multiple concurrent threads. They
* support concurrent reading and writing, though at most one thread may be
* reading and at most one thread may be writing at any given time. The {@link
@@ -87,7 +107,6 @@ import java.nio.channels.spi.*;
* or write operation while an invocation of one of these methods is in
* progress will block until that invocation is complete. </p>
*
- *
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
@@ -95,7 +114,7 @@ import java.nio.channels.spi.*;
public abstract class SocketChannel
extends AbstractSelectableChannel
- implements ByteChannel, ScatteringByteChannel, GatheringByteChannel
+ implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, NetworkChannel
{
/**
@@ -192,6 +211,73 @@ public abstract class SocketChannel
// -- Socket-specific operations --
/**
+ * @throws ConnectionPendingException
+ * If a non-blocking connection operation is already in progress on
+ * this channel
+ * @throws AlreadyBoundException {@inheritDoc}
+ * @throws UnsupportedAddressTypeException {@inheritDoc}
+ * @throws ClosedChannelException {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ *
+ * @since 1.7
+ */
+ @Override
+ public abstract SocketChannel bind(SocketAddress local)
+ throws IOException;
+
+ /**
+ * @throws IllegalArgumentException {@inheritDoc}
+ * @throws ClosedChannelException {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ *
+ * @since 1.7
+ */
+ @Override
+ public abstract <T> SocketChannel setOption(SocketOption<T> name, T value)
+ throws IOException;
+
+ /**
+ * Shutdown the connection for reading without closing the channel.
+ *
+ * <p> Once shutdown for reading then further reads on the channel will
+ * return {@code -1}, the end-of-stream indication. If the input side of the
+ * connection is already shutdown then invoking this method has no effect.
+ *
+ * @return The channel
+ *
+ * @throws NotYetConnectedException
+ * If this channel is not yet connected
+ * @throws ClosedChannelException
+ * If this channel is closed
+ * @throws IOException
+ * If some other I/O error occurs
+ *
+ * @since 1.7
+ */
+ public abstract SocketChannel shutdownInput() throws IOException;
+
+ /**
+ * Shutdown the connection for writing without closing the channel.
+ *
+ * <p> Once shutdown for writing then further attempts to write to the
+ * channel will throw {@link ClosedChannelException}. If the output side of
+ * the connection is already shutdown then invoking this method has no
+ * effect.
+ *
+ * @return The channel
+ *
+ * @throws NotYetConnectedException
+ * If this channel is not yet connected
+ * @throws ClosedChannelException
+ * If this channel is closed
+ * @throws IOException
+ * If some other I/O error occurs
+ *
+ * @since 1.7
+ */
+ public abstract SocketChannel shutdownOutput() throws IOException;
+
+ /**
* Retrieves a socket associated with this channel.
*
* <p> The returned object will not declare any public methods that are not
@@ -202,10 +288,10 @@ public abstract class SocketChannel
public abstract Socket socket();
/**
- * Tells whether or not this channel's network socket is connected. </p>
+ * Tells whether or not this channel's network socket is connected.
*
* @return <tt>true</tt> if, and only if, this channel's network socket
- * is connected
+ * is {@link #isOpen open} and connected
*/
public abstract boolean isConnected();
@@ -339,6 +425,22 @@ public abstract class SocketChannel
*/
public abstract boolean finishConnect() throws IOException;
+ /**
+ * Returns the remote address to which this channel's socket is connected.
+ *
+ * <p> Where the channel is bound and connected to an Internet Protocol
+ * socket address then the return value from this method is of type {@link
+ * java.net.InetSocketAddress}.
+ *
+ * @return The remote address; {@code null} if the channel is not {@link
+ * #isOpen open} or the channel's socket is not connected
+ *
+ * @throws IOException
+ * If an I/O error occurs
+ *
+ * @since 1.7
+ */
+ public abstract SocketAddress getConnectedAddress() throws IOException;
// -- ByteChannel operations --
--- a/src/share/classes/java/nio/channels/exceptions Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/nio/channels/exceptions Wed Sep 17 13:45:37 2008 -0700
@@ -146,3 +146,14 @@ gen OverlappingFileLockException "
* virtual machine, or when another thread is already waiting to lock an
* overlapping region of the same file." \
2047812138163068433L
+
+
+SINCE=1.7
+
+SUPER=IllegalStateException
+
+gen AlreadyBoundException "
+ * Unchecked exception thrown when an attempt is made to bind the socket a
+ * network oriented channel that is already bound." \
+ 6796072983322737592L
+
--- a/src/share/classes/java/nio/channels/spi/SelectorProvider.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/nio/channels/spi/SelectorProvider.java Wed Sep 17 13:45:37 2008 -0700
@@ -25,10 +25,8 @@
package java.nio.channels.spi;
-import java.io.FileDescriptor;
import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
+import java.net.ProtocolFamily;
import java.nio.channels.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -190,7 +188,25 @@ public abstract class SelectorProvider {
throws IOException;
/**
- * Opens a pipe. </p>
+ * Opens a datagram channel.
+ *
+ * @param family
+ * The protocol family
+ *
+ * @return A new datagram channel
+ *
+ * @throws UnsupportedOperationException
+ * If the specified protocol family is not supported
+ * @throws IOException
+ * If an I/O error occurs
+ *
+ * @since 1.7
+ */
+ public abstract DatagramChannel openDatagramChannel(ProtocolFamily family)
+ throws IOException;
+
+ /**
+ * Opens a pipe. </p>
*
* @return The new pipe
*/
--- a/src/share/classes/java/nio/charset/Charset.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/nio/charset/Charset.java Wed Sep 17 13:45:37 2008 -0700
@@ -85,6 +85,9 @@ import sun.security.action.GetPropertyAc
* <li> The dash character <tt>'-'</tt>
* (<tt>'&#92;u002d'</tt>,&nbsp;<small>HYPHEN-MINUS</small>),
*
+ * <li> The plus character <tt>'+'</tt>
+ * (<tt>'&#92;u002b'</tt>,&nbsp;<small>PLUS SIGN</small>),
+ *
* <li> The period character <tt>'.'</tt>
* (<tt>'&#92;u002e'</tt>,&nbsp;<small>FULL STOP</small>),
*
@@ -307,6 +310,7 @@ public abstract class Charset
if (c >= 'a' && c <= 'z') continue;
if (c >= '0' && c <= '9') continue;
if (c == '-' && i != 0) continue;
+ if (c == '+' && i != 0) continue;
if (c == ':' && i != 0) continue;
if (c == '_' && i != 0) continue;
if (c == '.' && i != 0) continue;
--- a/src/share/classes/java/util/zip/Inflater.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/util/zip/Inflater.java Wed Sep 17 13:45:37 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1996-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
@@ -73,10 +73,12 @@ public
public
class Inflater {
private long strm;
- private byte[] buf = new byte[0];
+ private byte[] buf = defaultBuf;
private int off, len;
private boolean finished;
private boolean needDict;
+
+ private static final byte[] defaultBuf = new byte[0];
static {
/* Zip library is loaded from System.initializeSystemClass */
@@ -318,6 +320,7 @@ class Inflater {
public synchronized void reset() {
ensureOpen();
reset(strm);
+ buf = defaultBuf;
finished = false;
needDict = false;
off = len = 0;
--- a/src/share/classes/java/util/zip/ZipFile.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/java/util/zip/ZipFile.java Wed Sep 17 13:45:37 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1995-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
@@ -278,7 +278,6 @@ class ZipFile implements ZipConstants {
int size = inflaters.size();
if (size > 0) {
Inflater inf = (Inflater)inflaters.remove(size - 1);
- inf.reset();
return inf;
} else {
return new Inflater(true);
@@ -291,6 +290,7 @@ class ZipFile implements ZipConstants {
*/
private void releaseInflater(Inflater inf) {
synchronized (inflaters) {
+ inf.reset();
inflaters.add(inf);
}
}
--- a/src/share/classes/javax/management/InstanceNotFoundException.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/javax/management/InstanceNotFoundException.java Wed Sep 17 13:45:37 2008 -0700
@@ -51,4 +51,16 @@ public class InstanceNotFoundException e
public InstanceNotFoundException(String message) {
super(message);
}
+
+ /**
+ * Constructor for the frequent case where the message is the ObjectName
+ * of the missing MBean.
+ *
+ * @param name the ObjectName of the missing MBean.
+ *
+ * @since 1.7
+ */
+ public InstanceNotFoundException(ObjectName name) {
+ this(name.toString());
+ }
}
--- a/src/share/classes/javax/management/MBeanPermission.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/javax/management/MBeanPermission.java Wed Sep 17 13:45:37 2008 -0700
@@ -25,6 +25,7 @@
package javax.management;
+import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.security.Permission;
@@ -42,10 +43,10 @@ import java.security.Permission;
* permission that you <em>need</em>. When a sensitive operation is
* being checked for permission, an MBeanPermission is constructed
* representing the permission you need. The operation is only
- * allowed if the permissions you have {@link #implies imply} the
+ * allowed if the permissions you have {@linkplain #implies imply} the
* permission you need.</p>
*
- * <p>An MBeanPermission contains four items of information:</p>
+ * <p>An MBeanPermission contains five items of information:</p>
*
* <ul>
*
@@ -56,6 +57,23 @@ import java.security.Permission;
* representing all actions.</p>
*
* <p>The action is returned by {@link #getActions()}.</p>
+ *
+ * <li id="MBeanServerName"><p>The <em>MBean Server name</em>.</p>
+ *
+ * <p>For a permission you need, this is the {@linkplain
+ * javax.management.MBeanServerFactory#getMBeanServerName
+ * name of the MBeanServer}
+ * containing the <a href="#MBeanName">MBean</a> for which the MBean
+ * permission is checked.</p>
+ *
+ * <p>For a permission you have, this is either the {@linkplain
+ * javax.management.MBeanServerFactory#getMBeanServerName
+ * name of the MBeanServer} in which the <a href="#MBeanName">MBean</a>
+ * you have this permission for must be registered,
+ * or a pattern against which that MBean Server name will be matched.<br>
+ * An {@code mbeanServerName} pattern can also be empty or the single
+ * character {@code "*"}, both of which will match any {@code MBeanServer} name.
+ * </p>
*
* <li><p>The <em>class name</em>.</p>
*
@@ -88,7 +106,7 @@ import java.security.Permission;
* or operation you can access, or it is empty or the single character
* "<code>*</code>", both of which grant access to any member.</p>
*
- * <li><p>The <em>object name</em>.</p>
+ * <li id="MBeanName"><p>The <em>object name</em>.</p>
*
* <p>For a permission you need, this is the {@link ObjectName} of the
* MBean you are accessing. For operations that do not reference a
@@ -103,15 +121,15 @@ import java.security.Permission;
* </ul>
*
* <p>If you have an MBeanPermission, it allows operations only if all
- * four of the items match.</p>
- *
- * <p>The class name, member, and object name can be written together
- * as a single string, which is the <em>name</em> of this permission.
+ * five of the items match.</p>
+ *
+ * <p>The MBean Server name, class name, member, and object name can be written
+ * together as a single string, which is the <em>name</em> of this permission.
* The name of the permission is the string returned by {@link
* Permission#getName() getName()}. The format of the string is:</p>
*
* <blockquote>
- * <code>className#member[objectName]</code>
+ * <code>mbeanServerName::className#member[objectName]</code>
* </blockquote>
*
* <p>The object name is written using the usual syntax for {@link
@@ -119,15 +137,18 @@ import java.security.Permission;
* <code>]</code>. It is terminated by a <code>]</code> character
* that is the last character in the string.</p>
*
- * <p>One or more of the <code>className</code>, <code>member</code>,
- * or <code>objectName</code> may be omitted. If the
- * <code>member</code> is omitted, the <code>#</code> may be too (but
+ * <p>One or more of the <code>mbeanServerName</code>, <code>className</code>,
+ * <code>member</code>, or <code>objectName</code> may be omitted. If the
+ * <code>mbeanServerName</code> is omitted, the <code>::</code> may be too (but
+ * does not have to be).
+ * If the <code>member</code> is omitted, the <code>#</code> may be too (but
* does not have to be). If the <code>objectName</code> is omitted,
* the <code>[]</code> may be too (but does not have to be). It is
- * not legal to omit all three items, that is to have a <em>name</em>
+ * not legal to omit all four items, that is to have a <em>name</em>
* that is the empty string.</p>
*
- * <p>One or more of the <code>className</code>, <code>member</code>,
+ * <p>One or more of the <code>mbeanServerName</code>, <code>className</code>,
+ * <code>member</code>,
* or <code>objectName</code> may be the character "<code>-</code>",
* which is equivalent to a null value. A null value is implied by
* any value (including another null value) but does not imply any
@@ -247,6 +268,13 @@ public class MBeanPermission extends Per
private transient ObjectName objectName;
/**
+ * The name of the MBeanServer in which this permission is checked, or
+ * granted. If null, is implied by any MBean Server name
+ * but does not imply any non-null MBean Server name.
+ */
+ private transient String mbeanServerName;
+
+ /**
* Parse <code>actions</code> parameter.
*/
private void parseActions() {
@@ -283,6 +311,13 @@ public class MBeanPermission extends Per
throw new IllegalArgumentException("MBeanPermission name " +
"cannot be empty");
+ final int sepIndex = name.indexOf("::");
+ if (sepIndex < 0) {
+ setMBeanServerName("*");
+ } else {
+ setMBeanServerName(name.substring(0,sepIndex));
+ }
+
/* The name looks like "class#member[objectname]". We subtract
elements from the right as we parse, so after parsing the
objectname we have "class#member" and after parsing the
@@ -290,11 +325,14 @@ public class MBeanPermission extends Per
// Parse ObjectName
- int openingBracket = name.indexOf("[");
+
+ final int start = (sepIndex<0)?0:sepIndex+2;
+ int openingBracket = name.indexOf("[",start);
if (openingBracket == -1) {
// If "[on]" missing then ObjectName("*:*")
//
objectName = ObjectName.WILDCARD;
+ name = name.substring(start);
} else {
if (!name.endsWith("]")) {
throw new IllegalArgumentException("MBeanPermission: " +
@@ -305,11 +343,11 @@ public class MBeanPermission extends Per
} else {
// Create ObjectName
//
+ String on = name.substring(openingBracket + 1,
+ name.length() - 1);
try {
// If "[]" then ObjectName("*:*")
//
- String on = name.substring(openingBracket + 1,
- name.length() - 1);
if (on.equals(""))
objectName = ObjectName.WILDCARD;
else if (on.equals("-"))
@@ -320,11 +358,11 @@ public class MBeanPermission extends Per
throw new IllegalArgumentException("MBeanPermission: " +
"The target name does " +
"not specify a valid " +
- "ObjectName");
+ "ObjectName", e);
}
}
- name = name.substring(0, openingBracket);
+ name = name.substring(start, openingBracket);
}
// Parse member
@@ -348,8 +386,9 @@ public class MBeanPermission extends Per
* Assign fields based on className, member, and objectName
* parameters.
*/
- private void initName(String className, String member,
- ObjectName objectName) {
+ private void initName(String mbeanServerName, String className,
+ String member, ObjectName objectName) {
+ setMBeanServerName(mbeanServerName);
setClassName(className);
setMember(member);
this.objectName = objectName;
@@ -381,19 +420,30 @@ public class MBeanPermission extends Per
this.member = member;
}
+ private void setMBeanServerName(String mbeanServerName) {
+ if (mbeanServerName == null || mbeanServerName.equals("-")) {
+ this.mbeanServerName = null;
+ } else if (mbeanServerName.equals("")) {
+ this.mbeanServerName = "*";
+ } else {
+ this.mbeanServerName = mbeanServerName;
+ }
+ }
+
+
/**
* <p>Create a new MBeanPermission object with the specified target name
* and actions.</p>
*
* <p>The target name is of the form
- * "<code>className#member[objectName]</code>" where each part is
- * optional. It must not be empty or null.</p>
+ * "<code>mbeanServerName::className#member[objectName]</code>" where
+ * each part is optional. It must not be empty or null.</p>
*
* <p>The actions parameter contains a comma-separated list of the
* desired actions granted on the target name. It must not be
* empty or null.</p>
*
- * @param name the triplet "className#member[objectName]".
+ * @param name the quadruplet "mbeanServerName::className#member[objectName]".
* @param actions the action string.
*
* @exception IllegalArgumentException if the <code>name</code> or
@@ -417,6 +467,12 @@ public class MBeanPermission extends Per
* "<code>className#member[objectName]</code>" where each part is
* optional. This will be the result of {@link #getName()} on the
* resultant MBeanPermission.</p>
+ *
+ * <p>This corresponds to a permission granted for all
+ * MBean servers present in the JVM and is equivalent to
+ * {@link #MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission("*",className,member,objectName,actions)}.
+ * </p>
*
* <p>The actions parameter contains a comma-separated list of the
* desired actions granted on the target name. It must not be
@@ -439,17 +495,67 @@ public class MBeanPermission extends Per
String member,
ObjectName objectName,
String actions) {
-
- super(makeName(className, member, objectName));
- initName(className, member, objectName);
+ this("*",className,member,objectName,actions);
+ }
+
+ /**
+ * <p>Create a new MBeanPermission object with the specified target name
+ * (MBean Server name, class name, member, object name) and actions.</p>
+ *
+ * <p>The MBean Server name, class name, member and object name
+ * parameters define a target name of the form
+ * "<code>mbeanServerName::className#member[objectName]</code>" where each
+ * part is optional. This will be the result of {@link #getName()} on the
+ * resultant MBeanPermission.
+ * If the <code>mbeanServerName</code> is empty or exactly {@code "*"}, then
+ * "{@code mbeanServerName::}" is omitted in that result.
+ * </p>
+ *
+ * <p>The actions parameter contains a comma-separated list of the
+ * desired actions granted on the target name. It must not be
+ * empty or null.</p>
+ *
+ * @param mbeanServerName the name of the {@code MBeanServer} to which this
+ * permission applies.
+ * May be null or <code>"-"</code>, which represents an MBeanServer name
+ * that is implied by any MBeanServer name but does not imply any other
+ * MBeanServer name.
+ * @param className the class name to which this permission applies.
+ * May be null or <code>"-"</code>, which represents a class name
+ * that is implied by any class name but does not imply any other
+ * class name.
+ * @param member the member to which this permission applies. May
+ * be null or <code>"-"</code>, which represents a member that is
+ * implied by any member but does not imply any other member.
+ * @param objectName the object name to which this permission
+ * applies. May be null, which represents an object name that is
+ * implied by any object name but does not imply any other object
+ * name.
+ * @param actions the action string.
+ *
+ * @since 1.7
+ */
+ public MBeanPermission(String mbeanServerName,
+ String className,
+ String member,
+ ObjectName objectName,
+ String actions) {
+
+ super(makeName(mbeanServerName,className, member, objectName));
+ initName(mbeanServerName,className, member, objectName);
this.actions = actions;
parseActions();
}
- private static String makeName(String className, String member,
+ private static String makeName(String mbeanServerName, String className,
+ String member,
ObjectName objectName) {
final StringBuilder name = new StringBuilder();
+ if (mbeanServerName == null)
+ mbeanServerName = "-";
+ if (!mbeanServerName.equals("") && !mbeanServerName.equals("*"))
+ name.append(mbeanServerName).append("::");
if (className == null)
className = "-";
name.append(className);
@@ -991,6 +1097,9 @@ public class MBeanPermission extends Per
*
* <li> <i>p</i> is an instance of MBeanPermission; and</li>
*
+ * <li> <i>p</i> has a null mbeanServerName or <i>p</i>'s mbeanServerName
+ * matches this object's mbeanServerName; and</li>
+ *
* <li> <i>p</i> has a null className or <i>p</i>'s className
* matches this object's className; and</li>
*
@@ -1003,6 +1112,13 @@ public class MBeanPermission extends Per
* <li> <i>p</i>'s actions are a subset of this object's actions</li>
*
* </ul>
+ *
+ * <p>If this object's mbeanServerName is a pattern, then <i>p</i>'s
+ * mbeanServerName is matched against that pattern. An empty
+ * mbeanServerName is equivalent to "{@code *}". A null
+ * mbeanServerName is equivalent to "{@code -}".</p>
+ * <p>If this object's mbeanServerName is "<code>*</code>" or is
+ * empty, <i>p</i>'s mbeanServerName always matches it.</p>
*
* <p>If this object's className is "<code>*</code>", <i>p</i>'s
* className always matches it. If it is "<code>a.*</code>", <i>p</i>'s
@@ -1049,6 +1165,12 @@ public class MBeanPermission extends Per
}
// Target name
+ //
+ // The 'mbeanServerName' check is true iff:
+ // 1) the mbeanServerName in 'this' permission is omitted or "*", or
+ // 2) the mbeanServerName in 'that' permission is omitted or "*", or
+ // 3) the mbeanServerName in 'this' permission does pattern
+ // matching with the mbeanServerName in 'that' permission.
//
// The 'className' check is true iff:
// 1) the className in 'this' permission is omitted or "*", or
@@ -1076,6 +1198,17 @@ public class MBeanPermission extends Per
expect that "that" contains a wildcard, since it is a
needed permission. So we assume that.classNameExactMatch. */
+ if (that.mbeanServerName == null) {
+ // bottom is implied
+ } else if (this.mbeanServerName == null) {
+ // bottom implies nothing but itself
+ return false;
+ } else if (that.mbeanServerName.equals(this.mbeanServerName)) {
+ // exact match
+ } else if (!Util.wildmatch(that.mbeanServerName,this.mbeanServerName)) {
+ return false; // no match
+ }
+
if (that.classNamePrefix == null) {
// bottom is implied
} else if (this.classNamePrefix == null) {
--- a/src/share/classes/javax/management/MBeanServer.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/javax/management/MBeanServer.java Wed Sep 17 13:45:37 2008 -0700
@@ -42,7 +42,7 @@ import javax.management.loading.ClassLoa
*
* <p>User code does not usually implement this interface. Instead,
* an object that implements this interface is obtained with one of
- * the methods in the {@link MBeanServerFactory} class.</p>
+ * the methods in the {@link javax.management.MBeanServerFactory} class.</p>
*
* <p>Every MBean which is added to the MBean server becomes
* manageable: its attributes and operations become remotely
@@ -62,8 +62,12 @@ import javax.management.loading.ClassLoa
* <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.</p>
*
* <p id="security">An object obtained from the {@link
- * MBeanServerFactory#createMBeanServer(String) createMBeanServer} or
- * {@link MBeanServerFactory#newMBeanServer(String) newMBeanServer}
+ * MBeanServerFactory#createMBeanServer(String) createMBeanServer}, {@link
+ * MBeanServerFactory#createNamedMBeanServer(String,String) createNamedMBeanServer},
+ * {@link
+ * MBeanServerFactory#newMBeanServer(String) newMBeanServer}, or
+ * {@link
+ * MBeanServerFactory#newNamedMBeanServer(String,String) newNamedMBeanServer}
* methods of the {@link MBeanServerFactory} class applies security
* checks to its methods, as follows.</p>
*
@@ -73,9 +77,26 @@ import javax.management.loading.ClassLoa
*
* <p>Assuming that there is a security manager, or that the
* implementation chooses to make checks anyway, the checks are made
- * as detailed below. In what follows, <code>className</code> is the
+ * as detailed below.
+ * In what follows, and unless otherwise specified:
+ * </p>
+ * <ul><li><code>className</code> is the
* string returned by {@link MBeanInfo#getClassName()} for the target
- * MBean.</p>
+ * MBean,</li>
+ * <li>{@code mbeanServerName} is the
+ * {@linkplain MBeanServerFactory#getMBeanServerName name of the
+ * MBean Server} in which the target MBean is registered. This is the
+ * value returned by {@link MBeanServerFactory#getMBeanServerName
+ * MBeanServerFactory.getMBeanServerName(MBeanServer)}, and
+ * is usually the {@code mbeanServerName} parameter that was supplied
+ * to the {@link
+ * MBeanServerFactory#createNamedMBeanServer(String,String)
+ * createNamedMBeanServer} or {@link
+ * MBeanServerFactory#newNamedMBeanServer(String,String) newNamedMBeanServer}
+ * methods of the {@link MBeanServerFactory} when the MBeanServer was created,
+ * or {@value javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if
+ * no name was supplied.
+ * </li></ul>
*
* <p>If a security check fails, the method throws {@link
* SecurityException}.</p>
@@ -89,78 +110,86 @@ import javax.management.loading.ClassLoa
*
* <li><p>For the {@link #invoke invoke} method, the caller's
* permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, operationName, name, "invoke")}.</p>
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, operationName, name, "invoke")}.
+ * </p>
*
* <li><p>For the {@link #getAttribute getAttribute} method, the
* caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, attribute, name, "getAttribute")}.</p>
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, attribute, name,
+ * "getAttribute")}.</p>
*
* <li><p>For the {@link #getAttributes getAttributes} method, the
* caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name, "getAttribute")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName,className, null, name, "getAttribute")}.
* Additionally, for each attribute <em>a</em> in the {@link
* AttributeList}, if the caller's permissions do not imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, <em>a</em>, name, "getAttribute")}, the
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, <em>a</em>, name,
+ * "getAttribute")}, the
* MBean server will behave as if that attribute had not been in the
* supplied list.</p>
*
* <li><p>For the {@link #setAttribute setAttribute} method, the
* caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, attrName, name, "setAttribute")}, where
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, attrName, name,
+ * "setAttribute")}, where
* <code>attrName</code> is {@link Attribute#getName()
* attribute.getName()}.</p>
*
* <li><p>For the {@link #setAttributes setAttributes} method, the
* caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name, "setAttribute")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, name, "setAttribute")}.
* Additionally, for each attribute <em>a</em> in the {@link
* AttributeList}, if the caller's permissions do not imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, <em>a</em>, name, "setAttribute")}, the
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, <em>a</em>, name,
+ * "setAttribute")}, the
* MBean server will behave as if that attribute had not been in the
* supplied list.</p>
*
* <li><p>For the <code>addNotificationListener</code> methods,
* the caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name,
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, name,
* "addNotificationListener")}.</p>
*
* <li><p>For the <code>removeNotificationListener</code> methods,
* the caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name,
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, name,
* "removeNotificationListener")}.</p>
*
* <li><p>For the {@link #getMBeanInfo getMBeanInfo} method, the
* caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name, "getMBeanInfo")}.</p>
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, name, "getMBeanInfo")}.
+ * </p>
*
* <li><p>For the {@link #getObjectInstance getObjectInstance} method,
* the caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name, "getObjectInstance")}.</p>
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, name,
+ * "getObjectInstance")}.</p>
*
* <li><p>For the {@link #isInstanceOf isInstanceOf} method, the
* caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name, "isInstanceOf")}.</p>
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, name, "isInstanceOf")}.
+ * </p>
*
* <li><p>For the {@link #queryMBeans queryMBeans} method, the
* caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(null, null, name, "queryMBeans")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, null, null, null, "queryMBeans")}.
* Additionally, for each MBean that matches <code>name</code>,
* if the caller's permissions do not imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name, "queryMBeans")}, the
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, name, "queryMBeans")}, the
* MBean server will behave as if that MBean did not exist.</p>
*
* <p>Certain query elements perform operations on the MBean server.
@@ -179,10 +208,10 @@ import javax.management.loading.ClassLoa
*
* <li><p>For the {@link #getDomains getDomains} method, the caller's
* permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(null, null, name, "getDomains")}. Additionally,
- * for each domain <var>d</var> in the returned array, if the caller's
- * permissions do not imply {@link
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, null, null, null, "getDomains")}.
+ * Additionally, for each domain <var>d</var> in the returned array, if the
+ * caller's permissions do not imply {@link
* MBeanPermission#MBeanPermission(String,String,ObjectName,String)
* MBeanPermission(null, null, new ObjectName("<var>d</var>:x=x"),
* "getDomains")}, the domain is eliminated from the array. Here,
@@ -191,21 +220,22 @@ import javax.management.loading.ClassLoa
*
* <li><p>For the {@link #getClassLoader getClassLoader} method, the
* caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, loaderName,
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, loaderName,
* "getClassLoader")}.</p>
*
* <li><p>For the {@link #getClassLoaderFor getClassLoaderFor} method,
* the caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, mbeanName,
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, mbeanName,
* "getClassLoaderFor")}.</p>
*
* <li><p>For the {@link #getClassLoaderRepository
* getClassLoaderRepository} method, the caller's permissions must
* imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(null, null, null, "getClassLoaderRepository")}.</p>
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, null, null, null,
+ * "getClassLoaderRepository")}.</p>
*
* <li><p>For the deprecated <code>deserialize</code> methods, the
* required permissions are the same as for the methods that replace
@@ -213,15 +243,15 @@ import javax.management.loading.ClassLoa
*
* <li><p>For the <code>instantiate</code> methods, the caller's
* permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, null, "instantiate")}.</p>
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, null, "instantiate")},
+ * where {@code className} is the name of the class which is to
+ * be instantiated.</p>
*
* <li><p>For the {@link #registerMBean registerMBean} method, the
* caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name, "registerMBean")}. Here
- * <code>className</code> is the string returned by {@link
- * MBeanInfo#getClassName()} for an object of this class.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, name, "registerMBean")}.
*
* <p>If the <code>MBeanPermission</code> check succeeds, the MBean's
* class is validated by checking that its {@link
@@ -241,8 +271,9 @@ import javax.management.loading.ClassLoa
*
* <li><p>For the {@link #unregisterMBean unregisterMBean} method,
* the caller's permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, name, "unregisterMBean")}.</p>
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
+ * MBeanPermission(mbeanServerName, className, null, name, "unregisterMBean")}.
+ * </p>
*
* </ul>
*
@@ -264,6 +295,8 @@ public interface MBeanServer extends MBe
* is sent as described <a href="#notif">above</a>.</p>
*
* @throws RuntimeOperationsException {@inheritDoc}
+ * @throws RuntimeMBeanException {@inheritDoc}
+ * @throws RuntimeErrorException {@inheritDoc}
*/
public ObjectInstance createMBean(String className, ObjectName name)
throws ReflectionException, InstanceAlreadyExistsException,
@@ -276,6 +309,8 @@ public interface MBeanServer extends MBe
* is sent as described <a href="#notif">above</a>.</p>
*
* @throws RuntimeOperationsException {@inheritDoc}
+ * @throws RuntimeMBeanException {@inheritDoc}
+ * @throws RuntimeErrorException {@inheritDoc}
*/
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName)
@@ -289,6 +324,8 @@ public interface MBeanServer extends MBe
* is sent as described <a href="#notif">above</a>.</p>
*
* @throws RuntimeOperationsException {@inheritDoc}
+ * @throws RuntimeMBeanException {@inheritDoc}
+ * @throws RuntimeErrorException {@inheritDoc}
*/
public ObjectInstance createMBean(String className, ObjectName name,
Object params[], String signature[])
@@ -302,6 +339,8 @@ public interface MBeanServer extends MBe
* is sent as described <a href="#notif">above</a>.</p>
*
* @throws RuntimeOperationsException {@inheritDoc}
+ * @throws RuntimeMBeanException {@inheritDoc}
+ * @throws RuntimeErrorException {@inheritDoc}
*/
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName, Object params[],
--- a/src/share/classes/javax/management/MBeanServerConnection.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/javax/management/MBeanServerConnection.java Wed Sep 17 13:45:37 2008 -0700
@@ -78,19 +78,19 @@ public interface MBeanServerConnection e
* MBean will not be registered.
* @exception RuntimeMBeanException If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
- * <CODE>RuntimeException</CODE>, the <CODE>createMBean<CODE> method will
+ * <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>createMBean<CODE> method
+ * registered even though the <CODE>createMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeMBeanException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
* @exception RuntimeErrorException If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws an
- * <CODE>Error</CODE>, the <CODE>createMBean<CODE> method will
+ * <CODE>Error</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeErrorException</CODE>, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>createMBean<CODE> method
+ * registered even though the <CODE>createMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeErrorException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
@@ -150,19 +150,19 @@ public interface MBeanServerConnection e
* MBean will not be registered.
* @exception RuntimeMBeanException If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
- * <CODE>RuntimeException</CODE>, the <CODE>createMBean<CODE> method will
+ * <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>createMBean<CODE> method
+ * registered even though the <CODE>createMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeMBeanException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
* @exception RuntimeErrorException If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws an
- * <CODE>Error</CODE>, the <CODE>createMBean<CODE> method will
+ * <CODE>Error</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeErrorException</CODE>, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>createMBean<CODE> method
+ * registered even though the <CODE>createMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeErrorException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
@@ -225,19 +225,19 @@ public interface MBeanServerConnection e
* MBean will not be registered.
* @exception RuntimeMBeanException If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
- * <CODE>RuntimeException</CODE>, the <CODE>createMBean<CODE> method will
+ * <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>createMBean<CODE> method
+ * registered even though the <CODE>createMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeMBeanException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
* @exception RuntimeErrorException If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws an
- * <CODE>Error</CODE>, the <CODE>createMBean<CODE> method will
+ * <CODE>Error</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeErrorException</CODE>, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>createMBean<CODE> method
+ * registered even though the <CODE>createMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeErrorException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
@@ -297,19 +297,19 @@ public interface MBeanServerConnection e
* MBean will not be registered.
* @exception RuntimeMBeanException If the <CODE>postRegister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
- * <CODE>RuntimeException</CODE>, the <CODE>createMBean<CODE> method will
+ * <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>createMBean<CODE> method
+ * registered even though the <CODE>createMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeMBeanException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
* @exception RuntimeErrorException If the <CODE>postRegister</CODE> method
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws an
- * <CODE>Error</CODE>, the <CODE>createMBean<CODE> method will
+ * <CODE>Error</CODE>, the <CODE>createMBean</CODE> method will
* throw a <CODE>RuntimeErrorException</CODE>, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the <CODE>createMBean<CODE> method
+ * registered even though the <CODE>createMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeErrorException</CODE> can
* also be thrown by <CODE>preRegister</CODE>, in which case the MBean
* will not be registered.
@@ -351,19 +351,19 @@ public interface MBeanServerConnection e
* has thrown an exception.
* @exception RuntimeMBeanException If the <CODE>postDeregister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
- * <CODE>RuntimeException</CODE>, the <CODE>unregisterMBean<CODE> method
+ * <CODE>RuntimeException</CODE>, the <CODE>unregisterMBean</CODE> method
* will throw a <CODE>RuntimeMBeanException</CODE>, although the MBean
* unregistration succeeded. In such a case, the MBean will be actually
- * unregistered even though the <CODE>unregisterMBean<CODE> method
+ * unregistered even though the <CODE>unregisterMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeMBeanException</CODE> can
* also be thrown by <CODE>preDeregister</CODE>, in which case the MBean
* will remain registered.
* @exception RuntimeErrorException If the <CODE>postDeregister</CODE>
* (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws an
- * <CODE>Error</CODE>, the <CODE>unregisterMBean<CODE> method will
+ * <CODE>Error</CODE>, the <CODE>unregisterMBean</CODE> method will
* throw a <CODE>RuntimeErrorException</CODE>, although the MBean
* unregistration succeeded. In such a case, the MBean will be actually
- * unregistered even though the <CODE>unregisterMBean<CODE> method
+ * unregistered even though the <CODE>unregisterMBean</CODE> method
* threw an exception. Note that <CODE>RuntimeMBeanException</CODE> can
* also be thrown by <CODE>preDeregister</CODE>, in which case the MBean
* will remain registered.
--- a/src/share/classes/javax/management/MBeanServerDelegate.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/javax/management/MBeanServerDelegate.java Wed Sep 17 13:45:37 2008 -0700
@@ -25,7 +25,9 @@
package javax.management;
+import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.defaults.ServiceName;
+import com.sun.jmx.mbeanserver.Util;
/**
* Represents the MBean server from the management point of view.
@@ -39,6 +41,7 @@ public class MBeanServerDelegate impleme
/** The MBean server agent identification.*/
private String mbeanServerId ;
+ private String mbeanServerName;
/** The NotificationBroadcasterSupport object that sends the
notifications */
@@ -68,6 +71,7 @@ public class MBeanServerDelegate impleme
public MBeanServerDelegate () {
stamp = getStamp();
broadcaster = new NotificationBroadcasterSupport() ;
+ mbeanServerName=null;
}
@@ -82,11 +86,100 @@ public class MBeanServerDelegate impleme
try {
localHost = java.net.InetAddress.getLocalHost().getHostName();
} catch (java.net.UnknownHostException e) {
+ JmxProperties.MISC_LOGGER.finest("Can't get local host name, " +
+ "using \"localhost\" instead. Cause is: "+e);
localHost = "localhost";
}
- mbeanServerId = localHost + "_" + stamp;
+ mbeanServerId =
+ Util.insertMBeanServerName(localHost + "_" + stamp,
+ mbeanServerName);
}
return mbeanServerId;
+ }
+
+ /**
+ * The name of the MBeanServer.
+ * @return The name of the MBeanServer, or {@value
+ * javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if no
+ * name was specified.
+ *
+ * @since 1.7
+ * @see #setMBeanServerName
+ */
+ public synchronized String getMBeanServerName() {
+ if (Util.isMBeanServerNameUndefined(mbeanServerName))
+ return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
+ return mbeanServerName;
+ }
+
+ /**
+ * Sets the name of the MBeanServer. The name will be embedded into the
+ * {@link #getMBeanServerId MBeanServerId} using the following format:<br>
+ * {@code mbeanServerId: <mbeanServerId>;mbeanServerName=<mbeanServerName>}
+ * <p>The characters {@code ':'} (colon), {@code ';'} (semicolon ),
+ * {@code '*'} (star) and {@code '?'} (question mark) are not legal in an
+ * MBean Server name.</p>
+ * <p>For instance, if the {@code mbeanServerName} provided is
+ * {@code "com.mycompany.myapp.server1"}, and the original
+ * {@code MBeanServerId} was {@code "myhost_1213353064145"},
+ * then {@code mbeanServerName} will be
+ * embedded in the {@code MBeanServerId} - and the new value of the
+ * {@code MBeanServerId} will be:
+ * </p>
+ * <pre>
+ * "myhost_1213353064145;mbeanServerName=com.mycompany.myapp.server1"
+ * </pre>
+ * <p>Note: The {@code mbeanServerName} is usually set by the
+ * {@code MBeanServerFactory}. It is set only once, before the
+ * MBean Server is returned by the factory. Once the MBean Server name is
+ * set, it is not possible to change it.
+ * </p>
+ * @param mbeanServerName The MBeanServer name.
+ * @throws IllegalArgumentException if the MBeanServerName is already set
+ * to a different value, or if the provided name contains
+ * illegal characters, or if the provided name is {@code ""}
+ * (the empty string) or "-" (dash).
+ * @throws UnsupportedOperationException if this object is of a legacy
+ * subclass of MBeanServerDelegate which overrides {@link
+ * #getMBeanServerId()}
+ * in a way that doesn't support setting an MBeanServer name.
+ * @see MBeanServerFactory#getMBeanServerName
+ * @since 1.7
+ */
+ public synchronized void setMBeanServerName(String mbeanServerName) {
+ // Sets the name on the delegate. For complex backward
+ // compatibility reasons it is not possible to give the
+ // name to the MBeanServerDelegate constructor.
+ //
+ // The method setMBeanServerName() will call getMBeanServerId()
+ // to check that the name is accurately set in the MBeanServerId.
+ // If not (which could happen if a custom MBeanServerDelegate
+ // implementation overrides getMBeanServerId() and was not updated
+ // with respect to JMX 2.0 spec), this method will throw an
+ // IllegalStateException...
+
+ // will fail if mbeanServerName is illegal
+ final String name = Util.checkServerName(mbeanServerName);
+
+ // can only set mbeanServerDelegate once.
+ if (this.mbeanServerName != null && !this.mbeanServerName.equals(name))
+ throw new IllegalArgumentException(
+ "MBeanServerName already set to a different value");
+
+ this.mbeanServerName = name;
+
+ // will fail if mbeanServerId already has a different mbeanServerName
+ mbeanServerId =
+ Util.insertMBeanServerName(getMBeanServerId(),name);
+
+ // check that we don't have a subclass which overrides
+ // getMBeanServerId() without setting mbeanServerName
+ if (!name.equals(
+ Util.extractMBeanServerName(getMBeanServerId())))
+ throw new UnsupportedOperationException(
+ "Can't set MBeanServerName in MBeanServerId - " +
+ "unsupported by "+this.getClass().getName()+"?");
+ // OK: at this point we know that we have correctly set mbeanServerName.
}
/**
@@ -210,15 +303,8 @@ public class MBeanServerDelegate impleme
*
* @since 1.6
*/
- public static final ObjectName DELEGATE_NAME;
- static {
- try {
- DELEGATE_NAME =
- new ObjectName("JMImplementation:type=MBeanServerDelegate");
- } catch (MalformedObjectNameException e) {
- throw new Error("Can't initialize delegate name", e);
- }
- }
+ public static final ObjectName DELEGATE_NAME =
+ Util.newObjectName("JMImplementation:type=MBeanServerDelegate");
/* Return a timestamp that is monotonically increasing even if
System.currentTimeMillis() isn't (for example, if you call this
--- a/src/share/classes/javax/management/MBeanServerFactory.java Thu Sep 11 11:27:16 2008 -0700
+++ b/src/share/classes/javax/management/MBeanServerFactory.java Wed Sep 17 13:45:37 2008 -0700
@@ -25,15 +25,18 @@
package javax.management;
+import com.sun.jmx.defaults.JmxProperties;
import static com.sun.jmx.defaults.JmxProperties.JMX_INITIAL_BUILDER;
import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
-import com.sun.jmx.interceptor.DefaultMBeanServerInterceptor;
import com.sun.jmx.mbeanserver.GetPropertyAction;
+import com.sun.jmx.mbeanserver.Util;
import java.security.AccessController;
import java.security.Permission;
import java.util.ArrayList;
+import java.util.List;
import java.util.logging.Level;
import javax.management.loading.ClassLoaderRepository;
+
/**
* <p>Provides MBean server references. There are no instances of
@@ -80,9 +83,52 @@ import javax.management.loading.ClassLoa
* returned by the default MBeanServerBuilder implementation, for the purpose
* of e.g. adding an additional security layer.</p>
*
+ * <p id="MBeanServerName">Since version 2.0 of the JMX API, when creating
+ * an MBeanServer,
+ * it is possible to specify an {@linkplain #getMBeanServerName
+ * MBean Server name}.
+ * To create an MBean Server with a name, the MBeanServerFactory provides two
+ * new methods:</p>
+ * <ul><li>{@link #createNamedMBeanServer
+ * createNamedMBeanServer(mbeanServerName, defaultDomain)}: creates a named
+ * MBeanServer and keeps an internal reference to the created object. The
+ * MBeanServer can be later retrieved using {@link #findMBeanServer
+ * findMBeanServer(mbeanServerId)} or
+ * {@link #findMBeanServerByName findMBeanServerByName(mbeanServerName)}, and
+ * can be released through {@link
+ * #releaseMBeanServer releaseMBeanServer(mbeanServer)}.</li>
+ * <li>{@link #newNamedMBeanServer
+ * newNamedMBeanServer(mbeanServerName, defaultDomain)}:
+ * creates a named MBeanServer without keeping any internal reference to the
+ * named server.</li>
+ * </ul>
+ * <p>The name of the MBeanServer is stored in the
+ * {@linkplain MBeanServerDelegate MBean Server delegate MBean}
+ * and is embedded in its {@link MBeanServerDelegate#getMBeanServerId
+ * MBeanServerId} attribute.</p>
+ * <p>The name of the MBeanServer is particularly useful when
+ * <a href="MBeanServer.html#security">MBean permissions</a> are checked:
+ * it makes it
+ * possible to distinguish between an MBean named "X" in MBeanServer named
+ * "M1", and another MBean of the same name "X" in another MBeanServer named
+ * "M2".</p>
+ * <p>When naming MBean servers it is recommended to use a name that starts
+ * with a Java package name. It is also recommended that the default domain and
+ * the MBeanServer name be the same.</p>
+ *
* @since 1.5
*/
public class MBeanServerFactory {
+
+ /**
+ * The <a href="#MBeanServerName">MBean Server name</a> that will be
+ * checked by a <a href="MBeanServer.html#security">permission you need</a>
+ * when checking access to an MBean registered in an MBeanServer for
+ * which no MBeanServer name was specified.
+ *
+ * @since 1.7
+ */
+ public final static String DEFAULT_MBEANSERVER_NAME = "default";
/*
* There are no instances of this class so don't generate the
@@ -222,37 +268,52 @@ public class MBeanServerFactory {
* <code>javax.management.builder.initial</code> exists and can be
* instantiated but is not assignment compatible with {@link
* MBeanServerBuilder}.
+ *
+ * @see #createNamedMBeanServer
*/
public static MBeanServer createMBeanServer(String domain) {
- checkPermission("createMBeanServer");
-
- final MBeanServer mBeanServer = newMBeanServer(domain);
- addMBeanServer(mBeanServer);
- return mBeanServer;
- }
-
- /**
- * <p>Return a new object implementing the MBeanServer interface
- * with a standard default domain name, without keeping an
- * internal reference to this new object. The default domain name
- * is used as the domain part in the ObjectName of MBeans when the
- * domain is specified by the user is null.</p>
- *
- * <p>The standard default domain name is
- * <code>DefaultDomain</code>.</p>
- *
- * <p>No reference is kept. <CODE>findMBeanServer</CODE> will not
- * be able to return a reference to this MBeanServer object, but
- * the garbage collector will be able to remove the MBeanServer
- * object when it is no longer referenced.</p>
- *
- * <p>This method is equivalent to <code>newMBeanServer(null)</code>.</p>
+ return createMBeanServer(null,domain);
+ }
+
+ /**
+ * <p>Return a new object implementing the {@link MBeanServer}
+ * interface with the specified
+ * <a href="#MBeanServerName">MBean Server name</a>
+ * and default domain name. The given MBean server name
+ * is used in <a href="MBeanServer.html#security">security checks</a>, and
+ * can also be used to {@linkplain #findMBeanServerByName(java.lang.String)
+ * find an MBeanServer by name}. The given
+ * domain name is used as the domain part in the ObjectName of
+ * MBeans when the domain is specified by the user is null.</p>
+ *
+ * <p>The MBeanServer reference is internally kept. This will