diff --git a/.hgtags b/.hgtags
index 75a9825e99c3ee88565553aaacbccaf33e07a592..5a4391f4df5a7edb593299553f18709e723fd3a9 100644
--- a/.hgtags
+++ b/.hgtags
@@ -8,3 +8,5 @@ b6d6877c1155621a175dccd12dc14c54f938fb8b jdk7-b30
b7474b739d13bacd9972f88ac91f6350b7b0be12 jdk7-b31
c51121419e30eac5f0fbbce45ff1711c4ce0de28 jdk7-b32
fa4c0a6cdd25d97d4e6f5d7aa180bcbb0e0d56af jdk7-b33
+434055a0716ee44bca712ebca02fc04b20e6e288 jdk7-b34
+cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35
diff --git a/make/common/Defs.gmk b/make/common/Defs.gmk
index a0cb9481c038c9f13ef0dd7dab3823e8e597405a..0c7e34014dfe62a10115186a83e586545ebea4d6 100644
--- a/make/common/Defs.gmk
+++ b/make/common/Defs.gmk
@@ -451,7 +451,7 @@ vpath %.$(OBJECT_SUFFIX) $(OBJDIR)
# namely jni.h, jvm.h, and jni_utils.h, plus their platform-specific
# relatives.
#
-VPATH.h = $(PLATFORM_SRC)/javavm/export$(CLASSPATH_SEPARATOR)$(SHARE_SRC)/javavm/export$(CLASSPATH_SEPARATOR)$(SHARE_SRC)/javavm/include$(CLASSPATH_SEPARATOR)$(PLATFORM_SRC)/javavm/include
+VPATH.h = $(PLATFORM_SRC)/javavm/export$(CLASSPATH_SEPARATOR)$(SHARE_SRC)/javavm/export
vpath %.h $(VPATH.h)
#
diff --git a/make/common/shared/Defs-windows.gmk b/make/common/shared/Defs-windows.gmk
index 250604136bc3141a57fc737d75610d51b10dc64b..d0be243d8e1b37f457f2194a661a4e064dc54581 100644
--- a/make/common/shared/Defs-windows.gmk
+++ b/make/common/shared/Defs-windows.gmk
@@ -539,6 +539,8 @@ else
WSCRIPT :=$(call FileExists,$(_WSCRIPT1),$(_WSCRIPT2))
endif
WSCRIPT:=$(call AltCheckSpaces,WSCRIPT)
+# batch mode no modal dialogs on errors, please.
+WSCRIPT += -B
# CSCRIPT: path to cscript.exe (used in creating install bundles)
ifdef ALT_CSCRIPT
@@ -561,6 +563,10 @@ else
MSIVAL2 :=$(call FileExists,$(_MSIVAL2_1),$(_MSIVAL2_2))
endif
MSIVAL2:=$(call AltCheckSpaces,MSIVAL2)
+# suppress msival2 checks, as it hangs jprt builds
+ifdef SKIP_MSIVAL2
+ MSIVAL2 := $(ECHO)
+endif
# LOGOCUB: path to cub file for (used in validating install msi files)
ifdef ALT_LOGOCUB
diff --git a/make/docs/CORE_PKGS.gmk b/make/docs/CORE_PKGS.gmk
index dfedc7e123781eb3cad4458ce62fee3f603d8fc6..4a41a2005bf6b361f6c223ae355cb07e085a36c2 100644
--- a/make/docs/CORE_PKGS.gmk
+++ b/make/docs/CORE_PKGS.gmk
@@ -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 \
diff --git a/make/java/java/FILES_java.gmk b/make/java/java/FILES_java.gmk
index b4a07fc352f3ec59bef6222693f542b5d7942110..2531ce7230ce3ffb1573b2ab1ad3c29e1537ad81 100644
--- a/make/java/java/FILES_java.gmk
+++ b/make/java/java/FILES_java.gmk
@@ -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)
diff --git a/make/java/java/mapfile-vers b/make/java/java/mapfile-vers
index ad0380979a94984fccef0db39553da27bfb8d6ad..77a78301af721f9aca72358a1b4ae554bbf2bc49 100644
--- a/make/java/java/mapfile-vers
+++ b/make/java/java/mapfile-vers
@@ -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;
diff --git a/make/java/jli/Makefile b/make/java/jli/Makefile
index 5a1c312d7abb07298a283e6afc5257c38e5b70b7..7a0c53f1ce2f72caa677630e274ebe77fa0ef88e 100644
--- a/make/java/jli/Makefile
+++ b/make/java/jli/Makefile
@@ -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
diff --git a/make/java/jli/mapfile-vers b/make/java/jli/mapfile-vers
index a9e8198dea1e7b06a810053f26de00bf8bbf3ef1..e04e4f13db94dc582bb3a426b1b777be03fb747f 100644
--- a/make/java/jli/mapfile-vers
+++ b/make/java/jli/mapfile-vers
@@ -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:
*;
};
diff --git a/make/java/net/mapfile-vers b/make/java/net/mapfile-vers
index 86cb351c9f935c9a60bf540146d400328f7ac62e..e7da6186ecc9dbcc7056b18984663553b3d63c95 100644
--- a/make/java/net/mapfile-vers
+++ b/make/java/net/mapfile-vers
@@ -57,7 +57,7 @@ SUNWprivate_1.1 {
Java_java_net_Inet6AddressImpl_isReachable0;
Java_java_net_NetworkInterface_init;
Java_java_net_NetworkInterface_getByName0;
- Java_java_net_NetworkInterface_getByIndex;
+ Java_java_net_NetworkInterface_getByIndex0;
Java_java_net_NetworkInterface_getByInetAddress0;
Java_java_net_NetworkInterface_getAll;
Java_java_net_NetworkInterface_isUp0;
diff --git a/make/java/nio/FILES_java.gmk b/make/java/nio/FILES_java.gmk
index 5958812adfb55160c41b3319254debce3320e52b..8a6177b0a0ba9c99ff85c03f856026b9f9be4d7d 100644
--- a/make/java/nio/FILES_java.gmk
+++ b/make/java/nio/FILES_java.gmk
@@ -26,6 +26,7 @@
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)
diff --git a/make/java/nio/Makefile b/make/java/nio/Makefile
index cff9ce5ceb29648f2bc50564199cf18c009f59c4..26c2f2fc68d0218fc30fad31bbaa39959878b1d6 100644
--- a/make/java/nio/Makefile
+++ b/make/java/nio/Makefile
@@ -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 @@ $(BUF_GEN)/%Exception.java: genExceptions.sh $(BUF_SRC)/exceptions
@$(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 @@ $(SCS_GEN)/StandardCharsets.java: genCharsetProvider.sh \
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
diff --git a/make/java/nio/mapfile-linux b/make/java/nio/mapfile-linux
index dc2044c9d7925ccbced446ad4654cebc307ddc79..3fb47b0eb7c0e42107f01113f529ee39b96726f9 100644
--- a/make/java/nio/mapfile-linux
+++ b/make/java/nio/mapfile-linux
@@ -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:
*;
diff --git a/make/java/nio/mapfile-solaris b/make/java/nio/mapfile-solaris
index 77ef8ea2ad9083b9d1cc08411a70facd251fe6f4..6e109e2fabaf9be9aed350acf55ece2eb833265f 100644
--- a/make/java/nio/mapfile-solaris
+++ b/make/java/nio/mapfile-solaris
@@ -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:
*;
diff --git a/make/java/verify/Makefile b/make/java/verify/Makefile
index c647d5085693035387ecd17c4025a2fe4b215cb6..24bcc0f48d4aa17f70190b3b69c9997e610bd543 100644
--- a/make/java/verify/Makefile
+++ b/make/java/verify/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 1999-2005 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
@@ -52,12 +52,6 @@ FILES_c = \
check_code.c \
check_format.c
-#
-# libverify.so needs these 2 header files (opcodes.h opcodes.length)
-# from the VM.
-#
-CPPFLAGS += -I$(SHARE_SRC)/javavm/include
-
#
# Targets.
#
diff --git a/make/jprt.properties b/make/jprt.properties
index 06abef8c8e6a1bb4bf13b4d4b072f34a63a918b4..e6666cb1d6c5e528ca8d0b95a0387ef2b31171a4 100644
--- a/make/jprt.properties
+++ b/make/jprt.properties
@@ -55,6 +55,5 @@ jprt.solaris_x64.build.platform.match32=solaris_i586_5.10
jprt.test.targets=*-*-*-jvm98
# Directories needed to build
-jprt.bundle.src.dirs=make src
jprt.bundle.exclude.src.dirs=build
diff --git a/make/mksample/nio/Makefile b/make/mksample/nio/Makefile
index a6e8fc46d964f8d3ddd066164374ca867014bd17..1f17a4cce20ab844cb7fa0c29d3b3c50466f9c55 100644
--- a/make/mksample/nio/Makefile
+++ b/make/mksample/nio/Makefile
@@ -31,7 +31,7 @@ BUILDDIR = ../..
PRODUCT = java
include $(BUILDDIR)/common/Defs.gmk
-SUBDIRS = server
+SUBDIRS = multicast server
all build clean clobber::
$(SUBDIRS-loop)
diff --git a/src/share/classes/sun/nio/ch/exceptions b/make/mksample/nio/multicast/Makefile
similarity index 65%
rename from src/share/classes/sun/nio/ch/exceptions
rename to make/mksample/nio/multicast/Makefile
index 55d295f871d4c5b03273f102d2c7d9188c975916..05a153a13150cef106a6ec44498f12f4e059b1db 100644
--- a/src/share/classes/sun/nio/ch/exceptions
+++ b/make/mksample/nio/multicast/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -23,17 +23,30 @@
# have any questions.
#
-# Generated exception classes for sun.nio.ch
+#
+# Makefile for the nio/multicast sample code
+#
+
+BUILDDIR = ../../..
+
+PRODUCT = java
+
+include $(BUILDDIR)/common/Defs.gmk
+
+SAMPLE_SRC_DIR = $(SHARE_SRC)/sample/nio/multicast
+SAMPLE_DST_DIR = $(SAMPLEDIR)/nio/multicast
+
+SAMPLE_FILES = \
+ $(SAMPLE_DST_DIR)/Reader.java \
+ $(SAMPLE_DST_DIR)/Sender.java \
+ $(SAMPLE_DST_DIR)/MulticastAddress.java
-SINCE=1.4
-PACKAGE=sun.nio.ch
-# This year should only change if the generated source is modified.
-COPYRIGHT_YEARS=2000-2007
+all build: $(SAMPLE_FILES)
+$(SAMPLE_DST_DIR)/%: $(SAMPLE_SRC_DIR)/%
+ $(install-file)
-SUPER=IllegalStateException
+clean clobber:
+ $(RM) -r $(SAMPLE_DST_DIR)
-gen AlreadyBoundException "
- * Unchecked exception thrown when an attempt is made to bind a {@link
- * SocketChannel} that is already bound." \
- 9002280723481772026L
+.PHONY: all build clean clobber
diff --git a/make/netbeans/awt2d/README b/make/netbeans/awt2d/README
index a990726b787c7d8b9d1aa1ad3c7b1c8275425d27..040c9e76919d4ad76f903542cf6a7e1905c3a091 100644
--- a/make/netbeans/awt2d/README
+++ b/make/netbeans/awt2d/README
@@ -145,7 +145,6 @@ Notes on using CND (C/C++ pack) with this project and NetBeans.
(a somewhat complete list of awt and 2d native directories on windows):
../../src/share/javavm/export;
- ../../src/share/javavm/include;
../../src/share/native/common;
../../src/share/native/sun/awt/debug;
../../src/share/native/sun/awt/image/cvutils;
diff --git a/make/sun/net/spi/Makefile b/make/sun/net/spi/Makefile
index 20583bc4eb73ef7018a4800c7f4e4f85acabc2cf..f969b87992acf8228384a1386ad924abb94b3b81 100644
--- a/make/sun/net/spi/Makefile
+++ b/make/sun/net/spi/Makefile
@@ -23,10 +23,6 @@
# have any questions.
#
-#
-# Makefile for building com/sun
-#
-
BUILDDIR = ../../..
include $(BUILDDIR)/common/Defs.gmk
diff --git a/make/sun/net/spi/nameservice/Makefile b/make/sun/net/spi/nameservice/Makefile
index b6593c71d559b5160360493991d1708244ba387b..b0ff374de3d09be753c34964cf9d298fd9ffb8f2 100644
--- a/make/sun/net/spi/nameservice/Makefile
+++ b/make/sun/net/spi/nameservice/Makefile
@@ -23,10 +23,6 @@
# have any questions.
#
-#
-# Makefile for building com/sun
-#
-
BUILDDIR = ../../../..
include $(BUILDDIR)/common/Defs.gmk
diff --git a/make/sun/net/spi/nameservice/dns/Makefile b/make/sun/net/spi/nameservice/dns/Makefile
index a882eada97a423cee91478836fa7057eff15e1d4..daf35125d110223c05b67a36c7bdc616b07de137 100644
--- a/make/sun/net/spi/nameservice/dns/Makefile
+++ b/make/sun/net/spi/nameservice/dns/Makefile
@@ -24,7 +24,7 @@
#
#
-# Makefile for building JNDI service provider toolkit
+# Makefile for building JNDI DNS name service provider
#
BUILDDIR = ../../../../..
diff --git a/make/tools/GenerateCharacter/check_class.c.template b/make/tools/GenerateCharacter/check_class.c.template
index d9a880f09707a7e6a8376aed94dd036367a1698c..02307e02a6beed7efab207038488a3bd48af814c 100644
--- a/make/tools/GenerateCharacter/check_class.c.template
+++ b/make/tools/GenerateCharacter/check_class.c.template
@@ -1,5 +1,5 @@
/*
- * Copyright 2002 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
@@ -37,7 +37,6 @@
#include "bool.h"
#include "utf.h"
#include "tree.h"
-#include "sys_api.h"
extern bool_t verify_class_codes(ClassClass *cb);
diff --git a/src/share/back/debugDispatch.c b/src/share/back/debugDispatch.c
index 98a86fe588956e54b85244f852979091a79311ab..fa633799061d4db55119980f9b8890cfa2b5f47d 100644
--- a/src/share/back/debugDispatch.c
+++ b/src/share/back/debugDispatch.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2005 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
@@ -41,7 +41,6 @@
#include "ArrayReferenceImpl.h"
#include "EventRequestImpl.h"
#include "StackFrameImpl.h"
-#include "typedefs.h"
static void **l1Array;
diff --git a/src/share/back/error_messages.c b/src/share/back/error_messages.c
index f40af69a335682f7779e8ccd92b96af89a44777d..30acacd4ef27966a80fa81da4670c993b5c593d3 100644
--- a/src/share/back/error_messages.c
+++ b/src/share/back/error_messages.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,6 @@
#include "util.h"
#include "proc_md.h"
-#include "typedefs.h"
/* Maximim length of a message */
#define MAX_MESSAGE_LEN MAXPATHLEN*2+512
diff --git a/src/share/back/inStream.c b/src/share/back/inStream.c
index 45534fcdc546d4ccbe82e16db1712cff79ac84c5..1f5b685c5adf5cca5d6a762df2dff9353f52b332 100644
--- a/src/share/back/inStream.c
+++ b/src/share/back/inStream.c
@@ -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
@@ -30,7 +30,6 @@
#include "bag.h"
#include "commonRef.h"
#include "FrameID.h"
-#include "typedefs.h"
#define INITIAL_REF_ALLOC 50
#define SMALLEST(a, b) ((a) < (b)) ? (a) : (b)
diff --git a/src/share/back/outStream.h b/src/share/back/outStream.h
index a57cc47115175140f8bc2708e3ff8b6482a224c2..83d1eb10ffebdc4bfcf71373471ac131de118033 100644
--- a/src/share/back/outStream.h
+++ b/src/share/back/outStream.h
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2005 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
@@ -26,8 +26,6 @@
#ifndef JDWP_OUTSTREAM_H
#define JDWP_OUTSTREAM_H
-#include "typedefs.h"
-
#include "transport.h"
#include "FrameID.h"
diff --git a/src/share/bin/emessages.h b/src/share/bin/emessages.h
index 03824bba5d1570138953afcd333d194c5257f263..008cc1f906a6e93cb7894c92ae9bbba7d8b7c3e0 100644
--- a/src/share/bin/emessages.h
+++ b/src/share/bin/emessages.h
@@ -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
diff --git a/src/share/bin/java.c b/src/share/bin/java.c
index f7cbcdc95bce46ab467dd1af347b882dd9ac5c95..89ae857b1366baadcd4ee0ba7c82b818b59e0db0 100644
--- a/src/share/bin/java.c
+++ b/src/share/bin/java.c
@@ -148,7 +148,7 @@ static void ShowSplashScreen();
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, jboolean speculative) {
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, jboolean speculative) {
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, jboolean speculative) {
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, jboolean speculative) {
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, char **main_class)
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, char **main_class)
* 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, char **main_class)
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, char **pjarfile,
* 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, char **pjarfile,
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 **penv, InvocationFunctions *ifn)
#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, const char **jargv, int *pargc, char ***parg
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 char **cpathv)
}
if (!GetApplicationHome(home, sizeof(home))) {
- ReportErrorMessage(CFG_ERROR5);
+ JLI_ReportErrorMessage(CFG_ERROR5);
return JNI_FALSE;
}
@@ -1691,7 +1691,7 @@ ReadKnownVMs(const char *jrepath, const char * arch, jboolean speculative)
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 char * arch, jboolean speculative)
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 char * arch, jboolean speculative)
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 char * arch, jboolean speculative)
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 char * arch, jboolean speculative)
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 char * arch, jboolean speculative)
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);
diff --git a/src/share/bin/java.h b/src/share/bin/java.h
index e6a08f3cf009b00ea68a6282164d4e5585745ec0..23871b5d2a1a045285a52da918417349e846935a 100644
--- a/src/share/bin/java.h
+++ b/src/share/bin/java.h
@@ -121,24 +121,20 @@ void CreateExecutionEnvironment(int *_argc,
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, ...);
-/*
- * Report an error message to stderr or a window as appropriate.
- */
-void ReportErrorMessage(const char * message, ...);
-void ReportErrorMessageSys(const char * format, ...);
+/* Reports a system error message to stderr or a window */
+void JLI_ReportErrorMessageSys(const char * message, ...);
-/*
- * Report an error message only to stderr.
- */
-void ReportMessage(const char * message, ...);
+/* Reports an error message only to stderr. */
+void JLI_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();
diff --git a/src/share/classes/com/sun/jmx/defaults/JmxProperties.java b/src/share/classes/com/sun/jmx/defaults/JmxProperties.java
index 89cd5bf16bf0c814cc1bc4e70134fe070db5e99a..b4bbbb78d49aff6ba1ae07daf04006033d53d7d8 100644
--- a/src/share/classes/com/sun/jmx/defaults/JmxProperties.java
+++ b/src/share/classes/com/sun/jmx/defaults/JmxProperties.java
@@ -176,6 +176,18 @@ public class JmxProperties {
public static final String RELATION_LOGGER_NAME =
"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.
*/
diff --git a/src/share/classes/com/sun/jmx/event/LeaseManager.java b/src/share/classes/com/sun/jmx/event/LeaseManager.java
index cb1b88bf514919d30f0065f4bd52e1299f3033ed..33409a06ce93e22f932a96ccd60e9835ab709a87 100644
--- a/src/share/classes/com/sun/jmx/event/LeaseManager.java
+++ b/src/share/classes/com/sun/jmx/event/LeaseManager.java
@@ -27,7 +27,6 @@ package com.sun.jmx.event;
import com.sun.jmx.remote.util.ClassLogger;
import java.util.concurrent.Executors;
-import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -115,6 +114,7 @@ public class LeaseManager {
scheduled = null;
}
callback.run();
+ executor.shutdown();
}
}
@@ -131,6 +131,13 @@ public class LeaseManager {
logger.trace("stop", "canceling lease");
scheduled.cancel(false);
scheduled = null;
+ try {
+ executor.shutdown();
+ } catch (SecurityException e) {
+ // OK: caller doesn't have RuntimePermission("modifyThread")
+ // which is unlikely in reality but triggers a test failure otherwise
+ logger.trace("stop", "exception from executor.shutdown", e);
+ }
}
private final Runnable callback;
@@ -138,7 +145,7 @@ public class LeaseManager {
private final ScheduledExecutorService executor
= Executors.newScheduledThreadPool(1,
- new DaemonThreadFactory("LeaseManager"));
+ new DaemonThreadFactory("JMX LeaseManager %d"));
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "LeaseManager");
diff --git a/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java b/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java
index 7de1b40e92d4f41ebfb2fe1ffb77428d6fb6f6ad..2fe4a3a152b8f54fa3557944cfdcc24a7b52f3de 100644
--- a/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java
+++ b/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java
@@ -95,7 +95,9 @@ public abstract class RepeatedSingletonJob implements Runnable {
executor.execute(this);
} catch (RejectedExecutionException e) {
logger.warning(
- "setEventReceiver", "Executor threw exception", e);
+ "execute",
+ "Executor threw exception (" + this.getClass().getName() + ")",
+ e);
throw new RejectedExecutionException(
"Executor.execute threw exception -" +
"should not be possible", e);
diff --git a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java
index 8bd6cba27ce4e676c75e5f9eafb7d408f2b536cb..7da3406b911e0a06c681c3afe6b61d55487258ba 100644
--- a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java
+++ b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java
@@ -25,33 +25,49 @@
package com.sun.jmx.interceptor;
-// java import
+
+// 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.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
-import java.util.logging.Level;
+import java.util.Queue;
import java.util.Set;
-import java.util.HashSet;
import java.util.WeakHashMap;
-import java.lang.ref.WeakReference;
-import java.security.AccessControlContext;
-import java.security.Permission;
-import java.security.ProtectionDomain;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+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.MBeanTrustPermission;
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.ReflectionException;
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.NotificationBroadcasterSupport;
*
* @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 DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
* 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 DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
new WeakHashMap
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ * Adds a listener to a registered MBean. 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.
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
*/
- public void addNotificationListener(ObjectName name,
- NotificationListener listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException;
-
-
+ public Object instantiate(String className, ObjectName loaderName)
+ throws ReflectionException, MBeanException,
+ InstanceNotFoundException;
/**
- * Adds a listener to a registered MBean. 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. 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. 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.
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
*/
- public void removeNotificationListener(ObjectName name,
- ObjectName listener)
- throws InstanceNotFoundException, ListenerNotFoundException;
+ public Object instantiate(String className, ObjectName loaderName,
+ Object[] params, String[] signature)
+ throws ReflectionException, MBeanException,
+ InstanceNotFoundException;
/**
- * Removes a listener from a registered MBean. The MBean must have a listener that exactly matches the
- * given The Removes a listener from a registered MBean. 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.
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
*/
- public void removeNotificationListener(ObjectName name,
- NotificationListener listener)
- throws InstanceNotFoundException, ListenerNotFoundException;
+ @Deprecated
+ public ObjectInputStream deserialize(String className, byte[] data)
+ throws OperationsException, ReflectionException;
/**
- * Removes a listener from a registered MBean. The MBean must have a listener that exactly matches the
- * given The 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;
-
- /**
- * 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();
}
+
diff --git a/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java b/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e1cf681e864caa3980b69f3faf62622a09c2069
--- /dev/null
+++ b/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.interceptor;
+
+import java.io.ObjectInputStream;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.OperationsException;
+import javax.management.ReflectionException;
+import javax.management.loading.ClassLoaderRepository;
+
+/**
+ * An abstract class for MBeanServerInterceptorSupport.
+ * Some methods in MBeanServerInterceptor should never be called.
+ * This base class provides an implementation of these methods that simply
+ * throw an {@link UnsupportedOperationException}.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ * Do not forget to call Return the MBeanServerDelegate representing the MBeanServer.
diff --git a/src/share/classes/com/sun/jmx/mbeanserver/Util.java b/src/share/classes/com/sun/jmx/mbeanserver/Util.java
index b0f4f1dbfdec1668e1eea9dca1457d1734d5ce60..6307adbf8d92442278539c4377a7fe6d3d386c67 100644
--- a/src/share/classes/com/sun/jmx/mbeanserver/Util.java
+++ b/src/share/classes/com/sun/jmx/mbeanserver/Util.java
@@ -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,23 @@ import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.WeakHashMap;
+import java.util.logging.Level;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerDelegate;
+import javax.management.MBeanServerFactory;
import javax.management.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 char[] ILLEGAL_MBEANSERVER_NAME_CHARS=";:*?".
+ toCharArray();
+
+
static
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * By default, this method always returns {@code domains}
+ *
+ * @param domains The domains to return.
+ * @param action "getDomains"
+ * @return a filtered list of domains.
+ */
+ String[] checkDomains(String[] domains, String action) {
+ return domains;
+ }
+
+ // A priori check for queryNames/queryMBeans/
+ void checkPattern(ObjectName routingPattern,
+ String member, String action) {
+ // pattern is checked only at posteriori by checkQuery.
+ // checking it a priori usually doesn't work, because ObjectName.apply
+ // does not work between two patterns.
+ // We only check that we have the permission requested for 'action'.
+ check(null,null,action);
+ }
+
+
+
+}
diff --git a/src/share/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java b/src/share/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..49f875144f2751604094023018b1c2678ba3dd06
--- /dev/null
+++ b/src/share/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.namespace;
+
+import com.sun.jmx.defaults.JmxProperties;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanServerConnection;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.event.EventClient;
+import javax.management.event.EventClientDelegateMBean;
+import javax.management.namespace.JMXNamespace;
+import javax.management.namespace.JMXNamespaces;
+import javax.management.remote.JMXAddressable;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXServiceURL;
+import javax.security.auth.Subject;
+
+/**
+ * A collection of methods that provide JMXConnector wrappers for
+ * JMXRemoteNamepaces underlying connectors.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * Note: all the standard JMXConnector implementations are serializable.
+ * This implementation here is not. Should it be?
+ * I believe it must not be serializable unless it becomes
+ * part of a public API (either standard or officially exposed
+ * and supported in a documented com.sun package)
+ **/
+ static class JMXCachingConnector
+ implements JMXConnector {
+
+ // private static final long serialVersionUID = -2279076110599707875L;
+
+ final JMXConnector source;
+
+ // if this object is made serializable, then the variable below
+ // needs to become volatile transient and be lazyly-created...
+ private final
+ Map
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ * {@link RoutingConnectionProxy}: to narrow down into an
+ * MBeanServerConnection. {@link RoutingServerProxy}: to narrow down into an MBeanServer. This class can also be used to "broaden" from a namespace. The same
+ * class is used for both purposes because in both cases all that happens
+ * is that ObjectNames are rewritten in one way on the way in (e.g. the
+ * parameter of getMBeanInfo) and another way on the way out (e.g. the
+ * return value of queryNames). Specifically, if you narrow into "a//" then you want to add the
+ * "a//" prefix to ObjectNames on the way in and subtract it on the way
+ * out. But ClientContext uses this class to subtract the
+ * "jmx.context//foo=bar//" prefix on the way in and add it back on the
+ * way out.
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ * The DO NOT USE THESE CLASSES DIRECTLY
+ This API is a Sun internal API and is subject to changes without notice.
+ The public API through wich these proprietary classes can be
+ invoked is located in
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * This class is consulted by {@link javax.management.ObjectName} at
+ * serialization / deserialization time.
+ * The serialization or deserialization context is established by
+ * by the {@link SerialRewritingProcessor} defined in this package.
+ *
+ * These classes are Sun proprietary APIs, subject to change without
+ * notice. Do not use these classes directly.
+ * The public API to rewrite ObjectNames embedded in parameters is
+ * defined in {@link javax.management.namespace.JMXNamespaces}.
+ *
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ * When entering a {@link javax.management.namespace
+ * namespace}, the {@code namespace} prefix is stripped from
+ * ObjectNames contained in input parameters. When leaving a
+ * {@code namespace},
+ * the {@code namespace} prefix is prepended to the ObjectNames contained in
+ * the result parameters returned from that {@code namespace}.
+ * Objects that need to perform these operations usually use a
+ * {@code RewritingProcessor} for that purpose. A default implementation of {@code RewritingProcessor} based on
+ * Java Object Serialization can be
+ * obtained from {@link #newRewritingProcessor newRewritingProcessor}.
+ *
+ * By default, the instances of {@code RewritingProcessor} returned by
+ * {@link #newRewritingProcessor newRewritingProcessor} will rewrite
+ * ObjectNames contained in instances of classes they don't know about by
+ * serializing and then deserializing such object instances. This will
+ * happen even if such instances don't - or can't contain ObjectNames,
+ * because the default implementation of {@code RewritingProcessor} will
+ * not be able to determine whether instances of such classes can/do contain
+ * instance of ObjectNames before serializing/deserializing them.
+ * If you are using custom classes that the default implementation of
+ * {@code RewritingProcessor} don't know about, it can be interesting to
+ * prevent an instance of {@code RewritingProcessor} to serialize/deserialize
+ * instances of such classes for nothing. In that case, you could customize
+ * the behavior of such a {@code RewritingProcessor} by wrapping it in a
+ * custom subclass of {@code RewritingProcessor} as shown below:
+ * Such a subclass may also provide an alternate way of rewriting
+ * custom subclasses for which rewriting is needed - for instance:
+ * If your application only uses {@link javax.management.MXBean MXBeans},
+ * or MBeans using simple types, and doesn't define any custom subclass of
+ * {@link javax.management.Notification}, you should never write such
+ * such {@code RewitingProcessor} implementations.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ * This is equivalent to calling {@link
+ * #RewritingProcessor(RewritingProcessor) RewritingProcessor(null)}.
+ *
+ * Returns {@code obj}, if it is known that {@code obj} doesn't contain
+ * any ObjectName, or a new copied instance of {@code obj} in which
+ * ObjectNames (if any) will have been rewritten, if {@code obj} contains
+ * ObjectNames, or if it is not known whether {@code obj} contains
+ * ObjectNames or not.
+ *
+ * The default implementation of this method is as follows: if the
+ * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
+ * null}, throws an {@link IllegalArgumentException}. Otherwise,
+ * returns {@code delegate.rewriteOutput(obj)}.
+ * This behavior can be overridden by subclasses as shown in this
+ * class {@link RewritingProcessor description}.
+ *
+ * Returns {@code obj}, if it is known that {@code obj} doesn't contain
+ * any ObjectName, or a new copied instance of {@code obj} in which
+ * ObjectNames (if any) will have been rewritten, if {@code obj} contains
+ * ObjectNames, or if it is not known whether {@code obj} contains
+ * ObjectNames or not.
+ *
+ * The default implementation of this method is as follows: if the
+ * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
+ * null}, throws an {@link IllegalArgumentException}. Otherwise,
+ * returns {@code delegate.rewriteInput(obj)}.
+ * This behavior can be overridden by subclasses as shown in this
+ * class {@link RewritingProcessor description}.
+ *
+ * The default implementation of this method is as follows: if the
+ * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
+ * null}, throws an {@link IllegalArgumentException}. Otherwise,
+ * returns {@code delegate.toSourceContext(targetName)}.
+ * This behavior can be overridden by subclasses as shown in this
+ * class {@link RewritingProcessor description}.
+ *
+ * The default implementation of this method is as follows: if the
+ * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
+ * null}, throws an {@link IllegalArgumentException}. Otherwise,
+ * returns {@code delegate.toTargetContext(sourceName)}.
+ * This behavior can be overridden by subclasses as shown in this
+ * class {@link RewritingProcessor description}.
+ *
+ * The default implementation of this method is as follows: if the
+ * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
+ * null}, throws an {@link IllegalArgumentException}. Otherwise,
+ * returns {@code delegate.toTargetContext(sourceMoi)}.
+ * This behavior can be overridden by subclasses as shown in this
+ * class {@link RewritingProcessor description}.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ *
+ * This API is a Sun internal API and is subject to changes without notice.
+ * The NEVER USE THESE CLASSES DIRECTLY
+ This API is a Sun internal API and is subject to changes without notice.
+ The public API through which these proprietary classes can be invoked is
+ located in
+ *
+ * @param transformation the name of the transformation, e.g.,
+ *
- *
- * @param transformation the name of the transformation, e.g.,
- * Channels Description A channel represents an open connection to an entity such as a
-hardware device, a file, a network socket, or a program component that is
-capable of performing one or more distinct I/O operations, for example reading
-or writing. As specified in the {@link java.nio.channels.Channel} interface,
-channels are either open or closed, and they are both asynchronously
-closeable and interruptible.
-
- The {@link java.nio.channels.Channel} interface is extended by several
-other interfaces, each of which specifies a new I/O operation.
-
- The {@link java.nio.channels.ReadableByteChannel} interface specifies a
-{@link java.nio.channels.ReadableByteChannel#read read} method that reads bytes
-from the channel into a buffer; similarly, the {@link
-java.nio.channels.WritableByteChannel} interface specifies a {@link
-java.nio.channels.WritableByteChannel#write write} method that writes bytes
-from a buffer to the channel. The {@link java.nio.channels.ByteChannel}
-interface unifies these two interfaces for the common case of channels that can
-both read and write bytes.
-
- The {@link java.nio.channels.ScatteringByteChannel} and {@link
-java.nio.channels.GatheringByteChannel} interfaces extend the {@link
-java.nio.channels.ReadableByteChannel} and {@link
-java.nio.channels.WritableByteChannel} interfaces, respectively, adding {@link
-java.nio.channels.ScatteringByteChannel#read read} and {@link
-java.nio.channels.GatheringByteChannel#write write} methods that take a
-sequence of buffers rather than a single buffer.
-
- The {@link java.nio.channels.Channels} utility class defines static methods
-that support the interoperation of the stream classes of the {@link
-java.io} package with the channel classes of this package. An appropriate
-channel can be constructed from an {@link java.io.InputStream} or an {@link
-java.io.OutputStream}, and conversely an {@link java.io.InputStream} or an
-{@link java.io.OutputStream} can be constructed from a channel. A {@link
-java.io.Reader} can be constructed that uses a given charset to decode bytes
-from a given readable byte channel, and conversely a {@link java.io.Writer} can
-be constructed that uses a given charset to encode characters into bytes and
-write them to a given writable byte channel.
-
-
- File channels Description The {@link java.nio.channels.FileChannel} class supports the usual
-operations of reading bytes from, and writing bytes to, a channel connected to
-a file, as well as those of querying and modifying the current file position
-and truncating the file to a specific size. It defines methods for acquiring
-locks on the whole file or on a specific region of a file; these methods return
-instances of the {@link java.nio.channels.FileLock} class. Finally, it defines
-methods for forcing updates to the file to be written to the storage device that
-contains it, for efficiently transferring bytes between the file and other
-channels, and for mapping a region of the file directly into memory. This last
-operation creates an instance of the {@link java.nio.MappedByteBuffer}
-class, which extends the {@link java.nio.ByteBuffer} class with several
-file-related operations.
-
- A getChannel method has been added to each of the {@link
-java.io.FileInputStream#getChannel FileInputStream}, {@link
-java.io.FileOutputStream#getChannel FileOutputStream}, and {@link
-java.io.RandomAccessFile#getChannel RandomAccessFile} classes of the {@link
-java.io java.io} package. Invoking this method upon an instance of one of
-these classes will return a file channel connected to the underlying file.
-
-
-
-
- Multiplexed, non-blocking I/O Description Multiplexed, non-blocking I/O, which is much more scalable than
-thread-oriented, blocking I/O, is provided by selectors, selectable
-channels, and selection keys.
-
- A selector is a multiplexor of selectable channels, which in turn are
-a special type of channel that can be put into non-blocking mode. To perform
-multiplexed I/O operations, one or more selectable channels are first created,
-put into non-blocking mode, and {@link
-java.nio.channels.SelectableChannel#register registered Once some channels have been registered with a selector, a selection operation can be performed in
-order to discover which channels, if any, have become ready to perform one or
-more of the operations in which interest was previously declared. If a channel
-is ready then the key returned when it was registered will be added to the
-selector's selected-key set. The key set, and the keys within it, can
-be examined in order to determine the operations for which each channel is
-ready. From each key one can retrieve the corresponding channel in order to
-perform whatever I/O operations are required.
-
- That a selection key indicates that its channel is ready for some operation
-is a hint, but not a guarantee, that such an operation can be performed by a
-thread without causing the thread to block. It is imperative that code that
-performs multiplexed I/O be written so as to ignore these hints when they prove
-to be incorrect.
-
- This package defines selectable-channel classes corresponding to the {@link
-java.net.DatagramSocket}, {@link java.net.ServerSocket}, and {@link
-java.net.Socket} classes defined in the {@link java.net} package.
-Minor changes to these classes have been made in order to support sockets that
-are associated with channels. This package also defines a simple class that
-implements unidirectional pipes. In all cases, a new selectable channel is
-created by invoking the static open method of the corresponding class.
-If a channel needs an associated socket then a socket will be created as a side
-effect of this operation.
-
- The implementation of selectors, selectable channels, and selection keys
-can be replaced by "plugging in" an alternative definition or instance of the
-{@link java.nio.channels.spi.SelectorProvider} class defined in the {@link
-java.nio.channels.spi} package. It is not expected that many developers
-will actually make use of this facility; it is provided primarily so that
-sophisticated users can take advantage of operating-system-specific
-I/O-multiplexing mechanisms when very high performance is required.
-
- Much of the bookkeeping and synchronization required to implement the
-multiplexed-I/O abstractions is performed by the {@link
-java.nio.channels.spi.AbstractInterruptibleChannel}, {@link
-java.nio.channels.spi.AbstractSelectableChannel}, {@link
-java.nio.channels.spi.AbstractSelectionKey}, and {@link
-java.nio.channels.spi.AbstractSelector} classes in the {@link
-java.nio.channels.spi} package. When defining a custom selector provider,
-only the {@link java.nio.channels.spi.AbstractSelector} and {@link
-java.nio.channels.spi.AbstractSelectionKey} classes should be subclassed
-directly; custom channel classes should extend the appropriate {@link
-java.nio.channels.SelectableChannel} subclasses defined in this package.
-
- Unless otherwise noted, passing a null argument to a constructor
-or method in any class or interface in this package will cause a {@link
-java.lang.NullPointerException NullPointerException} to be thrown.
-
-
-@since 1.4
-@author Mark Reinhold
-@author JSR-51 Expert Group
-
-
-
diff --git a/src/share/classes/java/nio/channels/spi/SelectorProvider.java b/src/share/classes/java/nio/channels/spi/SelectorProvider.java
index 9a8a3cc707c87a4854fc3a27eb125d9c03d0075f..dc61c9c270abc391044eb95504b3c80d5db517a6 100644
--- a/src/share/classes/java/nio/channels/spi/SelectorProvider.java
+++ b/src/share/classes/java/nio/channels/spi/SelectorProvider.java
@@ -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. An MBeanPermission contains four items of information: An MBeanPermission contains five items of information: The action is returned by {@link #getActions()}. The MBean Server name. For a permission you need, this is the {@linkplain
+ * javax.management.MBeanServerFactory#getMBeanServerName
+ * name of the MBeanServer}
+ * containing the MBean for which the MBean
+ * permission is checked. For a permission you have, this is either the {@linkplain
+ * javax.management.MBeanServerFactory#getMBeanServerName
+ * name of the MBeanServer} in which the MBean
+ * you have this permission for must be registered,
+ * or a pattern against which that MBean Server name will be matched. The class name. For a permission you need, this is the class name of an MBean
@@ -88,7 +106,7 @@ import java.security.Permission;
* or operation you can access, or it is empty or the single character
* " The object name. The object name. 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;
* If you have an MBeanPermission, it allows operations only if all
- * four of the items match. The class name, member, and object name can be written together
- * as a single string, which is the name of this permission.
+ * The MBean Server name, class name, member, and object name can be written
+ * together as a single string, which is the name of this permission.
* The name of the permission is the string returned by {@link
* Permission#getName() getName()}. The format of the string is: The object name is written using the usual syntax for {@link
@@ -119,15 +137,18 @@ import java.security.Permission;
* One or more of the One or more of the One or more of the One or more of the Create a new MBeanPermission object with the specified target name
* and actions. The target name is of the form
- * "ObjectInstance
, containing the
- * ObjectName
and the Java class name of the newly
- * instantiated MBean.
- *
- * @exception ReflectionException Wraps a
- * java.lang.ClassNotFoundException
or a
- * java.lang.Exception
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
- * preRegister
(MBeanRegistration
- * 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
- * java.lang.IllegalArgumentException
: The className
- * passed in parameter is null, the ObjectName
passed
- * in parameter contains a pattern or no ObjectName
- * is specified for the MBean.
- */
- public ObjectInstance createMBean(String className, ObjectName name,
- Object params[], String signature[])
- throws ReflectionException, InstanceAlreadyExistsException,
- MBeanRegistrationException, MBeanException,
- NotCompliantMBeanException;
-
- /**
- * 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 ObjectInstance
, containing the
- * ObjectName
and the Java class name of the newly
- * instantiated MBean.
- *
- * @exception ReflectionException Wraps a
- * java.lang.ClassNotFoundException
or a
- * java.lang.Exception
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
- * preRegister
(MBeanRegistration
- * 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
- * java.lang.IllegalArgumentException
: The className
- * passed in parameter is null, the ObjectName
passed
- * in parameter contains a pattern or no ObjectName
- * is specified for the MBean.
- *
- */
- public ObjectInstance createMBean(String className, ObjectName name,
- ObjectName loaderName, Object params[],
- String signature[])
- throws ReflectionException, InstanceAlreadyExistsException,
- MBeanRegistrationException, MBeanException,
- NotCompliantMBeanException, 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 ObjectInstance
for the MBean that has
- * been registered.
- *
- * @exception InstanceAlreadyExistsException The MBean is already
- * under the control of the MBean server.
- * @exception MBeanRegistrationException The
- * preRegister
(MBeanRegistration
- * 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
- * java.lang.IllegalArgumentException
: The object
- * passed in parameter is null or no object name is specified.
- */
- public ObjectInstance registerMBean(Object object, ObjectName name)
- throws InstanceAlreadyExistsException, MBeanRegistrationException,
- NotCompliantMBeanException;
-
- /**
- * 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
- * ((MBeanRegistration
interface) method of the MBean
- * has thrown an exception.
- * @exception RuntimeOperationsException Wraps a
- * java.lang.IllegalArgumentException
: The object
- * name in parameter is null or the MBean you are when trying to
- * unregister is the {@link javax.management.MBeanServerDelegate
- * MBeanServerDelegate} MBean.
- *
- */
- public void unregisterMBean(ObjectName name)
- throws InstanceNotFoundException, MBeanRegistrationException;
-
- /**
- * Gets the ObjectInstance
for a given MBean
- * registered with the MBean server.
- *
- * @param name The object name of the MBean.
- *
- * @return The ObjectInstance
associated to the MBean
- * specified by name.
- *
- * @exception InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- */
- public ObjectInstance getObjectInstance(ObjectName name)
- throws InstanceNotFoundException;
-
- /**
- * 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
- * ObjectName
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
- * ObjectInstance
objects (containing the
- * ObjectName
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 ObjectInstance
- * objects for the selected MBeans. If no MBean satisfies the
- * query an empty list is returned.
- */
- public SetObjectName
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 Setjava.lang.IllegalArgumentException
: 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
- * java.lang.Exception
thrown when trying to invoke
- * the setter.
- * @exception RuntimeOperationsException Wraps a
- * java.lang.IllegalArgumentException
: 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
- * java.lang.IllegalArgumentException
: 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
- * java.lang.Exception
thrown when trying to invoke
- * the setter.
- * @exception RuntimeOperationsException Wraps a
- * java.lang.IllegalArgumentException
: 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
- * java.lang.IllegalArgumentException
: 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
- * java.lang.Exception
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();
-
+public interface MBeanServerInterceptor extends MBeanServer {
/**
- * Returns the list of domains in which any MBean is currently
- * registered.
+ * This method should never be called.
+ * Usually hrows UnsupportedOperationException.
*/
- public String[] getDomains();
-
+ public Object instantiate(String className)
+ throws ReflectionException, MBeanException;
/**
- * listener
exists but does not implement the {@link
- * NotificationListener} interface.
- * @exception IOException A communication problem occurred when
- * talking to the MBean server.
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
*/
- public void addNotificationListener(ObjectName name,
- ObjectName listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException;
+ public Object instantiate(String className, Object[] params,
+ String[] signature) throws ReflectionException, MBeanException;
/**
- * Removes a listener from a registered MBean.
- *
- * listener
, filter
, and
- * handback
parameters. If there is more than one
- * such listener, only one is removed.filter
and handback
parameters
- * may be null if and only if they are null in a listener to be
- * removed.listener
, filter
, and
- * handback
parameters. If there is more than one
- * such listener, only one is removed.filter
and handback
parameters
- * may be null if and only if they are null in a listener to be
- * removed.MBeanInfo
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.
+ * This method should never be called.
+ * Usually throws UnsupportedOperationException.
*/
- 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 ObjectName
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;
-
- /**
- * initialize(outer,delegate)
+ * before using this object.
+ *
+ * @param outer A pointer to the MBeanServer object that must be
+ * passed to the MBeans when invoking their
+ * {@link javax.management.MBeanRegistration} interface.
+ * @param delegate A pointer to the MBeanServerDelegate associated
+ * with the new MBeanServer. The new MBeanServer must register
+ * this MBean in its MBean repository.
+ * @param instantiator The MBeanInstantiator that will be used to
+ * instantiate MBeans and take care of class loading issues.
+ * @param repository The repository to use for this MBeanServer
+ */
+ public NamespaceDispatchInterceptor(MBeanServer outer,
+ MBeanServerDelegate delegate,
+ MBeanInstantiator instantiator,
+ Repository repository) {
+ nextInterceptor = new DomainDispatchInterceptor(outer,delegate,
+ instantiator,repository,this);
+ serverName = Util.getMBeanServerSecurityName(delegate);
+ }
+
+ // TODO: Should move that to JMXNamespace? or to ObjectName?
+ /**
+ * Get first name space in ObjectName path. Ignore leading namespace
+ * separators.
+ **/
+ static String getFirstNamespace(ObjectName name) {
+ if (name == null) return "";
+ final String domain = name.getDomain();
+ if (domain.equals("")) return "";
+
+ // skip leading separators
+ int first = 0;
+ while (domain.startsWith(NAMESPACE_SEPARATOR,first))
+ first += NAMESPACE_SEPARATOR_LENGTH;
+
+ // go to next separator
+ final int end = domain.indexOf(NAMESPACE_SEPARATOR,first);
+ if (end == -1) return ""; // no namespace
+
+ // This is the first element in the namespace path.
+ final String namespace = domain.substring(first,end);
+
+ return namespace;
+ }
+
+ /**
+ * Called by the DefaultMBeanServerInterceptor, just before adding an
+ * MBean to the repository.
+ *
+ * @param resource the MBean to be registered.
+ * @param logicalName the name of the MBean to be registered.
+ */
+ final void checkLocallyRegistrable(Object resource,
+ ObjectName logicalName) {
+ if (!(resource instanceof JMXNamespace) &&
+ logicalName.getDomain().contains(NAMESPACE_SEPARATOR))
+ throw new IllegalArgumentException(String.valueOf(logicalName)+
+ ": Invalid ObjectName for an instance of " +
+ resource.getClass().getName());
+ }
+
+ final boolean isLocalHandlerNameFor(String namespace,
+ ObjectName handlerName) {
+ return handlerName.getDomain().equals(namespace+NAMESPACE_SEPARATOR) &&
+ JMXNamespace.TYPE_ASSIGNMENT.equals(
+ handlerName.getKeyPropertyListString());
+ }
+
+ @Override
+ final MBeanServer getInterceptorOrNullFor(ObjectName name) {
+ final String namespace = getFirstNamespace(name);
+ if (namespace.equals("") || isLocalHandlerNameFor(namespace,name) ||
+ name.getDomain().equals(namespace+NAMESPACE_SEPARATOR)) {
+ LOG.finer("dispatching to local name space");
+ return nextInterceptor;
+ }
+ final NamespaceInterceptor ns = getInterceptor(namespace);
+ if (LOG.isLoggable(Level.FINER)) {
+ if (ns != null) {
+ LOG.finer("dispatching to name space: " + namespace);
+ } else {
+ LOG.finer("no handler for: " + namespace);
+ }
+ }
+ return ns;
+ }
+
+ @Override
+ final QueryInterceptor getInterceptorForQuery(ObjectName pattern) {
+ final String namespace = getFirstNamespace(pattern);
+ if (namespace.equals("") || isLocalHandlerNameFor(namespace,pattern) ||
+ pattern.getDomain().equals(namespace+NAMESPACE_SEPARATOR)) {
+ LOG.finer("dispatching to local name space");
+ return new QueryInterceptor(nextInterceptor);
+ }
+ final NamespaceInterceptor ns = getInterceptor(namespace);
+ if (LOG.isLoggable(Level.FINER)) {
+ if (ns != null) {
+ LOG.finer("dispatching to name space: " + namespace);
+ } else {
+ LOG.finer("no handler for: " + namespace);
+ }
+ }
+ if (ns == null) return null;
+ return new QueryInterceptor(ns);
+ }
+
+ @Override
+ final ObjectName getHandlerNameFor(String key)
+ throws MalformedObjectNameException {
+ return ObjectName.getInstance(key+NAMESPACE_SEPARATOR,
+ "type", JMXNamespace.TYPE);
+ }
+
+ @Override
+ final public String getHandlerKey(ObjectName name) {
+ return getFirstNamespace(name);
+ }
+
+ @Override
+ final NamespaceInterceptor createInterceptorFor(String key,
+ ObjectName name, JMXNamespace handler,
+ Queue?
, standing for any one
- character, and *
, 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) {
@@ -477,10 +396,10 @@ public class Repository {
// Set domain to default if domain is empty and not already set
if (dom.length() == 0)
- name = Util.newObjectName(domain + name.toString());
+ name = ObjectName.valueOf(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?
,
+ standing for any one character,
+ and *
, 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 ?
, standing for any one
+ character, and *
, 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 com.sun.jmx.namespace
packagecom.sun.jmx.namespace
package contains
+ sun specific implementation classes used to implement the
+ JMX namespaces.
+ javax.management.namespace
+ package.
+
+ * The {@code RewritingProcessor} allows a somewhat larger
+ * transformation in which part of a prefix {@link #newRewritingProcessor
+ * remove} can be replaced by another prefix {@link #newRewritingProcessor
+ * add}. The transformation described above correspond to the case where
+ * {@code remove} is the stripped {@link javax.management.namespace
+ * namespace} prefix (removed when entering the {@code namespace}) and
+ * {@code add} is the empty String {@code ""}.
+ *
+ * It is interesting to note that {@link
+ * javax.management.JMXNamespaces#narrowToNamespace narrowToNamespace}
+ * operations use the inverse transformation (that is, {@code remove} is
+ * the empty String {@code ""} and {@code add} is the {@link
+ * javax.management.namespace namespace} prefix).
+ *
+ * On a more general scale, {@link #rewriteInput rewriteInput} removes
+ * {@link #newRewritingProcessor remove} and the prepend {@link
+ * #newRewritingProcessor add}, and {@link #rewriteOutput rewriteOutput}
+ * does the opposite, removing {@link #newRewritingProcessor add}, and
+ * then adding {@link #newRewritingProcessor remove}.
+ *
+ * An implementation of {@code RewritingProcessor} should make sure that
+ * rewriteInput(rewriteOutput(x,clp),clp)
and
+ * rewriteOutput(rewriteInput(x,clp),clp)
always return
+ * {@code x} or an exact clone of {@code x}.
+ *
+ * public class MyRewritingProcessor extends RewritingProcessor {
+ * MyRewritingProcessor(String remove, String add) {
+ * this(RewritingProcessor.newRewritingProcessor(remove,add));
+ * }
+ * MyRewritingProcessor(RewritingProcessor delegate) {
+ * super(delegate);
+ * }
+ *
+ *
+ *
+ * public class MyRewritingProcessor extends RewritingProcessor {
+ * MyRewritingProcessor(String remove, String add) {
+ * this(RewritingProcessor.newRewritingProcessor(remove,add));
+ * }
+ * MyRewritingProcessor(RewritingProcessor delegate) {
+ * super(delegate);
+ * }
+ *
+ *
+ * com.sun.jmx.namespace.serial
packagecom.sun.jmx.namespace.serial
package contains
+ sun specific implementation classes used to switch namespace
+ prefixes in ObjectName during serialization.
+ javax.management.namespace.JMXNamespaces
+ Transformation algorithm
*
@@ -167,20 +160,6 @@ public abstract class SignatureAlgorithmSpi {
protected abstract void engineSetParameter(AlgorithmParameterSpec params)
throws XMLSignatureException;
- /** Field _doc */
- Document _doc = null;
-
- /**
- * Method engineSetDocument
- *
- * @param doc
- */
- protected void engineSetDocument(Document doc) {
- this._doc = doc;
- }
-
- /** Field _constructionElement */
- Element _constructionElement = null;
/**
* Method engineGetContextFromElement
@@ -188,7 +167,6 @@ public abstract class SignatureAlgorithmSpi {
* @param element
*/
protected void engineGetContextFromElement(Element element) {
- this._constructionElement = element;
}
/**
@@ -199,4 +177,7 @@ public abstract class SignatureAlgorithmSpi {
*/
protected abstract void engineSetHMACOutputLength(int HMACOutputLength)
throws XMLSignatureException;
+
+ public void reset() {
+ }
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java b/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java
index 0e89024bf265d7c1e302af34ef0777edc41cf88f..d3495bb567f4ed2402a7876e0ee91b4a22e12f2d 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java
@@ -45,7 +45,7 @@ import org.w3c.dom.Text;
/**
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*/
public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
@@ -74,8 +74,8 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
public IntegrityHmac() throws XMLSignatureException {
String algorithmID = JCEMapper.translateURItoJCEID(this.engineGetURI());
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Created IntegrityHmacSHA1 using " + algorithmID);
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Created IntegrityHmacSHA1 using " + algorithmID);
try {
this._macAlgorithm = Mac.getInstance(algorithmID);
@@ -99,6 +99,10 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
throw new XMLSignatureException("empty");
}
+ public void reset() {
+ _HMACOutputLength=0;
+ }
+
/**
* Proxy method for {@link java.security.Signature#verify(byte[])}
* which is executed on the internal {@link java.security.Signature} object.
@@ -145,7 +149,20 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
try {
this._macAlgorithm.init(secretKey);
} catch (InvalidKeyException ex) {
- throw new XMLSignatureException("empty", ex);
+ // reinstantiate Mac object to work around bug in JDK
+ // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+ Mac mac = this._macAlgorithm;
+ try {
+ this._macAlgorithm = Mac.getInstance
+ (_macAlgorithm.getAlgorithm());
+ } catch (Exception e) {
+ // this shouldn't occur, but if it does, restore previous Mac
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "Exception when reinstantiating Mac:" + e);
+ }
+ this._macAlgorithm = mac;
+ }
+ throw new XMLSignatureException("empty", ex);
}
}
@@ -323,7 +340,7 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
*/
protected String engineGetJCEAlgorithmString() {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "engineGetJCEAlgorithmString()");
+ log.log(java.util.logging.Level.FINE, "engineGetJCEAlgorithmString()");
return this._macAlgorithm.getAlgorithm();
}
@@ -397,7 +414,8 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
/**
* Class IntegrityHmacSHA1
*
- * @author $Author: raul $
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
*/
public static class IntegrityHmacSHA1 extends IntegrityHmac {
@@ -423,7 +441,8 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
/**
* Class IntegrityHmacSHA256
*
- * @author $Author: raul $
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
*/
public static class IntegrityHmacSHA256 extends IntegrityHmac {
@@ -449,7 +468,8 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
/**
* Class IntegrityHmacSHA384
*
- * @author $Author: raul $
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
*/
public static class IntegrityHmacSHA384 extends IntegrityHmac {
@@ -475,7 +495,8 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
/**
* Class IntegrityHmacSHA512
*
- * @author $Author: raul $
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
*/
public static class IntegrityHmacSHA512 extends IntegrityHmac {
@@ -501,7 +522,8 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
/**
* Class IntegrityHmacRIPEMD160
*
- * @author $Author: raul $
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
*/
public static class IntegrityHmacRIPEMD160 extends IntegrityHmac {
@@ -527,7 +549,8 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
/**
* Class IntegrityHmacMD5
*
- * @author $Author: raul $
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
*/
public static class IntegrityHmacMD5 extends IntegrityHmac {
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java b/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java
index fde23e8fc880ea4014abcc069c4e7304a3962005..ccc01b01c58e644461f42d9b69c2878de613f417 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureBaseRSA.java
@@ -3,7 +3,7 @@
* DO NOT REMOVE OR ALTER!
*/
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2007 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,6 @@
*/
package com.sun.org.apache.xml.internal.security.algorithms.implementations;
-
-
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -38,329 +36,344 @@ import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi
import com.sun.org.apache.xml.internal.security.signature.XMLSignature;
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
-
/**
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*/
public abstract class SignatureBaseRSA extends SignatureAlgorithmSpi {
- /** {@link java.util.logging} logging facility */
+ /** {@link java.util.logging} logging facility */
static java.util.logging.Logger log =
- java.util.logging.Logger.getLogger(SignatureBaseRSA.class.getName());
+ java.util.logging.Logger.getLogger
+ (SignatureBaseRSA.class.getName());
/** @inheritDoc */
- public abstract String engineGetURI();
+ public abstract String engineGetURI();
- /** Field algorithm */
- private java.security.Signature _signatureAlgorithm = null;
+ /** Field algorithm */
+ private java.security.Signature _signatureAlgorithm = null;
- /**
- * Constructor SignatureRSA
- *
- * @throws XMLSignatureException
- */
- public SignatureBaseRSA() throws XMLSignatureException {
+ /**
+ * Constructor SignatureRSA
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureBaseRSA() throws XMLSignatureException {
- String algorithmID = JCEMapper.translateURItoJCEID(this.engineGetURI());
+ String algorithmID = JCEMapper.translateURItoJCEID(this.engineGetURI());
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Created SignatureDSA using " + algorithmID);
- String provider=JCEMapper.getProviderId();
- try {
- if (provider==null) {
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Created SignatureRSA using " + algorithmID);
+ String provider=JCEMapper.getProviderId();
+ try {
+ if (provider==null) {
this._signatureAlgorithm = Signature.getInstance(algorithmID);
- } else {
+ } else {
this._signatureAlgorithm = Signature.getInstance(algorithmID,provider);
- }
- } catch (java.security.NoSuchAlgorithmException ex) {
- Object[] exArgs = { algorithmID,
- ex.getLocalizedMessage() };
+ }
+ } catch (java.security.NoSuchAlgorithmException ex) {
+ Object[] exArgs = { algorithmID, ex.getLocalizedMessage() };
+
+ throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
+ } catch (NoSuchProviderException ex) {
+ Object[] exArgs = { algorithmID, ex.getLocalizedMessage() };
+
+ throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws XMLSignatureException {
+
+ try {
+ this._signatureAlgorithm.setParameter(params);
+ } catch (InvalidAlgorithmParameterException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected boolean engineVerify(byte[] signature)
+ throws XMLSignatureException {
+
+ try {
+ return this._signatureAlgorithm.verify(signature);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineInitVerify(Key publicKey) throws XMLSignatureException {
+
+ if (!(publicKey instanceof PublicKey)) {
+ String supplied = publicKey.getClass().getName();
+ String needed = PublicKey.class.getName();
+ Object exArgs[] = { supplied, needed };
+
+ throw new XMLSignatureException
+ ("algorithms.WrongKeyForThisOperation", exArgs);
+ }
+
+ try {
+ this._signatureAlgorithm.initVerify((PublicKey) publicKey);
+ } catch (InvalidKeyException ex) {
+ // reinstantiate Signature object to work around bug in JDK
+ // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+ Signature sig = this._signatureAlgorithm;
+ try {
+ this._signatureAlgorithm = Signature.getInstance
+ (_signatureAlgorithm.getAlgorithm());
+ } catch (Exception e) {
+ // this shouldn't occur, but if it does, restore previous
+ // Signature
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "Exception when reinstantiating Signature:" + e);
+ }
+ this._signatureAlgorithm = sig;
+ }
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected byte[] engineSign() throws XMLSignatureException {
+ try {
+ return this._signatureAlgorithm.sign();
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineInitSign(Key privateKey, SecureRandom secureRandom)
+ throws XMLSignatureException {
+
+ if (!(privateKey instanceof PrivateKey)) {
+ String supplied = privateKey.getClass().getName();
+ String needed = PrivateKey.class.getName();
+ Object exArgs[] = { supplied, needed };
+
+ throw new XMLSignatureException
+ ("algorithms.WrongKeyForThisOperation", exArgs);
+ }
+
+ try {
+ this._signatureAlgorithm.initSign
+ ((PrivateKey) privateKey, secureRandom);
+ } catch (InvalidKeyException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineInitSign(Key privateKey) throws XMLSignatureException {
+
+ if (!(privateKey instanceof PrivateKey)) {
+ String supplied = privateKey.getClass().getName();
+ String needed = PrivateKey.class.getName();
+ Object exArgs[] = { supplied, needed };
+
+ throw new XMLSignatureException
+ ("algorithms.WrongKeyForThisOperation", exArgs);
+ }
+
+ try {
+ this._signatureAlgorithm.initSign((PrivateKey) privateKey);
+ } catch (InvalidKeyException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineUpdate(byte[] input) throws XMLSignatureException {
+ try {
+ this._signatureAlgorithm.update(input);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineUpdate(byte input) throws XMLSignatureException {
+ try {
+ this._signatureAlgorithm.update(input);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineUpdate(byte buf[], int offset, int len)
+ throws XMLSignatureException {
+ try {
+ this._signatureAlgorithm.update(buf, offset, len);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected String engineGetJCEAlgorithmString() {
+ return this._signatureAlgorithm.getAlgorithm();
+ }
+
+ /** @inheritDoc */
+ protected String engineGetJCEProviderName() {
+ return this._signatureAlgorithm.getProvider().getName();
+ }
+
+ /** @inheritDoc */
+ protected void engineSetHMACOutputLength(int HMACOutputLength)
+ throws XMLSignatureException {
+ throw new XMLSignatureException
+ ("algorithms.HMACOutputLengthOnlyForHMAC");
+ }
- throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
- } catch (NoSuchProviderException ex) {
- Object[] exArgs = { algorithmID,
- ex.getLocalizedMessage() };
+ /** @inheritDoc */
+ protected void engineInitSign(
+ Key signingKey, AlgorithmParameterSpec algorithmParameterSpec)
+ throws XMLSignatureException {
+ throw new XMLSignatureException(
+ "algorithms.CannotUseAlgorithmParameterSpecOnRSA");
+ }
+
+ /**
+ * Class SignatureRSASHA1
+ *
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
+ */
+ public static class SignatureRSASHA1 extends SignatureBaseRSA {
+
+ /**
+ * Constructor SignatureRSASHA1
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureRSASHA1() throws XMLSignatureException {
+ super();
+ }
+
+ /** @inheritDoc */
+ public String engineGetURI() {
+ return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+ }
+ }
+
+ /**
+ * Class SignatureRSASHA256
+ *
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
+ */
+ public static class SignatureRSASHA256 extends SignatureBaseRSA {
+
+ /**
+ * Constructor SignatureRSASHA256
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureRSASHA256() throws XMLSignatureException {
+ super();
+ }
+
+ /** @inheritDoc */
+ public String engineGetURI() {
+ return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;
+ }
+ }
+
+ /**
+ * Class SignatureRSASHA384
+ *
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
+ */
+ public static class SignatureRSASHA384 extends SignatureBaseRSA {
+
+ /**
+ * Constructor SignatureRSASHA384
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureRSASHA384() throws XMLSignatureException {
+ super();
+ }
+
+ /** @inheritDoc */
+ public String engineGetURI() {
+ return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;
+ }
+ }
+
+ /**
+ * Class SignatureRSASHA512
+ *
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
+ */
+ public static class SignatureRSASHA512 extends SignatureBaseRSA {
+
+ /**
+ * Constructor SignatureRSASHA512
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureRSASHA512() throws XMLSignatureException {
+ super();
+ }
+
+ /** @inheritDoc */
+ public String engineGetURI() {
+ return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;
+ }
+ }
+
+ /**
+ * Class SignatureRSARIPEMD160
+ *
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
+ */
+ public static class SignatureRSARIPEMD160 extends SignatureBaseRSA {
+
+ /**
+ * Constructor SignatureRSARIPEMD160
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureRSARIPEMD160() throws XMLSignatureException {
+ super();
+ }
+
+ /** @inheritDoc */
+ public String engineGetURI() {
+ return XMLSignature.ALGO_ID_SIGNATURE_RSA_RIPEMD160;
+ }
+ }
+
+ /**
+ * Class SignatureRSAMD5
+ *
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
+ */
+ public static class SignatureRSAMD5 extends SignatureBaseRSA {
+
+ /**
+ * Constructor SignatureRSAMD5
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureRSAMD5() throws XMLSignatureException {
+ super();
+ }
- throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
+ /** @inheritDoc */
+ public String engineGetURI() {
+ return XMLSignature.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5;
}
- }
-
- /** @inheritDoc */
- protected void engineSetParameter(AlgorithmParameterSpec params)
- throws XMLSignatureException {
-
- try {
- this._signatureAlgorithm.setParameter(params);
- } catch (InvalidAlgorithmParameterException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /** @inheritDoc */
- protected boolean engineVerify(byte[] signature)
- throws XMLSignatureException {
-
- try {
- return this._signatureAlgorithm.verify(signature);
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /** @inheritDoc */
- protected void engineInitVerify(Key publicKey) throws XMLSignatureException {
-
- if (!(publicKey instanceof PublicKey)) {
- String supplied = publicKey.getClass().getName();
- String needed = PublicKey.class.getName();
- Object exArgs[] = { supplied, needed };
-
- throw new XMLSignatureException("algorithms.WrongKeyForThisOperation",
- exArgs);
- }
-
- try {
- this._signatureAlgorithm.initVerify((PublicKey) publicKey);
- } catch (InvalidKeyException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /** @inheritDoc */
- protected byte[] engineSign() throws XMLSignatureException {
-
- try {
- return this._signatureAlgorithm.sign();
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /** @inheritDoc */
- protected void engineInitSign(Key privateKey, SecureRandom secureRandom)
- throws XMLSignatureException {
-
- if (!(privateKey instanceof PrivateKey)) {
- String supplied = privateKey.getClass().getName();
- String needed = PrivateKey.class.getName();
- Object exArgs[] = { supplied, needed };
-
- throw new XMLSignatureException("algorithms.WrongKeyForThisOperation",
- exArgs);
- }
-
- try {
- this._signatureAlgorithm.initSign((PrivateKey) privateKey,
- secureRandom);
- } catch (InvalidKeyException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /** @inheritDoc */
- protected void engineInitSign(Key privateKey) throws XMLSignatureException {
-
- if (!(privateKey instanceof PrivateKey)) {
- String supplied = privateKey.getClass().getName();
- String needed = PrivateKey.class.getName();
- Object exArgs[] = { supplied, needed };
-
- throw new XMLSignatureException("algorithms.WrongKeyForThisOperation",
- exArgs);
- }
-
- try {
- this._signatureAlgorithm.initSign((PrivateKey) privateKey);
- } catch (InvalidKeyException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /** @inheritDoc */
- protected void engineUpdate(byte[] input) throws XMLSignatureException {
-
- try {
- this._signatureAlgorithm.update(input);
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /** @inheritDoc */
- protected void engineUpdate(byte input) throws XMLSignatureException {
-
- try {
- this._signatureAlgorithm.update(input);
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /** @inheritDoc */
- protected void engineUpdate(byte buf[], int offset, int len)
- throws XMLSignatureException {
-
- try {
- this._signatureAlgorithm.update(buf, offset, len);
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /** @inheritDoc */
- protected String engineGetJCEAlgorithmString() {
- return this._signatureAlgorithm.getAlgorithm();
- }
-
- /** @inheritDoc */
- protected String engineGetJCEProviderName() {
- return this._signatureAlgorithm.getProvider().getName();
- }
-
- /** @inheritDoc */
- protected void engineSetHMACOutputLength(int HMACOutputLength)
- throws XMLSignatureException {
- throw new XMLSignatureException("algorithms.HMACOutputLengthOnlyForHMAC");
- }
-
- /** @inheritDoc */
- protected void engineInitSign(
- Key signingKey, AlgorithmParameterSpec algorithmParameterSpec)
- throws XMLSignatureException {
- throw new XMLSignatureException(
- "algorithms.CannotUseAlgorithmParameterSpecOnRSA");
- }
-
- /**
- * Class SignatureRSASHA1
- *
- * @author $Author: raul $
- */
- public static class SignatureRSASHA1 extends SignatureBaseRSA {
-
- /**
- * Constructor SignatureRSASHA1
- *
- * @throws XMLSignatureException
- */
- public SignatureRSASHA1() throws XMLSignatureException {
- super();
- }
-
- /** @inheritDoc */
- public String engineGetURI() {
- return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
- }
- }
-
- /**
- * Class SignatureRSASHA256
- *
- * @author $Author: raul $
- */
- public static class SignatureRSASHA256 extends SignatureBaseRSA {
-
- /**
- * Constructor SignatureRSASHA256
- *
- * @throws XMLSignatureException
- */
- public SignatureRSASHA256() throws XMLSignatureException {
- super();
- }
-
- /** @inheritDoc */
- public String engineGetURI() {
- return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;
- }
- }
-
- /**
- * Class SignatureRSASHA384
- *
- * @author $Author: raul $
- */
- public static class SignatureRSASHA384 extends SignatureBaseRSA {
-
- /**
- * Constructor SignatureRSASHA384
- *
- * @throws XMLSignatureException
- */
- public SignatureRSASHA384() throws XMLSignatureException {
- super();
- }
-
- /** @inheritDoc */
- public String engineGetURI() {
- return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;
- }
- }
-
- /**
- * Class SignatureRSASHA512
- *
- * @author $Author: raul $
- */
- public static class SignatureRSASHA512 extends SignatureBaseRSA {
-
- /**
- * Constructor SignatureRSASHA512
- *
- * @throws XMLSignatureException
- */
- public SignatureRSASHA512() throws XMLSignatureException {
- super();
- }
-
- /** @inheritDoc */
- public String engineGetURI() {
- return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;
- }
- }
-
- /**
- * Class SignatureRSARIPEMD160
- *
- * @author $Author: raul $
- */
- public static class SignatureRSARIPEMD160 extends SignatureBaseRSA {
-
- /**
- * Constructor SignatureRSARIPEMD160
- *
- * @throws XMLSignatureException
- */
- public SignatureRSARIPEMD160() throws XMLSignatureException {
- super();
- }
-
- /** @inheritDoc */
- public String engineGetURI() {
- return XMLSignature.ALGO_ID_SIGNATURE_RSA_RIPEMD160;
- }
- }
-
- /**
- * Class SignatureRSAMD5
- *
- * @author $Author: raul $
- */
- public static class SignatureRSAMD5 extends SignatureBaseRSA {
-
- /**
- * Constructor SignatureRSAMD5
- *
- * @throws XMLSignatureException
- */
- public SignatureRSAMD5() throws XMLSignatureException {
- super();
- }
-
- /** @inheritDoc */
- public String engineGetURI() {
- return XMLSignature.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5;
- }
- }
+ }
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java b/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java
index 355579b7e5385ee4a97f324d0a8d1436436a4987..615aa436e462358b457b5d002ba8e52f8b4aa096 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java
@@ -20,8 +20,6 @@
*/
package com.sun.org.apache.xml.internal.security.algorithms.implementations;
-
-
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -39,342 +37,359 @@ import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
import com.sun.org.apache.xml.internal.security.utils.Base64;
import com.sun.org.apache.xml.internal.security.utils.Constants;
-
/**
*
- * @author $Author: vishal $
+ * @author $Author: mullan $
*/
public class SignatureDSA extends SignatureAlgorithmSpi {
- /** {@link java.util.logging} logging facility */
+ /** {@link java.util.logging} logging facility */
static java.util.logging.Logger log =
java.util.logging.Logger.getLogger(SignatureDSA.class.getName());
- /** Field _URI */
- public static final String _URI = Constants.SignatureSpecNS + "dsa-sha1";
-
- /** Field algorithm */
- private java.security.Signature _signatureAlgorithm = null;
-
- /**
- * Method engineGetURI
- *
- * @inheritDoc
- */
- protected String engineGetURI() {
- return SignatureDSA._URI;
- }
-
- /**
- * Constructor SignatureDSA
- *
- * @throws XMLSignatureException
- */
- public SignatureDSA() throws XMLSignatureException {
-
- String algorithmID = JCEMapper.translateURItoJCEID(SignatureDSA._URI);
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Created SignatureDSA using " + algorithmID);
-
- try {
- this._signatureAlgorithm = Signature.getInstance(algorithmID);
- } catch (java.security.NoSuchAlgorithmException ex) {
- Object[] exArgs = { algorithmID,
- ex.getLocalizedMessage() };
-
- throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
- }
- }
-
- /**
- * @inheritDoc
- */
- protected void engineSetParameter(AlgorithmParameterSpec params)
- throws XMLSignatureException {
-
- try {
- this._signatureAlgorithm.setParameter(params);
- } catch (InvalidAlgorithmParameterException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /**
- * @inheritDoc
- */
- protected boolean engineVerify(byte[] signature)
+ /** Field _URI */
+ public static final String _URI = Constants.SignatureSpecNS + "dsa-sha1";
+
+ /** Field algorithm */
+ private java.security.Signature _signatureAlgorithm = null;
+
+ /**
+ * Method engineGetURI
+ *
+ * @inheritDoc
+ */
+ protected String engineGetURI() {
+ return SignatureDSA._URI;
+ }
+
+ /**
+ * Constructor SignatureDSA
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureDSA() throws XMLSignatureException {
+
+ String algorithmID = JCEMapper.translateURItoJCEID(SignatureDSA._URI);
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Created SignatureDSA using " + algorithmID);
+
+ String provider = JCEMapper.getProviderId();
+ try {
+ if (provider == null) {
+ this._signatureAlgorithm = Signature.getInstance(algorithmID);
+ } else {
+ this._signatureAlgorithm =
+ Signature.getInstance(algorithmID, provider);
+ }
+ } catch (java.security.NoSuchAlgorithmException ex) {
+ Object[] exArgs = { algorithmID, ex.getLocalizedMessage() };
+ throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
+ } catch (java.security.NoSuchProviderException ex) {
+ Object[] exArgs = { algorithmID, ex.getLocalizedMessage() };
+ throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws XMLSignatureException {
+
+ try {
+ this._signatureAlgorithm.setParameter(params);
+ } catch (InvalidAlgorithmParameterException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected boolean engineVerify(byte[] signature)
throws XMLSignatureException {
- try {
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Called DSA.verify() on " + Base64.encode(signature));
-
- byte[] jcebytes = SignatureDSA.convertXMLDSIGtoASN1(signature);
-
- return this._signatureAlgorithm.verify(jcebytes);
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- } catch (IOException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /**
- * @inheritDoc
- */
- protected void engineInitVerify(Key publicKey) throws XMLSignatureException {
-
- if (!(publicKey instanceof PublicKey)) {
- String supplied = publicKey.getClass().getName();
- String needed = PublicKey.class.getName();
- Object exArgs[] = { supplied, needed };
-
- throw new XMLSignatureException("algorithms.WrongKeyForThisOperation",
- exArgs);
- }
-
- try {
- this._signatureAlgorithm.initVerify((PublicKey) publicKey);
- } catch (InvalidKeyException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /**
- * @inheritDoc
- */
- protected byte[] engineSign() throws XMLSignatureException {
-
- try {
- byte jcebytes[] = this._signatureAlgorithm.sign();
-
- return SignatureDSA.convertASN1toXMLDSIG(jcebytes);
- } catch (IOException ex) {
- throw new XMLSignatureException("empty", ex);
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /**
- * @inheritDoc
- */
- protected void engineInitSign(Key privateKey, SecureRandom secureRandom)
+ try {
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Called DSA.verify() on " + Base64.encode(signature));
+
+ byte[] jcebytes = SignatureDSA.convertXMLDSIGtoASN1(signature);
+
+ return this._signatureAlgorithm.verify(jcebytes);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ } catch (IOException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected void engineInitVerify(Key publicKey) throws XMLSignatureException {
+
+ if (!(publicKey instanceof PublicKey)) {
+ String supplied = publicKey.getClass().getName();
+ String needed = PublicKey.class.getName();
+ Object exArgs[] = { supplied, needed };
+
+ throw new XMLSignatureException
+ ("algorithms.WrongKeyForThisOperation", exArgs);
+ }
+
+ try {
+ this._signatureAlgorithm.initVerify((PublicKey) publicKey);
+ } catch (InvalidKeyException ex) {
+ // reinstantiate Signature object to work around bug in JDK
+ // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+ Signature sig = this._signatureAlgorithm;
+ try {
+ this._signatureAlgorithm = Signature.getInstance
+ (_signatureAlgorithm.getAlgorithm());
+ } catch (Exception e) {
+ // this shouldn't occur, but if it does, restore previous
+ // Signature
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "Exception when reinstantiating Signature:" + e);
+ }
+ this._signatureAlgorithm = sig;
+ }
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected byte[] engineSign() throws XMLSignatureException {
+
+ try {
+ byte jcebytes[] = this._signatureAlgorithm.sign();
+
+ return SignatureDSA.convertASN1toXMLDSIG(jcebytes);
+ } catch (IOException ex) {
+ throw new XMLSignatureException("empty", ex);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected void engineInitSign(Key privateKey, SecureRandom secureRandom)
throws XMLSignatureException {
- if (!(privateKey instanceof PrivateKey)) {
- String supplied = privateKey.getClass().getName();
- String needed = PrivateKey.class.getName();
- Object exArgs[] = { supplied, needed };
+ if (!(privateKey instanceof PrivateKey)) {
+ String supplied = privateKey.getClass().getName();
+ String needed = PrivateKey.class.getName();
+ Object exArgs[] = { supplied, needed };
- throw new XMLSignatureException("algorithms.WrongKeyForThisOperation",
- exArgs);
- }
+ throw new XMLSignatureException
+ ("algorithms.WrongKeyForThisOperation", exArgs);
+ }
- try {
- this._signatureAlgorithm.initSign((PrivateKey) privateKey,
+ try {
+ this._signatureAlgorithm.initSign((PrivateKey) privateKey,
secureRandom);
- } catch (InvalidKeyException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /**
- * @inheritDoc
- */
- protected void engineInitSign(Key privateKey) throws XMLSignatureException {
-
- if (!(privateKey instanceof PrivateKey)) {
- String supplied = privateKey.getClass().getName();
- String needed = PrivateKey.class.getName();
- Object exArgs[] = { supplied, needed };
-
- throw new XMLSignatureException("algorithms.WrongKeyForThisOperation",
- exArgs);
- }
-
- try {
- this._signatureAlgorithm.initSign((PrivateKey) privateKey);
- } catch (InvalidKeyException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /**
- * @inheritDoc
- */
- protected void engineUpdate(byte[] input) throws XMLSignatureException {
-
- try {
- this._signatureAlgorithm.update(input);
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /**
- * @inheritDoc
- */
- protected void engineUpdate(byte input) throws XMLSignatureException {
-
- try {
- this._signatureAlgorithm.update(input);
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /**
- * @inheritDoc
- */
- protected void engineUpdate(byte buf[], int offset, int len)
- throws XMLSignatureException {
-
- try {
- this._signatureAlgorithm.update(buf, offset, len);
- } catch (SignatureException ex) {
- throw new XMLSignatureException("empty", ex);
- }
- }
-
- /**
- * Method engineGetJCEAlgorithmString
- *
- * @inheritDoc
- */
- protected String engineGetJCEAlgorithmString() {
- return this._signatureAlgorithm.getAlgorithm();
- }
-
- /**
- * Method engineGetJCEProviderName
- *
- * @inheritDoc
- */
- protected String engineGetJCEProviderName() {
- return this._signatureAlgorithm.getProvider().getName();
- }
-
-
- /**
- * Converts an ASN.1 DSA value to a XML Signature DSA Value.
- *
- * The JAVA JCE DSA Signature algorithm creates ASN.1 encoded (r,s) value
- * pairs; the XML Signature requires the core BigInteger values.
- *
- * @param asn1Bytes
- * @return the decode bytes
- *
- * @throws IOException
- * @see 6.4.1 DSA
- */
- private static byte[] convertASN1toXMLDSIG(byte asn1Bytes[])
+ } catch (InvalidKeyException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected void engineInitSign(Key privateKey) throws XMLSignatureException {
+
+ if (!(privateKey instanceof PrivateKey)) {
+ String supplied = privateKey.getClass().getName();
+ String needed = PrivateKey.class.getName();
+ Object exArgs[] = { supplied, needed };
+
+ throw new XMLSignatureException
+ ("algorithms.WrongKeyForThisOperation", exArgs);
+ }
+
+ try {
+ this._signatureAlgorithm.initSign((PrivateKey) privateKey);
+ } catch (InvalidKeyException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected void engineUpdate(byte[] input) throws XMLSignatureException {
+ try {
+ this._signatureAlgorithm.update(input);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected void engineUpdate(byte input) throws XMLSignatureException {
+ try {
+ this._signatureAlgorithm.update(input);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected void engineUpdate(byte buf[], int offset, int len)
+ throws XMLSignatureException {
+ try {
+ this._signatureAlgorithm.update(buf, offset, len);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /**
+ * Method engineGetJCEAlgorithmString
+ *
+ * @inheritDoc
+ */
+ protected String engineGetJCEAlgorithmString() {
+ return this._signatureAlgorithm.getAlgorithm();
+ }
+
+ /**
+ * Method engineGetJCEProviderName
+ *
+ * @inheritDoc
+ */
+ protected String engineGetJCEProviderName() {
+ return this._signatureAlgorithm.getProvider().getName();
+ }
+
+ /**
+ * Converts an ASN.1 DSA value to a XML Signature DSA Value.
+ *
+ * The JAVA JCE DSA Signature algorithm creates ASN.1 encoded (r,s) value
+ * pairs; the XML Signature requires the core BigInteger values.
+ *
+ * @param asn1Bytes
+ * @return the decode bytes
+ *
+ * @throws IOException
+ * @see 6.4.1 DSA
+ */
+ private static byte[] convertASN1toXMLDSIG(byte asn1Bytes[])
throws IOException {
- byte rLength = asn1Bytes[3];
- int i;
+ byte rLength = asn1Bytes[3];
+ int i;
- for (i = rLength; (i > 0) && (asn1Bytes[(4 + rLength) - i] == 0); i--);
+ for (i = rLength; (i > 0) && (asn1Bytes[(4 + rLength) - i] == 0); i--);
- byte sLength = asn1Bytes[5 + rLength];
- int j;
+ byte sLength = asn1Bytes[5 + rLength];
+ int j;
- for (j = sLength;
+ for (j = sLength;
(j > 0) && (asn1Bytes[(6 + rLength + sLength) - j] == 0); j--);
- if ((asn1Bytes[0] != 48) || (asn1Bytes[1] != asn1Bytes.length - 2)
+ if ((asn1Bytes[0] != 48) || (asn1Bytes[1] != asn1Bytes.length - 2)
|| (asn1Bytes[2] != 2) || (i > 20)
|| (asn1Bytes[4 + rLength] != 2) || (j > 20)) {
- throw new IOException("Invalid ASN.1 format of DSA signature");
- }
- byte xmldsigBytes[] = new byte[40];
+ throw new IOException("Invalid ASN.1 format of DSA signature");
+ }
+ byte xmldsigBytes[] = new byte[40];
- System.arraycopy(asn1Bytes, (4 + rLength) - i, xmldsigBytes, 20 - i,
+ System.arraycopy(asn1Bytes, (4 + rLength) - i, xmldsigBytes, 20 - i,
i);
- System.arraycopy(asn1Bytes, (6 + rLength + sLength) - j, xmldsigBytes,
+ System.arraycopy(asn1Bytes, (6 + rLength + sLength) - j, xmldsigBytes,
40 - j, j);
- return xmldsigBytes;
- }
-
- /**
- * Converts a XML Signature DSA Value to an ASN.1 DSA value.
- *
- * The JAVA JCE DSA Signature algorithm creates ASN.1 encoded (r,s) value
- * pairs; the XML Signature requires the core BigInteger values.
- *
- * @param xmldsigBytes
- * @return the encoded ASN.1 bytes
- *
- * @throws IOException
- * @see 6.4.1 DSA
- */
- private static byte[] convertXMLDSIGtoASN1(byte xmldsigBytes[])
+ return xmldsigBytes;
+ }
+
+ /**
+ * Converts a XML Signature DSA Value to an ASN.1 DSA value.
+ *
+ * The JAVA JCE DSA Signature algorithm creates ASN.1 encoded (r,s) value
+ * pairs; the XML Signature requires the core BigInteger values.
+ *
+ * @param xmldsigBytes
+ * @return the encoded ASN.1 bytes
+ *
+ * @throws IOException
+ * @see 6.4.1 DSA
+ */
+ private static byte[] convertXMLDSIGtoASN1(byte xmldsigBytes[])
throws IOException {
- if (xmldsigBytes.length != 40) {
- throw new IOException("Invalid XMLDSIG format of DSA signature");
- }
+ if (xmldsigBytes.length != 40) {
+ throw new IOException("Invalid XMLDSIG format of DSA signature");
+ }
- int i;
+ int i;
- for (i = 20; (i > 0) && (xmldsigBytes[20 - i] == 0); i--);
+ for (i = 20; (i > 0) && (xmldsigBytes[20 - i] == 0); i--);
- int j = i;
+ int j = i;
- if (xmldsigBytes[20 - i] < 0) {
+ if (xmldsigBytes[20 - i] < 0) {
j += 1;
- }
-
- int k;
-
- for (k = 20; (k > 0) && (xmldsigBytes[40 - k] == 0); k--);
-
- int l = k;
-
- if (xmldsigBytes[40 - k] < 0) {
- l += 1;
- }
-
- byte asn1Bytes[] = new byte[6 + j + l];
-
- asn1Bytes[0] = 48;
- asn1Bytes[1] = (byte) (4 + j + l);
- asn1Bytes[2] = 2;
- asn1Bytes[3] = (byte) j;
-
- System.arraycopy(xmldsigBytes, 20 - i, asn1Bytes, (4 + j) - i, i);
-
- asn1Bytes[4 + j] = 2;
- asn1Bytes[5 + j] = (byte) l;
-
- System.arraycopy(xmldsigBytes, 40 - k, asn1Bytes, (6 + j + l) - k, k);
-
- return asn1Bytes;
- }
-
- /**
- * Method engineSetHMACOutputLength
- *
- * @param HMACOutputLength
- * @throws XMLSignatureException
- */
- protected void engineSetHMACOutputLength(int HMACOutputLength)
- throws XMLSignatureException {
- throw new XMLSignatureException("algorithms.HMACOutputLengthOnlyForHMAC");
- }
-
- /**
- * Method engineInitSign
- *
- * @param signingKey
- * @param algorithmParameterSpec
- * @throws XMLSignatureException
- */
- protected void engineInitSign(
- Key signingKey, AlgorithmParameterSpec algorithmParameterSpec)
- throws XMLSignatureException {
- throw new XMLSignatureException(
- "algorithms.CannotUseAlgorithmParameterSpecOnDSA");
- }
+ }
+
+ int k;
+
+ for (k = 20; (k > 0) && (xmldsigBytes[40 - k] == 0); k--);
+
+ int l = k;
+
+ if (xmldsigBytes[40 - k] < 0) {
+ l += 1;
+ }
+
+ byte asn1Bytes[] = new byte[6 + j + l];
+
+ asn1Bytes[0] = 48;
+ asn1Bytes[1] = (byte) (4 + j + l);
+ asn1Bytes[2] = 2;
+ asn1Bytes[3] = (byte) j;
+
+ System.arraycopy(xmldsigBytes, 20 - i, asn1Bytes, (4 + j) - i, i);
+
+ asn1Bytes[4 + j] = 2;
+ asn1Bytes[5 + j] = (byte) l;
+
+ System.arraycopy(xmldsigBytes, 40 - k, asn1Bytes, (6 + j + l) - k, k);
+
+ return asn1Bytes;
+ }
+
+ /**
+ * Method engineSetHMACOutputLength
+ *
+ * @param HMACOutputLength
+ * @throws XMLSignatureException
+ */
+ protected void engineSetHMACOutputLength(int HMACOutputLength)
+ throws XMLSignatureException {
+ throw new XMLSignatureException(
+ "algorithms.HMACOutputLengthOnlyForHMAC");
+ }
+
+ /**
+ * Method engineInitSign
+ *
+ * @param signingKey
+ * @param algorithmParameterSpec
+ * @throws XMLSignatureException
+ */
+ protected void engineInitSign(
+ Key signingKey, AlgorithmParameterSpec algorithmParameterSpec)
+ throws XMLSignatureException {
+ throw new XMLSignatureException(
+ "algorithms.CannotUseAlgorithmParameterSpecOnDSA");
+ }
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java b/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java
new file mode 100644
index 0000000000000000000000000000000000000000..18fdffe28fb5533db2fbef538505501d98983141
--- /dev/null
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java
@@ -0,0 +1,384 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.org.apache.xml.internal.security.algorithms.implementations;
+
+
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.AlgorithmParameterSpec;
+
+import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper;
+import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi;
+import com.sun.org.apache.xml.internal.security.signature.XMLSignature;
+import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
+import com.sun.org.apache.xml.internal.security.utils.Base64;
+
+
+/**
+ *
+ * @author $Author: mullan $
+ */
+public abstract class SignatureECDSA extends SignatureAlgorithmSpi {
+
+ /** {@link java.util.logging} logging facility */
+ static java.util.logging.Logger log =
+ java.util.logging.Logger.getLogger(SignatureECDSA.class.getName());
+
+ /** @inheritDoc */
+ public abstract String engineGetURI();
+
+ /** Field algorithm */
+ private java.security.Signature _signatureAlgorithm = null;
+
+ /**
+ * Converts an ASN.1 ECDSA value to a XML Signature ECDSA Value.
+ *
+ * The JAVA JCE ECDSA Signature algorithm creates ASN.1 encoded (r,s) value
+ * pairs; the XML Signature requires the core BigInteger values.
+ *
+ * @param asn1Bytes
+ * @return the decode bytes
+ *
+ * @throws IOException
+ * @see 6.4.1 DSA
+ * @see 3.3. ECDSA Signatures
+ */
+ private static byte[] convertASN1toXMLDSIG(byte asn1Bytes[])
+ throws IOException {
+
+ byte rLength = asn1Bytes[3];
+ int i;
+
+ for (i = rLength; (i > 0) && (asn1Bytes[(4 + rLength) - i] == 0); i--);
+
+ byte sLength = asn1Bytes[5 + rLength];
+ int j;
+
+ for (j = sLength;
+ (j > 0) && (asn1Bytes[(6 + rLength + sLength) - j] == 0); j--);
+
+ if ((asn1Bytes[0] != 48) || (asn1Bytes[1] != asn1Bytes.length - 2)
+ || (asn1Bytes[2] != 2) || (i > 24)
+ || (asn1Bytes[4 + rLength] != 2) || (j > 24)) {
+ throw new IOException("Invalid ASN.1 format of ECDSA signature");
+ }
+ byte xmldsigBytes[] = new byte[48];
+
+ System.arraycopy(asn1Bytes, (4 + rLength) - i, xmldsigBytes, 24 - i,
+ i);
+ System.arraycopy(asn1Bytes, (6 + rLength + sLength) - j, xmldsigBytes,
+ 48 - j, j);
+
+ return xmldsigBytes;
+ }
+
+ /**
+ * Converts a XML Signature ECDSA Value to an ASN.1 DSA value.
+ *
+ * The JAVA JCE ECDSA Signature algorithm creates ASN.1 encoded (r,s) value
+ * pairs; the XML Signature requires the core BigInteger values.
+ *
+ * @param xmldsigBytes
+ * @return the encoded ASN.1 bytes
+ *
+ * @throws IOException
+ * @see 6.4.1 DSA
+ * @see 3.3. ECDSA Signatures
+ */
+ private static byte[] convertXMLDSIGtoASN1(byte xmldsigBytes[])
+ throws IOException {
+
+ if (xmldsigBytes.length != 48) {
+ throw new IOException("Invalid XMLDSIG format of ECDSA signature");
+ }
+
+ int i;
+
+ for (i = 24; (i > 0) && (xmldsigBytes[24 - i] == 0); i--);
+
+ int j = i;
+
+ if (xmldsigBytes[24 - i] < 0) {
+ j += 1;
+ }
+
+ int k;
+
+ for (k = 24; (k > 0) && (xmldsigBytes[48 - k] == 0); k--);
+
+ int l = k;
+
+ if (xmldsigBytes[48 - k] < 0) {
+ l += 1;
+ }
+
+ byte asn1Bytes[] = new byte[6 + j + l];
+
+ asn1Bytes[0] = 48;
+ asn1Bytes[1] = (byte) (4 + j + l);
+ asn1Bytes[2] = 2;
+ asn1Bytes[3] = (byte) j;
+
+ System.arraycopy(xmldsigBytes, 24 - i, asn1Bytes, (4 + j) - i, i);
+
+ asn1Bytes[4 + j] = 2;
+ asn1Bytes[5 + j] = (byte) l;
+
+ System.arraycopy(xmldsigBytes, 48 - k, asn1Bytes, (6 + j + l) - k, k);
+
+ return asn1Bytes;
+ }
+
+ /**
+ * Constructor SignatureRSA
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureECDSA() throws XMLSignatureException {
+
+ String algorithmID = JCEMapper.translateURItoJCEID(this.engineGetURI());
+
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Created SignatureECDSA using " + algorithmID);
+ String provider=JCEMapper.getProviderId();
+ try {
+ if (provider==null) {
+ this._signatureAlgorithm = Signature.getInstance(algorithmID);
+ } else {
+ this._signatureAlgorithm = Signature.getInstance(algorithmID,provider);
+ }
+ } catch (java.security.NoSuchAlgorithmException ex) {
+ Object[] exArgs = { algorithmID,
+ ex.getLocalizedMessage() };
+
+ throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
+ } catch (NoSuchProviderException ex) {
+ Object[] exArgs = { algorithmID,
+ ex.getLocalizedMessage() };
+
+ throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws XMLSignatureException {
+
+ try {
+ this._signatureAlgorithm.setParameter(params);
+ } catch (InvalidAlgorithmParameterException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected boolean engineVerify(byte[] signature)
+ throws XMLSignatureException {
+
+ try {
+ byte[] jcebytes = SignatureECDSA.convertXMLDSIGtoASN1(signature);
+
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Called ECDSA.verify() on " + Base64.encode(signature));
+
+ return this._signatureAlgorithm.verify(jcebytes);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ } catch (IOException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineInitVerify(Key publicKey) throws XMLSignatureException {
+
+ if (!(publicKey instanceof PublicKey)) {
+ String supplied = publicKey.getClass().getName();
+ String needed = PublicKey.class.getName();
+ Object exArgs[] = { supplied, needed };
+
+ throw new XMLSignatureException("algorithms.WrongKeyForThisOperation",
+ exArgs);
+ }
+
+ try {
+ this._signatureAlgorithm.initVerify((PublicKey) publicKey);
+ } catch (InvalidKeyException ex) {
+ // reinstantiate Signature object to work around bug in JDK
+ // see: http://bugs.sun.com/view_bug.do?bug_id=4953555
+ Signature sig = this._signatureAlgorithm;
+ try {
+ this._signatureAlgorithm = Signature.getInstance
+ (_signatureAlgorithm.getAlgorithm());
+ } catch (Exception e) {
+ // this shouldn't occur, but if it does, restore previous
+ // Signature
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "Exception when reinstantiating Signature:" + e);
+ }
+ this._signatureAlgorithm = sig;
+ }
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected byte[] engineSign() throws XMLSignatureException {
+
+ try {
+ byte jcebytes[] = this._signatureAlgorithm.sign();
+
+ return SignatureECDSA.convertASN1toXMLDSIG(jcebytes);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ } catch (IOException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineInitSign(Key privateKey, SecureRandom secureRandom)
+ throws XMLSignatureException {
+
+ if (!(privateKey instanceof PrivateKey)) {
+ String supplied = privateKey.getClass().getName();
+ String needed = PrivateKey.class.getName();
+ Object exArgs[] = { supplied, needed };
+
+ throw new XMLSignatureException("algorithms.WrongKeyForThisOperation",
+ exArgs);
+ }
+
+ try {
+ this._signatureAlgorithm.initSign((PrivateKey) privateKey,
+ secureRandom);
+ } catch (InvalidKeyException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineInitSign(Key privateKey) throws XMLSignatureException {
+
+ if (!(privateKey instanceof PrivateKey)) {
+ String supplied = privateKey.getClass().getName();
+ String needed = PrivateKey.class.getName();
+ Object exArgs[] = { supplied, needed };
+
+ throw new XMLSignatureException("algorithms.WrongKeyForThisOperation",
+ exArgs);
+ }
+
+ try {
+ this._signatureAlgorithm.initSign((PrivateKey) privateKey);
+ } catch (InvalidKeyException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineUpdate(byte[] input) throws XMLSignatureException {
+
+ try {
+ this._signatureAlgorithm.update(input);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineUpdate(byte input) throws XMLSignatureException {
+
+ try {
+ this._signatureAlgorithm.update(input);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected void engineUpdate(byte buf[], int offset, int len)
+ throws XMLSignatureException {
+
+ try {
+ this._signatureAlgorithm.update(buf, offset, len);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException("empty", ex);
+ }
+ }
+
+ /** @inheritDoc */
+ protected String engineGetJCEAlgorithmString() {
+ return this._signatureAlgorithm.getAlgorithm();
+ }
+
+ /** @inheritDoc */
+ protected String engineGetJCEProviderName() {
+ return this._signatureAlgorithm.getProvider().getName();
+ }
+
+ /** @inheritDoc */
+ protected void engineSetHMACOutputLength(int HMACOutputLength)
+ throws XMLSignatureException {
+ throw new XMLSignatureException("algorithms.HMACOutputLengthOnlyForHMAC");
+ }
+
+ /** @inheritDoc */
+ protected void engineInitSign(
+ Key signingKey, AlgorithmParameterSpec algorithmParameterSpec)
+ throws XMLSignatureException {
+ throw new XMLSignatureException(
+ "algorithms.CannotUseAlgorithmParameterSpecOnRSA");
+ }
+
+ /**
+ * Class SignatureRSASHA1
+ *
+ * @author $Author: mullan $
+ * @version $Revision: 1.2 $
+ */
+ public static class SignatureECDSASHA1 extends SignatureECDSA {
+
+ /**
+ * Constructor SignatureRSASHA1
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureECDSASHA1() throws XMLSignatureException {
+ super();
+ }
+
+ /** @inheritDoc */
+ public String engineGetURI() {
+ return XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA1;
+ }
+ }
+
+}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/CanonicalizationException.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/CanonicalizationException.java
index 732334c36562e12bd133eb2c1ed50e972a1f8e8e..36c98cfe7900fa70a430ac01ca123e17f6962610 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/CanonicalizationException.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/CanonicalizationException.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java
index eb7cb6cad0103150cfa2382588a2ffc6da1f556b..a4181233d6029ceaa3fb52b84574be5d5535b274 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java
@@ -3,7 +3,7 @@
* DO NOT REMOVE OR ALTER!
*/
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2008 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,6 @@
*/
package com.sun.org.apache.xml.internal.security.c14n;
-
-
import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.util.HashMap;
@@ -37,318 +35,326 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
-
/**
- *
*
* @author Christian Geuer-Pollmann
*/
public class Canonicalizer {
- //J-
- /** The output encoding of canonicalized data */
- public static final String ENCODING = "UTF8";
+ /** The output encoding of canonicalized data */
+ public static final String ENCODING = "UTF8";
+
+ /**
+ * XPath Expresion for selecting every node and continuous comments joined
+ * in only one node
+ */
+ public static final String XPATH_C14N_WITH_COMMENTS_SINGLE_NODE =
+ "(.//. | .//@* | .//namespace::*)";
+
+ /**
+ * The URL defined in XML-SEC Rec for inclusive c14n without comments.
+ */
+ public static final String ALGO_ID_C14N_OMIT_COMMENTS =
+ "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
+ /**
+ * The URL defined in XML-SEC Rec for inclusive c14n with comments.
+ */
+ public static final String ALGO_ID_C14N_WITH_COMMENTS =
+ ALGO_ID_C14N_OMIT_COMMENTS + "#WithComments";
+ /**
+ * The URL defined in XML-SEC Rec for exclusive c14n without comments.
+ */
+ public static final String ALGO_ID_C14N_EXCL_OMIT_COMMENTS =
+ "http://www.w3.org/2001/10/xml-exc-c14n#";
+ /**
+ * The URL defined in XML-SEC Rec for exclusive c14n with comments.
+ */
+ public static final String ALGO_ID_C14N_EXCL_WITH_COMMENTS =
+ ALGO_ID_C14N_EXCL_OMIT_COMMENTS + "WithComments";
+ /**
+ * The URI for inclusive c14n 1.1 without comments.
+ */
+ public static final String ALGO_ID_C14N11_OMIT_COMMENTS =
+ "http://www.w3.org/2006/12/xml-c14n11";
+ /**
+ * The URI for inclusive c14n 1.1 with comments.
+ */
+ public static final String ALGO_ID_C14N11_WITH_COMMENTS =
+ ALGO_ID_C14N11_OMIT_COMMENTS + "#WithComments";
+
+ static boolean _alreadyInitialized = false;
+ static Map _canonicalizerHash = null;
+ protected CanonicalizerSpi canonicalizerSpi = null;
- /**
- * XPath Expresion for selecting every node and continuos comments joined in only one node
+ /**
+ * Method init
+ *
*/
- public static final String XPATH_C14N_WITH_COMMENTS_SINGLE_NODE = "(.//. | .//@* | .//namespace::*)";
+ public static void init() {
+ if (!Canonicalizer._alreadyInitialized) {
+ Canonicalizer._canonicalizerHash = new HashMap(10);
+ Canonicalizer._alreadyInitialized = true;
+ }
+ }
- /**
- * The URL defined in XML-SEC Rec for inclusive c14n without comments.
+ /**
+ * Constructor Canonicalizer
+ *
+ * @param algorithmURI
+ * @throws InvalidCanonicalizerException
*/
- public static final String ALGO_ID_C14N_OMIT_COMMENTS = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
- /**
- * The URL defined in XML-SEC Rec for inclusive c14n with comments.
- */
- public static final String ALGO_ID_C14N_WITH_COMMENTS = ALGO_ID_C14N_OMIT_COMMENTS + "#WithComments";
- /**
- * The URL defined in XML-SEC Rec for exclusive c14n without comments.
- */
- public static final String ALGO_ID_C14N_EXCL_OMIT_COMMENTS = "http://www.w3.org/2001/10/xml-exc-c14n#";
- /**
- * The URL defined in XML-SEC Rec for exclusive c14n with comments.
- */
- public static final String ALGO_ID_C14N_EXCL_WITH_COMMENTS = ALGO_ID_C14N_EXCL_OMIT_COMMENTS + "WithComments";
-
- static boolean _alreadyInitialized = false;
- static Map _canonicalizerHash = null;
-
- protected CanonicalizerSpi canonicalizerSpi = null;
- //J+
-
- /**
- * Method init
- *
- */
- public static void init() {
-
- if (!Canonicalizer._alreadyInitialized) {
- Canonicalizer._canonicalizerHash = new HashMap(10);
- Canonicalizer._alreadyInitialized = true;
- }
- }
-
- /**
- * Constructor Canonicalizer
- *
- * @param algorithmURI
- * @throws InvalidCanonicalizerException
- */
- private Canonicalizer(String algorithmURI)
+ private Canonicalizer(String algorithmURI)
throws InvalidCanonicalizerException {
- try {
- Class implementingClass = getImplementingClass(algorithmURI);
-
- this.canonicalizerSpi =
- (CanonicalizerSpi) implementingClass.newInstance();
- this.canonicalizerSpi.reset=true;
- } catch (Exception e) {
- Object exArgs[] = { algorithmURI };
-
- throw new InvalidCanonicalizerException(
- "signature.Canonicalizer.UnknownCanonicalizer", exArgs);
- }
- }
-
- /**
- * Method getInstance
- *
- * @param algorithmURI
- * @return a Conicicalizer instance ready for the job
- * @throws InvalidCanonicalizerException
- */
- public static final Canonicalizer getInstance(String algorithmURI)
+ try {
+ Class implementingClass = getImplementingClass(algorithmURI);
+
+ this.canonicalizerSpi =
+ (CanonicalizerSpi) implementingClass.newInstance();
+ this.canonicalizerSpi.reset=true;
+ } catch (Exception e) {
+ Object exArgs[] = { algorithmURI };
+
+ throw new InvalidCanonicalizerException(
+ "signature.Canonicalizer.UnknownCanonicalizer", exArgs);
+ }
+ }
+
+ /**
+ * Method getInstance
+ *
+ * @param algorithmURI
+ * @return a Conicicalizer instance ready for the job
+ * @throws InvalidCanonicalizerException
+ */
+ public static final Canonicalizer getInstance(String algorithmURI)
throws InvalidCanonicalizerException {
- Canonicalizer c14nizer = new Canonicalizer(algorithmURI);
+ Canonicalizer c14nizer = new Canonicalizer(algorithmURI);
- return c14nizer;
- }
+ return c14nizer;
+ }
- /**
- * Method register
- *
- * @param algorithmURI
- * @param implementingClass
- * @throws AlgorithmAlreadyRegisteredException
- */
- public static void register(String algorithmURI, String implementingClass)
+ /**
+ * Method register
+ *
+ * @param algorithmURI
+ * @param implementingClass
+ * @throws AlgorithmAlreadyRegisteredException
+ */
+ public static void register(String algorithmURI, String implementingClass)
throws AlgorithmAlreadyRegisteredException {
- // check whether URI is already registered
- Class registeredClass = getImplementingClass(algorithmURI);
+ // check whether URI is already registered
+ Class registeredClass = getImplementingClass(algorithmURI);
- if (registeredClass != null) {
- Object exArgs[] = { algorithmURI, registeredClass };
+ if (registeredClass != null) {
+ Object exArgs[] = { algorithmURI, registeredClass };
- throw new AlgorithmAlreadyRegisteredException(
- "algorithm.alreadyRegistered", exArgs);
- }
+ throw new AlgorithmAlreadyRegisteredException(
+ "algorithm.alreadyRegistered", exArgs);
+ }
- try {
- _canonicalizerHash.put(algorithmURI, Class.forName(implementingClass));
+ try {
+ _canonicalizerHash.put(algorithmURI, Class.forName(implementingClass));
} catch (ClassNotFoundException e) {
- throw new RuntimeException("c14n class not found");
+ throw new RuntimeException("c14n class not found");
}
- }
-
- /**
- * Method getURI
- *
- * @return the URI defined for this c14n instance.
- */
- public final String getURI() {
- return this.canonicalizerSpi.engineGetURI();
- }
-
- /**
- * Method getIncludeComments
- *
- * @return true if the c14n respect the comments.
- */
- public boolean getIncludeComments() {
- return this.canonicalizerSpi.engineGetIncludeComments();
- }
-
- /**
- * This method tries to canonicalize the given bytes. It's possible to even
- * canonicalize non-wellformed sequences if they are well-formed after being
- * wrapped with a >a<...>/a<
.
- *
- * @param inputBytes
- * @return the result of the conicalization.
- * @throws CanonicalizationException
- * @throws java.io.IOException
- * @throws javax.xml.parsers.ParserConfigurationException
- * @throws org.xml.sax.SAXException
- */
- public byte[] canonicalize(byte[] inputBytes)
+ }
+
+ /**
+ * Method getURI
+ *
+ * @return the URI defined for this c14n instance.
+ */
+ public final String getURI() {
+ return this.canonicalizerSpi.engineGetURI();
+ }
+
+ /**
+ * Method getIncludeComments
+ *
+ * @return true if the c14n respect the comments.
+ */
+ public boolean getIncludeComments() {
+ return this.canonicalizerSpi.engineGetIncludeComments();
+ }
+
+ /**
+ * This method tries to canonicalize the given bytes. It's possible to even
+ * canonicalize non-wellformed sequences if they are well-formed after being
+ * wrapped with a >a<...>/a<
.
+ *
+ * @param inputBytes
+ * @return the result of the conicalization.
+ * @throws CanonicalizationException
+ * @throws java.io.IOException
+ * @throws javax.xml.parsers.ParserConfigurationException
+ * @throws org.xml.sax.SAXException
+ */
+ public byte[] canonicalize(byte[] inputBytes)
throws javax.xml.parsers.ParserConfigurationException,
java.io.IOException, org.xml.sax.SAXException,
CanonicalizationException {
- ByteArrayInputStream bais = new ByteArrayInputStream(inputBytes);
- InputSource in = new InputSource(bais);
- DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
-
- dfactory.setNamespaceAware(true);
-
- // needs to validate for ID attribute nomalization
- dfactory.setValidating(true);
-
- DocumentBuilder db = dfactory.newDocumentBuilder();
-
- /*
- * for some of the test vectors from the specification,
- * there has to be a validatin parser for ID attributes, default
- * attribute values, NMTOKENS, etc.
- * Unfortunaltely, the test vectors do use different DTDs or
- * even no DTD. So Xerces 1.3.1 fires many warnings about using
- * ErrorHandlers.
- *
- * Text from the spec:
- *
- * The input octet stream MUST contain a well-formed XML document,
- * but the input need not be validated. However, the attribute
- * value normalization and entity reference resolution MUST be
- * performed in accordance with the behaviors of a validating
- * XML processor. As well, nodes for default attributes (declared
- * in the ATTLIST with an AttValue but not specified) are created
- * in each element. Thus, the declarations in the document type
- * declaration are used to help create the canonical form, even
- * though the document type declaration is not retained in the
- * canonical form.
- *
- */
- db.setErrorHandler(new com.sun.org.apache.xml.internal.security.utils
- .IgnoreAllErrorHandler());
-
- Document document = db.parse(in);
- byte result[] = this.canonicalizeSubtree(document);
-
- return result;
- }
-
- /**
- * Canonicalizes the subtree rooted by node
.
- *
- * @param node The node to canicalize
- * @return the result of the c14n.
- *
- * @throws CanonicalizationException
- */
- public byte[] canonicalizeSubtree(Node node)
+ ByteArrayInputStream bais = new ByteArrayInputStream(inputBytes);
+ InputSource in = new InputSource(bais);
+ DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
+
+ dfactory.setNamespaceAware(true);
+
+ // needs to validate for ID attribute nomalization
+ dfactory.setValidating(true);
+
+ DocumentBuilder db = dfactory.newDocumentBuilder();
+
+ /*
+ * for some of the test vectors from the specification,
+ * there has to be a validatin parser for ID attributes, default
+ * attribute values, NMTOKENS, etc.
+ * Unfortunaltely, the test vectors do use different DTDs or
+ * even no DTD. So Xerces 1.3.1 fires many warnings about using
+ * ErrorHandlers.
+ *
+ * Text from the spec:
+ *
+ * The input octet stream MUST contain a well-formed XML document,
+ * but the input need not be validated. However, the attribute
+ * value normalization and entity reference resolution MUST be
+ * performed in accordance with the behaviors of a validating
+ * XML processor. As well, nodes for default attributes (declared
+ * in the ATTLIST with an AttValue but not specified) are created
+ * in each element. Thus, the declarations in the document type
+ * declaration are used to help create the canonical form, even
+ * though the document type declaration is not retained in the
+ * canonical form.
+ *
+ */
+ db.setErrorHandler(new com.sun.org.apache.xml.internal.security.utils
+ .IgnoreAllErrorHandler());
+
+ Document document = db.parse(in);
+ byte result[] = this.canonicalizeSubtree(document);
+
+ return result;
+ }
+
+ /**
+ * Canonicalizes the subtree rooted by node
.
+ *
+ * @param node The node to canicalize
+ * @return the result of the c14n.
+ *
+ * @throws CanonicalizationException
+ */
+ public byte[] canonicalizeSubtree(Node node)
throws CanonicalizationException {
- return this.canonicalizerSpi.engineCanonicalizeSubTree(node);
- }
-
- /**
- * Canonicalizes the subtree rooted by node
.
- *
- * @param node
- * @param inclusiveNamespaces
- * @return the result of the c14n.
- * @throws CanonicalizationException
- */
- public byte[] canonicalizeSubtree(Node node, String inclusiveNamespaces)
+ return this.canonicalizerSpi.engineCanonicalizeSubTree(node);
+ }
+
+ /**
+ * Canonicalizes the subtree rooted by node
.
+ *
+ * @param node
+ * @param inclusiveNamespaces
+ * @return the result of the c14n.
+ * @throws CanonicalizationException
+ */
+ public byte[] canonicalizeSubtree(Node node, String inclusiveNamespaces)
throws CanonicalizationException {
- return this.canonicalizerSpi.engineCanonicalizeSubTree(node,
+ return this.canonicalizerSpi.engineCanonicalizeSubTree(node,
inclusiveNamespaces);
- }
-
- /**
- * Canonicalizes an XPath node set. The xpathNodeSet
is treated
- * as a list of XPath nodes, not as a list of subtrees.
- *
- * @param xpathNodeSet
- * @return the result of the c14n.
- * @throws CanonicalizationException
- */
- public byte[] canonicalizeXPathNodeSet(NodeList xpathNodeSet)
+ }
+
+ /**
+ * Canonicalizes an XPath node set. The xpathNodeSet
is treated
+ * as a list of XPath nodes, not as a list of subtrees.
+ *
+ * @param xpathNodeSet
+ * @return the result of the c14n.
+ * @throws CanonicalizationException
+ */
+ public byte[] canonicalizeXPathNodeSet(NodeList xpathNodeSet)
throws CanonicalizationException {
- return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet);
- }
-
- /**
- * Canonicalizes an XPath node set. The xpathNodeSet
is treated
- * as a list of XPath nodes, not as a list of subtrees.
- *
- * @param xpathNodeSet
- * @param inclusiveNamespaces
- * @return the result of the c14n.
- * @throws CanonicalizationException
- */
- public byte[] canonicalizeXPathNodeSet(
+ return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet);
+ }
+
+ /**
+ * Canonicalizes an XPath node set. The xpathNodeSet
is treated
+ * as a list of XPath nodes, not as a list of subtrees.
+ *
+ * @param xpathNodeSet
+ * @param inclusiveNamespaces
+ * @return the result of the c14n.
+ * @throws CanonicalizationException
+ */
+ public byte[] canonicalizeXPathNodeSet(
NodeList xpathNodeSet, String inclusiveNamespaces)
throws CanonicalizationException {
- return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet,
+ return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet,
inclusiveNamespaces);
- }
-
- /**
- * Canonicalizes an XPath node set.
- *
- * @param xpathNodeSet
- * @return the result of the c14n.
- * @throws CanonicalizationException
- */
- public byte[] canonicalizeXPathNodeSet(Set xpathNodeSet)
+ }
+
+ /**
+ * Canonicalizes an XPath node set.
+ *
+ * @param xpathNodeSet
+ * @return the result of the c14n.
+ * @throws CanonicalizationException
+ */
+ public byte[] canonicalizeXPathNodeSet(Set xpathNodeSet)
throws CanonicalizationException {
- return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet);
- }
-
- /**
- * Canonicalizes an XPath node set.
- *
- * @param xpathNodeSet
- * @param inclusiveNamespaces
- * @return the result of the c14n.
- * @throws CanonicalizationException
- */
- public byte[] canonicalizeXPathNodeSet(
- Set xpathNodeSet, String inclusiveNamespaces)
- throws CanonicalizationException {
- return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet,
- inclusiveNamespaces);
- }
-
- /**
- * Sets the writter where the cannocalization ends. ByteArrayOutputStream if
- * none is setted.
- * @param os
- */
- public void setWriter(OutputStream os) {
- this.canonicalizerSpi.setWriter(os);
- }
-
- /**
- * Returns the name of the implementing {@link CanonicalizerSpi} class
- *
- * @return the name of the implementing {@link CanonicalizerSpi} class
- */
- public String getImplementingCanonicalizerClass() {
- return this.canonicalizerSpi.getClass().getName();
- }
-
- /**
- * Method getImplementingClass
- *
- * @param URI
- * @return the name of the class that implements the give URI
- */
- private static Class getImplementingClass(String URI) {
- return (Class) _canonicalizerHash.get(URI);
- }
-
- /**
- * Set the canonicalizator behaviour to not reset.
- *
- */
- public void notReset() {
- this.canonicalizerSpi.reset=false;
- }
+ return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet);
+ }
+
+ /**
+ * Canonicalizes an XPath node set.
+ *
+ * @param xpathNodeSet
+ * @param inclusiveNamespaces
+ * @return the result of the c14n.
+ * @throws CanonicalizationException
+ */
+ public byte[] canonicalizeXPathNodeSet(Set xpathNodeSet,
+ String inclusiveNamespaces) throws CanonicalizationException {
+ return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet,
+ inclusiveNamespaces);
+ }
+
+ /**
+ * Sets the writer where the canonicalization ends. ByteArrayOutputStream
+ * if none is set.
+ * @param os
+ */
+ public void setWriter(OutputStream os) {
+ this.canonicalizerSpi.setWriter(os);
+ }
+
+ /**
+ * Returns the name of the implementing {@link CanonicalizerSpi} class
+ *
+ * @return the name of the implementing {@link CanonicalizerSpi} class
+ */
+ public String getImplementingCanonicalizerClass() {
+ return this.canonicalizerSpi.getClass().getName();
+ }
+
+ /**
+ * Method getImplementingClass
+ *
+ * @param URI
+ * @return the name of the class that implements the given URI
+ */
+ private static Class getImplementingClass(String URI) {
+ return (Class) _canonicalizerHash.get(URI);
+ }
+
+ /**
+ * Set the canonicalizer behaviour to not reset.
+ */
+ public void notReset() {
+ this.canonicalizerSpi.reset = false;
+ }
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/InvalidCanonicalizerException.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/InvalidCanonicalizerException.java
index 8af3ed88050382964bdf23e08cb4b091549a9d8f..9fb1531b7e910fa002e3373c8aec289c38d4df35 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/InvalidCanonicalizerException.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/InvalidCanonicalizerException.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/helper/AttrCompare.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/helper/AttrCompare.java
index 46fdc660338e01752ad1fbe93dbe5b147298e0e7..802abda2862d10a033e43d2541c4f123ad623693 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/helper/AttrCompare.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/helper/AttrCompare.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
@@ -21,17 +20,17 @@
*/
package com.sun.org.apache.xml.internal.security.c14n.helper;
-
-
import com.sun.org.apache.xml.internal.security.utils.Constants;
import org.w3c.dom.Attr;
-
+import java.io.Serializable;
+import java.util.Comparator;
/**
* Compares two attributes based on the C14n specification.
*
*
- *
*
- * $todo$ Should we implement java.util.Comparator and import java.util.Arrays to use Arrays.sort(intarray);
* @author Christian Geuer-Pollmann
*/
-public class AttrCompare implements java.util.Comparator {
-
- private final int ATTR0_BEFORE_ATTR1 = -1;
- private final int ATTR1_BEFORE_ATTR0 = 1;
-
- private final static String XMLNS=Constants.NamespaceSpecNS;
- /**
- * Compares two attributes based on the C14n specification.
- *
- *
- *
- *
- * @param obj0 casted Attr
- * @param obj1 casted Attr
- * @return returns a negative integer, zero, or a positive integer as obj0 is less than, equal to, or greater than obj1
- *
- */
- public int compare(Object obj0, Object obj1) {
-
- Attr attr0 = (Attr) obj0;
- Attr attr1 = (Attr) obj1;
- String namespaceURI0 = attr0.getNamespaceURI();
- String namespaceURI1 = attr1.getNamespaceURI();
-
- boolean isNamespaceAttr0 =
- XMLNS.equals(namespaceURI0);
- boolean isNamespaceAttr1 =
- XMLNS.equals(namespaceURI1);
-
- if (isNamespaceAttr0) {
- if (isNamespaceAttr1) {
-
- // both are namespaces
- String localname0 = attr0.getLocalName();
- String localname1 = attr1.getLocalName();
-
- if (localname0.equals("xmlns")) {
- localname0 = "";
+public class AttrCompare implements Comparator, Serializable {
+
+ private final static long serialVersionUID = -7113259629930576230L;
+ private final static int ATTR0_BEFORE_ATTR1 = -1;
+ private final static int ATTR1_BEFORE_ATTR0 = 1;
+ private final static String XMLNS=Constants.NamespaceSpecNS;
+
+ /**
+ * Compares two attributes based on the C14n specification.
+ *
+ *
+ *
+ *
+ * @param obj0 casted Attr
+ * @param obj1 casted Attr
+ * @return returns a negative integer, zero, or a positive integer as
+ * obj0 is less than, equal to, or greater than obj1
+ *
+ */
+ public int compare(Object obj0, Object obj1) {
+
+ Attr attr0 = (Attr) obj0;
+ Attr attr1 = (Attr) obj1;
+ String namespaceURI0 = attr0.getNamespaceURI();
+ String namespaceURI1 = attr1.getNamespaceURI();
+
+ boolean isNamespaceAttr0 = XMLNS==namespaceURI0;
+ boolean isNamespaceAttr1 = XMLNS==namespaceURI1;
+
+ if (isNamespaceAttr0) {
+ if (isNamespaceAttr1) {
+ // both are namespaces
+ String localname0 = attr0.getLocalName();
+ String localname1 = attr1.getLocalName();
+
+ if (localname0.equals("xmlns")) {
+ localname0 = "";
+ }
+
+ if (localname1.equals("xmlns")) {
+ localname1 = "";
+ }
+
+ return localname0.compareTo(localname1);
}
+ // attr0 is a namespace, attr1 is not
+ return ATTR0_BEFORE_ATTR1;
+ }
- if (localname1.equals("xmlns")) {
- localname1 = "";
- }
-
- return localname0.compareTo(localname1);
- }
- // attr0 is a namespace, attr1 is not
- return ATTR0_BEFORE_ATTR1;
-
- }
- if (isNamespaceAttr1) {
-
+ if (isNamespaceAttr1) {
// attr1 is a namespace, attr0 is not
return ATTR1_BEFORE_ATTR0;
- }
-
- // none is a namespae
-
- if (namespaceURI0 == null) {
- if (namespaceURI1 == null) {
- /*
- String localName0 = attr0.getLocalName();
- String localName1 = attr1.getLocalName();
- return localName0.compareTo(localName1);
- */
+ }
+ // none is a namespace
+ if (namespaceURI0 == null) {
+ if (namespaceURI1 == null) {
String name0 = attr0.getName();
String name1 = attr1.getName();
return name0.compareTo(name1);
+ }
+ return ATTR0_BEFORE_ATTR1;
}
- return ATTR0_BEFORE_ATTR1;
- }
- if (namespaceURI1 == null) {
- return ATTR1_BEFORE_ATTR0;
- }
- int a = namespaceURI0.compareTo(namespaceURI1);
-
- if (a != 0) {
- return a;
- }
- /*
- String localName0 = ;
- String localName1 =;*/
-
- return (attr0.getLocalName())
- .compareTo( attr1.getLocalName());
+ if (namespaceURI1 == null) {
+ return ATTR1_BEFORE_ATTR0;
+ }
- }
+ int a = namespaceURI0.compareTo(namespaceURI1);
+ if (a != 0) {
+ return a;
+ }
+ return (attr0.getLocalName()).compareTo(attr1.getLocalName());
+ }
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11.java
new file mode 100644
index 0000000000000000000000000000000000000000..4790fd890432a907e8c04e470b6aa4106f986cf9
--- /dev/null
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11.java
@@ -0,0 +1,684 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Copyright 2008 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.org.apache.xml.internal.security.c14n.implementations;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import java.util.logging.Logger;
+import java.util.logging.Logger;
+import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
+import com.sun.org.apache.xml.internal.security.c14n.helper.C14nHelper;
+import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
+import com.sun.org.apache.xml.internal.security.utils.Constants;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
+
+/**
+ * Implements
+ * Canonical XML Version 1.1, a W3C Proposed Recommendation from 29
+ * January 2008.
+ *
+ * @author Sean Mullan
+ * @author Raul Benito
+ * @version $Revision: 1.2 $
+ */
+public abstract class Canonicalizer11 extends CanonicalizerBase {
+ boolean firstCall = true;
+ final SortedSet result = new TreeSet(COMPARE);
+ static final String XMLNS_URI = Constants.NamespaceSpecNS;
+ static final String XML_LANG_URI = Constants.XML_LANG_SPACE_SpecNS;
+
+ static Logger log = Logger.getLogger(Canonicalizer11.class.getName());
+
+ static class XmlAttrStack {
+ int currentLevel = 0;
+ int lastlevel = 0;
+ XmlsStackElement cur;
+ static class XmlsStackElement {
+ int level;
+ boolean rendered = false;
+ List nodes = new ArrayList();
+ };
+ List levels = new ArrayList();
+ void push(int level) {
+ currentLevel = level;
+ if (currentLevel == -1)
+ return;
+ cur = null;
+ while (lastlevel >= currentLevel) {
+ levels.remove(levels.size() - 1);
+ if (levels.size() == 0) {
+ lastlevel = 0;
+ return;
+ }
+ lastlevel=((XmlsStackElement)levels.get(levels.size()-1)).level;
+ }
+ }
+ void addXmlnsAttr(Attr n) {
+ if (cur == null) {
+ cur = new XmlsStackElement();
+ cur.level = currentLevel;
+ levels.add(cur);
+ lastlevel = currentLevel;
+ }
+ cur.nodes.add(n);
+ }
+ void getXmlnsAttr(Collection col) {
+ if (cur == null) {
+ cur = new XmlsStackElement();
+ cur.level = currentLevel;
+ lastlevel = currentLevel;
+ levels.add(cur);
+ }
+ int size = levels.size() - 2;
+ boolean parentRendered = false;
+ XmlsStackElement e = null;
+ if (size == -1) {
+ parentRendered = true;
+ } else {
+ e = (XmlsStackElement) levels.get(size);
+ if (e.rendered && e.level+1 == currentLevel)
+ parentRendered = true;
+ }
+ if (parentRendered) {
+ col.addAll(cur.nodes);
+ cur.rendered = true;
+ return;
+ }
+
+ Map loa = new HashMap();
+ List baseAttrs = new ArrayList();
+ boolean successiveOmitted = true;
+ for (;size>=0;size--) {
+ e = (XmlsStackElement) levels.get(size);
+ if (e.rendered) {
+ successiveOmitted = false;
+ }
+ Iterator it = e.nodes.iterator();
+ while (it.hasNext() && successiveOmitted) {
+ Attr n = (Attr) it.next();
+ if (n.getLocalName().equals("base")) {
+ if (!e.rendered) {
+ baseAttrs.add(n);
+ }
+ } else if (!loa.containsKey(n.getName()))
+ loa.put(n.getName(), n);
+ }
+ }
+ if (!baseAttrs.isEmpty()) {
+ Iterator it = cur.nodes.iterator();
+ String base = null;
+ Attr baseAttr = null;
+ while (it.hasNext()) {
+ Attr n = (Attr) it.next();
+ if (n.getLocalName().equals("base")) {
+ base = n.getValue();
+ baseAttr = n;
+ break;
+ }
+ }
+ it = baseAttrs.iterator();
+ while (it.hasNext()) {
+ Attr n = (Attr) it.next();
+ if (base == null) {
+ base = n.getValue();
+ baseAttr = n;
+ } else {
+ try {
+ base = joinURI(n.getValue(), base);
+ } catch (URISyntaxException ue) {
+ ue.printStackTrace();
+ }
+ }
+ }
+ if (base != null && base.length() != 0) {
+ baseAttr.setValue(base);
+ col.add(baseAttr);
+ }
+ }
+
+ cur.rendered = true;
+ col.addAll(loa.values());
+ }
+ };
+ XmlAttrStack xmlattrStack = new XmlAttrStack();
+
+ /**
+ * Constructor Canonicalizer11
+ *
+ * @param includeComments
+ */
+ public Canonicalizer11(boolean includeComments) {
+ super(includeComments);
+ }
+
+ /**
+ * Returns the Attr[]s to be outputted for the given element.
+ *
+ * The code of this method is a copy of {@link #handleAttributes(Element,
+ * NameSpaceSymbTable)},
+ * whereas it takes into account that subtree-c14n is -- well --
+ * subtree-based.
+ * So if the element in question isRoot of c14n, it's parent is not in the
+ * node set, as well as all other ancestors.
+ *
+ * @param E
+ * @param ns
+ * @return the Attr[]s to be outputted
+ * @throws CanonicalizationException
+ */
+ Iterator handleAttributesSubtree(Element E, NameSpaceSymbTable ns)
+ throws CanonicalizationException {
+ if (!E.hasAttributes() && !firstCall) {
+ return null;
+ }
+ // result will contain the attrs which have to be outputted
+ final SortedSet result = this.result;
+ result.clear();
+ NamedNodeMap attrs = E.getAttributes();
+ int attrsLength = attrs.getLength();
+
+ for (int i = 0; i < attrsLength; i++) {
+ Attr N = (Attr) attrs.item(i);
+ String NUri = N.getNamespaceURI();
+
+ if (XMLNS_URI != NUri) {
+ // It's not a namespace attr node. Add to the result and
+ // continue.
+ result.add(N);
+ continue;
+ }
+
+ String NName = N.getLocalName();
+ String NValue = N.getValue();
+ if (XML.equals(NName)
+ && XML_LANG_URI.equals(NValue)) {
+ // The default mapping for xml must not be output.
+ continue;
+ }
+
+ Node n = ns.addMappingAndRender(NName, NValue, N);
+
+ if (n != null) {
+ // Render the ns definition
+ result.add(n);
+ if (C14nHelper.namespaceIsRelative(N)) {
+ Object exArgs[] = {E.getTagName(), NName, N.getNodeValue()};
+ throw new CanonicalizationException(
+ "c14n.Canonicalizer.RelativeNamespace", exArgs);
+ }
+ }
+ }
+
+ if (firstCall) {
+ // It is the first node of the subtree
+ // Obtain all the namespaces defined in the parents, and added
+ // to the output.
+ ns.getUnrenderedNodes(result);
+ // output the attributes in the xml namespace.
+ xmlattrStack.getXmlnsAttr(result);
+ firstCall = false;
+ }
+
+ return result.iterator();
+ }
+
+ /**
+ * Returns the Attr[]s to be outputted for the given element.
+ *
+ * IMPORTANT: This method expects to work on a modified DOM tree, i.e. a
+ * DOM which has been prepared using
+ * {@link com.sun.org.apache.xml.internal.security.utils.XMLUtils#circumventBug2650(
+ * org.w3c.dom.Document)}.
+ *
+ * @param E
+ * @param ns
+ * @return the Attr[]s to be outputted
+ * @throws CanonicalizationException
+ */
+ Iterator handleAttributes(Element E, NameSpaceSymbTable ns)
+ throws CanonicalizationException {
+ // result will contain the attrs which have to be output
+ xmlattrStack.push(ns.getLevel());
+ boolean isRealVisible = isVisibleDO(E, ns.getLevel()) == 1;
+ NamedNodeMap attrs = null;
+ int attrsLength = 0;
+ if (E.hasAttributes()) {
+ attrs = E.getAttributes();
+ attrsLength = attrs.getLength();
+ }
+
+ SortedSet result = this.result;
+ result.clear();
+
+ for (int i = 0; i < attrsLength; i++) {
+ Attr N = (Attr) attrs.item(i);
+ String NUri = N.getNamespaceURI();
+
+ if (XMLNS_URI != NUri) {
+ // A non namespace definition node.
+ if (XML_LANG_URI == NUri) {
+ if (N.getLocalName().equals("id")) {
+ if (isRealVisible) {
+ // treat xml:id like any other attribute
+ // (emit it, but don't inherit it)
+ result.add(N);
+ }
+ } else {
+ xmlattrStack.addXmlnsAttr(N);
+ }
+ } else if (isRealVisible) {
+ // The node is visible add the attribute to the list of
+ // output attributes.
+ result.add(N);
+ }
+ // keep working
+ continue;
+ }
+
+ String NName = N.getLocalName();
+ String NValue = N.getValue();
+ if ("xml".equals(NName)
+ && XML_LANG_URI.equals(NValue)) {
+ /* except omit namespace node with local name xml, which defines
+ * the xml prefix, if its string value is
+ * http://www.w3.org/XML/1998/namespace.
+ */
+ continue;
+ }
+ // add the prefix binding to the ns symb table.
+ // ns.addInclusiveMapping(NName,NValue,N,isRealVisible);
+ if (isVisible(N)) {
+ if (!isRealVisible && ns.removeMappingIfRender(NName)) {
+ continue;
+ }
+ // The xpath select this node output it if needed.
+ // Node n = ns.addMappingAndRenderXNodeSet
+ // (NName, NValue, N, isRealVisible);
+ Node n = ns.addMappingAndRender(NName, NValue, N);
+ if (n != null) {
+ result.add(n);
+ if (C14nHelper.namespaceIsRelative(N)) {
+ Object exArgs[] =
+ { E.getTagName(), NName, N.getNodeValue() };
+ throw new CanonicalizationException(
+ "c14n.Canonicalizer.RelativeNamespace", exArgs);
+ }
+ }
+ } else {
+ if (isRealVisible && NName != XMLNS) {
+ ns.removeMapping(NName);
+ } else {
+ ns.addMapping(NName, NValue, N);
+ }
+ }
+ }
+ if (isRealVisible) {
+ // The element is visible, handle the xmlns definition
+ Attr xmlns = E.getAttributeNodeNS(XMLNS_URI, XMLNS);
+ Node n = null;
+ if (xmlns == null) {
+ // No xmlns def just get the already defined.
+ n = ns.getMapping(XMLNS);
+ } else if (!isVisible(xmlns)) {
+ // There is a defn but the xmlns is not selected by the xpath.
+ // then xmlns=""
+ n = ns.addMappingAndRender(XMLNS, "", nullNode);
+ }
+ // output the xmlns def if needed.
+ if (n != null) {
+ result.add(n);
+ }
+ // Float all xml:* attributes of the unselected parent elements to
+ // this one. addXmlAttributes(E,result);
+ xmlattrStack.getXmlnsAttr(result);
+ ns.getUnrenderedNodes(result);
+ }
+
+ return result.iterator();
+ }
+
+ /**
+ * Always throws a CanonicalizationException because this is inclusive c14n.
+ *
+ * @param xpathNodeSet
+ * @param inclusiveNamespaces
+ * @return none it always fails
+ * @throws CanonicalizationException always
+ */
+ public byte[] engineCanonicalizeXPathNodeSet(Set xpathNodeSet,
+ String inclusiveNamespaces) throws CanonicalizationException {
+ throw new CanonicalizationException(
+ "c14n.Canonicalizer.UnsupportedOperation");
+ }
+
+ /**
+ * Always throws a CanonicalizationException because this is inclusive c14n.
+ *
+ * @param rootNode
+ * @param inclusiveNamespaces
+ * @return none it always fails
+ * @throws CanonicalizationException
+ */
+ public byte[] engineCanonicalizeSubTree(Node rootNode,
+ String inclusiveNamespaces) throws CanonicalizationException {
+ throw new CanonicalizationException(
+ "c14n.Canonicalizer.UnsupportedOperation");
+ }
+
+ void circumventBugIfNeeded(XMLSignatureInput input)
+ throws CanonicalizationException, ParserConfigurationException,
+ IOException, SAXException {
+ if (!input.isNeedsToBeExpanded())
+ return;
+ Document doc = null;
+ if (input.getSubNode() != null) {
+ doc = XMLUtils.getOwnerDocument(input.getSubNode());
+ } else {
+ doc = XMLUtils.getOwnerDocument(input.getNodeSet());
+ }
+ XMLUtils.circumventBug2650(doc);
+ }
+
+ void handleParent(Element e, NameSpaceSymbTable ns) {
+ if (!e.hasAttributes()) {
+ return;
+ }
+ xmlattrStack.push(-1);
+ NamedNodeMap attrs = e.getAttributes();
+ int attrsLength = attrs.getLength();
+ for (int i = 0; i < attrsLength; i++) {
+ Attr N = (Attr) attrs.item(i);
+ if (Constants.NamespaceSpecNS != N.getNamespaceURI()) {
+ // Not a namespace definition, ignore.
+ if (XML_LANG_URI == N.getNamespaceURI()) {
+ xmlattrStack.addXmlnsAttr(N);
+ }
+ continue;
+ }
+
+ String NName = N.getLocalName();
+ String NValue = N.getNodeValue();
+ if (XML.equals(NName)
+ && Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) {
+ continue;
+ }
+ ns.addMapping(NName,NValue,N);
+ }
+ }
+
+ private static String joinURI(String baseURI, String relativeURI)
+ throws URISyntaxException {
+ String bscheme = null;
+ String bauthority = null;
+ String bpath = "";
+ String bquery = null;
+ String bfragment = null; // Is this correct?
+
+ // pre-parse the baseURI
+ if (baseURI != null) {
+ if (baseURI.endsWith("..")) {
+ baseURI = baseURI + "/";
+ }
+ URI base = new URI(baseURI);
+ bscheme = base.getScheme();
+ bauthority = base.getAuthority();
+ bpath = base.getPath();
+ bquery = base.getQuery();
+ bfragment = base.getFragment();
+ }
+
+ URI r = new URI(relativeURI);
+ String rscheme = r.getScheme();
+ String rauthority = r.getAuthority();
+ String rpath = r.getPath();
+ String rquery = r.getQuery();
+ String rfragment = null;
+
+ String tscheme, tauthority, tpath, tquery, tfragment;
+ if (rscheme != null && rscheme.equals(bscheme)) {
+ rscheme = null;
+ }
+ if (rscheme != null) {
+ tscheme = rscheme;
+ tauthority = rauthority;
+ tpath = removeDotSegments(rpath);
+ tquery = rquery;
+ } else {
+ if (rauthority != null) {
+ tauthority = rauthority;
+ tpath = removeDotSegments(rpath);
+ tquery = rquery;
+ } else {
+ if (rpath.length() == 0) {
+ tpath = bpath;
+ if (rquery != null) {
+ tquery = rquery;
+ } else {
+ tquery = bquery;
+ }
+ } else {
+ if (rpath.startsWith("/")) {
+ tpath = removeDotSegments(rpath);
+ } else {
+ if (bauthority != null && bpath.length() == 0) {
+ tpath = "/" + rpath;
+ } else {
+ int last = bpath.lastIndexOf('/');
+ if (last == -1) {
+ tpath = rpath;
+ } else {
+ tpath = bpath.substring(0, last+1) + rpath;
+ }
+ }
+ tpath = removeDotSegments(tpath);
+ }
+ tquery = rquery;
+ }
+ tauthority = bauthority;
+ }
+ tscheme = bscheme;
+ }
+ tfragment = rfragment;
+ return new URI(tscheme, tauthority, tpath, tquery, tfragment).toString();
+ }
+
+ private static String removeDotSegments(String path) {
+
+ log.log(java.util.logging.Level.FINE, "STEP OUTPUT BUFFER\t\tINPUT BUFFER");
+
+ // 1. The input buffer is initialized with the now-appended path
+ // components then replace occurrences of "//" in the input buffer
+ // with "/" until no more occurrences of "//" are in the input buffer.
+ String input = path;
+ while (input.indexOf("//") > -1) {
+ input = input.replaceAll("//", "/");
+ }
+
+ // Initialize the output buffer with the empty string.
+ StringBuffer output = new StringBuffer();
+
+ // If the input buffer starts with a root slash "/" then move this
+ // character to the output buffer.
+ if (input.charAt(0) == '/') {
+ output.append("/");
+ input = input.substring(1);
+ }
+
+ printStep("1 ", output.toString(), input);
+
+ // While the input buffer is not empty, loop as follows
+ while (input.length() != 0) {
+ // 2A. If the input buffer begins with a prefix of "./",
+ // then remove that prefix from the input buffer
+ // else if the input buffer begins with a prefix of "../", then
+ // if also the output does not contain the root slash "/" only,
+ // then move this prefix to the end of the output buffer else
+ // remove that prefix
+ if (input.startsWith("./")) {
+ input = input.substring(2);
+ printStep("2A", output.toString(), input);
+ } else if (input.startsWith("../")) {
+ input = input.substring(3);
+ if (!output.toString().equals("/")) {
+ output.append("../");
+ }
+ printStep("2A", output.toString(), input);
+ // 2B. if the input buffer begins with a prefix of "/./" or "/.",
+ // where "." is a complete path segment, then replace that prefix
+ // with "/" in the input buffer; otherwise,
+ } else if (input.startsWith("/./")) {
+ input = input.substring(2);
+ printStep("2B", output.toString(), input);
+ } else if (input.equals("/.")) {
+ // FIXME: what is complete path segment?
+ input = input.replaceFirst("/.", "/");
+ printStep("2B", output.toString(), input);
+ // 2C. if the input buffer begins with a prefix of "/../" or "/..",
+ // where ".." is a complete path segment, then replace that prefix
+ // with "/" in the input buffer and if also the output buffer is
+ // empty, last segment in the output buffer equals "../" or "..",
+ // where ".." is a complete path segment, then append ".." or "/.."
+ // for the latter case respectively to the output buffer else
+ // remove the last segment and its preceding "/" (if any) from the
+ // output buffer and if hereby the first character in the output
+ // buffer was removed and it was not the root slash then delete a
+ // leading slash from the input buffer; otherwise,
+ } else if (input.startsWith("/../")) {
+ input = input.substring(3);
+ if (output.length() == 0) {
+ output.append("/");
+ } else if (output.toString().endsWith("../")) {
+ output.append("..");
+ } else if (output.toString().endsWith("..")) {
+ output.append("/..");
+ } else {
+ int index = output.lastIndexOf("/");
+ if (index == -1) {
+ output = new StringBuffer();
+ if (input.charAt(0) == '/') {
+ input = input.substring(1);
+ }
+ } else {
+ output = output.delete(index, output.length());
+ }
+ }
+ printStep("2C", output.toString(), input);
+ } else if (input.equals("/..")) {
+ // FIXME: what is complete path segment?
+ input = input.replaceFirst("/..", "/");
+ if (output.length() == 0) {
+ output.append("/");
+ } else if (output.toString().endsWith("../")) {
+ output.append("..");
+ } else if (output.toString().endsWith("..")) {
+ output.append("/..");
+ } else {
+ int index = output.lastIndexOf("/");
+ if (index == -1) {
+ output = new StringBuffer();
+ if (input.charAt(0) == '/') {
+ input = input.substring(1);
+ }
+ } else {
+ output = output.delete(index, output.length());
+ }
+ }
+ printStep("2C", output.toString(), input);
+ // 2D. if the input buffer consists only of ".", then remove
+ // that from the input buffer else if the input buffer consists
+ // only of ".." and if the output buffer does not contain only
+ // the root slash "/", then move the ".." to the output buffer
+ // else delte it.; otherwise,
+ } else if (input.equals(".")) {
+ input = "";
+ printStep("2D", output.toString(), input);
+ } else if (input.equals("..")) {
+ if (!output.toString().equals("/"))
+ output.append("..");
+ input = "";
+ printStep("2D", output.toString(), input);
+ // 2E. move the first path segment (if any) in the input buffer
+ // to the end of the output buffer, including the initial "/"
+ // character (if any) and any subsequent characters up to, but not
+ // including, the next "/" character or the end of the input buffer.
+ } else {
+ int end = -1;
+ int begin = input.indexOf('/');
+ if (begin == 0) {
+ end = input.indexOf('/', 1);
+ } else {
+ end = begin;
+ begin = 0;
+ }
+ String segment;
+ if (end == -1) {
+ segment = input.substring(begin);
+ input = "";
+ } else {
+ segment = input.substring(begin, end);
+ input = input.substring(end);
+ }
+ output.append(segment);
+ printStep("2E", output.toString(), input);
+ }
+ }
+
+ // 3. Finally, if the only or last segment of the output buffer is
+ // "..", where ".." is a complete path segment not followed by a slash
+ // then append a slash "/". The output buffer is returned as the result
+ // of remove_dot_segments
+ if (output.toString().endsWith("..")) {
+ output.append("/");
+ printStep("3 ", output.toString(), input);
+ }
+
+ return output.toString();
+ }
+
+ private static void printStep(String step, String output, String input) {
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, " " + step + ": " + output);
+ if (output.length() == 0) {
+ log.log(java.util.logging.Level.FINE, "\t\t\t\t" + input);
+ } else {
+ log.log(java.util.logging.Level.FINE, "\t\t\t" + input);
+ }
+ }
+ }
+}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11_OmitComments.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11_OmitComments.java
new file mode 100644
index 0000000000000000000000000000000000000000..31903667f606de63a33954c907ba9a7b7fc42fbe
--- /dev/null
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11_OmitComments.java
@@ -0,0 +1,41 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Copyright 2008 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.org.apache.xml.internal.security.c14n.implementations;
+
+import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
+
+/**
+ * @author Sean Mullan
+ */
+public class Canonicalizer11_OmitComments extends Canonicalizer11 {
+
+ public Canonicalizer11_OmitComments() {
+ super(false);
+ }
+
+ public final String engineGetURI() {
+ return Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS;
+ }
+
+ public final boolean engineGetIncludeComments() {
+ return false;
+ }
+}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11_WithComments.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11_WithComments.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba650c10872ca6b9dbe609e411da98bb5b5cc44c
--- /dev/null
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11_WithComments.java
@@ -0,0 +1,41 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Copyright 2008 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.org.apache.xml.internal.security.c14n.implementations;
+
+import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
+
+/**
+ * @author Sean Mullan
+ */
+public class Canonicalizer11_WithComments extends Canonicalizer11 {
+
+ public Canonicalizer11_WithComments() {
+ super(true);
+ }
+
+ public final String engineGetURI() {
+ return Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS;
+ }
+
+ public final boolean engineGetIncludeComments() {
+ return true;
+ }
+}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java
index 5dbeb60f98519e7f083052696214278f0a8faffa..541c2d63c99574da4cd210b2d61d7d4479f3a57f 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
@@ -23,20 +22,30 @@ package com.sun.org.apache.xml.internal.security.c14n.implementations;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
+import javax.xml.parsers.ParserConfigurationException;
+
import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
import com.sun.org.apache.xml.internal.security.c14n.helper.C14nHelper;
+import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
import com.sun.org.apache.xml.internal.security.utils.Constants;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
/**
@@ -44,13 +53,92 @@ import org.w3c.dom.Node;
* XML Version 1.0, a W3C Recommendation from 15 March 2001.
*
* @author Christian Geuer-Pollmann
@@ -192,7 +229,8 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase {
*/
Iterator handleAttributes(Element E, NameSpaceSymbTable ns ) throws CanonicalizationException {
// result will contain the attrs which have to be outputted
- boolean isRealVisible=isVisible(E);
+ xmlattrStack.push(ns.getLevel());
+ boolean isRealVisible=isVisibleDO(E,ns.getLevel())==1;
NamedNodeMap attrs = null;
int attrsLength = 0;
if (E.hasAttributes()) {
@@ -204,16 +242,15 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase {
SortedSet result = this.result;
result.clear();
-
for (int i = 0; i < attrsLength; i++) {
Attr N = (Attr) attrs.item(i);
- String NName=N.getLocalName();
- String NValue=N.getValue();
String NUri =N.getNamespaceURI();
- if (!XMLNS_URI.equals(NUri)) {
+ if (XMLNS_URI!=NUri) {
//A non namespace definition node.
- if (isRealVisible){
+ if (XML_LANG_URI==NUri) {
+ xmlattrStack.addXmlnsAttr(N);
+ } else if (isRealVisible){
//The node is visible add the attribute to the list of output attributes.
result.add(N);
}
@@ -221,7 +258,8 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase {
continue;
}
-
+ String NName=N.getLocalName();
+ String NValue=N.getValue();
if ("xml".equals(NName)
&& XML_LANG_URI.equals(NValue)) {
/* except omit namespace node with local name xml, which defines
@@ -232,16 +270,26 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase {
//add the prefix binding to the ns symb table.
//ns.addInclusiveMapping(NName,NValue,N,isRealVisible);
if (isVisible(N)) {
- //The xpath select this node output it if needed.
- Node n=ns.addMappingAndRenderXNodeSet(NName,NValue,N,isRealVisible);
- if (n!=null) {
+ if (!isRealVisible && ns.removeMappingIfRender(NName)) {
+ continue;
+ }
+ //The xpath select this node output it if needed.
+ //Node n=ns.addMappingAndRenderXNodeSet(NName,NValue,N,isRealVisible);
+ Node n=ns.addMappingAndRender(NName,NValue,N);
+ if (n!=null) {
result.add(n);
if (C14nHelper.namespaceIsRelative(N)) {
Object exArgs[] = { E.getTagName(), NName, N.getNodeValue() };
throw new CanonicalizationException(
"c14n.Canonicalizer.RelativeNamespace", exArgs);
- }
- }
+ }
+ }
+ } else {
+ if (isRealVisible && NName!=XMLNS) {
+ ns.removeMapping(NName);
+ } else {
+ ns.addMapping(NName,NValue,N);
+ }
}
}
if (isRealVisible) {
@@ -254,84 +302,21 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase {
} else if ( !isVisible(xmlns)) {
//There is a definition but the xmlns is not selected by the xpath.
//then xmlns=""
- n=ns.addMappingAndRenderXNodeSet(XMLNS,"",nullNode,true);
+ n=ns.addMappingAndRender(XMLNS,"",nullNode);
}
//output the xmlns def if needed.
if (n!=null) {
result.add(n);
}
//Float all xml:* attributes of the unselected parent elements to this one.
- addXmlAttributes(E,result);
+ //addXmlAttributes(E,result);
+ xmlattrStack.getXmlnsAttr(result);
+ ns.getUnrenderedNodes(result);
+
}
return result.iterator();
}
- /**
- * Float the xml:* attributes of the unselected parent nodes to the ciurrent node.
- * @param E
- * @param result
- */
- private void addXmlAttributes(Element E, SortedSet result) {
- /* The processing of an element node E MUST be modified slightly when an
- * XPath node-set is given as input and the element's parent is omitted
- * from the node-set. The method for processing the attribute axis of an
- * element E in the node-set is enhanced. All element nodes along E's
- * ancestor axis are examined for nearest occurrences of attributes in
- * the xml namespace, such as xml:lang and xml:space (whether or not they
- * are in the node-set). From this list of attributes, remove any that are
- * in E's attribute axis (whether or not they are in the node-set). Then,
- * lexicographically merge this attribute list with the nodes of E's
- * attribute axis that are in the node-set. The result of visiting the
- * attribute axis is computed by processing the attribute nodes in this
- * merged attribute list.
- */
-
- // E is in the node-set
- Node parent = E.getParentNode();
- Map loa = new HashMap();
-
- if ((parent != null) && (parent.getNodeType() == Node.ELEMENT_NODE)
- &&!isVisible(parent)) {
-
- // parent element is not in node set
- for (Node ancestor = parent;
- (ancestor != null)
- && (ancestor.getNodeType() == Node.ELEMENT_NODE);
- ancestor = ancestor.getParentNode()) {
- Element el=((Element) ancestor);
- if (!el.hasAttributes()) {
- continue;
- }
- // for all ancestor elements
- NamedNodeMap ancestorAttrs =el.getAttributes();
-
- for (int i = 0; i < ancestorAttrs.getLength(); i++) {
-
- // for all attributes in the ancestor element
- Attr currentAncestorAttr = (Attr) ancestorAttrs.item(i);
-
- if (XML_LANG_URI.equals(
- currentAncestorAttr.getNamespaceURI())) {
-
- // do we have an xml:* ?
- if (!E.hasAttributeNS(
- XML_LANG_URI,
- currentAncestorAttr.getLocalName())) {
-
- // the xml:* attr is not in E
- if (!loa.containsKey(currentAncestorAttr.getName())) {
- loa.put(currentAncestorAttr.getName(),
- currentAncestorAttr);
- }
- }
- }
- }
- }
- }
- result.addAll(loa.values());
-
-}
-
/**
* Always throws a CanonicalizationException because this is inclusive c14n.
*
@@ -363,4 +348,43 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase {
throw new CanonicalizationException(
"c14n.Canonicalizer.UnsupportedOperation");
}
+ void circumventBugIfNeeded(XMLSignatureInput input) throws CanonicalizationException, ParserConfigurationException, IOException, SAXException {
+ if (!input.isNeedsToBeExpanded())
+ return;
+ Document doc = null;
+ if (input.getSubNode() != null) {
+ doc=XMLUtils.getOwnerDocument(input.getSubNode());
+ } else {
+ doc=XMLUtils.getOwnerDocument(input.getNodeSet());
+ }
+ XMLUtils.circumventBug2650(doc);
+
+ }
+
+ void handleParent(Element e, NameSpaceSymbTable ns) {
+ if (!e.hasAttributes()) {
+ return;
+ }
+ xmlattrStack.push(-1);
+ NamedNodeMap attrs = e.getAttributes();
+ int attrsLength = attrs.getLength();
+ for (int i = 0; i < attrsLength; i++) {
+ Attr N = (Attr) attrs.item(i);
+ if (Constants.NamespaceSpecNS!=N.getNamespaceURI()) {
+ //Not a namespace definition, ignore.
+ if (XML_LANG_URI==N.getNamespaceURI()) {
+ xmlattrStack.addXmlnsAttr(N);
+ }
+ continue;
+ }
+
+ String NName=N.getLocalName();
+ String NValue=N.getNodeValue();
+ if (XML.equals(NName)
+ && Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) {
+ continue;
+ }
+ ns.addMapping(NName,NValue,N);
+ }
+ }
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java
index 18f697366cf51c12194970fda695aba978cda1bd..679c7b5088b7ca62547ca329e33a354d0f5f9015 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
@@ -21,20 +20,26 @@
*/
package com.sun.org.apache.xml.internal.security.c14n.implementations;
+import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
+import javax.xml.parsers.ParserConfigurationException;
+
import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
import com.sun.org.apache.xml.internal.security.c14n.helper.C14nHelper;
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
import com.sun.org.apache.xml.internal.security.transforms.params.InclusiveNamespaces;
import com.sun.org.apache.xml.internal.security.utils.Constants;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
/**
* Implements " Exclusive XML
@@ -47,6 +52,7 @@ import org.w3c.dom.Node;
* THIS implementation is a complete rewrite of the algorithm.
*
* @author Christian Geuer-Pollmann
- *
- *
- * @param name
- * @param value
- * @param writer
- * @throws IOException
- */
- static final void outputAttrToWriter(final String name, final String value, final OutputStream writer) throws IOException {
- writer.write(' ');
- writeStringToUtf8(name,writer);
- writer.write(equalsStr);
- byte []toWrite;
- final int length = value.length();
- for (int i=0;i < length; i++) {
- char c = value.charAt(i);
-
- switch (c) {
-
- case '&' :
- toWrite=_AMP_;
- //writer.write(_AMP_);
- break;
-
- case '<' :
- toWrite=_LT_;
- //writer.write(_LT_);
- break;
-
- case '"' :
- toWrite=_QUOT_;
- //writer.write(_QUOT_);
- break;
-
- case 0x09 : // '\t'
- toWrite=__X9_;
- //writer.write(__X9_);
- break;
-
- case 0x0A : // '\n'
- toWrite=__XA_;
- //writer.write(__XA_);
- break;
-
- case 0x0D : // '\r'
- toWrite=__XD_;
- //writer.write(__XD_);
- break;
-
- default :
- writeCharToUtf8(c,writer);
- //this._writer.write(c);
- continue;
- }
- writer.write(toWrite);
- }
-
- writer.write('\"');
- }
-
- final static void writeCharToUtf8(final char c,final OutputStream out) throws IOException{
- char ch;
- if (/*(c >= 0x0001) &&*/ (c <= 0x007F)) {
- out.write(c);
- return;
- }
- int bias;
- int write;
- if (c > 0x07FF) {
- ch=(char)(c>>>12);
- write=0xE0;
- if (ch>0) {
- write |= ( ch & 0x0F);
- }
- out.write(write);
- write=0x80;
- bias=0x3F;
- } else {
- write=0xC0;
- bias=0x1F;
- }
- ch=(char)(c>>>6);
- if (ch>0) {
- write|= (ch & bias);
- }
- out.write(write);
- out.write(0x80 | ((c) & 0x3F));
-
- }
-
- final static void writeStringToUtf8(final String str,final OutputStream out) throws IOException{
- final int length=str.length();
- int i=0;
- char c;
- while (i&
<
"
#x9
, #xA, and #xD, with character
- * references. The character references are written in uppercase
- * hexadecimal with no leading zeroes (for example, #xD
is represented
- * by the character reference 
)
+ *
+ *
+ * @param name
+ * @param value
+ * @param writer
+ * @throws IOException
+ */
+ static final void outputAttrToWriter(final String name, final String value, final OutputStream writer,
+ final Map cache) throws IOException {
+ writer.write(' ');
+ UtfHelpper.writeByte(name,writer,cache);
+ writer.write(equalsStr);
+ byte []toWrite;
+ final int length = value.length();
+ int i=0;
+ while (i < length) {
+ char c = value.charAt(i++);
+
+ switch (c) {
+
+ case '&' :
+ toWrite=_AMP_;
+ break;
+
+ case '<' :
+ toWrite=_LT_;
+ break;
+
+ case '"' :
+ toWrite=_QUOT_;
+ break;
+
+ case 0x09 : // '\t'
+ toWrite=__X9_;
+ break;
+
+ case 0x0A : // '\n'
+ toWrite=__XA_;
+ break;
+
+ case 0x0D : // '\r'
+ toWrite=__XD_;
+ break;
+
+ default :
+ if (c < 0x80 ) {
+ writer.write(c);
+ } else {
+ UtfHelpper.writeCharToUtf8(c,writer);
+ };
+ continue;
+ }
+ writer.write(toWrite);
+ }
- /**
- * @param _writer The _writer to set.
- */
- public void setWriter(OutputStream _writer) {
- this._writer = _writer;
- }
+ writer.write('\"');
+ }
+
+ /**
+ * Outputs a PI to the internal Writer.
+ *
+ * @param currentPI
+ * @param writer where to write the things
+ * @throws IOException
+ */
+ static final void outputPItoWriter(ProcessingInstruction currentPI, OutputStream writer,int position) throws IOException {
+
+ if (position == NODE_AFTER_DOCUMENT_ELEMENT) {
+ writer.write('\n');
+ }
+ writer.write(_BEGIN_PI);
+
+ final String target = currentPI.getTarget();
+ int length = target.length();
+
+ for (int i = 0; i < length; i++) {
+ char c=target.charAt(i);
+ if (c==0x0D) {
+ writer.write(__XD_);
+ } else {
+ if (c < 0x80) {
+ writer.write(c);
+ } else {
+ UtfHelpper.writeCharToUtf8(c,writer);
+ };
+ }
+ }
+
+ final String data = currentPI.getData();
+
+ length = data.length();
+
+ if (length > 0) {
+ writer.write(' ');
+
+ for (int i = 0; i < length; i++) {
+ char c=data.charAt(i);
+ if (c==0x0D) {
+ writer.write(__XD_);
+ } else {
+ UtfHelpper.writeCharToUtf8(c,writer);
+ }
+ }
+ }
+
+ writer.write(_END_PI);
+ if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
+ writer.write('\n');
+ }
+ }
+
+ /**
+ * Method outputCommentToWriter
+ *
+ * @param currentComment
+ * @param writer writer where to write the things
+ * @throws IOException
+ */
+ static final void outputCommentToWriter(Comment currentComment, OutputStream writer,int position) throws IOException {
+ if (position == NODE_AFTER_DOCUMENT_ELEMENT) {
+ writer.write('\n');
+ }
+ writer.write(_BEGIN_COMM);
+
+ final String data = currentComment.getData();
+ final int length = data.length();
+
+ for (int i = 0; i < length; i++) {
+ char c=data.charAt(i);
+ if (c==0x0D) {
+ writer.write(__XD_);
+ } else {
+ if (c < 0x80) {
+ writer.write(c);
+ } else {
+ UtfHelpper.writeCharToUtf8(c,writer);
+ };
+ }
+ }
+
+ writer.write(_END_COMM);
+ if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
+ writer.write('\n');
+ }
+ }
+
+ /**
+ * Outputs a Text of CDATA section to the internal Writer.
+ *
+ * @param text
+ * @param writer writer where to write the things
+ * @throws IOException
+ */
+ static final void outputTextToWriter(final String text, final OutputStream writer) throws IOException {
+ final int length = text.length();
+ byte []toWrite;
+ for (int i = 0; i < length; i++) {
+ char c = text.charAt(i);
+
+ switch (c) {
+
+ case '&' :
+ toWrite=_AMP_;
+ break;
+
+ case '<' :
+ toWrite=_LT_;
+ break;
+
+ case '>' :
+ toWrite=_GT_;
+ break;
+
+ case 0xD :
+ toWrite=__XD_;
+ break;
+
+ default :
+ if (c < 0x80) {
+ writer.write(c);
+ } else {
+ UtfHelpper.writeCharToUtf8(c,writer);
+ };
+ continue;
+ }
+ writer.write(toWrite);
+ }
+ }
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java
index bad23010f11c02eeacc16bc6abe61f0d631c4049..538d369748c0da7e07d1d7d8bc97ec2b17d177b6 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java
@@ -20,16 +20,10 @@
*/
package com.sun.org.apache.xml.internal.security.c14n.implementations;
-import java.lang.reflect.Array;
-import java.util.AbstractList;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
-
import org.w3c.dom.Attr;
@@ -46,21 +40,26 @@ import org.w3c.dom.Node;
public class NameSpaceSymbTable {
/**The map betwen prefix-> entry table. */
- SymbMap symb = new SymbMap();
+ SymbMap symb;
/**The level of nameSpaces (for Inclusive visibility).*/
int nameSpaces=0;
/**The stacks for removing the definitions when doing pop.*/
- List level = new ArrayList();
+ List level;
boolean cloned=true;
static final String XMLNS="xmlns";
+ final static SymbMap initialMap=new SymbMap();
+ static {
+ NameSpaceSymbEntry ne=new NameSpaceSymbEntry("",null,true,XMLNS);
+ ne.lastrendered="";
+ initialMap.put(XMLNS,ne);
+ }
/**
* Default constractor
**/
public NameSpaceSymbTable() {
+ level = new ArrayList(10);
//Insert the default binding for xmlns.
- NameSpaceSymbEntry ne=new NameSpaceSymbEntry("",null,true);
- ne.lastrendered="";
- symb.put(XMLNS,ne);
+ symb=(SymbMap) initialMap.clone();
}
/**
@@ -75,8 +74,14 @@ public class NameSpaceSymbTable {
NameSpaceSymbEntry n=(NameSpaceSymbEntry)(it.next());
//put them rendered?
if ((!n.rendered) && (n.n!=null)) {
+ n=(NameSpaceSymbEntry) n.clone();
+ needsClone();
+ symb.put(n.prefix,n);
+ n.lastrendered=n.uri;
+ n.rendered=true;
+
result.add(n.n);
- n.rendered=true;
+
}
}
}
@@ -104,10 +109,6 @@ public class NameSpaceSymbTable {
**/
public void push() {
//Put the number of namespace definitions in the stack.
- /**if (cloned) {
- Object ob[]= {symb,cloned ? symb : null};
- level.add(ob);
- } **/
level.add(null);
cloned=false;
}
@@ -124,7 +125,7 @@ public class NameSpaceSymbTable {
if (size==0) {
cloned=false;
} else
- cloned=(level.get(size-1)!=symb);
+ cloned=(level.get(size-1)!=symb);
} else {
cloned=false;
}
@@ -134,8 +135,7 @@ public class NameSpaceSymbTable {
final void needsClone() {
if (!cloned) {
- level.remove(level.size()-1);
- level.add(symb);
+ level.set(level.size()-1,symb);
symb=(SymbMap) symb.clone();
cloned=true;
}
@@ -200,7 +200,7 @@ public class NameSpaceSymbTable {
return false;
}
//Creates and entry in the table for this new definition.
- NameSpaceSymbEntry ne=new NameSpaceSymbEntry(uri,n,false);
+ NameSpaceSymbEntry ne=new NameSpaceSymbEntry(uri,n,false,prefix);
needsClone();
symb.put(prefix, ne);
if (ob != null) {
@@ -238,7 +238,7 @@ public class NameSpaceSymbTable {
return null;
}
- NameSpaceSymbEntry ne=new NameSpaceSymbEntry(uri,n,true);
+ NameSpaceSymbEntry ne=new NameSpaceSymbEntry(uri,n,true,prefix);
ne.lastrendered=uri;
needsClone();
symb.put(prefix, ne);
@@ -251,53 +251,38 @@ public class NameSpaceSymbTable {
}
return ne.n;
}
- /**
- * Adds & gets(if needed) the attribute node that defines the binding for the prefix.
- * Take on account if the rules of rendering in the inclusive c14n.
- * For inclusive c14n.
- * @param prefix the prefix to obtain the attribute.
- * @param outputNode the container element is an output element.
- * @param uri the Uri of the definition
- * @param n the attribute that have the definition
- * @return null if there is no need to render the prefix. Otherwise the node of
- * definition.
- **/
- public Node addMappingAndRenderXNodeSet(String prefix, String uri,Attr n,boolean outputNode) {
+
+ public int getLevel() {
+ // TODO Auto-generated method stub
+ return level.size();
+ }
+
+ public void removeMapping(String prefix) {
NameSpaceSymbEntry ob = symb.get(prefix);
- int visibleNameSpaces=nameSpaces;
- if ((ob!=null) && uri.equals(ob.uri)) {
- if (!ob.rendered) {
- ob=(NameSpaceSymbEntry)ob.clone();
- needsClone();
- symb.put(prefix,ob);
- ob.rendered=true;
- ob.level=visibleNameSpaces;
- return ob.n;
- }
- ob=(NameSpaceSymbEntry)ob.clone();
+
+ if (ob!=null) {
needsClone();
- symb.put(prefix,ob);
- if (outputNode && (((visibleNameSpaces-ob.level)<2) || XMLNS.equals(prefix)) ) {
- ob.level=visibleNameSpaces;
- return null; //Already rendered, just return nulll
- }
- ob.level=visibleNameSpaces;
- return ob.n;
- }
+ symb.put(prefix,null);
+ }
+ }
- NameSpaceSymbEntry ne=new NameSpaceSymbEntry(uri,n,true);
- ne.level=nameSpaces;
- ne.rendered=true;
- needsClone();
- symb.put(prefix, ne);
- if (ob != null) {
- ne.lastrendered=ob.lastrendered;
+ public void removeMappingIfNotRender(String prefix) {
+ NameSpaceSymbEntry ob = symb.get(prefix);
- if ((ob.lastrendered!=null)&& (ob.lastrendered.equals(uri))) {
- ne.rendered=true;
- }
- }
- return ne.n;
+ if (ob!=null && !ob.rendered) {
+ needsClone();
+ symb.put(prefix,null);
+ }
+ }
+
+ public boolean removeMappingIfRender(String prefix) {
+ NameSpaceSymbEntry ob = symb.get(prefix);
+
+ if (ob!=null && ob.rendered) {
+ needsClone();
+ symb.put(prefix,null);
+ }
+ return false;
}
}
@@ -305,10 +290,11 @@ public class NameSpaceSymbTable {
* The internal structure of NameSpaceSymbTable.
**/
class NameSpaceSymbEntry implements Cloneable {
- NameSpaceSymbEntry(String name,Attr n,boolean rendered) {
+ NameSpaceSymbEntry(String name,Attr n,boolean rendered,String prefix) {
this.uri=name;
this.rendered=rendered;
this.n=n;
+ this.prefix=prefix;
}
/** @inheritDoc */
public Object clone() {
@@ -320,6 +306,7 @@ class NameSpaceSymbEntry implements Cloneable {
}
/** The level where the definition was rendered(Only for inclusive) */
int level=0;
+ String prefix;
/**The URI that the prefix defines */
String uri;
/**The last output in the URI for this prefix (This for speed reason).*/
@@ -330,53 +317,57 @@ class NameSpaceSymbEntry implements Cloneable {
Attr n;
};
-class SymbMap implements Cloneable{
- int free=23;
- NameSpaceSymbEntry[] entries=new NameSpaceSymbEntry[free];
- String[] keys=new String[free];
-
- void put(String key, NameSpaceSymbEntry value) {
+class SymbMap implements Cloneable {
+ int free=23;
+ NameSpaceSymbEntry[] entries;
+ String[] keys;
+ SymbMap() {
+ entries=new NameSpaceSymbEntry[free];
+ keys=new String[free];
+ }
+ void put(String key, NameSpaceSymbEntry value) {
int index = index(key);
- Object oldKey = keys[index];
- keys[index] = key;
- entries[index] = value;
+ Object oldKey = keys[index];
+ keys[index] = key;
+ entries[index] = value;
if (oldKey==null || !oldKey.equals(key)) {
- if (--free == 0) {
- free=entries.length;
- int newCapacity = free<<2;
- rehash(newCapacity);
- }
+ if (--free == 0) {
+ free=entries.length;
+ int newCapacity = free<<2;
+ rehash(newCapacity);
+ }
}
}
List entrySet() {
- List a=new ArrayList();
- for (int i=0;i&
<
"
#x9
, #xA, and #xD, with character
+ * references. The character references are written in uppercase
+ * hexadecimal with no leading zeroes (for example, #xD
is represented
+ * by the character reference 
)XMLCipher
that implements the specified
+ * transformation, operates on the specified context document and serializes
+ * the document with the specified canonicalization algorithm before it
+ * encrypts the document.
+ * XMLCipher.TRIPLEDES
which is
+ * shorthand for
+ * "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
+ * @param canon the name of the c14n algorithm, if
+ * null
use standard serializer
+ * @return
+ * @throws XMLEncryptionException
+ */
+
+ public static XMLCipher getInstance(String transformation, String canon)
+ throws XMLEncryptionException {
+ XMLCipher instance = XMLCipher.getInstance(transformation);
+
+ if (canon != null) {
+ try {
+ instance._canon = Canonicalizer.getInstance(canon);
+ } catch (InvalidCanonicalizerException ice) {
+ throw new XMLEncryptionException("empty", ice);
+ }
+ }
+
+ return instance;
+ }
+
+ public static XMLCipher getInstance(String transformation,Cipher cipher) throws XMLEncryptionException {
// sanity checks
logger.log(java.util.logging.Level.FINE, "Getting XMLCipher...");
if (null == transformation)
@@ -321,8 +354,8 @@ public class XMLCipher {
instance._kek = null;
- /* Create a canonicaliser - used when serialising DOM to octets
- * prior to encryption (and for the reverse) */
+ /* Create a canonicaliser - used when serialising DOM to octets
+ * prior to encryption (and for the reverse) */
try {
instance._canon = Canonicalizer.getInstance
@@ -346,41 +379,6 @@ public class XMLCipher {
return (instance);
}
-
-
- /**
- * Returns an XMLCipher
that implements the specified
- * transformation, operates on the specified context document and serializes
- * the document with the specified canonicalization algorithm before it
- * encrypts the document.
- * XMLCipher.TRIPLEDES
which is
- * shorthand for
- * "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
- * @param canon the name of the c14n algorithm, if
- * null
use standard serializer
- * @return
- * @throws XMLEncryptionException
- */
-
- public static XMLCipher getInstance(String transformation, String canon)
- throws XMLEncryptionException {
- XMLCipher instance = XMLCipher.getInstance(transformation);
-
- if (canon != null) {
- try {
- instance._canon = Canonicalizer.getInstance(canon);
- } catch (InvalidCanonicalizerException ice) {
- throw new XMLEncryptionException("empty", ice);
- }
- }
-
- return instance;
- }
-
-
/**
* Returns an XMLCipher
that implements the specified
* transformation and operates on the specified context document.
@@ -396,7 +394,7 @@ public class XMLCipher {
public static XMLCipher getProviderInstance(String transformation, String provider)
throws XMLEncryptionException {
// sanity checks
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Getting XMLCipher...");
+ logger.log(java.util.logging.Level.FINE, "Getting XMLCipher...");
if (null == transformation)
logger.log(java.util.logging.Level.SEVERE, "Transformation unexpectedly null...");
if(null == provider)
@@ -429,9 +427,9 @@ public class XMLCipher {
instance._contextCipher = Cipher.getInstance(jceAlgorithm, provider);
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "cipher._algorithm = " +
+ logger.log(java.util.logging.Level.FINE, "cipher._algorithm = " +
instance._contextCipher.getAlgorithm());
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "provider.name = " + provider);
+ logger.log(java.util.logging.Level.FINE, "provider.name = " + provider);
} catch (NoSuchAlgorithmException nsae) {
throw new XMLEncryptionException("empty", nsae);
} catch (NoSuchProviderException nspre) {
@@ -490,7 +488,7 @@ public class XMLCipher {
public static XMLCipher getInstance()
throws XMLEncryptionException {
// sanity checks
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Getting XMLCipher for no transformation...");
+ logger.log(java.util.logging.Level.FINE, "Getting XMLCipher for no transformation...");
XMLCipher instance = new XMLCipher();
@@ -532,7 +530,7 @@ public class XMLCipher {
throws XMLEncryptionException {
// sanity checks
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Getting XMLCipher, provider but no transformation");
+ logger.log(java.util.logging.Level.FINE, "Getting XMLCipher, provider but no transformation");
if(null == provider)
logger.log(java.util.logging.Level.SEVERE, "Provider unexpectedly null..");
if("" == provider)
@@ -578,7 +576,7 @@ public class XMLCipher {
*/
public void init(int opmode, Key key) throws XMLEncryptionException {
// sanity checks
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Initializing XMLCipher...");
+ logger.log(java.util.logging.Level.FINE, "Initializing XMLCipher...");
_ek = null;
_ed = null;
@@ -586,18 +584,18 @@ public class XMLCipher {
switch (opmode) {
case ENCRYPT_MODE :
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "opmode = ENCRYPT_MODE");
+ logger.log(java.util.logging.Level.FINE, "opmode = ENCRYPT_MODE");
_ed = createEncryptedData(CipherData.VALUE_TYPE, "NO VALUE YET");
break;
case DECRYPT_MODE :
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "opmode = DECRYPT_MODE");
+ logger.log(java.util.logging.Level.FINE, "opmode = DECRYPT_MODE");
break;
case WRAP_MODE :
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "opmode = WRAP_MODE");
+ logger.log(java.util.logging.Level.FINE, "opmode = WRAP_MODE");
_ek = createEncryptedKey(CipherData.VALUE_TYPE, "NO VALUE YET");
break;
case UNWRAP_MODE :
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "opmode = UNWRAP_MODE");
+ logger.log(java.util.logging.Level.FINE, "opmode = UNWRAP_MODE");
break;
default :
logger.log(java.util.logging.Level.SEVERE, "Mode unexpectedly invalid");
@@ -622,7 +620,7 @@ public class XMLCipher {
public EncryptedData getEncryptedData() {
// Sanity checks
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Returning EncryptedData");
+ logger.log(java.util.logging.Level.FINE, "Returning EncryptedData");
return _ed;
}
@@ -640,7 +638,7 @@ public class XMLCipher {
public EncryptedKey getEncryptedKey() {
// Sanity checks
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Returning EncryptedKey");
+ logger.log(java.util.logging.Level.FINE, "Returning EncryptedKey");
return _ek;
}
@@ -750,11 +748,11 @@ public class XMLCipher {
*/
private Document encryptElement(Element element) throws Exception{
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypting element...");
+ logger.log(java.util.logging.Level.FINE, "Encrypting element...");
if(null == element)
logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null...");
if(_cipherMode != ENCRYPT_MODE)
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE...");
+ logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE...");
if (_algorithm == null) {
throw new XMLEncryptionException("XMLCipher instance without transformation specified");
@@ -785,11 +783,11 @@ public class XMLCipher {
*/
private Document encryptElementContent(Element element) throws
/* XMLEncryption */Exception {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypting element content...");
+ logger.log(java.util.logging.Level.FINE, "Encrypting element content...");
if(null == element)
logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null...");
if(_cipherMode != ENCRYPT_MODE)
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE...");
+ logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE...");
if (_algorithm == null) {
throw new XMLEncryptionException("XMLCipher instance without transformation specified");
@@ -815,7 +813,7 @@ public class XMLCipher {
*/
public Document doFinal(Document context, Document source) throws
/* XMLEncryption */Exception {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Processing source document...");
+ logger.log(java.util.logging.Level.FINE, "Processing source document...");
if(null == context)
logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null...");
if(null == source)
@@ -855,7 +853,7 @@ public class XMLCipher {
*/
public Document doFinal(Document context, Element element) throws
/* XMLEncryption */Exception {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Processing source element...");
+ logger.log(java.util.logging.Level.FINE, "Processing source element...");
if(null == context)
logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null...");
if(null == element)
@@ -898,7 +896,7 @@ public class XMLCipher {
*/
public Document doFinal(Document context, Element element, boolean content)
throws /* XMLEncryption*/ Exception {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Processing source element...");
+ logger.log(java.util.logging.Level.FINE, "Processing source element...");
if(null == context)
logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null...");
if(null == element)
@@ -952,6 +950,34 @@ public class XMLCipher {
return encryptData(context, element, false);
}
+ /**
+ * Returns an EncryptedData
interface. Use this operation if
+ * you want to have full control over the serialization of the element
+ * or element content.
+ *
+ * This does not change the source document in any way.
+ *
+ * @param context the context Document
.
+ * @param type a URI identifying type information about the plaintext form
+ * of the encrypted content (may be null
)
+ * @param serializedData the serialized data
+ * @return the EncryptedData
+ * @throws Exception
+ */
+ public EncryptedData encryptData(Document context, String type,
+ InputStream serializedData) throws Exception {
+
+ logger.log(java.util.logging.Level.FINE, "Encrypting element...");
+ if (null == context)
+ logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null...");
+ if (null == serializedData)
+ logger.log(java.util.logging.Level.SEVERE, "Serialized data unexpectedly null...");
+ if (_cipherMode != ENCRYPT_MODE)
+ logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE...");
+
+ return encryptData(context, null, type, serializedData);
+ }
+
/**
* Returns an EncryptedData
interface. Use this operation if
* you want to have full control over the contents of the
@@ -966,160 +992,60 @@ public class XMLCipher {
* @return the EncryptedData
* @throws Exception
*/
- public EncryptedData encryptData(Document context, Element element, boolean contentMode) throws
- /* XMLEncryption */ Exception {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypting element...");
- if (null == context)
- logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null...");
- if (null == element)
- logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null...");
- if (_cipherMode != ENCRYPT_MODE)
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE...");
+ public EncryptedData encryptData(
+ Document context, Element element, boolean contentMode)
+ throws /* XMLEncryption */ Exception {
- _contextDocument = context;
-
- if (_algorithm == null) {
- throw new XMLEncryptionException("XMLCipher instance without transformation specified");
- }
-
- String serializedOctets = null;
- if (contentMode) {
- NodeList children = element.getChildNodes();
- if ((null != children)) {
- serializedOctets = _serializer.serialize(children);
- } else {
- Object exArgs[] = { "Element has no content." };
- throw new XMLEncryptionException("empty", exArgs);
- }
- } else {
- serializedOctets = _serializer.serialize(element);
- }
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Serialized octets:\n" + serializedOctets);
-
- byte[] encryptedBytes = null;
-
- // Now create the working cipher if none was created already
- Cipher c;
- if (_contextCipher == null) {
- String jceAlgorithm =
- JCEMapper.translateURItoJCEID(_algorithm);
-
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "alg = " + jceAlgorithm);
-
- try {
- if (_requestedJCEProvider == null)
- c = Cipher.getInstance(jceAlgorithm);
- else
- c = Cipher.getInstance(jceAlgorithm, _requestedJCEProvider);
- } catch (NoSuchAlgorithmException nsae) {
- throw new XMLEncryptionException("empty", nsae);
- } catch (NoSuchProviderException nspre) {
- throw new XMLEncryptionException("empty", nspre);
- } catch (NoSuchPaddingException nspae) {
- throw new XMLEncryptionException("empty", nspae);
- }
- }
- else {
- c = _contextCipher;
- }
- // Now perform the encryption
-
- try {
- // Should internally generate an IV
- // todo - allow user to set an IV
- c.init(_cipherMode, _key);
- } catch (InvalidKeyException ike) {
- throw new XMLEncryptionException("empty", ike);
- }
-
- try {
- encryptedBytes =
- c.doFinal(serializedOctets.getBytes("UTF-8"));
-
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Expected cipher.outputSize = " +
- Integer.toString(c.getOutputSize(
- serializedOctets.getBytes().length)));
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Actual cipher.outputSize = " +
- Integer.toString(encryptedBytes.length));
- } catch (IllegalStateException ise) {
- throw new XMLEncryptionException("empty", ise);
- } catch (IllegalBlockSizeException ibse) {
- throw new XMLEncryptionException("empty", ibse);
- } catch (BadPaddingException bpe) {
- throw new XMLEncryptionException("empty", bpe);
- } catch (UnsupportedEncodingException uee) {
- throw new XMLEncryptionException("empty", uee);
- }
-
- // Now build up to a properly XML Encryption encoded octet stream
- // IvParameterSpec iv;
-
- byte[] iv = c.getIV();
- byte[] finalEncryptedBytes =
- new byte[iv.length + encryptedBytes.length];
- System.arraycopy(iv, 0, finalEncryptedBytes, 0,
- iv.length);
- System.arraycopy(encryptedBytes, 0, finalEncryptedBytes,
- iv.length,
- encryptedBytes.length);
-
- String base64EncodedEncryptedOctets = Base64.encode(finalEncryptedBytes);
-
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypted octets:\n" + base64EncodedEncryptedOctets);
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypted octets length = " +
- base64EncodedEncryptedOctets.length());
-
- try {
- CipherData cd = _ed.getCipherData();
- CipherValue cv = cd.getCipherValue();
- // cv.setValue(base64EncodedEncryptedOctets.getBytes());
- cv.setValue(base64EncodedEncryptedOctets);
-
- if (contentMode) {
- _ed.setType(
- new URI(EncryptionConstants.TYPE_CONTENT).toString());
- } else {
- _ed.setType(
- new URI(EncryptionConstants.TYPE_ELEMENT).toString());
- }
- EncryptionMethod method =
- _factory.newEncryptionMethod(new URI(_algorithm).toString());
- _ed.setEncryptionMethod(method);
- } catch (URI.MalformedURIException mfue) {
- throw new XMLEncryptionException("empty", mfue);
- }
- return (_ed);
- }
-
-
-
- public EncryptedData encryptData(Document context, byte [] serializedOctets, boolean contentMode) throws
- /* XMLEncryption */ Exception {
logger.log(java.util.logging.Level.FINE, "Encrypting element...");
if (null == context)
logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null...");
- if (null == serializedOctets)
- logger.log(java.util.logging.Level.SEVERE, "Canonicalized Data is unexpectedly null...");
+ if (null == element)
+ logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null...");
if (_cipherMode != ENCRYPT_MODE)
logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in ENCRYPT_MODE...");
+ if (contentMode) {
+ return encryptData
+ (context, element, EncryptionConstants.TYPE_CONTENT, null);
+ } else {
+ return encryptData
+ (context, element, EncryptionConstants.TYPE_ELEMENT, null);
+ }
+ }
+
+ private EncryptedData encryptData(
+ Document context, Element element, String type,
+ InputStream serializedData) throws /* XMLEncryption */ Exception {
+
_contextDocument = context;
if (_algorithm == null) {
- throw new XMLEncryptionException("XMLCipher instance without transformation specified");
+ throw new XMLEncryptionException
+ ("XMLCipher instance without transformation specified");
}
-
- logger.log(java.util.logging.Level.FINE, "Serialized octets:\n" + serializedOctets);
+ String serializedOctets = null;
+ if (serializedData == null) {
+ if (type == EncryptionConstants.TYPE_CONTENT) {
+ NodeList children = element.getChildNodes();
+ if (null != children) {
+ serializedOctets = _serializer.serialize(children);
+ } else {
+ Object exArgs[] = { "Element has no content." };
+ throw new XMLEncryptionException("empty", exArgs);
+ }
+ } else {
+ serializedOctets = _serializer.serialize(element);
+ }
+ logger.log(java.util.logging.Level.FINE, "Serialized octets:\n" + serializedOctets);
+ }
byte[] encryptedBytes = null;
// Now create the working cipher if none was created already
Cipher c;
if (_contextCipher == null) {
- String jceAlgorithm =
- JCEMapper.translateURItoJCEID(_algorithm);
-
+ String jceAlgorithm = JCEMapper.translateURItoJCEID(_algorithm);
logger.log(java.util.logging.Level.FINE, "alg = " + jceAlgorithm);
try {
@@ -1148,41 +1074,47 @@ public class XMLCipher {
}
try {
- encryptedBytes =
- c.doFinal(serializedOctets);
-
- logger.log(java.util.logging.Level.FINE, "Expected cipher.outputSize = " +
+ if (serializedData != null) {
+ int numBytes;
+ byte[] buf = new byte[8192];
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ while ((numBytes = serializedData.read(buf)) != -1) {
+ byte[] data = c.update(buf, 0, numBytes);
+ baos.write(data);
+ }
+ baos.write(c.doFinal());
+ encryptedBytes = baos.toByteArray();
+ } else {
+ encryptedBytes = c.doFinal(serializedOctets.getBytes("UTF-8"));
+ logger.log(java.util.logging.Level.FINE, "Expected cipher.outputSize = " +
Integer.toString(c.getOutputSize(
- serializedOctets.length)));
+ serializedOctets.getBytes().length)));
+ }
logger.log(java.util.logging.Level.FINE, "Actual cipher.outputSize = " +
- Integer.toString(encryptedBytes.length));
+ Integer.toString(encryptedBytes.length));
} catch (IllegalStateException ise) {
throw new XMLEncryptionException("empty", ise);
} catch (IllegalBlockSizeException ibse) {
throw new XMLEncryptionException("empty", ibse);
} catch (BadPaddingException bpe) {
throw new XMLEncryptionException("empty", bpe);
- } catch (Exception uee) {
+ } catch (UnsupportedEncodingException uee) {
throw new XMLEncryptionException("empty", uee);
}
// Now build up to a properly XML Encryption encoded octet stream
// IvParameterSpec iv;
-
byte[] iv = c.getIV();
byte[] finalEncryptedBytes =
new byte[iv.length + encryptedBytes.length];
- System.arraycopy(iv, 0, finalEncryptedBytes, 0,
- iv.length);
- System.arraycopy(encryptedBytes, 0, finalEncryptedBytes,
- iv.length,
- encryptedBytes.length);
-
+ System.arraycopy(iv, 0, finalEncryptedBytes, 0, iv.length);
+ System.arraycopy(encryptedBytes, 0, finalEncryptedBytes, iv.length,
+ encryptedBytes.length);
String base64EncodedEncryptedOctets = Base64.encode(finalEncryptedBytes);
logger.log(java.util.logging.Level.FINE, "Encrypted octets:\n" + base64EncodedEncryptedOctets);
logger.log(java.util.logging.Level.FINE, "Encrypted octets length = " +
- base64EncodedEncryptedOctets.length());
+ base64EncodedEncryptedOctets.length());
try {
CipherData cd = _ed.getCipherData();
@@ -1190,15 +1122,11 @@ public class XMLCipher {
// cv.setValue(base64EncodedEncryptedOctets.getBytes());
cv.setValue(base64EncodedEncryptedOctets);
- if (contentMode) {
- _ed.setType(
- new URI(EncryptionConstants.TYPE_CONTENT).toString());
- } else {
- _ed.setType(
- new URI(EncryptionConstants.TYPE_ELEMENT).toString());
+ if (type != null) {
+ _ed.setType(new URI(type).toString());
}
EncryptionMethod method =
- _factory.newEncryptionMethod(new URI(_algorithm).toString());
+ _factory.newEncryptionMethod(new URI(_algorithm).toString());
_ed.setEncryptionMethod(method);
} catch (URI.MalformedURIException mfue) {
throw new XMLEncryptionException("empty", mfue);
@@ -1206,7 +1134,6 @@ public class XMLCipher {
return (_ed);
}
-
/**
* Returns an EncryptedData
interface. Use this operation if
* you want to load an EncryptedData
structure from a DOM
@@ -1219,7 +1146,7 @@ public class XMLCipher {
*/
public EncryptedData loadEncryptedData(Document context, Element element)
throws XMLEncryptionException {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Loading encrypted element...");
+ logger.log(java.util.logging.Level.FINE, "Loading encrypted element...");
if(null == context)
logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null...");
if(null == element)
@@ -1246,13 +1173,13 @@ public class XMLCipher {
public EncryptedKey loadEncryptedKey(Document context, Element element)
throws XMLEncryptionException {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Loading encrypted key...");
+ logger.log(java.util.logging.Level.FINE, "Loading encrypted key...");
if(null == context)
logger.log(java.util.logging.Level.SEVERE, "Context document unexpectedly null...");
if(null == element)
logger.log(java.util.logging.Level.SEVERE, "Element unexpectedly null...");
if(_cipherMode != UNWRAP_MODE && _cipherMode != DECRYPT_MODE)
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in UNWRAP_MODE or DECRYPT_MODE...");
+ logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in UNWRAP_MODE or DECRYPT_MODE...");
_contextDocument = context;
_ek = _factory.newEncryptedKey(element);
@@ -1290,12 +1217,12 @@ public class XMLCipher {
public EncryptedKey encryptKey(Document doc, Key key) throws
XMLEncryptionException {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypting key ...");
+ logger.log(java.util.logging.Level.FINE, "Encrypting key ...");
if(null == key)
logger.log(java.util.logging.Level.SEVERE, "Key unexpectedly null...");
if(_cipherMode != WRAP_MODE)
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in WRAP_MODE...");
+ logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in WRAP_MODE...");
if (_algorithm == null) {
@@ -1313,7 +1240,7 @@ public class XMLCipher {
String jceAlgorithm =
JCEMapper.translateURItoJCEID(_algorithm);
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "alg = " + jceAlgorithm);
+ logger.log(java.util.logging.Level.FINE, "alg = " + jceAlgorithm);
try {
if (_requestedJCEProvider == null)
@@ -1345,8 +1272,8 @@ public class XMLCipher {
String base64EncodedEncryptedOctets = Base64.encode(encryptedBytes);
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypted key octets:\n" + base64EncodedEncryptedOctets);
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Encrypted key octets length = " +
+ logger.log(java.util.logging.Level.FINE, "Encrypted key octets:\n" + base64EncodedEncryptedOctets);
+ logger.log(java.util.logging.Level.FINE, "Encrypted key octets length = " +
base64EncodedEncryptedOctets.length());
CipherValue cv = _ek.getCipherData().getCipherValue();
@@ -1376,10 +1303,10 @@ public class XMLCipher {
public Key decryptKey(EncryptedKey encryptedKey, String algorithm) throws
XMLEncryptionException {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decrypting key from previously loaded EncryptedKey...");
+ logger.log(java.util.logging.Level.FINE, "Decrypting key from previously loaded EncryptedKey...");
if(_cipherMode != UNWRAP_MODE)
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in UNWRAP_MODE...");
+ logger.log(java.util.logging.Level.FINE, "XMLCipher unexpectedly not in UNWRAP_MODE...");
if (algorithm == null) {
throw new XMLEncryptionException("Cannot decrypt a key without knowing the algorithm");
@@ -1387,7 +1314,7 @@ public class XMLCipher {
if (_key == null) {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Trying to find a KEK via key resolvers");
+ logger.log(java.util.logging.Level.FINE, "Trying to find a KEK via key resolvers");
KeyInfo ki = encryptedKey.getKeyInfo();
if (ki != null) {
@@ -1418,7 +1345,7 @@ public class XMLCipher {
JCEMapper.translateURItoJCEID(
encryptedKey.getEncryptionMethod().getAlgorithm());
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "JCE Algorithm = " + jceAlgorithm);
+ logger.log(java.util.logging.Level.FINE, "JCE Algorithm = " + jceAlgorithm);
try {
if (_requestedJCEProvider == null)
@@ -1448,7 +1375,7 @@ public class XMLCipher {
throw new XMLEncryptionException("empty", nsae);
}
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decryption of key type " + algorithm + " OK");
+ logger.log(java.util.logging.Level.FINE, "Decryption of key type " + algorithm + " OK");
return ret;
@@ -1478,14 +1405,9 @@ public class XMLCipher {
*
* @param node the Node
to clear.
*/
- private void removeContent(Node node) {
- NodeList list = node.getChildNodes();
- if (list.getLength() > 0) {
- Node n = list.item(0);
- if (null != n) {
- n.getParentNode().removeChild(n);
- }
- removeContent(node);
+ private static void removeContent(Node node) {
+ while (node.hasChildNodes()) {
+ node.removeChild(node.getFirstChild());
}
}
@@ -1499,7 +1421,7 @@ public class XMLCipher {
private Document decryptElement(Element element) throws
XMLEncryptionException {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decrypting element...");
+ logger.log(java.util.logging.Level.FINE, "Decrypting element...");
if(_cipherMode != DECRYPT_MODE)
logger.log(java.util.logging.Level.SEVERE, "XMLCipher unexpectedly not in DECRYPT_MODE...");
@@ -1512,7 +1434,7 @@ public class XMLCipher {
}
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decrypted octets:\n" + octets);
+ logger.log(java.util.logging.Level.FINE, "Decrypted octets:\n" + octets);
Node sourceParent = element.getParentNode();
@@ -1573,7 +1495,7 @@ public class XMLCipher {
public byte[] decryptToByteArray(Element element)
throws XMLEncryptionException {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Decrypting to ByteArray...");
+ logger.log(java.util.logging.Level.FINE, "Decrypting to ByteArray...");
if(_cipherMode != DECRYPT_MODE)
logger.log(java.util.logging.Level.SEVERE, "XMLCipher unexpectedly not in DECRYPT_MODE...");
@@ -2226,7 +2148,7 @@ public class XMLCipher {
AgreementMethod newAgreementMethod(Element element) throws
XMLEncryptionException {
if (null == element) {
- //complain
+ throw new NullPointerException("element is null");
}
String algorithm = element.getAttributeNS(null,
@@ -2292,7 +2214,7 @@ public class XMLCipher {
CipherData newCipherData(Element element) throws
XMLEncryptionException {
if (null == element) {
- // complain
+ throw new NullPointerException("element is null");
}
int type = 0;
@@ -2352,7 +2274,7 @@ public class XMLCipher {
(Element) transformsElements.item(0);
if (transformsElement != null) {
- if (logger.isLoggable(java.util.logging.Level.FINE)) logger.log(java.util.logging.Level.FINE, "Creating a DSIG based Transforms element");
+ logger.log(java.util.logging.Level.FINE, "Creating a DSIG based Transforms element");
try {
result.setTransforms(new TransformsImpl(transformsElement));
}
@@ -2411,34 +2333,28 @@ public class XMLCipher {
XMLEncryptionException {
EncryptedData result = null;
- NodeList dataElements = element.getElementsByTagNameNS(
- EncryptionConstants.EncryptionSpecNS,
- EncryptionConstants._TAG_CIPHERDATA);
+ NodeList dataElements = element.getElementsByTagNameNS(
+ EncryptionConstants.EncryptionSpecNS,
+ EncryptionConstants._TAG_CIPHERDATA);
- // Need to get the last CipherData found, as earlier ones will
- // be for elements in the KeyInfo lists
+ // Need to get the last CipherData found, as earlier ones will
+ // be for elements in the KeyInfo lists
Element dataElement =
- (Element) dataElements.item(dataElements.getLength() - 1);
+ (Element) dataElements.item(dataElements.getLength() - 1);
CipherData data = newCipherData(dataElement);
result = newEncryptedData(data);
- try {
- result.setId(element.getAttributeNS(
- null, EncryptionConstants._ATT_ID));
- result.setType(new URI(
- element.getAttributeNS(
- null, EncryptionConstants._ATT_TYPE)).toString());
- result.setMimeType(element.getAttributeNS(
- null, EncryptionConstants._ATT_MIMETYPE));
- result.setEncoding(new URI(
- element.getAttributeNS(
- null, Constants._ATT_ENCODING)).toString());
- } catch (URI.MalformedURIException mfue) {
- // do nothing
- }
+ result.setId(element.getAttributeNS(
+ null, EncryptionConstants._ATT_ID));
+ result.setType(
+ element.getAttributeNS(null, EncryptionConstants._ATT_TYPE));
+ result.setMimeType(element.getAttributeNS(
+ null, EncryptionConstants._ATT_MIMETYPE));
+ result.setEncoding(
+ element.getAttributeNS(null, Constants._ATT_ENCODING));
Element encryptionMethodElement =
(Element) element.getElementsByTagNameNS(
@@ -2450,18 +2366,18 @@ public class XMLCipher {
}
// BFL 16/7/03 - simple implementation
- // TODO: Work out how to handle relative URI
+ // TODO: Work out how to handle relative URI
Element keyInfoElement =
(Element) element.getElementsByTagNameNS(
Constants.SignatureSpecNS, Constants._TAG_KEYINFO).item(0);
if (null != keyInfoElement) {
- try {
- result.setKeyInfo(new KeyInfo(keyInfoElement, null));
- } catch (XMLSecurityException xse) {
- throw new XMLEncryptionException("Error loading Key Info",
- xse);
- }
+ try {
+ result.setKeyInfo(new KeyInfo(keyInfoElement, null));
+ } catch (XMLSecurityException xse) {
+ throw new XMLEncryptionException("Error loading Key Info",
+ xse);
+ }
}
// TODO: Implement
@@ -2511,31 +2427,25 @@ public class XMLCipher {
EncryptedKey newEncryptedKey(Element element) throws
XMLEncryptionException {
EncryptedKey result = null;
- NodeList dataElements = element.getElementsByTagNameNS(
- EncryptionConstants.EncryptionSpecNS,
- EncryptionConstants._TAG_CIPHERDATA);
+ NodeList dataElements = element.getElementsByTagNameNS(
+ EncryptionConstants.EncryptionSpecNS,
+ EncryptionConstants._TAG_CIPHERDATA);
Element dataElement =
- (Element) dataElements.item(dataElements.getLength() - 1);
+ (Element) dataElements.item(dataElements.getLength() - 1);
CipherData data = newCipherData(dataElement);
result = newEncryptedKey(data);
- try {
- result.setId(element.getAttributeNS(
- null, EncryptionConstants._ATT_ID));
- result.setType(new URI(
- element.getAttributeNS(
- null, EncryptionConstants._ATT_TYPE)).toString());
- result.setMimeType(element.getAttributeNS(
- null, EncryptionConstants._ATT_MIMETYPE));
- result.setEncoding(new URI(
- element.getAttributeNS(
- null, Constants._ATT_ENCODING)).toString());
- result.setRecipient(element.getAttributeNS(
- null, EncryptionConstants._ATT_RECIPIENT));
- } catch (URI.MalformedURIException mfue) {
- // do nothing
- }
+ result.setId(element.getAttributeNS(
+ null, EncryptionConstants._ATT_ID));
+ result.setType(
+ element.getAttributeNS(null, EncryptionConstants._ATT_TYPE));
+ result.setMimeType(element.getAttributeNS(
+ null, EncryptionConstants._ATT_MIMETYPE));
+ result.setEncoding(
+ element.getAttributeNS(null, Constants._ATT_ENCODING));
+ result.setRecipient(element.getAttributeNS(
+ null, EncryptionConstants._ATT_RECIPIENT));
Element encryptionMethodElement =
(Element) element.getElementsByTagNameNS(
@@ -2550,12 +2460,12 @@ public class XMLCipher {
(Element) element.getElementsByTagNameNS(
Constants.SignatureSpecNS, Constants._TAG_KEYINFO).item(0);
if (null != keyInfoElement) {
- try {
- result.setKeyInfo(new KeyInfo(keyInfoElement, null));
- } catch (XMLSecurityException xse) {
- throw new XMLEncryptionException("Error loading Key Info",
- xse);
- }
+ try {
+ result.setKeyInfo(new KeyInfo(keyInfoElement, null));
+ } catch (XMLSecurityException xse) {
+ throw new XMLEncryptionException
+ ("Error loading Key Info", xse);
+ }
}
// TODO: Implement
@@ -2581,7 +2491,8 @@ public class XMLCipher {
EncryptionConstants.EncryptionSpecNS,
EncryptionConstants._TAG_CARRIEDKEYNAME).item(0);
if (null != carriedNameElement) {
- result.setCarriedName(carriedNameElement.getNodeValue());
+ result.setCarriedName
+ (carriedNameElement.getFirstChild().getNodeValue());
}
return (result);
@@ -2680,13 +2591,8 @@ public class XMLCipher {
EncryptionProperty newEncryptionProperty(Element element) {
EncryptionProperty result = newEncryptionProperty();
- try {
- result.setTarget(new URI(
- element.getAttributeNS(
- null, EncryptionConstants._ATT_TARGET)).toString());
- } catch (URI.MalformedURIException mfue) {
- // do nothing
- }
+ result.setTarget(
+ element.getAttributeNS(null, EncryptionConstants._ATT_TARGET));
result.setId(element.getAttributeNS(
null, EncryptionConstants._ATT_ID));
// TODO: Make this lot work...
@@ -2943,7 +2849,7 @@ public class XMLCipher {
} catch (URI.MalformedURIException mfue) {
//complain
}
- algorithm = tmpAlgorithm.toString();
+ algorithmURI = tmpAlgorithm.toString();
}
// containsXXX()
methods return whether the KeyInfo
* contains the corresponding type.
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*/
public class KeyInfo extends SignatureElementProxy {
/** {@link java.util.logging} logging facility */
static java.util.logging.Logger log =
java.util.logging.Logger.getLogger(KeyInfo.class.getName());
+ List x509Datas=null;
+ List encryptedKeys=null;
-
+ static final List nullList;
+ static {
+ List list = new ArrayList();
+ list.add(null);
+ nullList = Collections.unmodifiableList(list);
+ }
/**
* Constructor KeyInfo
@@ -108,7 +117,6 @@ public class KeyInfo extends SignatureElementProxy {
XMLUtils.addReturnToElement(this._constructionElement);
-
}
/**
@@ -119,8 +127,8 @@ public class KeyInfo extends SignatureElementProxy {
* @throws XMLSecurityException
*/
public KeyInfo(Element element, String BaseURI) throws XMLSecurityException {
-
super(element, BaseURI);
+ // _storageResolvers.add(null);
}
@@ -131,7 +139,7 @@ public class KeyInfo extends SignatureElementProxy {
*/
public void setId(String Id) {
- if ((this._state == MODE_SIGN) && (Id != null)) {
+ if ((Id != null)) {
this._constructionElement.setAttributeNS(null, Constants._ATT_ID, Id);
IdResolver.registerElementById(this._constructionElement, Id);
}
@@ -162,10 +170,8 @@ public class KeyInfo extends SignatureElementProxy {
*/
public void add(KeyName keyname) {
- if (this._state == MODE_SIGN) {
this._constructionElement.appendChild(keyname.getElement());
XMLUtils.addReturnToElement(this._constructionElement);
- }
}
/**
@@ -219,11 +225,8 @@ public class KeyInfo extends SignatureElementProxy {
* @param keyvalue
*/
public void add(KeyValue keyvalue) {
-
- if (this._state == MODE_SIGN) {
this._constructionElement.appendChild(keyvalue.getElement());
XMLUtils.addReturnToElement(this._constructionElement);
- }
}
/**
@@ -241,11 +244,8 @@ public class KeyInfo extends SignatureElementProxy {
* @param mgmtdata
*/
public void add(MgmtData mgmtdata) {
-
- if (this._state == MODE_SIGN) {
this._constructionElement.appendChild(mgmtdata.getElement());
XMLUtils.addReturnToElement(this._constructionElement);
- }
}
/**
@@ -254,11 +254,8 @@ public class KeyInfo extends SignatureElementProxy {
* @param pgpdata
*/
public void add(PGPData pgpdata) {
-
- if (this._state == MODE_SIGN) {
this._constructionElement.appendChild(pgpdata.getElement());
XMLUtils.addReturnToElement(this._constructionElement);
- }
}
/**
@@ -279,11 +276,8 @@ public class KeyInfo extends SignatureElementProxy {
* @param retrievalmethod
*/
public void add(RetrievalMethod retrievalmethod) {
-
- if (this._state == MODE_SIGN) {
this._constructionElement.appendChild(retrievalmethod.getElement());
XMLUtils.addReturnToElement(this._constructionElement);
- }
}
/**
@@ -292,11 +286,8 @@ public class KeyInfo extends SignatureElementProxy {
* @param spkidata
*/
public void add(SPKIData spkidata) {
-
- if (this._state == MODE_SIGN) {
this._constructionElement.appendChild(spkidata.getElement());
XMLUtils.addReturnToElement(this._constructionElement);
- }
}
/**
@@ -305,11 +296,11 @@ public class KeyInfo extends SignatureElementProxy {
* @param x509data
*/
public void add(X509Data x509data) {
-
- if (this._state == MODE_SIGN) {
+ if (x509Datas==null)
+ x509Datas=new ArrayList();
+ x509Datas.add(x509data);
this._constructionElement.appendChild(x509data.getElement());
XMLUtils.addReturnToElement(this._constructionElement);
- }
}
/**
@@ -321,12 +312,11 @@ public class KeyInfo extends SignatureElementProxy {
public void add(EncryptedKey encryptedKey)
throws XMLEncryptionException {
-
- if (this._state == MODE_SIGN) {
+ if (encryptedKeys==null)
+ encryptedKeys=new ArrayList();
+ encryptedKeys.add(encryptedKey);
XMLCipher cipher = XMLCipher.getInstance();
this._constructionElement.appendChild(cipher.martial(encryptedKey));
- }
-
}
/**
@@ -335,11 +325,8 @@ public class KeyInfo extends SignatureElementProxy {
* @param element
*/
public void addUnknownElement(Element element) {
-
- if (this._state == MODE_SIGN) {
this._constructionElement.appendChild(element);
XMLUtils.addReturnToElement(this._constructionElement);
- }
}
/**
@@ -403,6 +390,9 @@ public class KeyInfo extends SignatureElementProxy {
*@return the number of the X509Data tags
*/
public int lengthX509Data() {
+ if (x509Datas!=null) {
+ return x509Datas.size();
+ }
return this.length(Constants.SignatureSpecNS, Constants._TAG_X509DATA);
}
@@ -550,7 +540,9 @@ public class KeyInfo extends SignatureElementProxy {
* @throws XMLSecurityException
*/
public X509Data itemX509Data(int i) throws XMLSecurityException {
-
+ if (x509Datas!=null) {
+ return (X509Data) x509Datas.get(i);
+ }
Element e = XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
Constants._TAG_X509DATA,i);
@@ -569,7 +561,9 @@ public class KeyInfo extends SignatureElementProxy {
*/
public EncryptedKey itemEncryptedKey(int i) throws XMLSecurityException {
-
+ if (encryptedKeys!=null) {
+ return (EncryptedKey) encryptedKeys.get(i);
+ }
Element e =
XMLUtils.selectXencNode(this._constructionElement.getFirstChild(),
EncryptionConstants._TAG_ENCRYPTEDKEY,i);
@@ -707,20 +701,20 @@ public class KeyInfo extends SignatureElementProxy {
PublicKey pk = this.getPublicKeyFromInternalResolvers();
if (pk != null) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I could find a key using the per-KeyInfo key resolvers");
+ log.log(java.util.logging.Level.FINE, "I could find a key using the per-KeyInfo key resolvers");
return pk;
}
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I couldn't find a key using the per-KeyInfo key resolvers");
+ log.log(java.util.logging.Level.FINE, "I couldn't find a key using the per-KeyInfo key resolvers");
pk = this.getPublicKeyFromStaticResolvers();
if (pk != null) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I could find a key using the system-wide key resolvers");
+ log.log(java.util.logging.Level.FINE, "I could find a key using the system-wide key resolvers");
return pk;
}
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I couldn't find a key using the system-wide key resolvers");
+ log.log(java.util.logging.Level.FINE, "I couldn't find a key using the system-wide key resolvers");
return null;
}
@@ -732,46 +726,29 @@ public class KeyInfo extends SignatureElementProxy {
* @throws KeyResolverException
*/
PublicKey getPublicKeyFromStaticResolvers() throws KeyResolverException {
-
- for (int i = 0; i < KeyResolver.length(); i++) {
- KeyResolver keyResolver = KeyResolver.item(i);
+ int length=KeyResolver.length();
+ int storageLength=this._storageResolvers.size();
+ Iterator it= KeyResolver.iterator();
+ for (int i = 0; i < length; i++) {
+ KeyResolverSpi keyResolver = (KeyResolverSpi) it.next();
Node currentChild=this._constructionElement.getFirstChild();
+ String uri= this.getBaseURI();
while (currentChild!=null) {
if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
- if (this._storageResolvers.size() == 0) {
-
- // if we do not have storage resolvers, we verify with null
- StorageResolver storage = null;
-
- if (keyResolver.canResolve((Element) currentChild,
- this.getBaseURI(), storage)) {
- PublicKey pk =
- keyResolver.resolvePublicKey((Element) currentChild,
- this.getBaseURI(),
- storage);
-
- if (pk != null) {
- return pk;
- }
- }
- } else {
- for (int k = 0; k < this._storageResolvers.size(); k++) {
+ for (int k = 0; k < storageLength; k++) {
StorageResolver storage =
(StorageResolver) this._storageResolvers.get(k);
- if (keyResolver.canResolve((Element) currentChild,
- this.getBaseURI(), storage)) {
- PublicKey pk =
- keyResolver.resolvePublicKey((Element) currentChild,
- this.getBaseURI(),
+ PublicKey pk =
+ keyResolver.engineLookupAndResolvePublicKey((Element) currentChild,
+ uri,
storage);
- if (pk != null) {
- return pk;
- }
+ if (pk != null) {
+ KeyResolver.hit(it);
+ return pk;
}
}
- }
}
currentChild=currentChild.getNextSibling();
}
@@ -786,50 +763,27 @@ public class KeyInfo extends SignatureElementProxy {
* @throws KeyResolverException
*/
PublicKey getPublicKeyFromInternalResolvers() throws KeyResolverException {
-
- for (int i = 0; i < this.lengthInternalKeyResolver(); i++) {
+ int length=lengthInternalKeyResolver();
+ int storageLength=this._storageResolvers.size();
+ for (int i = 0; i < length; i++) {
KeyResolverSpi keyResolver = this.itemInternalKeyResolver(i);
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Try " + keyResolver.getClass().getName());
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Try " + keyResolver.getClass().getName());
Node currentChild=this._constructionElement.getFirstChild();
+ String uri=this.getBaseURI();
while (currentChild!=null) {
if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
- if (this._storageResolvers.size() == 0) {
-
- // if we do not have storage resolvers, we verify with null
- StorageResolver storage = null;
-
- if (keyResolver.engineCanResolve((Element) currentChild,
- this.getBaseURI(),
- storage)) {
- PublicKey pk =
- keyResolver
- .engineResolvePublicKey((Element) currentChild, this
- .getBaseURI(), storage);
+ for (int k = 0; k < storageLength; k++) {
+ StorageResolver storage =
+ (StorageResolver) this._storageResolvers.get(k);
+ PublicKey pk = keyResolver
+ .engineLookupAndResolvePublicKey((Element) currentChild, uri, storage);
if (pk != null) {
- return pk;
+ return pk;
}
}
- } else {
- for (int k = 0; k < this._storageResolvers.size(); k++) {
- StorageResolver storage =
- (StorageResolver) this._storageResolvers.get(k);
-
- if (keyResolver.engineCanResolve((Element) currentChild,
- this.getBaseURI(),
- storage)) {
- PublicKey pk = keyResolver
- .engineResolvePublicKey((Element) currentChild, this
- .getBaseURI(), storage);
-
- if (pk != null) {
- return pk;
- }
- }
- }
- }
}
currentChild=currentChild.getNextSibling();
}
@@ -850,12 +804,12 @@ public class KeyInfo extends SignatureElementProxy {
X509Certificate cert = this.getX509CertificateFromInternalResolvers();
if (cert != null) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE,
+ log.log(java.util.logging.Level.FINE,
"I could find a X509Certificate using the per-KeyInfo key resolvers");
return cert;
}
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE,
+ log.log(java.util.logging.Level.FINE,
"I couldn't find a X509Certificate using the per-KeyInfo key resolvers");
@@ -863,12 +817,12 @@ public class KeyInfo extends SignatureElementProxy {
cert = this.getX509CertificateFromStaticResolvers();
if (cert != null) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE,
+ log.log(java.util.logging.Level.FINE,
"I could find a X509Certificate using the system-wide key resolvers");
return cert;
}
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE,
+ log.log(java.util.logging.Level.FINE,
"I couldn't find a X509Certificate using the system-wide key resolvers");
@@ -885,53 +839,44 @@ public class KeyInfo extends SignatureElementProxy {
*/
X509Certificate getX509CertificateFromStaticResolvers()
throws KeyResolverException {
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Start getX509CertificateFromStaticResolvers() with "
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Start getX509CertificateFromStaticResolvers() with "
+ KeyResolver.length() + " resolvers");
+ String uri=this.getBaseURI();
+ int length= KeyResolver.length();
+ int storageLength=this._storageResolvers.size();
+ Iterator it = KeyResolver.iterator();
+ for (int i = 0; i SubjectKeyIdentifier (id-ce-subjectKeyIdentifier) (2.5.29.14)
:
- * This extension identifies the public key being certified. It enables
- * distinct keys used by the same subject to be differentiated
- * (e.g., as key updating occurs).
- *
- * A key identifer shall be unique with respect to all key identifiers
- * for the subject with which it is used. This extension is always non-critical.
- */
- public static final String SKI_OID = "2.5.29.14";
-
- /**
- * Constructor X509SKI
- *
- * @param doc
- * @param skiBytes
- */
- public XMLX509SKI(Document doc, byte[] skiBytes) {
-
- super(doc);
-
- this.addBase64Text(skiBytes);
- }
-
- /**
- * Constructor XMLX509SKI
- *
- * @param doc
- * @param x509certificate
- * @throws XMLSecurityException
- */
- public XMLX509SKI(Document doc, X509Certificate x509certificate)
- throws XMLSecurityException {
-
- super(doc);
-
- this.addBase64Text(XMLX509SKI.getSKIBytesFromCert(x509certificate));
- }
-
- /**
- * Constructor XMLX509SKI
- *
- * @param element
- * @param BaseURI
- * @throws XMLSecurityException
- */
- public XMLX509SKI(Element element, String BaseURI)
+ /**
+ * SubjectKeyIdentifier (id-ce-subjectKeyIdentifier) (2.5.29.14)
:
+ * This extension identifies the public key being certified. It enables
+ * distinct keys used by the same subject to be differentiated
+ * (e.g., as key updating occurs).
+ *
+ * A key identifer shall be unique with respect to all key identifiers
+ * for the subject with which it is used. This extension is always non-critical.
+ */
+ public static final String SKI_OID = "2.5.29.14";
+
+ /**
+ * Constructor X509SKI
+ *
+ * @param doc
+ * @param skiBytes
+ */
+ public XMLX509SKI(Document doc, byte[] skiBytes) {
+ super(doc);
+ this.addBase64Text(skiBytes);
+ }
+
+ /**
+ * Constructor XMLX509SKI
+ *
+ * @param doc
+ * @param x509certificate
+ * @throws XMLSecurityException
+ */
+ public XMLX509SKI(Document doc, X509Certificate x509certificate)
throws XMLSecurityException {
- super(element, BaseURI);
- }
-
- /**
- * Method getSKIBytes
- *
- * @return the skibytes
- * @throws XMLSecurityException
- */
- public byte[] getSKIBytes() throws XMLSecurityException {
- return this.getBytesFromTextChild();
- }
-
- /**
- * Method getSKIBytesFromCert
- *
- * @param cert
- * @return sky bytes from the given certificate
- *
- * @throws XMLSecurityException
- * @see java.security.cert.X509Extension#getExtensionValue(java.lang.String)
- */
- public static byte[] getSKIBytesFromCert(X509Certificate cert)
+ super(doc);
+ this.addBase64Text(XMLX509SKI.getSKIBytesFromCert(x509certificate));
+ }
+
+ /**
+ * Constructor XMLX509SKI
+ *
+ * @param element
+ * @param BaseURI
+ * @throws XMLSecurityException
+ */
+ public XMLX509SKI(Element element, String BaseURI)
throws XMLSecurityException {
-
- try {
-
- /*
- * Gets the DER-encoded OCTET string for the extension value (extnValue)
- * identified by the passed-in oid String. The oid string is
- * represented by a set of positive whole numbers separated by periods.
- */
- byte[] derEncodedValue = cert.getExtensionValue(XMLX509SKI.SKI_OID);
-
- if (cert.getVersion() < 3) {
+ super(element, BaseURI);
+ }
+
+ /**
+ * Method getSKIBytes
+ *
+ * @return the skibytes
+ * @throws XMLSecurityException
+ */
+ public byte[] getSKIBytes() throws XMLSecurityException {
+ return this.getBytesFromTextChild();
+ }
+
+ /**
+ * Method getSKIBytesFromCert
+ *
+ * @param cert
+ * @return ski bytes from the given certificate
+ *
+ * @throws XMLSecurityException
+ * @see java.security.cert.X509Extension#getExtensionValue(java.lang.String)
+ */
+ public static byte[] getSKIBytesFromCert(X509Certificate cert)
+ throws XMLSecurityException {
+
+ if (cert.getVersion() < 3) {
Object exArgs[] = { new Integer(cert.getVersion()) };
-
throw new XMLSecurityException("certificate.noSki.lowVersion",
exArgs);
- }
-
- byte[] extensionValue = null;
-
- /**
- * Use sun.security.util.DerValue if it is present.
- */
- try {
- DerValue dervalue = new DerValue(derEncodedValue);
- if (dervalue == null) {
- throw new XMLSecurityException("certificate.noSki.null");
- }
- if (dervalue.tag != DerValue.tag_OctetString) {
- throw new XMLSecurityException("certificate.noSki.notOctetString");
- }
- extensionValue = dervalue.getOctetString();
- } catch (NoClassDefFoundError e) {
- }
-
- /**
- * Fall back to org.bouncycastle.asn1.DERInputStream
- */
- if (extensionValue == null) {
- try {
- Class clazz = Class.forName("org.bouncycastle.asn1.DERInputStream");
- if (clazz != null) {
- Constructor constructor = clazz.getConstructor(new Class[]{InputStream.class});
- InputStream is = (InputStream) constructor.newInstance(new Object[]{new ByteArrayInputStream(derEncodedValue)});
- Method method = clazz.getMethod("readObject", new Class[]{});
- Object obj = method.invoke(is, new Object[]{});
- if (obj == null) {
- throw new XMLSecurityException("certificate.noSki.null");
- }
- Class clazz2 = Class.forName("org.bouncycastle.asn1.ASN1OctetString");
- if (!clazz2.isInstance(obj)) {
- throw new XMLSecurityException("certificate.noSki.notOctetString");
- }
- Method method2 = clazz2.getMethod("getOctets", new Class[]{});
- extensionValue = (byte[]) method2.invoke(obj, new Object[]{});
- }
- } catch (Throwable t) {
- }
- }
-
- /**
- * Strip away first two bytes from the DerValue (tag and length)
- */
- byte abyte0[] = new byte[extensionValue.length - 2];
-
- System.arraycopy(extensionValue, 2, abyte0, 0, abyte0.length);
-
- /*
- byte abyte0[] = new byte[derEncodedValue.length - 4];
- System.arraycopy(derEncodedValue, 4, abyte0, 0, abyte0.length);
+ }
+
+ /*
+ * Gets the DER-encoded OCTET string for the extension value
+ * (extnValue) identified by the passed-in oid String. The oid
+ * string is represented by a set of positive whole numbers
+ * separated by periods.
+ */
+ byte[] extensionValue = cert.getExtensionValue(XMLX509SKI.SKI_OID);
+ if (extensionValue == null) {
+ throw new XMLSecurityException("certificate.noSki.null");
+ }
+
+ /**
+ * Strip away first four bytes from the extensionValue
+ * The first two bytes are the tag and length of the extensionValue
+ * OCTET STRING, and the next two bytes are the tag and length of
+ * the skid OCTET STRING.
*/
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Base64 of SKI is " + Base64.encode(abyte0));
+ byte skidValue[] = new byte[extensionValue.length - 4];
+
+ System.arraycopy(extensionValue, 4, skidValue, 0, skidValue.length);
- return abyte0;
- } catch (IOException ex) {
- throw new XMLSecurityException("generic.EmptyMessage", ex);
- }
- }
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "Base64 of SKI is " + Base64.encode(skidValue));
+ }
- /** @inheritDoc */
- public boolean equals(Object obj) {
+ return skidValue;
+ }
- if (!obj.getClass().getName().equals(this.getClass().getName())) {
- return false;
- }
+ /** @inheritDoc */
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (!this.getClass().getName().equals(obj.getClass().getName())) {
+ return false;
+ }
- XMLX509SKI other = (XMLX509SKI) obj;
+ XMLX509SKI other = (XMLX509SKI) obj;
- try {
- return java.security.MessageDigest.isEqual(other.getSKIBytes(),
+ try {
+ return java.security.MessageDigest.isEqual(other.getSKIBytes(),
this.getSKIBytes());
- } catch (XMLSecurityException ex) {
- return false;
- }
- }
-
- /** @inheritDoc */
- public String getBaseLocalName() {
- return Constants._TAG_X509SKI;
- }
+ } catch (XMLSecurityException ex) {
+ return false;
+ }
+ }
+
+ /** @inheritDoc */
+ public String getBaseLocalName() {
+ return Constants._TAG_X509SKI;
+ }
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SubjectName.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SubjectName.java
index 548ec7ba57d1bad16553ffe908677a3e0ffc4603..8d51da2e2fdd29b4a604f9c3bd9a77249a8e5c34 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SubjectName.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SubjectName.java
@@ -20,8 +20,6 @@
*/
package com.sun.org.apache.xml.internal.security.keys.content.x509;
-
-
import java.security.cert.X509Certificate;
import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
@@ -33,15 +31,11 @@ import org.w3c.dom.Element;
/**
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*/
public class XMLX509SubjectName extends SignatureElementProxy
implements XMLX509DataContent {
- /** {@link java.util.logging} logging facility */
- static java.util.logging.Logger log =
- java.util.logging.Logger.getLogger(XMLX509SubjectName.class.getName());
-
/**
* Constructor X509SubjectName
*
@@ -88,23 +82,21 @@ public class XMLX509SubjectName extends SignatureElementProxy
return RFC2253Parser.normalize(this.getTextFromTextChild());
}
- /** @inheritDoc */
- public boolean equals(Object obj) {
-
- if (!obj.getClass().getName().equals(this.getClass().getName())) {
- return false;
- }
-
- XMLX509SubjectName other = (XMLX509SubjectName) obj;
- String otherSubject = other.getSubjectName();
- String thisSubject = this.getSubjectName();
+ /** @inheritDoc */
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
- if (otherSubject.equals(thisSubject)) {
- return true;
- }
+ if (!this.getClass().getName().equals(obj.getClass().getName())) {
+ return false;
+ }
- return false;
+ XMLX509SubjectName other = (XMLX509SubjectName) obj;
+ String otherSubject = other.getSubjectName();
+ String thisSubject = this.getSubjectName();
+ return thisSubject.equals(otherSubject);
}
/** @inheritDoc */
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/InvalidKeyResolverException.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/InvalidKeyResolverException.java
index 6e3d408d43de05c4011dc37349b59c18b3763302..3b3508005cbdbb23661f0fb7e31c5a6f76be7fc0 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/InvalidKeyResolverException.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/InvalidKeyResolverException.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
@@ -29,7 +28,7 @@ import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
/**
*
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*/
public class InvalidKeyResolverException extends XMLSecurityException {
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java
index 488a59731c424cc0d37fff21f0f5dfe2c311c136..1da9dbb362f6926468faa00cc42ccc529d7cfa97 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
@@ -26,6 +25,7 @@ package com.sun.org.apache.xml.internal.security.keys.keyresolver;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import javax.crypto.SecretKey;
@@ -39,7 +39,8 @@ import org.w3c.dom.Node;
* KeyResolver is factory class for subclass of KeyResolverSpi that
* represent child element of KeyInfo.
*
- * @author $Author: raul $
+ * @author $Author: mullan $
+ * @version %I%, %G%
*/
public class KeyResolver {
@@ -72,6 +73,7 @@ public class KeyResolver {
InstantiationException {
this._resolverSpi =
(KeyResolverSpi) Class.forName(className).newInstance();
+ this._resolverSpi.setGlobalResolver(true);
}
/**
@@ -83,40 +85,82 @@ public class KeyResolver {
return KeyResolver._resolverVector.size();
}
+ public static void hit(Iterator hintI) {
+ ResolverIterator hint = (ResolverIterator) hintI;
+ int i = hint.i;
+ if (i!=1 && hint.res ==_resolverVector) {
+ List resolverVector=(List)((ArrayList)_resolverVector).clone();
+ Object ob=resolverVector.remove(i-1);
+ resolverVector.add(0,ob);
+ _resolverVector=resolverVector;
+ } else {
+ //System.out.println("KeyResolver hitting");
+ }
+ }
+
/**
- * Method item
+ * Method getInstance
+ *
+ * @param element
+ * @param BaseURI
+ * @param storage
+ * @return The certificate represented by the element.
*
- * @param i
- * @return the number i resolver registerd
* @throws KeyResolverException
*/
- public static KeyResolver item(int i) throws KeyResolverException {
+ public static final X509Certificate getX509Certificate(
+ Element element, String BaseURI, StorageResolver storage)
+ throws KeyResolverException {
+
+ // use the old vector to not be hit by updates
+ List resolverVector = KeyResolver._resolverVector;
+ for (int i = 0; i < resolverVector.size(); i++) {
+ KeyResolver resolver=
+ (KeyResolver) resolverVector.get(i);
- KeyResolver resolver = (KeyResolver) KeyResolver._resolverVector.get(i);
- if (resolver==null) {
- throw new KeyResolverException("utils.resolver.noClass");
+ if (resolver==null) {
+ Object exArgs[] = {
+ (((element != null)
+ && (element.getNodeType() == Node.ELEMENT_NODE))
+ ? element.getTagName()
+ : "null") };
+
+ throw new KeyResolverException("utils.resolver.noClass", exArgs);
+ }
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "check resolvability by class " + resolver.getClass());
+
+ X509Certificate cert=resolver.resolveX509Certificate(element, BaseURI, storage);
+ if (cert!=null) {
+ return cert;
+ }
}
- return resolver;
- }
+ Object exArgs[] = {
+ (((element != null) && (element.getNodeType() == Node.ELEMENT_NODE))
+ ? element.getTagName()
+ : "null") };
+ throw new KeyResolverException("utils.resolver.noClass", exArgs);
+ }
/**
* Method getInstance
*
* @param element
* @param BaseURI
* @param storage
- * @return the instance that happends to implement the thing.
+ * @return the public key contained in the element
*
* @throws KeyResolverException
*/
- public static final KeyResolver getInstance(
+ public static final PublicKey getPublicKey(
Element element, String BaseURI, StorageResolver storage)
throws KeyResolverException {
- for (int i = 0; i < KeyResolver._resolverVector.size(); i++) {
+ List resolverVector = KeyResolver._resolverVector;
+ for (int i = 0; i < resolverVector.size(); i++) {
KeyResolver resolver=
- (KeyResolver) KeyResolver._resolverVector.get(i);
+ (KeyResolver) resolverVector.get(i);
if (resolver==null) {
Object exArgs[] = {
@@ -127,11 +171,19 @@ public class KeyResolver {
throw new KeyResolverException("utils.resolver.noClass", exArgs);
}
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "check resolvability by class " + resolver.getClass());
-
- if (resolver.canResolve(element, BaseURI, storage)) {
- return resolver;
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "check resolvability by class " + resolver.getClass());
+
+ PublicKey cert=resolver.resolvePublicKey(element, BaseURI, storage);
+ if (cert!=null) {
+ if (i!=0 && resolverVector==_resolverVector) {
+ //update resolver.
+ resolverVector=(List)((ArrayList)_resolverVector).clone();
+ Object ob=resolverVector.remove(i);
+ resolverVector.add(0,ob);
+ _resolverVector=resolverVector;
+ }
+ return cert;
}
}
@@ -182,34 +234,6 @@ public class KeyResolver {
KeyResolver._resolverVector.add(0, className);
}
- /*
- * Method resolve
- *
- * @param element
- *
- * @throws KeyResolverException
- */
-
- /**
- * Method resolveStatic
- *
- * @param element
- * @param BaseURI
- * @param storage
- * @return resolve from the static register an element
- *
- * @throws KeyResolverException
- */
- public static PublicKey resolveStatic(
- Element element, String BaseURI, StorageResolver storage)
- throws KeyResolverException {
-
- KeyResolver myResolver = KeyResolver.getInstance(element, BaseURI,
- storage);
-
- return myResolver.resolvePublicKey(element, BaseURI, storage);
- }
-
/**
* Method resolve
*
@@ -223,7 +247,7 @@ public class KeyResolver {
public PublicKey resolvePublicKey(
Element element, String BaseURI, StorageResolver storage)
throws KeyResolverException {
- return this._resolverSpi.engineResolvePublicKey(element, BaseURI, storage);
+ return this._resolverSpi.engineLookupAndResolvePublicKey(element, BaseURI, storage);
}
/**
@@ -239,7 +263,7 @@ public class KeyResolver {
public X509Certificate resolveX509Certificate(
Element element, String BaseURI, StorageResolver storage)
throws KeyResolverException {
- return this._resolverSpi.engineResolveX509Certificate(element, BaseURI,
+ return this._resolverSpi.engineLookupResolveX509Certificate(element, BaseURI,
storage);
}
@@ -253,7 +277,7 @@ public class KeyResolver {
public SecretKey resolveSecretKey(
Element element, String BaseURI, StorageResolver storage)
throws KeyResolverException {
- return this._resolverSpi.engineResolveSecretKey(element, BaseURI,
+ return this._resolverSpi.engineLookupAndResolveSecretKey(element, BaseURI,
storage);
}
@@ -277,14 +301,6 @@ public class KeyResolver {
return this._resolverSpi.engineGetProperty(key);
}
- /**
- * Method getPropertyKeys
- *
- * @return the properties key registerd in this resolver
- */
- public String[] getPropertyKeys() {
- return this._resolverSpi.engineGetPropertyKeys();
- }
/**
* Method understandsProperty
@@ -296,18 +312,6 @@ public class KeyResolver {
return this._resolverSpi.understandsProperty(propertyToTest);
}
- /**
- * Method canResolve
- *
- * @param element
- * @param BaseURI
- * @param storage
- * @return true if can resolve the key in the element
- */
- public boolean canResolve(Element element, String BaseURI,
- StorageResolver storage) {
- return this._resolverSpi.engineCanResolve(element, BaseURI, storage);
- }
/**
* Method resolverClassName
@@ -317,4 +321,37 @@ public class KeyResolver {
public String resolverClassName() {
return this._resolverSpi.getClass().getName();
}
+
+ static class ResolverIterator implements Iterator {
+ List res;
+ Iterator it;
+ int i;
+ public ResolverIterator(List list) {
+ res = list;
+ it = res.iterator();
+ }
+ public boolean hasNext() {
+ // TODO Auto-generated method stub
+ return it.hasNext();
+ }
+
+ public Object next() {
+ i++;
+ KeyResolver resolver = (KeyResolver) it.next();
+ if (resolver==null) {
+ throw new RuntimeException("utils.resolver.noClass");
+ }
+
+ return resolver._resolverSpi;
+ }
+
+ public void remove() {
+ // TODO Auto-generated method stub
+
+ }
+
+ };
+ public static Iterator iterator() {
+ return new ResolverIterator(_resolverVector);
+ }
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverException.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverException.java
index 4248c8dfa6b280119a59b98acd6ac82c7261cf78..f0069949b2f804ec02fe458b4179c80ca023a059 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverException.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverException.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
@@ -31,7 +30,7 @@ import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
*
*
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*
*/
public class KeyResolverException extends XMLSecurityException {
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java
index a6b99825ebc5294f67fe34e55e7c8fac7d7f1bad..dc2865bcfc4d67632320bda1a65d2b22e05e18a4 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java
@@ -20,17 +20,15 @@
*/
package com.sun.org.apache.xml.internal.security.keys.keyresolver;
-
-
import java.security.PublicKey;
import java.security.cert.X509Certificate;
+import java.util.HashMap;
import javax.crypto.SecretKey;
import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver;
import org.w3c.dom.Element;
-
/**
* This class is abstract class for a child KeyInfo Elemnet.
*
@@ -41,14 +39,10 @@ import org.w3c.dom.Element;
* JAVACLASS="MyPackage.MyKeyValueImpl"//gt;
*
*
- * @author $Author: raul $
+ * @author $Author: mullan $
+ * @version $Revision: 1.5 $
*/
public abstract class KeyResolverSpi {
-
- /** {@link java.util.logging} logging facility */
- static java.util.logging.Logger log =
- java.util.logging.Logger.getLogger(KeyResolverSpi.class.getName());
-
/**
* This method helps the {@link com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver} to decide whether a
* {@link com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi} is able to perform the requested action.
@@ -56,10 +50,12 @@ public abstract class KeyResolverSpi {
* @param element
* @param BaseURI
* @param storage
- * @return true if can resolve the key in the element
+ * @return
*/
- abstract public boolean engineCanResolve(Element element, String BaseURI,
- StorageResolver storage);
+ public boolean engineCanResolve(Element element, String BaseURI,
+ StorageResolver storage) {
+ throw new UnsupportedOperationException();
+ }
/**
* Method engineResolvePublicKey
@@ -71,9 +67,60 @@ public abstract class KeyResolverSpi {
*
* @throws KeyResolverException
*/
- abstract public PublicKey engineResolvePublicKey(
+ public PublicKey engineResolvePublicKey(
Element element, String BaseURI, StorageResolver storage)
- throws KeyResolverException;
+ throws KeyResolverException {
+ throw new UnsupportedOperationException();
+ };
+
+ /**
+ * Method engineResolvePublicKey
+ *
+ * @param element
+ * @param BaseURI
+ * @param storage
+ * @return resolved public key from the registered from the element.
+ *
+ * @throws KeyResolverException
+ */
+ public PublicKey engineLookupAndResolvePublicKey(
+ Element element, String BaseURI, StorageResolver storage)
+ throws KeyResolverException {
+ KeyResolverSpi tmp = cloneIfNeeded();
+ if (!tmp.engineCanResolve(element, BaseURI, storage))
+ return null;
+ return tmp.engineResolvePublicKey(element, BaseURI, storage);
+ }
+
+ private KeyResolverSpi cloneIfNeeded() throws KeyResolverException {
+ KeyResolverSpi tmp=this;
+ if (globalResolver) {
+ try {
+ tmp = (KeyResolverSpi) getClass().newInstance();
+ } catch (InstantiationException e) {
+ throw new KeyResolverException("",e);
+ } catch (IllegalAccessException e) {
+ throw new KeyResolverException("",e);
+ }
+ }
+ return tmp;
+ }
+
+ /**
+ * Method engineResolveCertificate
+ *
+ * @param element
+ * @param BaseURI
+ * @param storage
+ * @return resolved X509Certificate key from the registered from the elements
+ *
+ * @throws KeyResolverException
+ */
+ public X509Certificate engineResolveX509Certificate(
+ Element element, String BaseURI, StorageResolver storage)
+ throws KeyResolverException{
+ throw new UnsupportedOperationException();
+ };
/**
* Method engineResolveCertificate
@@ -85,9 +132,30 @@ public abstract class KeyResolverSpi {
*
* @throws KeyResolverException
*/
- abstract public X509Certificate engineResolveX509Certificate(
+ public X509Certificate engineLookupResolveX509Certificate(
Element element, String BaseURI, StorageResolver storage)
- throws KeyResolverException;
+ throws KeyResolverException {
+ KeyResolverSpi tmp = cloneIfNeeded();
+ if (!tmp.engineCanResolve(element, BaseURI, storage))
+ return null;
+ return tmp.engineResolveX509Certificate(element, BaseURI, storage);
+
+ }
+ /**
+ * Method engineResolveSecretKey
+ *
+ * @param element
+ * @param BaseURI
+ * @param storage
+ * @return resolved SecretKey key from the registered from the elements
+ *
+ * @throws KeyResolverException
+ */
+ public SecretKey engineResolveSecretKey(
+ Element element, String BaseURI, StorageResolver storage)
+ throws KeyResolverException{
+ throw new UnsupportedOperationException();
+ };
/**
* Method engineResolveSecretKey
@@ -99,12 +167,19 @@ public abstract class KeyResolverSpi {
*
* @throws KeyResolverException
*/
- abstract public SecretKey engineResolveSecretKey(
+ public SecretKey engineLookupAndResolveSecretKey(
Element element, String BaseURI, StorageResolver storage)
- throws KeyResolverException;
+ throws KeyResolverException {
+ KeyResolverSpi tmp = cloneIfNeeded();
+ if (!tmp.engineCanResolve(element, BaseURI, storage))
+ return null;
+ return tmp.engineResolveSecretKey(element, BaseURI, storage);
+ }
/** Field _properties */
- protected java.util.Map _properties = new java.util.HashMap(10);
+ protected java.util.Map _properties = null;
+
+ protected boolean globalResolver=false;
/**
* Method engineSetProperty
@@ -113,19 +188,8 @@ public abstract class KeyResolverSpi {
* @param value
*/
public void engineSetProperty(String key, String value) {
-
- java.util.Iterator i = this._properties.keySet().iterator();
-
- while (i.hasNext()) {
- String c = (String) i.next();
-
- if (c.equals(key)) {
- key = c;
-
- break;
- }
- }
-
+ if (_properties==null)
+ _properties=new HashMap();
this._properties.put(key, value);
}
@@ -136,31 +200,12 @@ public abstract class KeyResolverSpi {
* @return obtain the property appointed by key
*/
public String engineGetProperty(String key) {
-
- java.util.Iterator i = this._properties.keySet().iterator();
-
- while (i.hasNext()) {
- String c = (String) i.next();
-
- if (c.equals(key)) {
- key = c;
-
- break;
- }
- }
+ if (_properties==null)
+ return null;
return (String) this._properties.get(key);
}
- /**
- * Method engineGetPropertyKeys
- *
- * @return the keys of properties known by this resolver
- */
- public String[] engineGetPropertyKeys() {
- return new String[0];
- }
-
/**
* Method understandsProperty
*
@@ -168,17 +213,13 @@ public abstract class KeyResolverSpi {
* @return true if understood the property
*/
public boolean understandsProperty(String propertyToTest) {
+ if (_properties==null)
+ return false;
- String[] understood = this.engineGetPropertyKeys();
-
- if (understood != null) {
- for (int i = 0; i < understood.length; i++) {
- if (understood[i].equals(propertyToTest)) {
- return true;
- }
- }
- }
-
- return false;
+ return this._properties.get(propertyToTest)!=null;
}
+ public void setGlobalResolver(boolean globalResolver) {
+ this.globalResolver = globalResolver;
+ }
+
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/DSAKeyValueResolver.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/DSAKeyValueResolver.java
index efda14c1a4a0066417e062dae7100c9e908f5539..20bf7bad777fa08e94f5f79fddb9fcd45646a18e 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/DSAKeyValueResolver.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/DSAKeyValueResolver.java
@@ -37,46 +37,10 @@ import org.w3c.dom.Element;
/**
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*/
public class DSAKeyValueResolver extends KeyResolverSpi {
- /** Field _dsaKeyElement */
- private Element _dsaKeyElement = null;
-
- /** @inheritDoc */
- public boolean engineCanResolve(Element element, String BaseURI,
- StorageResolver storage) {
-
- if (element == null) {
- return false;
- }
-
- boolean isKeyValue = XMLUtils.elementIsInSignatureSpace(element,
- Constants._TAG_KEYVALUE);
- boolean isDSAKeyValue = XMLUtils.elementIsInSignatureSpace(element,
- Constants._TAG_DSAKEYVALUE);
-
- if (isKeyValue) {
-
- this._dsaKeyElement =
- XMLUtils.selectDsNode(element.getFirstChild(),Constants._TAG_DSAKEYVALUE,0);
-
- if (this._dsaKeyElement != null) {
- return true;
- }
- } else if (isDSAKeyValue) {
-
- // this trick is needed to allow the RetrievalMethodResolver to eat a
- // ds:DSAKeyValue directly (without KeyValue)
- this._dsaKeyElement = element;
-
- return true;
- }
-
- return false;
- }
-
/**
* Method engineResolvePublicKey
*
@@ -85,20 +49,30 @@ public class DSAKeyValueResolver extends KeyResolverSpi {
* @param storage
* @return null if no {@link PublicKey} could be obtained
*/
- public PublicKey engineResolvePublicKey(
+ public PublicKey engineLookupAndResolvePublicKey(
Element element, String BaseURI, StorageResolver storage) {
+ if (element == null) {
+ return null;
+ }
+ Element dsaKeyElement=null;
+ boolean isKeyValue = XMLUtils.elementIsInSignatureSpace(element,
+ Constants._TAG_KEYVALUE);
+ if (isKeyValue) {
+ dsaKeyElement =
+ XMLUtils.selectDsNode(element.getFirstChild(),Constants._TAG_DSAKEYVALUE,0);
+ } else if (XMLUtils.elementIsInSignatureSpace(element,
+ Constants._TAG_DSAKEYVALUE)) {
+ // this trick is needed to allow the RetrievalMethodResolver to eat a
+ // ds:DSAKeyValue directly (without KeyValue)
+ dsaKeyElement = element;
+ }
- if (this._dsaKeyElement == null) {
- boolean weCanResolve = this.engineCanResolve(element, BaseURI,
- storage);
-
- if (!weCanResolve || (this._dsaKeyElement == null)) {
- return null;
- }
+ if (dsaKeyElement == null) {
+ return null;
}
try {
- DSAKeyValue dsaKeyValue = new DSAKeyValue(this._dsaKeyElement,
+ DSAKeyValue dsaKeyValue = new DSAKeyValue(dsaKeyElement,
BaseURI);
PublicKey pk = dsaKeyValue.getPublicKey();
@@ -112,13 +86,13 @@ public class DSAKeyValueResolver extends KeyResolverSpi {
/** @inheritDoc */
- public X509Certificate engineResolveX509Certificate(
+ public X509Certificate engineLookupResolveX509Certificate(
Element element, String BaseURI, StorageResolver storage) {
return null;
}
/** @inheritDoc */
- public javax.crypto.SecretKey engineResolveSecretKey(
+ public javax.crypto.SecretKey engineLookupAndResolveSecretKey(
Element element, String BaseURI, StorageResolver storage){
return null;
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/EncryptedKeyResolver.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/EncryptedKeyResolver.java
index 4b44f1c50d15434bf71c3bf98cf349f4921422bd..6adc050e8935b37d90faa61fe67d373d72353a33 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/EncryptedKeyResolver.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/EncryptedKeyResolver.java
@@ -56,7 +56,6 @@ public class EncryptedKeyResolver extends KeyResolverSpi {
RSAKeyValueResolver.class.getName());
- Key _key;
Key _kek;
String _algorithm;
@@ -66,7 +65,6 @@ public class EncryptedKeyResolver extends KeyResolverSpi {
* @param algorithm
*/
public EncryptedKeyResolver(String algorithm) {
- _key = null;
_kek = null;
_algorithm=algorithm;
}
@@ -78,64 +76,49 @@ public class EncryptedKeyResolver extends KeyResolverSpi {
*/
public EncryptedKeyResolver(String algorithm, Key kek) {
- _key = null;
_algorithm = algorithm;
_kek = kek;
}
- /**
- * Method engineCanResolve
- *
- * @param element
- * @param BaseURI
- * @param storage
- * @return true if can resolve the key in the element
- *
- */
-
- public boolean engineCanResolve(Element element, String BaseURI,
- StorageResolver storage) {
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "EncryptedKeyResolver - Can I resolve " + element.getTagName());
-
- if (element == null) {
- return false;
- }
-
- boolean isEncryptedKey = XMLUtils.elementIsInEncryptionSpace(element,
- EncryptionConstants._TAG_ENCRYPTEDKEY);
-
- if (isEncryptedKey) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Passed an Encrypted Key");
- try {
- XMLCipher cipher = XMLCipher.getInstance();
- cipher.init(XMLCipher.UNWRAP_MODE, _kek);
- EncryptedKey ek = cipher.loadEncryptedKey(element);
- _key = cipher.decryptKey(ek, _algorithm);
- }
- catch (Exception e) {}
- }
-
- return (_key != null);
- }
-
/** @inheritDoc */
- public PublicKey engineResolvePublicKey(
+ public PublicKey engineLookupAndResolvePublicKey(
Element element, String BaseURI, StorageResolver storage) {
return null;
}
/** @inheritDoc */
- public X509Certificate engineResolveX509Certificate(
+ public X509Certificate engineLookupResolveX509Certificate(
Element element, String BaseURI, StorageResolver storage) {
return null;
}
/** @inheritDoc */
- public javax.crypto.SecretKey engineResolveSecretKey(
+ public javax.crypto.SecretKey engineLookupAndResolveSecretKey(
Element element, String BaseURI, StorageResolver storage) {
- return (SecretKey) _key;
+ SecretKey key=null;
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "EncryptedKeyResolver - Can I resolve " + element.getTagName());
+
+ if (element == null) {
+ return null;
+ }
+
+ boolean isEncryptedKey = XMLUtils.elementIsInEncryptionSpace(element,
+ EncryptionConstants._TAG_ENCRYPTEDKEY);
+
+ if (isEncryptedKey) {
+ log.log(java.util.logging.Level.FINE, "Passed an Encrypted Key");
+ try {
+ XMLCipher cipher = XMLCipher.getInstance();
+ cipher.init(XMLCipher.UNWRAP_MODE, _kek);
+ EncryptedKey ek = cipher.loadEncryptedKey(element);
+ key = (SecretKey) cipher.decryptKey(ek, _algorithm);
+ }
+ catch (Exception e) {}
+ }
+
+ return key;
}
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java
index 541de7307f458702c775dffb48f4e5e648db3fc6..fb38e8725908901a545533d178af3b79ad3ca120 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
@@ -38,7 +37,7 @@ import org.w3c.dom.Element;
/**
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*/
public class RSAKeyValueResolver extends KeyResolverSpi {
@@ -48,75 +47,55 @@ public class RSAKeyValueResolver extends KeyResolverSpi {
RSAKeyValueResolver.class.getName());
/** Field _rsaKeyElement */
- private Element _rsaKeyElement = null;
- /** @inheritDoc */
- public boolean engineCanResolve(Element element, String BaseURI,
- StorageResolver storage) {
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Can I resolve " + element.getTagName());
+ /** @inheritDoc */
+ public PublicKey engineLookupAndResolvePublicKey(
+ Element element, String BaseURI, StorageResolver storage) {
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Can I resolve " + element.getTagName());
if (element == null) {
- return false;
+ return null;
}
- boolean isKeyValue = XMLUtils.elementIsInSignatureSpace(element,
- Constants._TAG_KEYVALUE);
- boolean isRSAKeyValue = XMLUtils.elementIsInSignatureSpace(element,
- Constants._TAG_RSAKEYVALUE);
-
- if (isKeyValue) {
- this._rsaKeyElement = XMLUtils.selectDsNode(element.getFirstChild(),
- Constants._TAG_RSAKEYVALUE, 0);
-
- if (this._rsaKeyElement != null) {
- return true;
- }
- } else if (isRSAKeyValue) {
-
+ boolean isKeyValue = XMLUtils.elementIsInSignatureSpace(element,
+ Constants._TAG_KEYVALUE);
+ Element rsaKeyElement=null;
+ if (isKeyValue) {
+ rsaKeyElement = XMLUtils.selectDsNode(element.getFirstChild(),
+ Constants._TAG_RSAKEYVALUE, 0);
+ } else if (XMLUtils.elementIsInSignatureSpace(element,
+ Constants._TAG_RSAKEYVALUE)) {
// this trick is needed to allow the RetrievalMethodResolver to eat a
// ds:RSAKeyValue directly (without KeyValue)
- this._rsaKeyElement = element;
-
- return true;
- }
-
- return false;
- }
-
- /** @inheritDoc */
- public PublicKey engineResolvePublicKey(
- Element element, String BaseURI, StorageResolver storage) {
+ rsaKeyElement = element;
+ }
- if (this._rsaKeyElement == null) {
- boolean weCanResolve = this.engineCanResolve(element, BaseURI,
- storage);
- if (!weCanResolve || (this._rsaKeyElement == null)) {
- return null;
- }
+ if (rsaKeyElement == null) {
+ return null;
}
try {
- RSAKeyValue rsaKeyValue = new RSAKeyValue(this._rsaKeyElement,
+ RSAKeyValue rsaKeyValue = new RSAKeyValue(rsaKeyElement,
BaseURI);
return rsaKeyValue.getPublicKey();
} catch (XMLSecurityException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
+ log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
}
return null;
}
/** @inheritDoc */
- public X509Certificate engineResolveX509Certificate(
+ public X509Certificate engineLookupResolveX509Certificate(
Element element, String BaseURI, StorageResolver storage) {
return null;
}
/** @inheritDoc */
- public javax.crypto.SecretKey engineResolveSecretKey(
+ public javax.crypto.SecretKey engineLookupAndResolveSecretKey(
Element element, String BaseURI, StorageResolver storage) {
return null;
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RetrievalMethodResolver.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RetrievalMethodResolver.java
index d8d98bdb9e9651f47049990b377e4a6f7267c344..3dff21824457cf144b05888576feecc1ec74bd4b 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RetrievalMethodResolver.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RetrievalMethodResolver.java
@@ -28,7 +28,15 @@ import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+import javax.xml.parsers.ParserConfigurationException;
+
+import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
import com.sun.org.apache.xml.internal.security.keys.content.RetrievalMethod;
import com.sun.org.apache.xml.internal.security.keys.content.x509.XMLX509Certificate;
@@ -44,6 +52,7 @@ import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
/**
@@ -55,7 +64,7 @@ import org.w3c.dom.Node;
* RetrievalMethodResolver cannot handle itself, resolving of the extracted
* element is delegated back to the KeyResolver mechanism.
*
- * @author $Author: raul $
+ * @author $Author: mullan $ modified by Dave Garcia
*/
public class RetrievalMethodResolver extends KeyResolverSpi {
@@ -65,198 +74,170 @@ public class RetrievalMethodResolver extends KeyResolverSpi {
RetrievalMethodResolver.class.getName());
/**
- * Method engineCanResolve
+ * Method engineResolvePublicKey
* @inheritDoc
* @param element
* @param BaseURI
* @param storage
*
*/
- public boolean engineCanResolve(Element element, String BaseURI,
- StorageResolver storage) {
+ public PublicKey engineLookupAndResolvePublicKey(
+ Element element, String BaseURI, StorageResolver storage)
+ {
+ if (!XMLUtils.elementIsInSignatureSpace(element,
+ Constants._TAG_RETRIEVALMETHOD)) {
+ return null;
+ }
- if
- (!XMLUtils.elementIsInSignatureSpace(element,
- Constants._TAG_RETRIEVALMETHOD)) {
- return false;
- }
+ try {
+ //Create a retrieval method over the given element
+ RetrievalMethod rm = new RetrievalMethod(element, BaseURI);
+ String type = rm.getType();
+ XMLSignatureInput resource=resolveInput(rm,BaseURI);
+ if (RetrievalMethod.TYPE_RAWX509.equals(type)) {
+ //a raw certificate, direct parsing is done!
+ X509Certificate cert=getRawCertificate(resource);
+ if (cert != null) {
+ return cert.getPublicKey();
+ }
+ return null;
+ };
+ Element e = obtainRefrenceElement(resource);
+ return resolveKey(e,BaseURI,storage);
+ } catch (XMLSecurityException ex) {
+ log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
+ } catch (CertificateException ex) {
+ log.log(java.util.logging.Level.FINE, "CertificateException", ex);
+ } catch (IOException ex) {
+ log.log(java.util.logging.Level.FINE, "IOException", ex);
+ } catch (ParserConfigurationException e) {
+ log.log(java.util.logging.Level.FINE, "ParserConfigurationException", e);
+ } catch (SAXException e) {
+ log.log(java.util.logging.Level.FINE, "SAXException", e);
+ }
+ return null;
+ }
- return true;
+ static private Element obtainRefrenceElement(XMLSignatureInput resource) throws CanonicalizationException, ParserConfigurationException, IOException, SAXException, KeyResolverException {
+ Element e;
+ if (resource.isElement()){
+ e=(Element) resource.getSubNode();
+ } else if (resource.isNodeSet()) {
+ //Retrieved resource is a nodeSet
+ e=getDocumentElement(resource.getNodeSet());
+ } else {
+ //Retrieved resource is an inputStream
+ byte inputBytes[] = resource.getBytes();
+ e = getDocFromBytes(inputBytes);
+ //otherwise, we parse the resource, create an Element and delegate
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "we have to parse " + inputBytes.length + " bytes");
+ }
+ return e;
}
/**
- * Method engineResolvePublicKey
+ * Method engineResolveX509Certificate
* @inheritDoc
* @param element
* @param BaseURI
* @param storage
*
*/
- public PublicKey engineResolvePublicKey(
+ public X509Certificate engineLookupResolveX509Certificate(
Element element, String BaseURI, StorageResolver storage)
{
+ if (!XMLUtils.elementIsInSignatureSpace(element,
+ Constants._TAG_RETRIEVALMETHOD)) {
+ return null;
+ }
- try {
+ try {
RetrievalMethod rm = new RetrievalMethod(element, BaseURI);
- Attr uri = rm.getURIAttr();
-
- // type can be null because it's optional
- String type = rm.getType();
- Transforms transforms = rm.getTransforms();
- ResourceResolver resRes = ResourceResolver.getInstance(uri, BaseURI);
-
- if (resRes != null) {
- XMLSignatureInput resource = resRes.resolve(uri, BaseURI);
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Before applying Transforms, resource has "
- + resource.getBytes().length + "bytes");
-
- if (transforms != null) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "We have Transforms");
-
- resource = transforms.performTransforms(resource);
- }
- if (true) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "After applying Transforms, resource has "
- + resource.getBytes().length + "bytes");
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Resolved to resource " + resource.getSourceURI());
- }
-
- byte inputBytes[] = resource.getBytes();
-
- if ((type != null) && type.equals(RetrievalMethod.TYPE_RAWX509)) {
-
- // if the resource stores a raw certificate, we have to handle it
- CertificateFactory certFact =
- CertificateFactory
- .getInstance(XMLX509Certificate.JCA_CERT_ID);
- X509Certificate cert =
- (X509Certificate) certFact
- .generateCertificate(new ByteArrayInputStream(inputBytes));
-
- if (cert != null) {
- return cert.getPublicKey();
- }
- } else {
-
- // otherwise, we parse the resource, create an Element and delegate
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "we have to parse " + inputBytes.length + " bytes");
-
- Element e = this.getDocFromBytes(inputBytes);
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"
- + e.getLocalName() + " Element");
-
- if (e != null) {
- KeyResolver newKeyResolver = KeyResolver.getInstance(getFirstElementChild(e),
- BaseURI, storage);
-
- if (newKeyResolver != null) {
- return newKeyResolver.resolvePublicKey(getFirstElementChild(e), BaseURI,
- storage);
- }
- }
- }
- }
+ String type = rm.getType();
+ XMLSignatureInput resource=resolveInput(rm,BaseURI);
+ if (RetrievalMethod.TYPE_RAWX509.equals(type)) {
+ X509Certificate cert=getRawCertificate(resource);
+ return cert;
+ }
+ Element e = obtainRefrenceElement(resource);
+ return resolveCertificate(e,BaseURI,storage);
} catch (XMLSecurityException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
+ log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
} catch (CertificateException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "CertificateException", ex);
+ log.log(java.util.logging.Level.FINE, "CertificateException", ex);
} catch (IOException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "IOException", ex);
- }
-
+ log.log(java.util.logging.Level.FINE, "IOException", ex);
+ } catch (ParserConfigurationException e) {
+ log.log(java.util.logging.Level.FINE, "ParserConfigurationException", e);
+ } catch (SAXException e) {
+ log.log(java.util.logging.Level.FINE, "SAXException", e);
+ }
return null;
}
/**
- * Method engineResolveX509Certificate
- * @inheritDoc
- * @param element
+ * Retrieves a x509Certificate from the given information
+ * @param e
* @param BaseURI
* @param storage
- *
+ * @return
+ * @throws KeyResolverException
*/
- public X509Certificate engineResolveX509Certificate(
- Element element, String BaseURI, StorageResolver storage)
- {
-
- try {
- RetrievalMethod rm = new RetrievalMethod(element, BaseURI);
- Attr uri = rm.getURIAttr();
- Transforms transforms = rm.getTransforms();
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Asked to resolve URI " + uri);
-
- ResourceResolver resRes = ResourceResolver.getInstance(uri, BaseURI);
-
- if (resRes != null) {
- XMLSignatureInput resource = resRes.resolve(uri, BaseURI);
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Before applying Transforms, resource has "
- + resource.getBytes().length + "bytes");
-
- if (transforms != null) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "We have Transforms");
-
- resource = transforms.performTransforms(resource);
- }
-
- if (true) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "After applying Transforms, resource has "
- + resource.getBytes().length + "bytes");
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Resolved to resource " + resource.getSourceURI());
- }
-
- byte inputBytes[] = resource.getBytes();
-
- if ((rm.getType() != null)
- && rm.getType().equals(RetrievalMethod.TYPE_RAWX509)) {
-
- // if the resource stores a raw certificate, we have to handle it
- CertificateFactory certFact =
- CertificateFactory
- .getInstance(XMLX509Certificate.JCA_CERT_ID);
- X509Certificate cert =
- (X509Certificate) certFact
- .generateCertificate(new ByteArrayInputStream(inputBytes));
-
- if (cert != null) {
- return cert;
- }
- } else {
-
- // otherwise, we parse the resource, create an Element and delegate
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "we have to parse " + inputBytes.length + " bytes");
-
- Element e = this.getDocFromBytes(inputBytes);
-
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"
- + e.getLocalName() + " Element");
-
- if (e != null) {
- KeyResolver newKeyResolver = KeyResolver.getInstance(getFirstElementChild(e),
- BaseURI, storage);
+ static private X509Certificate resolveCertificate(Element e,String BaseURI,StorageResolver storage) throws KeyResolverException{
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"+ e.getLocalName() + " Element");
+ //An element has been provided
+ if (e != null) {
+ return KeyResolver.getX509Certificate(e,BaseURI, storage);
+ }
+ return null;
+ }
- if (newKeyResolver != null) {
- return newKeyResolver.resolveX509Certificate(getFirstElementChild(e), BaseURI,
- storage);
+ /**
+ * Retrieves a x509Certificate from the given information
+ * @param e
+ * @param BaseURI
+ * @param storage
+ * @return
+ * @throws KeyResolverException
+ */
+ static private PublicKey resolveKey(Element e,String BaseURI,StorageResolver storage) throws KeyResolverException{
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"+ e.getLocalName() + " Element");
+ //An element has been provided
+ if (e != null) {
+ return KeyResolver.getPublicKey(e,BaseURI, storage);
}
- }
- }
- }
- } catch (XMLSecurityException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
- } catch (CertificateException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "CertificateException", ex);
- } catch (IOException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "IOException", ex);
- }
+ return null;
+ }
- return null;
+ static private X509Certificate getRawCertificate(XMLSignatureInput resource) throws CanonicalizationException, IOException, CertificateException{
+ byte inputBytes[] = resource.getBytes();
+ // if the resource stores a raw certificate, we have to handle it
+ CertificateFactory certFact =CertificateFactory.getInstance(XMLX509Certificate.JCA_CERT_ID);
+ X509Certificate cert =(X509Certificate) certFact.generateCertificate(new ByteArrayInputStream(inputBytes));
+ return cert;
+ }
+ /**
+ * Resolves the input from the given retrieval method
+ * @return
+ * @throws XMLSecurityException
+ */
+ static private XMLSignatureInput resolveInput(RetrievalMethod rm,String BaseURI) throws XMLSecurityException{
+ Attr uri = rm.getURIAttr();
+ //Apply the trnasforms
+ Transforms transforms = rm.getTransforms();
+ ResourceResolver resRes = ResourceResolver.getInstance(uri, BaseURI);
+ if (resRes != null) {
+ XMLSignatureInput resource = resRes.resolve(uri, BaseURI);
+ if (transforms != null) {
+ log.log(java.util.logging.Level.FINE, "We have Transforms");
+ resource = transforms.performTransforms(resource);
+ }
+ return resource;
+ }
+ return null;
}
/**
@@ -266,18 +247,13 @@ public class RetrievalMethodResolver extends KeyResolverSpi {
* @return the Document Element after parsing bytes
* @throws KeyResolverException if something goes wrong
*/
- Element getDocFromBytes(byte[] bytes) throws KeyResolverException {
-
+ static Element getDocFromBytes(byte[] bytes) throws KeyResolverException {
try {
- javax.xml.parsers.DocumentBuilderFactory dbf =
- javax.xml.parsers.DocumentBuilderFactory.newInstance();
-
+ javax.xml.parsers.DocumentBuilderFactory dbf =javax.xml.parsers.DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
-
javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
org.w3c.dom.Document doc =
db.parse(new java.io.ByteArrayInputStream(bytes));
-
return doc.getDocumentElement();
} catch (org.xml.sax.SAXException ex) {
throw new KeyResolverException("empty", ex);
@@ -296,16 +272,43 @@ public class RetrievalMethodResolver extends KeyResolverSpi {
* @param storage
*
*/
- public javax.crypto.SecretKey engineResolveSecretKey(
+ public javax.crypto.SecretKey engineLookupAndResolveSecretKey(
Element element, String BaseURI, StorageResolver storage)
{
return null;
}
- static Element getFirstElementChild(Element e){
- Node n=e.getFirstChild();
- while (n!=null && n.getNodeType()!=Node.ELEMENT_NODE) {
- n=n.getNextSibling();
- }
- return (Element)n;
+
+ static Element getDocumentElement(Set set) {
+ Iterator it=set.iterator();
+ Element e=null;
+ while (it.hasNext()) {
+ Node currentNode=(Node)it.next();
+ if (currentNode instanceof Element) {
+ e=(Element)currentNode;
+ break;
+ }
+
+ }
+ List parents=new ArrayList(10);
+
+ //Obtain all the parents of the elemnt
+ do {
+ parents.add(e);
+ Node n=e.getParentNode();
+ if (!(n instanceof Element )) {
+ break;
+ }
+ e=(Element)n;
+ } while (e!=null);
+ //Visit them in reverse order.
+ ListIterator it2=parents.listIterator(parents.size()-1);
+ Element ele=null;
+ while (it2.hasPrevious()) {
+ ele=(Element)it2.previous();
+ if (set.contains(ele)) {
+ return ele;
+ }
+ }
+ return null;
}
}
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509CertificateResolver.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509CertificateResolver.java
index 16264c998687fce2ae6c3c52c10211462561e0fb..06a49c6708e7c70dfb639bb2d0dffa0bbae7092a 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509CertificateResolver.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509CertificateResolver.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
@@ -41,7 +40,7 @@ import org.w3c.dom.Element;
* Resolves Certificates which are directly contained inside a
* ds:X509Certificate
Element.
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*/
public class X509CertificateResolver extends KeyResolverSpi {
@@ -49,47 +48,7 @@ public class X509CertificateResolver extends KeyResolverSpi {
static java.util.logging.Logger log =
java.util.logging.Logger.getLogger(X509CertificateResolver.class.getName());
- /** Field _dsaKeyElement */
- Element[] _x509CertKeyElements = null;
-
- /**
- * Method engineCanResolve
- * @inheritDoc
- * @param element
- * @param BaseURI
- * @param storage
- *
- */
- public boolean engineCanResolve(Element element, String BaseURI,
- StorageResolver storage) {
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Can I resolve " + element.getTagName() + "?");
-
- if (!XMLUtils.elementIsInSignatureSpace(element,
- Constants._TAG_X509DATA)) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I can't");
-
- return false;
- }
-
- this._x509CertKeyElements = XMLUtils.selectDsNodes(element.getFirstChild(),
- Constants._TAG_X509CERTIFICATE);
-
- if ((this._x509CertKeyElements != null)
- && (this._x509CertKeyElements.length > 0)) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Yes Sir, I can");
-
- return true;
- }
-
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I can't");
-
- return false;
- }
-
- /** Field _x509certObject[] */
- XMLX509Certificate _x509certObject[] = null;
/**
* Method engineResolvePublicKey
@@ -100,11 +59,11 @@ public class X509CertificateResolver extends KeyResolverSpi {
*
* @throws KeyResolverException
*/
- public PublicKey engineResolvePublicKey(
+ public PublicKey engineLookupAndResolvePublicKey(
Element element, String BaseURI, StorageResolver storage)
throws KeyResolverException {
- X509Certificate cert = this.engineResolveX509Certificate(element,
+ X509Certificate cert = this.engineLookupResolveX509Certificate(element,
BaseURI, storage);
if (cert != null) {
@@ -123,43 +82,33 @@ public class X509CertificateResolver extends KeyResolverSpi {
*
* @throws KeyResolverException
*/
- public X509Certificate engineResolveX509Certificate(
+ public X509Certificate engineLookupResolveX509Certificate(
Element element, String BaseURI, StorageResolver storage)
throws KeyResolverException {
try {
- if ((this._x509CertKeyElements == null)
- || (this._x509CertKeyElements.length == 0)) {
- boolean weCanResolve = this.engineCanResolve(element, BaseURI,
- storage);
-
- if (!weCanResolve || (this._x509CertKeyElements == null)
- || (this._x509CertKeyElements.length == 0)) {
- return null;
- }
+ Element[] els=XMLUtils.selectDsNodes(element.getFirstChild(),
+ Constants._TAG_X509CERTIFICATE);
+ if ((els == null) || (els.length == 0)) {
+ Element el=XMLUtils.selectDsNode(element.getFirstChild(),
+ Constants._TAG_X509DATA,0);
+ if (el!=null) {
+ return engineLookupResolveX509Certificate(el, BaseURI, storage);
+ }
+ return null;
}
- this._x509certObject =
- new XMLX509Certificate[this._x509CertKeyElements.length];
-
// populate Object array
- for (int i = 0; i < this._x509CertKeyElements.length; i++) {
- this._x509certObject[i] =
- new XMLX509Certificate(this._x509CertKeyElements[i]
- , BaseURI);
- }
-
- for (int i = 0; i < this._x509certObject.length; i++) {
- X509Certificate cert = this._x509certObject[i].getX509Certificate();
-
- if (cert != null) {
- return cert;
+ for (int i = 0; i < els.length; i++) {
+ XMLX509Certificate xmlCert=new XMLX509Certificate(els[i], BaseURI);
+ X509Certificate cert = xmlCert.getX509Certificate();
+ if (cert!=null) {
+ return cert;
}
}
-
return null;
} catch (XMLSecurityException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
+ log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
throw new KeyResolverException("generic.EmptyMessage", ex);
}
@@ -173,7 +122,7 @@ public class X509CertificateResolver extends KeyResolverSpi {
* @param storage
*
*/
- public javax.crypto.SecretKey engineResolveSecretKey(
+ public javax.crypto.SecretKey engineLookupAndResolveSecretKey(
Element element, String BaseURI, StorageResolver storage)
{
return null;
diff --git a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509IssuerSerialResolver.java b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509IssuerSerialResolver.java
index c4e824747ba198707875933156e282f6cbb0aa77..8f717e716897187aaaa2828bb5d6bca6d0ba76de 100644
--- a/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509IssuerSerialResolver.java
+++ b/src/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/X509IssuerSerialResolver.java
@@ -2,7 +2,6 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
@@ -39,7 +38,7 @@ import org.w3c.dom.Element;
/**
*
- * @author $Author: raul $
+ * @author $Author: mullan $
*/
public class X509IssuerSerialResolver extends KeyResolverSpi {
@@ -48,44 +47,13 @@ public class X509IssuerSerialResolver extends KeyResolverSpi {
java.util.logging.Logger.getLogger(
X509IssuerSerialResolver.class.getName());
- /** @inheritDoc */
- public boolean engineCanResolve(Element element, String BaseURI,
- StorageResolver storage) {
- if (true)
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Can I resolve " + element.getTagName() + "?");
-
- X509Data x509data = null;
- try {
- x509data = new X509Data(element, BaseURI);
- } catch (XMLSignatureException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I can't");
-
- return false;
- } catch (XMLSecurityException ex) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I can't");
-
- return false;
- }
-
- if (x509data == null) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I can't");
- return false;
- }
-
- if (x509data.containsIssuerSerial()) {
- return true;
- }
-
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I can't");
- return false;
- }
/** @inheritDoc */
- public PublicKey engineResolvePublicKey(
+ public PublicKey engineLookupAndResolvePublicKey(
Element element, String BaseURI, StorageResolver storage)
throws KeyResolverException {
- X509Certificate cert = this.engineResolveX509Certificate(element,
+ X509Certificate cert = this.engineLookupResolveX509Certificate(element,
BaseURI, storage);
if (cert != null) {
@@ -96,10 +64,31 @@ public class X509IssuerSerialResolver extends KeyResolverSpi {
}
/** @inheritDoc */
- public X509Certificate engineResolveX509Certificate(
+ public X509Certificate engineLookupResolveX509Certificate(
Element element, String BaseURI, StorageResolver storage)
throws KeyResolverException {
-
+ if (log.isLoggable(java.util.logging.Level.FINE))
+ log.log(java.util.logging.Level.FINE, "Can I resolve " + element.getTagName() + "?");
+
+ X509Data x509data = null;
+ try {
+ x509data = new X509Data(element, BaseURI);
+ } catch (XMLSignatureException ex) {
+ log.log(java.util.logging.Level.FINE, "I can't");
+ return null;
+ } catch (XMLSecurityException ex) {
+ log.log(java.util.logging.Level.FINE, "I can't");
+ return null;
+ }
+
+ if (x509data == null) {
+ log.log(java.util.logging.Level.FINE, "I can't");
+ return null;
+ }
+
+ if (!x509data.containsIssuerSerial()) {
+ return null;
+ }
try {
if (storage == null) {
Object exArgs[] = { Constants._TAG_X509ISSUERSERIAL };
@@ -107,53 +96,52 @@ public class X509IssuerSerialResolver extends KeyResolverSpi {
new KeyResolverException("KeyResolver.needStorageResolver",
exArgs);
- if (log.isLoggable(java.util.logging.Level.INFO)) log.log(java.util.logging.Level.INFO, "", ex);
+ log.log(java.util.logging.Level.INFO, "", ex);
throw ex;
}
- X509Data x509data = new X509Data(element, BaseURI);
int noOfISS = x509data.lengthIssuerSerial();
while (storage.hasNext()) {
X509Certificate cert = storage.next();
XMLX509IssuerSerial certSerial = new XMLX509IssuerSerial(element.getOwnerDocument(), cert);
- if (true) {
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Found Certificate Issuer: "
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "Found Certificate Issuer: "
+ certSerial.getIssuerName());
- if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Found Certificate Serial: "
+ log.log(java.util.logging.Level.FINE, "Found Certificate Serial: "
+ certSerial.getSerialNumber().toString());
}
for (int i=0; i
-
-
-
-
- {@link java.nio.channels.Channel}
- A nexus for I/O operations
- {@link java.nio.channels.ReadableByteChannel}
- Can read into a buffer
- {@link java.nio.channels.ScatteringByteChannel}
- Can read into a sequence of buffers
- {@link java.nio.channels.WritableByteChannel}
- Can write from a buffer
- {@link java.nio.channels.GatheringByteChannel}
- Can write from a sequence of buffers
- {@link java.nio.channels.ByteChannel}
- Can read/write to/from a buffer
-{@link java.nio.channels.Channels}
- Utility methods for channel/stream interoperation
-
-
-
-
- {@link java.nio.channels.FileChannel}
- Reads, writes, maps, and manipulates files
- {@link java.nio.channels.FileLock}
- A lock on a (region of a) file
-{@link java.nio.MappedByteBuffer}
- A direct byte buffer mapped to a region of a file
-
-
-
-
- {@link java.nio.channels.SelectableChannel}
- A channel that can be multiplexed
- {@link java.nio.channels.DatagramChannel}
- A channel for a {@link java.net.DatagramSocket java.net.DatagramSocket}
- {@link java.nio.channels.Pipe.SinkChannel}
- The write end of a pipe
- {@link java.nio.channels.Pipe.SourceChannel}
- The read end of a pipe
- {@link java.nio.channels.ServerSocketChannel}
- A channel for a {@link java.net.ServerSocket java.net.ServerSocket}
- {@link java.nio.channels.SocketChannel}
- A channel for a {@link java.net.Socket java.net.Socket}
- {@link java.nio.channels.Selector}
- A multiplexor of selectable channels
- {@link java.nio.channels.SelectionKey}
- A token representing the registration
of a channel
- with a selector
-{@link java.nio.channels.Pipe}
- Two channels that form a unidirectional pipe }
-with a selector. Registering a channel specifies the set of I/O operations
-that will be tested for readiness by the selector, and returns a selection key that represents the
-registration.
-
-
*
@@ -57,6 +58,23 @@ import java.security.Permission;
*
*
*
*
+ * An {@code mbeanServerName} pattern can also be empty or the single
+ * character {@code "*"}, both of which will match any {@code MBeanServer} name.
+ * *
", both of which grant access to any member.
- *
*
* className#member[objectName]
+ * mbeanServerName::className#member[objectName]
* ]
. It is terminated by a ]
character
* that is the last character in the string.className
, member
,
- * or objectName
may be omitted. If the
- * member
is omitted, the #
may be too (but
+ * mbeanServerName
, className
,
+ * member
, or objectName
may be omitted. If the
+ * mbeanServerName
is omitted, the ::
may be too (but
+ * does not have to be).
+ * If the member
is omitted, the #
may be too (but
* does not have to be). If the objectName
is omitted,
* the []
may be too (but does not have to be). It is
- * not legal to omit all three items, that is to have a name
+ * not legal to omit all four items, that is to have a name
* that is the empty string.className
, member
,
+ * mbeanServerName
, className
,
+ * member
,
* or objectName
may be the character "-
",
* which is equivalent to a null value. A null value is implied by
* any value (including another null value) but does not imply any
@@ -246,6 +267,13 @@ public class MBeanPermission extends Permission {
*/
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 actions
parameter.
*/
@@ -283,6 +311,13 @@ public class MBeanPermission extends Permission {
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 Permission {
// 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 Permission {
} 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 Permission {
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 Permission {
* 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 Permission {
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;
+ }
+ }
+
+
/**
* className#member[objectName]
" where each part is
- * optional. It must not be empty or null.mbeanServerName::className#member[objectName]
" where
+ * each part is optional. It must not be empty or null.
The actions parameter contains a comma-separated list of the * desired actions granted on the target name. It must not be * empty or null.
* - * @param name the triplet "className#member[objectName]". + * @param name the quadruplet "mbeanServerName::className#member[objectName]". * @param actions the action string. * * @exception IllegalArgumentException if thename
or
@@ -418,6 +468,12 @@ public class MBeanPermission extends Permission {
* optional. This will be the result of {@link #getName()} on the
* resultant MBeanPermission.
*
+ * 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)}. + *
+ * *The actions parameter contains a comma-separated list of the * desired actions granted on the target name. It must not be * empty or null.
@@ -439,17 +495,67 @@ public class MBeanPermission extends Permission { String member, ObjectName objectName, String actions) { + this("*",className,member,objectName,actions); + } + + /** + *Create a new MBeanPermission object with the specified target name + * (MBean Server name, class name, member, object name) and actions.
+ * + *The MBean Server name, class name, member and object name
+ * parameters define a target name of the form
+ * "mbeanServerName::className#member[objectName]
" where each
+ * part is optional. This will be the result of {@link #getName()} on the
+ * resultant MBeanPermission.
+ * If the mbeanServerName
is empty or exactly {@code "*"}, then
+ * "{@code mbeanServerName::}" is omitted in that result.
+ *
The actions parameter contains a comma-separated list of the + * desired actions granted on the target name. It must not be + * empty or null.
+ * + * @param mbeanServerName the name of the {@code MBeanServer} to which this + * permission applies. + * May be null or"-"
, 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 "-"
, 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 "-"
, 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(className, member, objectName));
- initName(className, member, objectName);
+ 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 Permission {
*
* If this object's mbeanServerName is a pattern, then p's + * mbeanServerName is matched against that pattern. An empty + * mbeanServerName is equivalent to "{@code *}". A null + * mbeanServerName is equivalent to "{@code -}".
+ *If this object's mbeanServerName is "*
" or is
+ * empty, p's mbeanServerName always matches it.
If this object's className is "*
", p's
* className always matches it. If it is "a.*
", p's
* className matches it if it begins with "a.
".
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.
+ * the methods in the {@link javax.management.MBeanServerFactory} class. * *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.ClassLoaderRepository;
* JMImplementation:type=MBeanServerDelegate
.
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.
* @@ -73,9 +77,26 @@ import javax.management.loading.ClassLoaderRepository; * *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, className
is the
+ * as detailed below.
+ * In what follows, and unless otherwise specified:
+ *
className
is the
* string returned by {@link MBeanInfo#getClassName()} for the target
- * MBean.
+ * MBean,If a security check fails, the method throws {@link * SecurityException}.
@@ -89,78 +110,86 @@ import javax.management.loading.ClassLoaderRepository; * *For the {@link #invoke invoke} method, the caller's * permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,ObjectName,String) - * MBeanPermission(className, operationName, name, "invoke")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) + * MBeanPermission(mbeanServerName, className, operationName, name, "invoke")}. + * * *For the {@link #getAttribute getAttribute} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,ObjectName,String) - * MBeanPermission(className, attribute, name, "getAttribute")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) + * MBeanPermission(mbeanServerName, className, attribute, name, + * "getAttribute")}. * *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 a in the {@link * AttributeList}, if the caller's permissions do not imply {@link - * MBeanPermission#MBeanPermission(String,String,ObjectName,String) - * MBeanPermission(className, a, name, "getAttribute")}, the + * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) + * MBeanPermission(mbeanServerName, className, a, name, + * "getAttribute")}, the * MBean server will behave as if that attribute had not been in the * supplied list.
* *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
* attrName
is {@link Attribute#getName()
* attribute.getName()}.
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 a in the {@link * AttributeList}, if the caller's permissions do not imply {@link - * MBeanPermission#MBeanPermission(String,String,ObjectName,String) - * MBeanPermission(className, a, name, "setAttribute")}, the + * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) + * MBeanPermission(mbeanServerName, className, a, name, + * "setAttribute")}, the * MBean server will behave as if that attribute had not been in the * supplied list.
* *For the addNotificationListener
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")}.
For the removeNotificationListener
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")}.
For the {@link #getMBeanInfo getMBeanInfo} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,ObjectName,String) - * MBeanPermission(className, null, name, "getMBeanInfo")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) + * MBeanPermission(mbeanServerName, className, null, name, "getMBeanInfo")}. + * * *For the {@link #getObjectInstance getObjectInstance} method, * the caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,ObjectName,String) - * MBeanPermission(className, null, name, "getObjectInstance")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) + * MBeanPermission(mbeanServerName, className, null, name, + * "getObjectInstance")}. * *For the {@link #isInstanceOf isInstanceOf} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,ObjectName,String) - * MBeanPermission(className, null, name, "isInstanceOf")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) + * MBeanPermission(mbeanServerName, className, null, name, "isInstanceOf")}. + * * *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 name
,
* 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.
Certain query elements perform operations on the MBean server. @@ -179,10 +208,10 @@ import javax.management.loading.ClassLoaderRepository; * *
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 d 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 d in the returned array, if the + * caller's permissions do not imply {@link * MBeanPermission#MBeanPermission(String,String,ObjectName,String) * MBeanPermission(null, null, new ObjectName("d:x=x"), * "getDomains")}, the domain is eliminated from the array. Here, @@ -191,21 +220,22 @@ import javax.management.loading.ClassLoaderRepository; * *
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")}.
* *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")}.
* *For the {@link #getClassLoaderRepository * getClassLoaderRepository} method, the caller's permissions must * imply {@link - * MBeanPermission#MBeanPermission(String,String,ObjectName,String) - * MBeanPermission(null, null, null, "getClassLoaderRepository")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) + * MBeanPermission(mbeanServerName, null, null, null, + * "getClassLoaderRepository")}. * *For the deprecated deserialize
methods, the
* required permissions are the same as for the methods that replace
@@ -213,15 +243,15 @@ import javax.management.loading.ClassLoaderRepository;
*
*
For the instantiate
methods, the caller's
* permissions must imply {@link
- * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
- * MBeanPermission(className, null, null, "instantiate")}.
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
- * className
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")}.
*
*
If the MBeanPermission
check succeeds, the MBean's
* class is validated by checking that its {@link
@@ -241,8 +271,9 @@ import javax.management.loading.ClassLoaderRepository;
*
*
For the {@link #unregisterMBean unregisterMBean} method, * the caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,ObjectName,String) - * MBeanPermission(className, null, name, "unregisterMBean")}.
+ * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) + * MBeanPermission(mbeanServerName, className, null, name, "unregisterMBean")}. + * * * * @@ -264,6 +295,8 @@ public interface MBeanServer extends MBeanServerConnection { * is sent as described above. * * @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 MBeanServerConnection { * is sent as described above. * * @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 MBeanServerConnection { * is sent as described above. * * @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 MBeanServerConnection { * is sent as described above. * * @throws RuntimeOperationsException {@inheritDoc} + * @throws RuntimeMBeanException {@inheritDoc} + * @throws RuntimeErrorException {@inheritDoc} */ public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object params[], diff --git a/src/share/classes/javax/management/MBeanServerConnection.java b/src/share/classes/javax/management/MBeanServerConnection.java index 779301491542fe0818c77d2b76ee5c919f66b873..8b0dd6646ce157603eb6e8e98dd7ec2367d3093a 100644 --- a/src/share/classes/javax/management/MBeanServerConnection.java +++ b/src/share/classes/javax/management/MBeanServerConnection.java @@ -78,19 +78,19 @@ public interface MBeanServerConnection extends NotificationManager { * MBean will not be registered. * @exception RuntimeMBeanException If thepostRegister
* (MBeanRegistration
interface) method of the MBean throws a
- * RuntimeException
, the createMBean method will
+ * RuntimeException
, the createMBean
method will
* throw a RuntimeMBeanException
, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the createMBean method
+ * registered even though the createMBean
method
* threw an exception. Note that RuntimeMBeanException
can
* also be thrown by preRegister
, in which case the MBean
* will not be registered.
* @exception RuntimeErrorException If the postRegister
* (MBeanRegistration
interface) method of the MBean throws an
- * Error
, the createMBean method will
+ * Error
, the createMBean
method will
* throw a RuntimeErrorException
, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the createMBean method
+ * registered even though the createMBean
method
* threw an exception. Note that RuntimeErrorException
can
* also be thrown by preRegister
, in which case the MBean
* will not be registered.
@@ -150,19 +150,19 @@ public interface MBeanServerConnection extends NotificationManager {
* MBean will not be registered.
* @exception RuntimeMBeanException If the postRegister
* (MBeanRegistration
interface) method of the MBean throws a
- * RuntimeException
, the createMBean method will
+ * RuntimeException
, the createMBean
method will
* throw a RuntimeMBeanException
, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the createMBean method
+ * registered even though the createMBean
method
* threw an exception. Note that RuntimeMBeanException
can
* also be thrown by preRegister
, in which case the MBean
* will not be registered.
* @exception RuntimeErrorException If the postRegister
* (MBeanRegistration
interface) method of the MBean throws an
- * Error
, the createMBean method will
+ * Error
, the createMBean
method will
* throw a RuntimeErrorException
, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the createMBean method
+ * registered even though the createMBean
method
* threw an exception. Note that RuntimeErrorException
can
* also be thrown by preRegister
, in which case the MBean
* will not be registered.
@@ -225,19 +225,19 @@ public interface MBeanServerConnection extends NotificationManager {
* MBean will not be registered.
* @exception RuntimeMBeanException If the postRegister
* (MBeanRegistration
interface) method of the MBean throws a
- * RuntimeException
, the createMBean method will
+ * RuntimeException
, the createMBean
method will
* throw a RuntimeMBeanException
, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the createMBean method
+ * registered even though the createMBean
method
* threw an exception. Note that RuntimeMBeanException
can
* also be thrown by preRegister
, in which case the MBean
* will not be registered.
* @exception RuntimeErrorException If the postRegister
* (MBeanRegistration
interface) method of the MBean throws an
- * Error
, the createMBean method will
+ * Error
, the createMBean
method will
* throw a RuntimeErrorException
, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the createMBean method
+ * registered even though the createMBean
method
* threw an exception. Note that RuntimeErrorException
can
* also be thrown by preRegister
, in which case the MBean
* will not be registered.
@@ -297,19 +297,19 @@ public interface MBeanServerConnection extends NotificationManager {
* MBean will not be registered.
* @exception RuntimeMBeanException If the postRegister
* (MBeanRegistration
interface) method of the MBean throws a
- * RuntimeException
, the createMBean method will
+ * RuntimeException
, the createMBean
method will
* throw a RuntimeMBeanException
, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the createMBean method
+ * registered even though the createMBean
method
* threw an exception. Note that RuntimeMBeanException
can
* also be thrown by preRegister
, in which case the MBean
* will not be registered.
* @exception RuntimeErrorException If the postRegister
method
* (MBeanRegistration
interface) method of the MBean throws an
- * Error
, the createMBean method will
+ * Error
, the createMBean
method will
* throw a RuntimeErrorException
, although the MBean creation
* and registration succeeded. In such a case, the MBean will be actually
- * registered even though the createMBean method
+ * registered even though the createMBean
method
* threw an exception. Note that RuntimeErrorException
can
* also be thrown by preRegister
, in which case the MBean
* will not be registered.
@@ -351,19 +351,19 @@ public interface MBeanServerConnection extends NotificationManager {
* has thrown an exception.
* @exception RuntimeMBeanException If the postDeregister
* (MBeanRegistration
interface) method of the MBean throws a
- * RuntimeException
, the unregisterMBean method
+ * RuntimeException
, the unregisterMBean
method
* will throw a RuntimeMBeanException
, although the MBean
* unregistration succeeded. In such a case, the MBean will be actually
- * unregistered even though the unregisterMBean method
+ * unregistered even though the unregisterMBean
method
* threw an exception. Note that RuntimeMBeanException
can
* also be thrown by preDeregister
, in which case the MBean
* will remain registered.
* @exception RuntimeErrorException If the postDeregister
* (MBeanRegistration
interface) method of the MBean throws an
- * Error
, the unregisterMBean method will
+ * Error
, the unregisterMBean
method will
* throw a RuntimeErrorException
, although the MBean
* unregistration succeeded. In such a case, the MBean will be actually
- * unregistered even though the unregisterMBean method
+ * unregistered even though the unregisterMBean
method
* threw an exception. Note that RuntimeMBeanException
can
* also be thrown by preDeregister
, in which case the MBean
* will remain registered.
diff --git a/src/share/classes/javax/management/MBeanServerDelegate.java b/src/share/classes/javax/management/MBeanServerDelegate.java
index 4ee9766306b4b0e2aa86f95e1999d3d19ddb8c00..00b82a92ff827575263abf885ce98b4cd175ba39 100644
--- a/src/share/classes/javax/management/MBeanServerDelegate.java
+++ b/src/share/classes/javax/management/MBeanServerDelegate.java
@@ -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 implements MBeanServerDelegateMBean,
/** 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 implements MBeanServerDelegateMBean,
public MBeanServerDelegate () {
stamp = getStamp();
broadcaster = new NotificationBroadcasterSupport() ;
+ mbeanServerName=null;
}
@@ -82,13 +86,102 @@ public class MBeanServerDelegate implements MBeanServerDelegateMBean,
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:
+ * {@code mbeanServerId: ;mbeanServerName=}
+ * The characters {@code ':'} (colon), {@code ';'} (semicolon ),
+ * {@code '*'} (star) and {@code '?'} (question mark) are not legal in an
+ * MBean Server name.
+ * 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:
+ *
+ *
+ * "myhost_1213353064145;mbeanServerName=com.mycompany.myapp.server1"
+ *
+ * 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.
+ *
+ * @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.
+ }
+
/**
* Returns the full name of the JMX specification implemented
* by this product.
@@ -210,15 +303,8 @@ public class MBeanServerDelegate implements MBeanServerDelegateMBean,
*
* @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 =
+ ObjectName.valueOf("JMImplementation:type=MBeanServerDelegate");
/* Return a timestamp that is monotonically increasing even if
System.currentTimeMillis() isn't (for example, if you call this
diff --git a/src/share/classes/javax/management/MBeanServerFactory.java b/src/share/classes/javax/management/MBeanServerFactory.java
index 743ca3a1827da1b86538cf166c960d85747990d2..7657af1080e6872f2d9d79125766754fb69a908e 100644
--- a/src/share/classes/javax/management/MBeanServerFactory.java
+++ b/src/share/classes/javax/management/MBeanServerFactory.java
@@ -25,16 +25,19 @@
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;
+
/**
* Provides MBean server references. There are no instances of
* this class.
@@ -80,10 +83,53 @@ import javax.management.loading.ClassLoaderRepository;
* returned by the default MBeanServerBuilder implementation, for the purpose
* of e.g. adding an additional security layer.
*
+ * 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:
+ * - {@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)}.
+ * - {@link #newNamedMBeanServer
+ * newNamedMBeanServer(mbeanServerName, defaultDomain)}:
+ * creates a named MBeanServer without keeping any internal reference to the
+ * named server.
+ *
+ * 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.
+ * The name of the MBeanServer is particularly useful when
+ * MBean permissions 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".
+ * 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.
+ *
* @since 1.5
*/
public class MBeanServerFactory {
+ /**
+ * The MBean Server name that will be
+ * checked by a permission you need
+ * 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
* default public constructor.
@@ -222,13 +268,78 @@ public class MBeanServerFactory {
* javax.management.builder.initial
exists and can be
* instantiated but is not assignment compatible with {@link
* MBeanServerBuilder}.
+ *
+ * @see #createNamedMBeanServer
*/
public static MBeanServer createMBeanServer(String domain) {
- checkPermission("createMBeanServer");
+ return createMBeanServer(null,domain);
+ }
- final MBeanServer mBeanServer = newMBeanServer(domain);
- addMBeanServer(mBeanServer);
- return mBeanServer;
+ /**
+ * Return a new object implementing the {@link MBeanServer}
+ * interface with the specified
+ * MBean Server name
+ * and default domain name. The given MBean server name
+ * is used in security checks, 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.
+ *
+ * The MBeanServer reference is internally kept. This will
+ * allow findMBeanServer
to return a reference to
+ * this MBeanServer object.
+ *
+ * @param mbeanServerName the name for the created
+ * MBeanServer. This is the name that will be included in the
+ * {@linkplain MBeanPermission permission you need} when checking
+ * MBean Permissions for accessing
+ * an MBean registered in the returned MBeanServer. The characters
+ * {@code ':'} (colon), {@code ';'} (semicolon), {@code '*'} (star)
+ * and {@code '?'} are not legal.
+ * It is recommended that the {@code mbeanServerName}
+ * be unique in the context of a JVM, and in the form of a java package
+ * identifier. If {@code mbeanServerName} is {@code null} then the created
+ * MBean Server has no name - and {@value #DEFAULT_MBEANSERVER_NAME} is used.
+ * Calling {@code createNamedMBeanServer(null,domain)} is equivalent
+ * to calling {@link #createMBeanServer(String) createMBeanServer(domain)}.
+ *
+ * @param domain the default domain name for the created
+ * MBeanServer. This is the value that will be returned by {@link
+ * MBeanServer#getDefaultDomain}. If a non null mbeanServerName is given,
+ * it is recommended to pass the same value as default domain.
+ *
+ * @return the newly created MBeanServer.
+ *
+ * @exception SecurityException if there is a SecurityManager and
+ * the caller's permissions do not include or imply {@link
+ * MBeanServerPermission}("createMBeanServer")
.
+ *
+ * @exception JMRuntimeException if the property
+ * javax.management.builder.initial
exists but the
+ * class it names cannot be instantiated through a public
+ * no-argument constructor; or if the instantiated builder returns
+ * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
+ * newMBeanServerDelegate} or {@link
+ * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
+ *
+ * @exception ClassCastException if the property
+ * javax.management.builder.initial
exists and can be
+ * instantiated but is not assignment compatible with {@link
+ * MBeanServerBuilder}.
+ *
+ * @exception IllegalArgumentException if the specified
+ * {@code mbeanServerName} is empty, or is {@code "-"}, or contains a
+ * character which is not legal.
+ *
+ * @exception UnsupportedOperationException if the specified
+ * {@code mbeanServerName} cannot be set.
+ *
+ * @since 1.7
+ */
+ public static MBeanServer createNamedMBeanServer(String mbeanServerName,
+ String domain) {
+ return createMBeanServer(mbeanServerName, domain);
}
/**
@@ -307,6 +418,88 @@ public class MBeanServerFactory {
* MBeanServerBuilder}.
*/
public static MBeanServer newMBeanServer(String domain) {
+ return newMBeanServer(null,domain);
+ }
+
+ /**
+ * Return a new object implementing the MBeanServer interface
+ * with the specified MBean server name
+ * and default domain name, without keeping an
+ * internal reference to this new object. The given MBean server name
+ * is used in security checks.
+ * 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.
+ *
+ * No reference is kept. findMBeanServer
and
+ * findMBeanServerByName
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.
+ *
+ * @param mbeanServerName the name for the created
+ * MBeanServer. This is the name that will be included in the
+ * {@linkplain MBeanPermission permission you need} when checking
+ * MBean Permissions for accessing
+ * an MBean registered in the returned MBeanServer. The characters
+ * {@code ':'} (colon), {@code ';'} (semicolon), {@code '*'} (star)
+ * and {@code '?'} are not legal.
+ * It is recommended that the mbeanServerName
+ * be unique in the context of a JVM, and in the form of a java package
+ * identifier. If {@code mbeanServerName} is {@code null} then the created
+ * MBean Server has no name - and {@value #DEFAULT_MBEANSERVER_NAME} is used.
+ * Calling {@code newNamedMBeanServer(null,domain)} is equivalent
+ * to calling {@link #newMBeanServer(String) newMBeanServer(domain)}.
+ *
+ * @param domain the default domain name for the created
+ * MBeanServer. This is the value that will be returned by {@link
+ * MBeanServer#getDefaultDomain}.
+ *
+ * @return the newly created MBeanServer.
+ *
+ * @exception SecurityException if there is a SecurityManager and the
+ * caller's permissions do not include or imply {@link
+ * MBeanServerPermission}("newMBeanServer")
.
+ *
+ * @exception JMRuntimeException if the property
+ * javax.management.builder.initial
exists but the
+ * class it names cannot be instantiated through a public
+ * no-argument constructor; or if the instantiated builder returns
+ * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
+ * newMBeanServerDelegate} or {@link
+ * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
+ *
+ * @exception ClassCastException if the property
+ * javax.management.builder.initial
exists and can be
+ * instantiated but is not assignment compatible with {@link
+ * MBeanServerBuilder}.
+ *
+ * @exception IllegalArgumentException if the specified
+ * {@code mbeanServerName} is empty, or is {@code "-"},
+ * or contains a character which is not legal.
+ *
+ * @exception UnsupportedOperationException if the specified
+ * {@code mbeanServerName} cannot be set.
+ *
+ * @since 1.7
+ */
+ public static MBeanServer newNamedMBeanServer(String mbeanServerName,
+ String domain) {
+ return newMBeanServer(mbeanServerName, domain);
+ }
+
+ private static MBeanServer createMBeanServer(String mbeanServerName,
+ String domain) {
+ checkPermission("createMBeanServer");
+
+ final MBeanServer mBeanServer =
+ newMBeanServer(mbeanServerName,domain);
+ addMBeanServer(mBeanServer);
+ return mBeanServer;
+ }
+
+ private static MBeanServer newMBeanServer(String mbeanServerName,
+ String domain) {
checkPermission("newMBeanServer");
// Get the builder. Creates a new one if necessary.
@@ -316,20 +509,50 @@ public class MBeanServerFactory {
synchronized(mbsBuilder) {
final MBeanServerDelegate delegate =
- mbsBuilder.newMBeanServerDelegate();
+ mbsBuilder.newMBeanServerDelegate();
if (delegate == null) {
final String msg =
- "MBeanServerBuilder.newMBeanServerDelegate() " +
- "returned null";
+ "MBeanServerBuilder.newMBeanServerDelegate() " +
+ "returned null";
throw new JMRuntimeException(msg);
}
+
+ // 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...
+ //
+ if (!Util.isMBeanServerNameUndefined(mbeanServerName)) {
+ delegate.setMBeanServerName(mbeanServerName);
+ }
+
final MBeanServer mbeanServer =
- mbsBuilder.newMBeanServer(domain,null,delegate);
+ mbsBuilder.newMBeanServer(domain,null,delegate);
if (mbeanServer == null) {
final String msg =
- "MBeanServerBuilder.newMBeanServer() returned null";
+ "MBeanServerBuilder.newMBeanServer() returned null";
throw new JMRuntimeException(msg);
}
+
+ // double check that the MBeanServer name is correctly set.
+ // "*" might mean that the caller doesn't have the permission
+ // to see the MBeanServer name.
+ //
+ final String mbsName = Util.getMBeanServerSecurityName(mbeanServer);
+ if (!mbsName.equals(Util.checkServerName(mbeanServerName))
+ && !mbsName.equals("*")) {
+ throw new UnsupportedOperationException(
+ "can't create MBeanServer with name \""+
+ mbeanServerName+"\" using "+
+ builder.getClass().getName());
+ }
+
return mbeanServer;
}
}
@@ -363,16 +586,107 @@ public class MBeanServerFactory {
ArrayList result = new ArrayList();
for (MBeanServer mbs : mBeanServerList) {
- String name = mBeanServerName(mbs);
+ String name = mBeanServerId(mbs);
if (agentId.equals(name))
result.add(mbs);
}
return result;
}
+ /**
+ * Returns a list of registered MBeanServer objects with the given name. A
+ * registered MBeanServer object is one that was created by one of
+ * the createMBeanServer
or createNamedMBeanServer
+ * methods and not subsequently released with releaseMBeanServer
.
+ * See the section about MBean Server names
+ * above.
+ *
+ * @param mbeanServerName The name of the MBeanServer to
+ * retrieve. If this parameter is null, all registered MBeanServers
+ * in this JVM are returned.
+ * Otherwise, only those MBeanServers that have a name
+ * matching mbeanServerName
are returned: this
+ * parameter can be a pattern, where {@code '*'} matches any
+ * sequence of characters and {@code '?'} matches any character.
+ * The name of an MBeanServer, if specified, is embedded in the
+ * MBeanServerId
attribute of its delegate MBean:
+ * this method will parse the MBeanServerId
to get the
+ * MBeanServer name. If this parameter is equal to {@code "*"} then
+ * all registered MBeanServers in this JVM are returned, whether they have
+ * a name or not: {@code findMBeanServerByName(null)},
+ * {@code findMBeanServerByName("*")} and {@code findMBeanServer(null)},
+ * are equivalent. It is also possible to get all MBeanServers for which
+ * no name was specified by calling findMBeanServerByName({@value
+ * #DEFAULT_MBEANSERVER_NAME})
.
+ *
+ * @return A list of MBeanServer objects.
+ *
+ * @exception SecurityException if there is a SecurityManager and the
+ * caller's permissions do not include or imply {@link
+ * MBeanServerPermission}("findMBeanServer")
.
+ *
+ * @see #getMBeanServerName(MBeanServer)
+ * @since 1.7
+ */
+ public synchronized static
+ List findMBeanServerByName(String mbeanServerName) {
+
+ checkPermission("findMBeanServer");
+
+ if (mbeanServerName==null || "*".equals(mbeanServerName))
+ return new ArrayList(mBeanServerList);
+
+ // noname=true iff we are looking for MBeanServers for which no name
+ // were specified.
+ ArrayList result = new ArrayList();
+ for (MBeanServer mbs : mBeanServerList) {
+ final String name = Util.getMBeanServerSecurityName(mbs);
+ if (Util.wildmatch(name, mbeanServerName)) result.add(mbs);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the name of the MBeanServer embedded in the MBeanServerId of
+ * the given {@code server}. If the given MBeanServerId doesn't contain
+ * any name, {@value #DEFAULT_MBEANSERVER_NAME} is returned.
+ * The MBeanServerId is expected to be of the form:
+ * {@code *[;mbeanServerName=[;*]]}
+ *
where {@code *} denotes any sequence of characters, and {@code [ ]}
+ * indicate optional parts.
+ *
+ * For instance, if an MBeanServer is created using {@link
+ * #createNamedMBeanServer(java.lang.String, java.lang.String)
+ * server =
+ * MBeanServerFactory.createNamedMBeanServer("com.mycompany.myapp.server1",
+ * null)} then {@code MBeanServerFactory.getMBeanServerName(server)}
+ * will return {@code "com.mycompany.myapp.server1"} and
+ * server.getAttribute({@link
+ * javax.management.MBeanServerDelegate#DELEGATE_NAME
+ * MBeanServerDelegate.DELEGATE_NAME}, "MBeanServerId")
will return
+ * something like
+ * {@code "myhost_1213353064145;mbeanServerName=com.mycompany.myapp.server1"}.
+ *
+ * See the section about MBean Server names
+ * above.
+ * @param server A named (or unnamed) MBeanServer.
+ * @return the name of the MBeanServer if found, or
+ * {@value #DEFAULT_MBEANSERVER_NAME} if no name is
+ * present in its MBeanServerId, or "*" if its
+ * MBeanServerId couldn't be obtained. Returning "*" means that
+ * only {@link MBeanPermission}s that allow all MBean Server names
+ * will apply to this MBean Server.
+ * @see MBeanServerDelegate
+ * @since 1.7
+ */
+ public static String getMBeanServerName(MBeanServer server) {
+ return Util.getMBeanServerSecurityName(server);
+ }
+
/**
* Return the ClassLoaderRepository used by the given MBeanServer.
- * This method is equivalent to {@link MBeanServer#getClassLoaderRepository() server.getClassLoaderRepository()}.
+ * This method is equivalent to {@link
+ * MBeanServer#getClassLoaderRepository() server.getClassLoaderRepository()}.
* @param server The MBeanServer under examination. Since JMX 1.2,
* if server
is null
, the result is a
* {@link NullPointerException}. This behavior differs from what
@@ -387,21 +701,23 @@ public class MBeanServerFactory {
*
**/
public static ClassLoaderRepository getClassLoaderRepository(
- MBeanServer server) {
+ MBeanServer server) {
return server.getClassLoaderRepository();
}
- private static String mBeanServerName(MBeanServer mbs) {
+ private static String mBeanServerId(MBeanServer mbs) {
try {
return (String) mbs.getAttribute(MBeanServerDelegate.DELEGATE_NAME,
- "MBeanServerId");
+ "MBeanServerId");
} catch (JMException e) {
+ JmxProperties.MISC_LOGGER.finest(
+ "Ignoring exception while getting MBeanServerId: "+e);
return null;
}
}
private static void checkPermission(String action)
- throws SecurityException {
+ throws SecurityException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
Permission perm = new MBeanServerPermission(action);
@@ -425,16 +741,16 @@ public class MBeanServerFactory {
}
private static final ArrayList mBeanServerList =
- new ArrayList();
+ new ArrayList();
/**
* Load the builder class through the context class loader.
* @param builderClassName The name of the builder class.
**/
private static Class loadBuilderClass(String builderClassName)
- throws ClassNotFoundException {
+ throws ClassNotFoundException {
final ClassLoader loader =
- Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().getContextClassLoader();
if (loader != null) {
// Try with context class loader
@@ -453,14 +769,14 @@ public class MBeanServerFactory {
**/
private static MBeanServerBuilder newBuilder(Class builderClass) {
try {
- final Object builder = builderClass.newInstance();
- return (MBeanServerBuilder)builder;
+ final Object abuilder = builderClass.newInstance();
+ return (MBeanServerBuilder)abuilder;
} catch (RuntimeException x) {
throw x;
} catch (Exception x) {
final String msg =
- "Failed to instantiate a MBeanServerBuilder from " +
- builderClass + ": " + x;
+ "Failed to instantiate a MBeanServerBuilder from " +
+ builderClass + ": " + x;
throw new JMRuntimeException(msg, x);
}
}
@@ -472,7 +788,7 @@ public class MBeanServerFactory {
private static synchronized void checkMBeanServerBuilder() {
try {
GetPropertyAction act =
- new GetPropertyAction(JMX_INITIAL_BUILDER);
+ new GetPropertyAction(JMX_INITIAL_BUILDER);
String builderClassName = AccessController.doPrivileged(act);
try {
@@ -493,8 +809,8 @@ public class MBeanServerFactory {
builder = newBuilder(newBuilderClass);
} catch (ClassNotFoundException x) {
final String msg =
- "Failed to load MBeanServerBuilder class " +
- builderClassName + ": " + x;
+ "Failed to load MBeanServerBuilder class " +
+ builderClassName + ": " + x;
throw new JMRuntimeException(msg, x);
}
} catch (RuntimeException x) {
diff --git a/src/share/classes/javax/management/MXBean.java b/src/share/classes/javax/management/MXBean.java
index 1773328ddc41241501e0331df64443a7bf42606a..f6691ccaeae6947d30cb34b9fa561f8be79a1368 100644
--- a/src/share/classes/javax/management/MXBean.java
+++ b/src/share/classes/javax/management/MXBean.java
@@ -469,8 +469,8 @@ public class MemoryPool
J, then J cannot be the type of a method
parameter or return value in an MXBean interface.
- If there is a way to convert opendata(J) back to
- J then we say that J is
+
If there is a way to convert
+ opendata(J) back to J then we say that J is
reconstructible. All method parameters in an MXBean
interface must be reconstructible, because when the MXBean
framework is invoking a method it will need to convert those
diff --git a/src/share/classes/javax/management/ObjectName.java b/src/share/classes/javax/management/ObjectName.java
index d06cb35eeb3f115e143ed661e0dfe3ed9349a7db..8185edc274206b2e4e49edfae73f0e47c8ebe3e9 100644
--- a/src/share/classes/javax/management/ObjectName.java
+++ b/src/share/classes/javax/management/ObjectName.java
@@ -27,6 +27,8 @@ package javax.management;
import com.sun.jmx.mbeanserver.GetPropertyAction;
import com.sun.jmx.mbeanserver.Util;
+import com.sun.jmx.namespace.serial.JMXNamespaceContext;
+
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
@@ -222,6 +224,17 @@ import java.util.Map;
@SuppressWarnings("serial") // don't complain serialVersionUID not constant
public class ObjectName implements Comparable, QueryExp {
+ /**
+ * The sequence of characters used to separate name spaces in a name space
+ * path.
+ *
+ * @see javax.management.namespace
+ * @since 1.7
+ **/
+ public static final String NAMESPACE_SEPARATOR = "//";
+ private static final int NAMESPACE_SEPARATOR_LENGTH =
+ NAMESPACE_SEPARATOR.length();
+
/**
* A structure recording property structure and
* proposing minimal services
@@ -251,16 +264,17 @@ public class ObjectName implements Comparable, QueryExp {
/**
* Returns a key string for receiver key
*/
- String getKeyString(String name) {
- return name.substring(_key_index, _key_index + _key_length);
+ String getKeyString(String name, int offset) {
+ final int start = _key_index+offset;
+ return name.substring(start, start + _key_length);
}
/**
* Returns a value string for receiver key
*/
- String getValueString(String name) {
- int in_begin = _key_index + _key_length + 1;
- int out_end = in_begin + _value_length;
+ String getValueString(String name, int offset) {
+ final int in_begin = _key_index + offset + _key_length + 1;
+ final int out_end = in_begin + _value_length;
return name.substring(in_begin, out_end);
}
}
@@ -393,6 +407,45 @@ public class ObjectName implements Comparable, QueryExp {
*/
private transient boolean _property_value_pattern = false;
+ private ObjectName(String newDomain, ObjectName aname)
+ throws MalformedObjectNameException{
+ copyToOtherDomain(newDomain,aname);
+ }
+
+ private void copyToOtherDomain(String domain, ObjectName aname)
+ throws MalformedObjectNameException {
+
+ // The domain cannot be null
+ if (domain == null)
+ throw new NullPointerException("domain cannot be null");
+
+ // The key property list cannot be null
+ if (aname == null)
+ throw new MalformedObjectNameException(
+ "key property list cannot be empty");
+
+ // checks domain validity. A side effect of this method is also to
+ // set the _domain_pattern flag.
+ if (!isDomain(domain))
+ throw new MalformedObjectNameException("Invalid domain: " + domain);
+
+ // init canonicalname
+ _domain_length = domain.length();
+
+ _canonicalName = (domain +
+ aname._canonicalName.substring(aname._domain_length)).intern();
+ _kp_array = aname._kp_array;
+ _ca_array = aname._ca_array;
+ _propertyList = aname._propertyList;
+ _property_list_pattern = aname._property_list_pattern;
+ _property_value_pattern = aname._property_value_pattern;
+ // TODO remove this hack
+ // if (toString().endsWith("//javax.management.service:type1=event_client_delegeate_mbean,type2=default")) {
+ // Thread.currentThread().dumpStack();
+ // throw new Error("************************ Gotcha!");
+ //}
+ }
+
// Instance private fields <=======================================
// Private fields <========================================
@@ -414,7 +467,7 @@ public class ObjectName implements Comparable, QueryExp {
* is null.
*/
private void construct(String name)
- throws MalformedObjectNameException, NullPointerException {
+ throws MalformedObjectNameException {
// The name cannot be null
if (name == null)
@@ -435,10 +488,10 @@ public class ObjectName implements Comparable, QueryExp {
}
// initialize parsing of the string
- char[] name_chars = name.toCharArray();
- int len = name_chars.length;
- char[] canonical_chars = new char[len]; // canonical form will be same
- // length at most
+ final char[] name_chars = name.toCharArray();
+ final int len = name_chars.length;
+ final char[] canonical_chars = new char[len]; // canonical form will
+ // be same length at most
int cname_index = 0;
int index = 0;
char c, c1;
@@ -637,10 +690,12 @@ public class ObjectName implements Comparable, QueryExp {
// we got the key and value part, prepare a property for this
if (!value_pattern) {
- prop = new Property(key_index, key_length, value_length);
+ prop = new Property(key_index-_domain_length,
+ key_length, value_length);
} else {
_property_value_pattern = true;
- prop = new PatternProperty(key_index, key_length, value_length);
+ prop = new PatternProperty(key_index-_domain_length,
+ key_length, value_length);
}
key_name = name.substring(key_index, key_index + key_length);
@@ -674,7 +729,7 @@ public class ObjectName implements Comparable, QueryExp {
* @exception NullPointerException One of the parameters is null.
*/
private void construct(String domain, Map props)
- throws MalformedObjectNameException, NullPointerException {
+ throws MalformedObjectNameException {
// The domain cannot be null
if (domain == null)
@@ -725,12 +780,12 @@ public class ObjectName implements Comparable, QueryExp {
boolean value_pattern = checkValue(value);
sb.append(value);
if (!value_pattern) {
- prop = new Property(key_index,
+ prop = new Property(key_index-_domain_length,
key.length(),
value.length());
} else {
_property_value_pattern = true;
- prop = new PatternProperty(key_index,
+ prop = new PatternProperty(key_index-_domain_length,
key.length(),
value.length());
}
@@ -810,9 +865,9 @@ public class ObjectName implements Comparable, QueryExp {
prop = _ca_array[i];
// length of prop including '=' char
prop_len = prop._key_length + prop._value_length + 1;
- System.arraycopy(specified_chars, prop._key_index,
+ System.arraycopy(specified_chars, prop._key_index+_domain_length,
canonical_chars, prop_index, prop_len);
- prop.setKeyIndex(prop_index);
+ prop.setKeyIndex(prop_index-_domain_length);
prop_index += prop_len;
if (i != last_index) {
canonical_chars[prop_index] = ',';
@@ -1016,7 +1071,7 @@ public class ObjectName implements Comparable, QueryExp {
* Check if the supplied key is a valid key.
*/
private static void checkKey(String key)
- throws MalformedObjectNameException, NullPointerException {
+ throws MalformedObjectNameException {
if (key == null) throw new
NullPointerException("Invalid key (null)");
@@ -1031,33 +1086,6 @@ public class ObjectName implements Comparable, QueryExp {
k[endKey] + "'");
}
- /*
- * Tests whether string s is matched by pattern p.
- * Supports "?", "*" each of which may be escaped with "\";
- * Not yet supported: internationalization; "\" inside brackets.
- * Wildcard matching routine by Karl Heuer. Public Domain.
- */
- private static boolean wildmatch(char[] s, char[] p, int si, int pi) {
- char c;
- final int slen = s.length;
- final int plen = p.length;
-
- while (pi < plen) { // While still string
- c = p[pi++];
- if (c == '?') {
- if (++si > slen) return false;
- } else if (c == '*') { // Wildcard
- if (pi >= plen) return true;
- do {
- if (wildmatch(s,p,si,pi)) return true;
- } while (++si < slen);
- return false;
- } else {
- if (si >= slen || c != s[si++]) return false;
- }
- }
- return (si == slen);
- }
// Category : Internal utilities <==============================
@@ -1177,15 +1205,43 @@ public class ObjectName implements Comparable, QueryExp {
cn = (String)in.readObject();
}
+ final JMXNamespaceContext ctxt =
+ JMXNamespaceContext.getDeserializationContext();
try {
- construct(cn);
+ construct(changeContext(ctxt,cn));
} catch (NullPointerException e) {
throw new InvalidObjectException(e.toString());
+ } catch (IllegalArgumentException e) {
+ throw new InvalidObjectException(e.toString());
} catch (MalformedObjectNameException e) {
throw new InvalidObjectException(e.toString());
}
}
+ private String changeContext(JMXNamespaceContext context, String nameString) {
+ final String old = context.prefixToRemove;
+ final String nw = context.prefixToAdd;
+ final int ol = old.length();
+ if (nameString.startsWith(NAMESPACE_SEPARATOR)) return nameString;
+ if (ol>0) {
+ if (!nameString.startsWith(old) ||
+ !nameString.startsWith(NAMESPACE_SEPARATOR,ol))
+ throw new IllegalArgumentException(
+ "Serialized ObjectName does not start with " + old +
+ ": " + nameString);
+ nameString = nameString.substring(ol+NAMESPACE_SEPARATOR_LENGTH);
+ }
+ if (!nw.equals("")) {
+ nameString = nw + NAMESPACE_SEPARATOR + nameString;
+ }
+ // TODO remove this hack
+ // if (nameString.endsWith("//javax.management.service:type1=event_client_delegeate_mbean,type2=default")) {
+ // System.err.println("old="+old+", nw="+nw);
+ // Thread.currentThread().dumpStack();
+ // throw new Error("************************ Gotcha!");
+ // }
+ return nameString;
+ }
/**
* Serializes an {@link ObjectName} to an {@link ObjectOutputStream}.
@@ -1248,15 +1304,22 @@ public class ObjectName implements Comparable, QueryExp {
private void writeObject(ObjectOutputStream out)
throws IOException {
+ final JMXNamespaceContext ctxt =
+ JMXNamespaceContext.getSerializationContext();
+
if (compat)
{
// Serializes this instance in the old serial form
// Read CR 6441274 before making any changes to this code
ObjectOutputStream.PutField fields = out.putFields();
- fields.put("domain", _canonicalName.substring(0, _domain_length));
+ final String domain =
+ changeContext(ctxt,_canonicalName.substring(0, _domain_length));
+ final String cn =
+ changeContext(ctxt,_canonicalName);
+ fields.put("domain", domain);
fields.put("propertyList", getKeyPropertyList());
fields.put("propertyListString", getKeyPropertyListString());
- fields.put("canonicalName", _canonicalName);
+ fields.put("canonicalName", cn);
fields.put("pattern", (_domain_pattern || _property_list_pattern));
fields.put("propertyPattern", _property_list_pattern);
out.writeFields();
@@ -1266,7 +1329,8 @@ public class ObjectName implements Comparable, QueryExp {
// Serializes this instance in the new serial form
//
out.defaultWriteObject();
- out.writeObject(getSerializedNameString());
+
+ out.writeObject(changeContext(ctxt,getSerializedNameString()));
}
}
@@ -1295,9 +1359,10 @@ public class ObjectName implements Comparable, QueryExp {
* @exception NullPointerException The name
parameter
* is null.
*
+ * @see #valueOf(String)
*/
public static ObjectName getInstance(String name)
- throws MalformedObjectNameException, NullPointerException {
+ throws MalformedObjectNameException {
return new ObjectName(name);
}
@@ -1322,10 +1387,11 @@ public class ObjectName implements Comparable, QueryExp {
* follow the rules for quoting.
* @exception NullPointerException One of the parameters is null.
*
+ * @see #valueOf(String, String, String)
*/
public static ObjectName getInstance(String domain, String key,
String value)
- throws MalformedObjectNameException, NullPointerException {
+ throws MalformedObjectNameException {
return new ObjectName(domain, key, value);
}
@@ -1353,10 +1419,11 @@ public class ObjectName implements Comparable, QueryExp {
* quoting.
* @exception NullPointerException One of the parameters is null.
*
+ * @see #valueOf(String, Hashtable)
*/
public static ObjectName getInstance(String domain,
Hashtable table)
- throws MalformedObjectNameException, NullPointerException {
+ throws MalformedObjectNameException {
return new ObjectName(domain, table);
}
@@ -1389,11 +1456,141 @@ public class ObjectName implements Comparable, QueryExp {
* @exception NullPointerException The name
is null.
*
*/
- public static ObjectName getInstance(ObjectName name)
- throws NullPointerException {
+ public static ObjectName getInstance(ObjectName name) {
if (name.getClass().equals(ObjectName.class))
return name;
- return Util.newObjectName(name.getSerializedNameString());
+ return valueOf(name.getSerializedNameString());
+ }
+
+ /**
+ * Return an instance of ObjectName that can be used anywhere
+ * an object obtained with {@link #ObjectName(String) new
+ * ObjectName(name)} can be used. The returned object may be of
+ * a subclass of ObjectName. Calling this method twice with the
+ * same parameters may return the same object or two equal but
+ * not identical objects.
+ *
+ * This method is equivalent to {@link #getInstance(String)} except that
+ * it does not throw any checked exceptions.
+ *
+ * @param name A string representation of the object name.
+ *
+ * @return an ObjectName corresponding to the given String.
+ *
+ * @exception IllegalArgumentException The string passed as a
+ * parameter does not have the right format. The {@linkplain
+ * Throwable#getCause() cause} of this exception will be a
+ * {@link MalformedObjectNameException}.
+ * @exception NullPointerException The name
parameter
+ * is null.
+ *
+ * @since 1.7
+ */
+ public static ObjectName valueOf(String name) {
+ try {
+ return getInstance(name);
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalArgumentException(e.getMessage(), e);
+ // Just plain IllegalArgumentException(e) produces an exception
+ // message "javax.management.MalformedObjectNameException: ..."
+ // which is distracting.
+ }
+ }
+
+ /**
+ * Return an instance of ObjectName that can be used anywhere
+ * an object obtained with {@link #ObjectName(String, String,
+ * String) new ObjectName(domain, key, value)} can be used. The
+ * returned object may be of a subclass of ObjectName. Calling
+ * this method twice with the same parameters may return the same
+ * object or two equal but not identical objects.
+ *
+ * This method is equivalent to {@link #getInstance(String, String,
+ * String)} except that it does not throw any checked exceptions.
+ *
+ * @param domain The domain part of the object name.
+ * @param key The attribute in the key property of the object name.
+ * @param value The value in the key property of the object name.
+ *
+ * @return an ObjectName corresponding to the given domain,
+ * key, and value.
+ *
+ * @exception IllegalArgumentException The
+ * domain
, key
, or value
+ * contains an illegal character, or value
does not
+ * follow the rules for quoting. The {@linkplain
+ * Throwable#getCause() cause} of this exception will be a
+ * {@link MalformedObjectNameException}.
+ * @exception NullPointerException One of the parameters is null.
+ *
+ * @since 1.7
+ */
+ public static ObjectName valueOf(String domain, String key, String value) {
+ try {
+ return getInstance(domain, key, value);
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalArgumentException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Return an instance of ObjectName that can be used anywhere
+ * an object obtained with {@link #ObjectName(String, Hashtable)
+ * new ObjectName(domain, table)} can be used. The returned
+ * object may be of a subclass of ObjectName. Calling this method
+ * twice with the same parameters may return the same object or
+ * two equal but not identical objects.
+ *
+ * This method is equivalent to {@link #getInstance(String, Hashtable)}
+ * except that it does not throw any checked exceptions.
+ *
+ * @param domain The domain part of the object name.
+ * @param table A hash table containing one or more key
+ * properties. The key of each entry in the table is the key of a
+ * key property in the object name. The associated value in the
+ * table is the associated value in the object name.
+ *
+ * @return an ObjectName corresponding to the given domain and
+ * key mappings.
+ *
+ * @exception IllegalArgumentException The domain
+ * contains an illegal character, or one of the keys or values in
+ * table
contains an illegal character, or one of the
+ * values in table
does not follow the rules for
+ * quoting. The {@linkplain Throwable#getCause() cause} of this exception
+ * will be a {@link MalformedObjectNameException}.
+ * @exception NullPointerException One of the parameters is null.
+ *
+ * @since 1.7
+ */
+ public static ObjectName valueOf(String domain,
+ Hashtable table) {
+ try {
+ return new ObjectName(domain, table);
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalArgumentException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Returns an {@code ObjectName} that is the same as this one but
+ * with the specified domain.
+ * This method preserves the original key order in the new instance.
+ * If the provided name has a key property pattern, it will also be
+ * preserved in the returned instance.
+ *
+ * @param newDomain The new domain for the returned instance;
+ * must not be null.
+ * @return A new {@code ObjectName} that is the same as {@code this}
+ * except the domain is {@code newDomain}.
+ * @throws NullPointerException if {@code newDomain} is null.
+ * @throws MalformedObjectNameException if the new domain is syntactically
+ * illegal.
+ * @since 1.7
+ **/
+ public final ObjectName withDomain(String newDomain)
+ throws MalformedObjectNameException {
+ return new ObjectName(newDomain, this);
}
/**
@@ -1405,9 +1602,11 @@ public class ObjectName implements Comparable, QueryExp {
* parameter does not have the right format.
* @exception NullPointerException The name
parameter
* is null.
+ *
+ * @see #valueOf(String)
*/
public ObjectName(String name)
- throws MalformedObjectNameException, NullPointerException {
+ throws MalformedObjectNameException {
construct(name);
}
@@ -1423,9 +1622,11 @@ public class ObjectName implements Comparable, QueryExp {
* contains an illegal character, or value
does not
* follow the rules for quoting.
* @exception NullPointerException One of the parameters is null.
+ *
+ * @see #valueOf(String, String, String)
*/
public ObjectName(String domain, String key, String value)
- throws MalformedObjectNameException, NullPointerException {
+ throws MalformedObjectNameException {
// If key or value are null a NullPointerException
// will be thrown by the put method in Hashtable.
//
@@ -1448,9 +1649,11 @@ public class ObjectName implements Comparable, QueryExp {
* values in table
does not follow the rules for
* quoting.
* @exception NullPointerException One of the parameters is null.
+ *
+ * @see #valueOf(String, Hashtable)
*/
public ObjectName(String domain, Hashtable table)
- throws MalformedObjectNameException, NullPointerException {
+ throws MalformedObjectNameException {
construct(domain, table);
/* The exception for when a key or value in the table is not a
String is now ClassCastException rather than
@@ -1544,13 +1747,12 @@ public class ObjectName implements Comparable, QueryExp {
*
* @since 1.6
*/
- public boolean isPropertyValuePattern(String property)
- throws NullPointerException, IllegalArgumentException {
+ public boolean isPropertyValuePattern(String property) {
if (property == null)
throw new NullPointerException("key property can't be null");
for (int i = 0; i < _ca_array.length; i++) {
Property prop = _ca_array[i];
- String key = prop.getKeyString(_canonicalName);
+ String key = prop.getKeyString(_canonicalName,_domain_length);
if (key.equals(property))
return (prop instanceof PatternProperty);
}
@@ -1606,7 +1808,7 @@ public class ObjectName implements Comparable, QueryExp {
*
* @exception NullPointerException If property
is null.
*/
- public String getKeyProperty(String property) throws NullPointerException {
+ public String getKeyProperty(String property) {
return _getKeyPropertyList().get(property);
}
@@ -1630,8 +1832,10 @@ public class ObjectName implements Comparable, QueryExp {
Property prop;
for (int i = len - 1; i >= 0; i--) {
prop = _ca_array[i];
- _propertyList.put(prop.getKeyString(_canonicalName),
- prop.getValueString(_canonicalName));
+ _propertyList.put(prop.getKeyString(_canonicalName,
+ _domain_length),
+ prop.getValueString(_canonicalName,
+ _domain_length));
}
}
}
@@ -1716,7 +1920,8 @@ public class ObjectName implements Comparable, QueryExp {
}
}
- return new String(dest_chars);
+ final String name = new String(dest_chars);
+ return name;
}
/**
@@ -1734,7 +1939,7 @@ public class ObjectName implements Comparable, QueryExp {
if (_kp_array.length == 0) return offset;
final char[] dest_chars = data;
- final char[] value = _canonicalName.toCharArray();
+ final char[] value = canonicalChars;
int index = offset;
final int len = _kp_array.length;
@@ -1742,7 +1947,7 @@ public class ObjectName implements Comparable, QueryExp {
for (int i = 0; i < len; i++) {
final Property prop = _kp_array[i];
final int prop_len = prop._key_length + prop._value_length + 1;
- System.arraycopy(value, prop._key_index, dest_chars, index,
+ System.arraycopy(value, prop._key_index+_domain_length, dest_chars, index,
prop_len);
index += prop_len;
if (i < last ) dest_chars[index++] = ',';
@@ -1816,7 +2021,7 @@ public class ObjectName implements Comparable, QueryExp {
// (because usage of intern())
ObjectName on = (ObjectName) object;
String on_string = on._canonicalName;
- if (_canonicalName == on_string) return true;
+ if (_canonicalName == on_string) return true; // ES: OK
// Because we are sharing canonical form between object names,
// we have finished the comparison at this stage ==> unequal
@@ -1862,8 +2067,7 @@ public class ObjectName implements Comparable, QueryExp {
* @exception NullPointerException if s
is null.
*
*/
- public static String quote(String s)
- throws NullPointerException {
+ public static String quote(String s) {
final StringBuilder buf = new StringBuilder("\"");
final int len = s.length();
for (int i = 0; i < len; i++) {
@@ -1907,8 +2111,7 @@ public class ObjectName implements Comparable, QueryExp {
* @exception NullPointerException if q
is null.
*
*/
- public static String unquote(String q)
- throws IllegalArgumentException, NullPointerException {
+ public static String unquote(String q) {
final StringBuilder buf = new StringBuilder();
final int len = q.length();
if (len < 2 || q.charAt(0) != '"' || q.charAt(len - 1) != '"')
@@ -1953,7 +2156,7 @@ public class ObjectName implements Comparable, QueryExp {
*
* @since 1.6
*/
- public static final ObjectName WILDCARD = Util.newObjectName("*:*");
+ public static final ObjectName WILDCARD = valueOf("*:*");
// Category : Utilities <===================================
@@ -1976,7 +2179,7 @@ public class ObjectName implements Comparable, QueryExp {
* @exception NullPointerException if name
is null.
*
*/
- public boolean apply(ObjectName name) throws NullPointerException {
+ public boolean apply(ObjectName name) {
if (name == null) throw new NullPointerException();
@@ -1997,9 +2200,9 @@ public class ObjectName implements Comparable, QueryExp {
private final boolean matchDomains(ObjectName name) {
if (_domain_pattern) {
// wildmatch domains
- final char[] dom_pattern = getDomain().toCharArray();
- final char[] dom_string = name.getDomain().toCharArray();
- return wildmatch(dom_string,dom_pattern,0,0);
+ // This ObjectName is the pattern
+ // The other ObjectName is the string.
+ return Util.wildpathmatch(name.getDomain(),getDomain());
}
return getDomain().equals(name.getDomain());
}
@@ -2025,7 +2228,7 @@ public class ObjectName implements Comparable, QueryExp {
// index in receiver
//
final Property p = props[i];
- final String k = p.getKeyString(cn);
+ final String k = p.getKeyString(cn,_domain_length);
final String v = nameProps.get(k);
// Did we find a value for this key ?
//
@@ -2034,15 +2237,13 @@ public class ObjectName implements Comparable, QueryExp {
//
if (_property_value_pattern && (p instanceof PatternProperty)) {
// wildmatch key property values
- final char[] val_pattern =
- p.getValueString(cn).toCharArray();
- final char[] val_string = v.toCharArray();
- if (wildmatch(val_string,val_pattern,0,0))
+ // p is the property pattern, v is the string
+ if (Util.wildmatch(v,p.getValueString(cn,_domain_length)))
continue;
else
return false;
}
- if (v.equals(p.getValueString(cn))) continue;
+ if (v.equals(p.getValueString(cn,_domain_length))) continue;
return false;
}
return true;
@@ -2109,6 +2310,10 @@ public class ObjectName implements Comparable, QueryExp {
* @since 1.6
*/
public int compareTo(ObjectName name) {
+ // Quick optimization:
+ //
+ if (name == this) return 0;
+
// (1) Compare domains
//
int domainValue = this.getDomain().compareTo(name.getDomain());
diff --git a/src/share/classes/javax/management/QueryNotificationFilter.java b/src/share/classes/javax/management/QueryNotificationFilter.java
index 42451088f2ede0a0ad8bc72c99472ae0e18ab0fa..7d1990fa2b9e1d703f57428aad47d37cd91fdb11 100644
--- a/src/share/classes/javax/management/QueryNotificationFilter.java
+++ b/src/share/classes/javax/management/QueryNotificationFilter.java
@@ -170,7 +170,7 @@ public class QueryNotificationFilter implements NotificationFilter {
private static final long serialVersionUID = -8408613922660635231L;
private static final ObjectName DEFAULT_NAME =
- Util.newObjectName(":type=Notification");
+ ObjectName.valueOf(":type=Notification");
private static final QueryExp trueQuery;
static {
ValueExp zero = Query.value(0);
diff --git a/src/share/classes/javax/management/event/EventClient.java b/src/share/classes/javax/management/event/EventClient.java
index 923ef90cd2f87cc6ccc351cf3fc5532e50b392ee..10a4df5004bcbbf7e09b0b96f7dd6035cb307be5 100644
--- a/src/share/classes/javax/management/event/EventClient.java
+++ b/src/share/classes/javax/management/event/EventClient.java
@@ -29,6 +29,7 @@ import com.sun.jmx.event.DaemonThreadFactory;
import com.sun.jmx.event.LeaseRenewer;
import com.sun.jmx.event.ReceiverBuffer;
import com.sun.jmx.event.RepeatedSingletonJob;
+import com.sun.jmx.namespace.JMXNamespaceUtils;
import com.sun.jmx.mbeanserver.PerThreadGroupPool;
import com.sun.jmx.remote.util.ClassLogger;
@@ -263,11 +264,12 @@ public class EventClient implements EventConsumer, NotificationManager {
new PerThreadGroupPool.Create() {
public ScheduledThreadPoolExecutor createThreadPool(ThreadGroup group) {
ThreadFactory daemonThreadFactory = new DaemonThreadFactory(
- "EventClient lease renewer %d");
+ "JMX EventClient lease renewer %d");
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(
20, daemonThreadFactory);
- exec.setKeepAliveTime(3, TimeUnit.SECONDS);
+ exec.setKeepAliveTime(1, TimeUnit.SECONDS);
exec.allowCoreThreadTimeOut(true);
+ exec.setRemoveOnCancelPolicy(true);
return exec;
}
};
@@ -1063,6 +1065,24 @@ public class EventClient implements EventConsumer, NotificationManager {
return clientId;
}
+ /**
+ * Returns a JMX Connector that will use an {@link EventClient}
+ * to subscribe for notifications. If the server doesn't have
+ * an {@link EventClientDelegateMBean}, then the connector will
+ * use the legacy notification mechanism instead.
+ *
+ * @param wrapped The underlying JMX Connector wrapped by the returned
+ * connector.
+ *
+ * @return A JMX Connector that will uses an {@link EventClient}, if
+ * available.
+ *
+ * @see EventClient#getEventClientConnection(MBeanServerConnection)
+ */
+ public static JMXConnector withEventClient(final JMXConnector wrapped) {
+ return JMXNamespaceUtils.withEventClient(wrapped);
+ }
+
private static final PerThreadGroupPool
leaseRenewerThreadPool = PerThreadGroupPool.make();
}
diff --git a/src/share/classes/javax/management/event/EventClientDelegate.java b/src/share/classes/javax/management/event/EventClientDelegate.java
index e5ce1f7be74b123c54b39c645574d53e12d1452c..cab3ff49238d5a4feeec540ec127f29a045a2bac 100644
--- a/src/share/classes/javax/management/event/EventClientDelegate.java
+++ b/src/share/classes/javax/management/event/EventClientDelegate.java
@@ -721,7 +721,10 @@ public class EventClientDelegate implements EventClientDelegateMBean {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
- ObjectInstance oi = (ObjectInstance) AccessController.doPrivileged(
+ final String serverName = getMBeanServerName();
+
+ ObjectInstance oi = (ObjectInstance)
+ AccessController.doPrivileged(
new PrivilegedExceptionAction
+ *
+ * Note: A JMXNamespace MBean cannot be registered
+ * simultaneously in two different
+ * MBean servers, or indeed in the same MBean Server with two
+ * different names. It is however possible to give the same MBeanServer
+ * instance to two different JMXNamespace MBeans, and thus create a graph
+ * rather than a tree.
+ *
+ *
+ * To view the content of a namespace, you will usually use an
+ * instance of {@link JMXNamespaceView}. For instance, given the
+ * namespace {@code "foo"} created above, you would do:
+ *
+ *
+ * final JMXNamespaceView view = new JMXNamespaceView(server);
+ * System.out.println("List of namespaces: "+Arrays.toString({@link JMXNamespaceView#list() view.list()}));
+ *
+ * final JMXNamespaceView foo = {@link JMXNamespaceView#down view.down("foo")};
+ * System.out.println({@link JMXNamespaceView#where() foo.where()}+" contains: " +
+ * {@link JMXNamespaceView#getMBeanServerConnection foo.getMBeanServerConnection()}.queryNames(null,null));
+ *
+ *
+ * JMX Namespace Permission Checks
+ *
+ * A special {@link JMXNamespacePermission} is defined to check access
+ * to MBean within namespaces.
+ * When a JMXNamespace MBean is registered in an
+ * MBean server created through the default {@link
+ * javax.management.MBeanServerBuilder}, and if a {@link
+ * SecurityManager SecurityManager} is
+ * {@linkplain System#getSecurityManager() present}, the MBeanServer will
+ * check a {@link JMXNamespacePermission} before invoking
+ * any method on the {@linkplain #getSourceServer source MBeanServer} of the
+ * JMXNamespace.
+ * {@linkplain JMXNamespacePermission JMX Namespace Permissions} are similar to
+ * {@linkplain javax.management.MBeanPermission MBean Permissions}, except
+ * that you usually cannot specify an MBean class name. You can however
+ * specify object name patterns - which will allow you for example to only grant
+ * permissions for MBeans having a specific {@code type=} key
+ * in their object name.
+ *
+ * Another difference is that {@link JMXNamespacePermission
+ * JMXNamespacePermission} also specifies from which namespace and which
+ * MBean server the permission is granted.
+ *
+ * In the rest of this document, the following terms are used:
+ *
+ * {@code server name} is the
+ * name of the
+ * MBeanServer in which the permission is granted.
+ * The name of an {@code MBeanServer} can be obtained by calling {@link
+ * javax.management.MBeanServerFactory#getMBeanServerName
+ * MBeanServerFactory.getMBeanServerName(mbeanServer)}
+ *
+ * {@code namespace} is the name of the namespace
+ * in the named MBean server for which the
+ * permission is granted. It doesn't contain any
+ * {@link JMXNamespaces#NAMESPACE_SEPARATOR namespace separator}.
+ *
+ * {@code mbean} is the name
+ * of the MBean in that {@code namespace}. This is the name of the MBean
+ * in the namespace's {@link JMXNamespace#getSourceServer() source mbean server}.
+ * It might contain no, one, or several {@link
+ * JMXNamespaces#NAMESPACE_SEPARATOR namespace separators}.
+ *
+ *
+ *
+ * For instance let's assume that some piece of code calls:
+ *
+ * final MBeanServer mbeanServer = ...;
+ * final ObjectName name = new ObjectName("a//b//c//D:k=v");
+ * mbeanServer.getAttribute(name,"Foo");
+ *
+ *
+ * Assuming that there is a security manager, or that the
+ * implementation chooses to make checks anyway, the checks that will
+ * be made in that case are:
+ *
+ *
+ * -
+ *
JMXNamespacePermission(mbeanServerName, "Foo", "a//b//c//D:k=v",
+ * "getAttribute")
+ * (where {@code mbeanServerName=MBeanServerFactory.getMBeanServerName(mbeanServer)},
+ * namespace="a"
, and {@code mbean="b//c//D:k=v"})
+ *
+ * - and in addition if namespace {@code "a"} is local,
+ *
JMXNamespacePermission(aSourceServerName,"Foo","b//c//D:k=v",
+ * "getAttribute")}
+ * (where
+ * {@code aSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(a))},
+ * namespace="b"
, and {@code mbean="c//D:k=v"}),
+ *
+ * - and in addition if namespace {@code "b"} is also local,
+ *
JMXNamespacePermission(bSourceServerName,"Foo","c//D:k=v",
+ * "getAttribute")}
+ * (where
+ * {@code bSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(b))},
+ * namespace="c"
, and {@code mbean="D:k=v"}),
+ *
+ * - and in addition if the source mbean server of namespace
+ * {@code "c"} is a also a local MBeanServer in this JVM,
+ * {@code MBeanPermission(cSourceServerName,
,"Foo","D:k=v","getAttrinute")},
+ * (where
+ * {@code cSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(c))}).
+ *
+ *
+ * For any of these MBean servers, if no name was supplied when
+ * creating that MBeanServer the {@link JMXNamespacePermission} is
+ * created with an {@code mbeanServerName} equal to
+ * {@value javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}.
+ *
+ * If the namespace {@code a} is in fact a remote {@code MBeanServer},
+ * for instance because namespace {@code a} is implemented by a {@link
+ * JMXRemoteNamespace} pointing to a distant MBeanServer located in
+ * another JMX agent, then checks 2,
+ * 3, and 4 will not
+ * be performed in the local JVM. They might or might not be performed in
+ * the remote agent, depending on how access control and permission
+ * checking are configured in the remote agent, and how authentication
+ * is configured in the connector used by the {@link
+ * JMXRemoteNamespace}.
+ *
+ * In all cases, {@linkplain JMXNamespacePermission JMX Namespace Permissions}
+ * are checked as follows:
+ * First, if there is no security manager ({@link
+ * System#getSecurityManager()} is null), then an implementation of
+ * of MBeanServer that supports JMX namespaces is free not to make any
+ * checks.
+ *
+ * Assuming that there is a security manager, or that the
+ * implementation chooses to make checks anyway, the checks are made
+ * as detailed below.
+ *
+ * If a security check fails, the method throws {@link
+ * SecurityException}.
+ *
+ *
+ *
+ * For the {@link MBeanServer#invoke invoke} method, the caller's
+ * permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, <operation name>, <namespace>//<mbean>, "invoke")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace.
+ *
+ *
+ * For the {@link MBeanServer#getAttribute getAttribute} method, the
+ * caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, <attribute>, <namespace>//<mbean>, "getAttribute")}.
+ *
+ *
+ * For the {@link MBeanServer#getAttributes getAttributes} method, the
+ * caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, <null>, <namespace>//<mbean>, "getAttribute")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace.
+ * Additionally, for each attribute att in the {@link
+ * javax.management.AttributeList}, if the caller's permissions do not
+ * imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, att,
+ * <namespace>//<mbean>, "getAttribute")}, the
+ * MBean server will behave as if that attribute had not been in the
+ * supplied list.
+ *
+ * For the {@link MBeanServer#setAttribute setAttribute} method, the
+ * caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, <attrName>, <namespace>//<mbean>, "setAttribute")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace, and
+ * attrName
is {@link javax.management.Attribute#getName()
+ * attribute.getName()}.
+ *
+ * For the {@link MBeanServer#setAttributes setAttributes} method, the
+ * caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, "setAttribute")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace.
+ * Additionally, for each attribute att in the {@link
+ * javax.management.AttributeList}, if the caller's permissions do not
+ * imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, att, <namespace>//<mbean>, "setAttribute")},
+ * the MBean server will behave as if that attribute had not been in the
+ * supplied list.
+ *
+ * For the addNotificationListener
methods,
+ * the caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
+ * "addNotificationListener")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace.
+ *
+ *
+ * For the removeNotificationListener
methods,
+ * the caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
+ * "removeNotificationListener")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace.
+ *
+ *
+ * For the {@link MBeanServer#getMBeanInfo getMBeanInfo} method, the
+ * caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
+ * "getMBeanInfo")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace.
+ *
+ *
+ * For the {@link MBeanServer#getObjectInstance getObjectInstance} method,
+ * the caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
+ * "getObjectInstance")},
+ * where mbean server name/a> is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace.
+ *
+ *
+ * For the {@link MBeanServer#isInstanceOf isInstanceOf} method, the
+ * caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
+ * "isInstanceOf")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace.
+ *
+ *
+ * For the {@link MBeanServer#queryMBeans queryMBeans} method, the
+ * caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, null,
+ * "queryMBeans")}.
+ * Additionally, for each MBean {@code mbean} that matches {@code pattern},
+ * if the caller's permissions do not imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
+ * "queryMBeans")}, the
+ * MBean server will behave as if that MBean did not exist.
+ *
+ * Certain query elements perform operations on the MBean server.
+ * However these operations are usually performed by the MBeanServer at the
+ * bottom of the namespace path, and therefore, do not involve any
+ * {@link JMXNamespacePermission} permission check. They might involve
+ * {@link javax.management.MBeanPermission} checks depending on how security
+ * in the JVM in which the bottom MBeanServer resides is implemented.
+ * See {@link javax.management.MBeanServer} for more details.
+ *
+ *
+ * For the {@link MBeanServer#queryNames queryNames} method, the checks
+ * are the same as for queryMBeans
except that
+ * "queryNames"
is used instead of
+ * "queryMBeans"
in the JMXNamespacePermission
+ * objects. Note that a "queryMBeans"
permission implies
+ * the corresponding "queryNames"
permission.
+ *
+ * For the {@link MBeanServer#getClassLoader getClassLoader} method, the
+ * caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<loaderName>,
+ * "getClassLoader")},
+ * where mbean server name/a> is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * loaderName is the name of the ClassLoader MBean
+ * which is accessed, in that namespace.
+ *
+ *
+ * For the {@link MBeanServer#getClassLoaderFor getClassLoaderFor} method,
+ * the caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
+ * "getClassLoaderFor")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which the action
+ * is performed, in that namespace.
+ *
+ *
+ * For the {@link MBeanServer#registerMBean registerMBean} method, the
+ * caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>,
+ * "registerMBean")}. Here
+ * class name
is the string returned by {@code
+ * obj.getClass().getName()} where {@code obj} is the mbean reference,
+ * is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean which is being
+ * registered, relative to that namespace.
+ *
+ *
For the createMBean
methods, the caller's
+ * permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>,
+ * "instantiate")} and
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>,
+ * "registerMBean")}, where
+ * class name
is the string passed as first argument to the {@code
+ * createMBean} method,
+ * mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean which is being
+ * created, relative to that namespace.
+ *
+ *
For the {@link MBeanServer#unregisterMBean unregisterMBean} method,
+ * the caller's permissions must imply {@link
+ * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
+ * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
+ * "unregisterMBean")},
+ * where mbean server name is the name of the
+ * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
+ * namespace is registered, and
+ * mbean is the name of the MBean on which is
+ * being unregistered, relative to that namespace.
+ *
+ *
+ *
+ * It must be noted that if all namespaces are local, and all
+ * local namespaces are implemented by regular MBean servers, that is, there
+ * are no {@linkplain MBeanServerSupport Virtual Namespaces}, then
+ * simple {@linkplain javax.management.MBeanPermission MBean Permission}
+ * checks might be enough to secure an application.
+ * In that case, it is possible to specify the following {@link
+ * JMXNamespacePermission} permission in the policy file, which implies all
+ * other JMX namespace permissions:
+ *
+ *
+ * permission javax.management.namespace.JMXNamespacePermission "*::*[]", "*";
+ *
+ *
+ * @since 1.7
+ */
+public class JMXNamespace
+ implements JMXNamespaceMBean, MBeanRegistration {
+
+ /**
+ * The standard value of the {@code type}
+ * property key that must be used to construct valid {@link
+ * JMXNamespaceMBean} ObjectNames.
+ * This is {@value #TYPE}.
+ **/
+ public static final String TYPE = "JMXNamespace";
+
+ /**
+ * The {@link ObjectName#getKeyPropertyListString keyPropertyListString}
+ * that must be used to construct valid {@link JMXNamespaceMBean}
+ * ObjectNames.
+ * This is
+ * {@value #TYPE_ASSIGNMENT}
.
+ **/
+ public static final String TYPE_ASSIGNMENT = "type="+TYPE;
+
+ private volatile MBeanServer mbeanServer; // the mbean server in which
+ // this MBean is registered.
+ private volatile ObjectName objectName; // the ObjectName of this MBean.
+ private final MBeanServer sourceServer; // the MBeanServer within = the
+ // name space (or the MBean server
+ // that contains it).
+ private final String uuid;
+
+ /**
+ * Creates a new JMXNamespace implemented by means of an MBean Server.
+ * A namespace is equivalent to an MBeanServer within an MBean Server.
+ * The {@code sourceServer} provided to this constructor is the MBean Server
+ * within.
+ * @param sourceServer the MBean server that implemented by this namespace.
+ * @see #getSourceServer
+ */
+ public JMXNamespace(MBeanServer sourceServer) {
+ this.sourceServer = sourceServer;
+ this.uuid = UUID.randomUUID().toString();
+ }
+
+ /**
+ * This method is part of the {@link MBeanRegistration} interface.
+ * The {@link JMXNamespace} class uses the {@link MBeanRegistration}
+ * interface in order to get a reference to the MBean server in which it is
+ * registered. It also checks the validity of its own ObjectName.
+ *
+ * This method is called by the MBean server.
+ * Application classes should never call this method directly.
+ *
+ * If this method is overridden, the overriding method should call
+ * {@code super.preRegister(server,name)}.
+ * @see MBeanRegistration#preRegister MBeanRegistration
+ * @see JMXNamespaces#getNamespaceObjectName getNamespaceObjectName
+ * @param name The object name of the MBean. name must be a
+ * syntactically valid JMXNamespace name, as returned by
+ * {@link JMXNamespaces#getNamespaceObjectName(java.lang.String)
+ * getNamespaceObjectName(namespace)}.
+ * @return The name under which the MBean is to be registered.
+ * @throws IllegalArgumentException if the name supplied is not valid.
+ * @throws Exception can be thrown by subclasses.
+ */
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception {
+ // need to synchronize to protect against multiple registration.
+ synchronized(this) {
+ if (objectName != null && ! objectName.equals(name))
+ throw new IllegalStateException(
+ "Already registered under another name: " + objectName);
+ objectName = validateHandlerName(name);
+ mbeanServer = server;
+ }
+ return name;
+ }
+
+ /**
+ * Validate the ObjectName supplied to preRegister.
+ * This method is introduced to allow standard subclasses to use
+ * an alternate naming scheme. For instance - if we want to
+ * reuse JMXNamespace in order to implement sessions...
+ * It is however only available for subclasses in this package.
+ **/
+ ObjectName validateHandlerName(ObjectName suppliedName) {
+ if (suppliedName == null)
+ throw new IllegalArgumentException("Must supply a valid name");
+ final String dirName = JMXNamespaces.
+ normalizeNamespaceName(suppliedName.getDomain());
+ final ObjectName handlerName =
+ JMXNamespaces.getNamespaceObjectName(dirName);
+ if (!suppliedName.equals(handlerName))
+ throw new IllegalArgumentException("invalid name space name: "+
+ suppliedName);
+ return suppliedName;
+ }
+
+ /**
+ * This method is part of the {@link MBeanRegistration} interface.
+ * The {@link JMXNamespace} class uses the {@link MBeanRegistration}
+ * interface in order to get a reference to the MBean server in which it is
+ * registered.
+ *
+ * This method is called by the MBean server. Application classes should
+ * not call this method directly. Subclasses are free to override this
+ * method with their own specific behavior - but the overriding method
+ * shoud still call {@code super.postRegister(registrationDone)}.
+ * @see MBeanRegistration#postRegister MBeanRegistration
+ */
+ public void postRegister(Boolean registrationDone) {
+ // nothing to do
+ }
+
+ /**
+ * This method is part of the {@link MBeanRegistration} interface.
+ * The {@link JMXNamespace} class uses the {@link MBeanRegistration}
+ * interface in order to get a reference to the MBean server in which it is
+ * registered.
+ *
+ * This method is called by the MBean server. Application classes should
+ * not call this method directly. Subclasses are free to override this
+ * method with their own specific behavior - but the overriding method
+ * shoud still call {@code super.preDeregister()}.
+ * @see MBeanRegistration#preDeregister MBeanRegistration
+ */
+ public void preDeregister() throws Exception {
+ // nothing to do
+ }
+
+ /**
+ * This method is part of the {@link MBeanRegistration} interface.
+ * It allows the {@code JMXNamespace} MBean to perform any operations
+ * needed after having been unregistered in the MBean server.
+ *
+ * This method is called by the MBean server. Application classes should
+ * not call this method directly. If a subclass overrides this
+ * method, the overriding method shoud call {@code super.postDeregister()}.
+ * @see MBeanRegistration#postDeregister MBeanRegistration
+ */
+ public void postDeregister() {
+ // need to synchronize to protect against multiple registration.
+ synchronized(this) {
+ mbeanServer = null;
+ objectName = null;
+ }
+ }
+
+
+ /**
+ * Returns the MBeanServer in which this MBean is registered,
+ * or null. Chiefly of interest for subclasses.
+ * @return the MBeanServer supplied to {@link #preRegister}.
+ **/
+ public final MBeanServer getMBeanServer() {
+ return mbeanServer;
+ }
+
+ /**
+ * Returns the MBeanServer that contains or emulates the source
+ * namespace. When a JMXNamespace MBean is registered in an
+ * MBean server created through the default {@link
+ * javax.management.MBeanServerBuilder}, the MBeanServer will
+ * check {@link JMXNamespacePermission} before invoking
+ * any method on the source MBeanServer of the JMXNamespace.
+ * See JMX Namespace Permission Checks
+ * above.
+ * @return an MBeanServer view of the source namespace
+ **/
+ public MBeanServer getSourceServer() {
+ return sourceServer;
+ }
+
+ /**
+ * Returns the ObjectName with which this MBean was registered,
+ * or null. Chiefly of interest for subclasses.
+ * @return the ObjectName supplied to {@link #preRegister}.
+ **/
+ public final ObjectName getObjectName() {
+ return objectName;
+ }
+
+ /**
+ * HandlerName used in traces.
+ **/
+ String getHandlerName() {
+ final ObjectName name = getObjectName();
+ if (name != null) return name.toString();
+ return this.toString();
+ }
+
+ /**
+ * In this class, this method returns {@link #getSourceServer
+ * getSourceServer()}.{@link javax.management.MBeanServer#getMBeanCount
+ * getMBeanCount()}.
+ *
This default behaviour may be redefined in subclasses.
+ * @throws java.io.IOException can be thrown by subclasses.
+ */
+ public Integer getMBeanCount() throws IOException {
+ return getSourceServer().getMBeanCount();
+ }
+
+ /**
+ * In this class, this method returns {@link #getSourceServer
+ * getSourceServer()}.{@link javax.management.MBeanServer#getDomains
+ * getDomains()}.
+ *
This default behaviour may be redefined in subclasses.
+ * @throws java.io.IOException can be thrown by subclasses.
+ */
+ public String[] getDomains() throws IOException {
+ return getSourceServer().getDomains();
+ }
+
+ /**
+ * In this class, this method returns {@link #getSourceServer
+ * getSourceServer()}.{@link javax.management.MBeanServer#getDefaultDomain
+ * getDefaultDomain()}.
+ *
This default behaviour may be redefined in subclasses.
+ * @throws java.io.IOException can be thrown by subclasses.
+ */
+ public String getDefaultDomain() throws IOException {
+ return getSourceServer().getDefaultDomain();
+ }
+
+ public final String getUUID() {
+ return uuid;
+ }
+
+}
diff --git a/src/share/classes/javax/management/namespace/JMXNamespaceMBean.java b/src/share/classes/javax/management/namespace/JMXNamespaceMBean.java
new file mode 100644
index 0000000000000000000000000000000000000000..4632b410ae756b7d7e3206a4eb42ed1c028af034
--- /dev/null
+++ b/src/share/classes/javax/management/namespace/JMXNamespaceMBean.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.management.namespace;
+
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * A {@link JMXNamespace} is an MBean that handles a name space in the
+ * MBeanServer hierarchical name space.
+ * @see JMXNamespace
+ * @since 1.7
+ */
+public interface JMXNamespaceMBean {
+
+ // Note: since getDomains(), getDefaultDomain(), and getMBeanCount()
+ // don't take any ObjectName parameters, the only efficient way
+ // to get these data is to call the corresponding method on the
+ // JMXNamespaceMBean that handles the name space.
+ //
+ // We need these methods to implement 'cd' (JMXNamespaces.narrowToNamespace)
+ // correctly.
+ //
+
+ /**
+ * Returns the list of domains currently implemented in the name space
+ * handled by this {@link JMXNamespace}.
+ * @throws IOException if the domain list cannot be obtained due to
+ * I/O problems (communication failures etc...).
+ * @return the list of domains currently implemented in the name space
+ * handled by this {@link JMXNamespace}.
+ * @see javax.management.MBeanServerConnection#getDomains
+ * MBeanServerConnection.getDomains
+ **/
+ public String[] getDomains() throws IOException;
+
+ /**
+ * Returns the default domain for the name space handled by
+ * this {@link JMXNamespace}.
+ * @throws IOException if the default domain cannot be obtained due to
+ * I/O problems (communication failures etc...).
+ * @return the default domain for the name space handled by
+ * this {@link JMXNamespace}.
+ * @see javax.management.MBeanServerConnection#getDefaultDomain
+ * MBeanServerConnection.getDefaultDomain
+ **/
+ public String getDefaultDomain() throws IOException;
+
+ /**
+ * Returns the number of MBeans registered in the name space handled by
+ * this {@link JMXNamespace}.
+ *
+ * @return the number of MBeans registered in the name space handled by
+ * this {@link JMXNamespace}.
+ *
+ * @throws IOException if the MBean count cannot be obtained due to
+ * I/O problems (communication failures etc...).
+ * @see javax.management.MBeanServerConnection#getMBeanCount
+ * MBeanServerConnection.getMBeanCount
+ */
+ public Integer getMBeanCount() throws IOException;
+
+ /**
+ * Returns a {@link java.util.UUID UUID string} which uniquely identifies
+ * this {@linkplain JMXNamespace} MBean.
+ * This information can be used to detect loops in the JMX name space graph.
+ * @return A unique ID identifying this MBean.
+ * @throws IOException if the MBean UUID cannot be obtained due to
+ * I/O problems (communication failures etc...).
+ */
+ public String getUUID() throws IOException;
+
+}
diff --git a/src/share/classes/javax/management/namespace/JMXNamespacePermission.java b/src/share/classes/javax/management/namespace/JMXNamespacePermission.java
new file mode 100644
index 0000000000000000000000000000000000000000..5dd012672b3ba2afe86057ea36c68f3fe9b8bcb0
--- /dev/null
+++ b/src/share/classes/javax/management/namespace/JMXNamespacePermission.java
@@ -0,0 +1,1474 @@
+/*
+ * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.management.namespace;
+
+import javax.management.*;
+import com.sun.jmx.mbeanserver.Util;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.security.Permission;
+
+/**
+ *
A permission controlling access to MBeans located in namespaces.
+ * If a security manager has been set using {@link
+ * System#setSecurityManager}, most operations on an MBean mounted in a
+ * namespace require that the caller's permissions imply a
+ * JMXNamespacePermission appropriate for the operation.
+ * This is described in detail in the
+ * documentation for the
+ * JMXNamespace
+ * class.
+ *
+ * As with other {@link Permission} objects,
+ * a JMXNamespacePermission can represent either a permission that
+ * you have or a permission that you need.
+ * When a sensitive operation is being checked for permission,
+ * a JMXNamespacePermission is constructed
+ * representing the permission you need. The operation is only
+ * allowed if the permissions you have {@linkplain #implies imply} the
+ * permission you need.
+ *
+ * A JMXNamespacePermission contains four items of information:
+ *
+ *
+ *
+ * The action.
+ * For a permission you need,
+ * this is one of the actions in the list below. For a permission you have, this is
+ * a comma-separated list of those actions, or *
,
+ * representing all actions.
+ *
+ * The action is returned by {@link #getActions()}.
+ *
+ * The MBean Server name.
+ *
+ * For a permission you need, this is the {@linkplain
+ * javax.management.MBeanServerFactory#getMBeanServerName
+ * name of the MBeanServer}
+ * from which the MBean is accessed.
+ *
+ * For a permission you have, this is either the {@linkplain
+ * javax.management.MBeanServerFactory#getMBeanServerName
+ * name of the MBeanServer} from which the MBean
+ * for which you have this permission is accessed,
+ * or a pattern against which that MBean Server name will be matched.
+ * An {@code mbeanServername} pattern can also be empty, or the single
+ * character {@code "*"}, both of which match any {@code MBeanServer} name.
+ * The string {@code "-"} doesn't match any MBeanServer name.
+ *
+ *
+ * Example:
+ *
+ * // grant permission to invoke the operation "stop" on any MBean
+ * // whose name matches "a//**//*:type=JMXConnectorServer" when
+ * // accessed from any MBeanServer whose name matches myapp.*"
+ * permission javax.management.namespace.JMXNamespacePermission "myapp.*::stop[a//**//*:type=JMXConnectorServer]", "invoke";
+ *
+ *
+ * The member.
+ *
+ * For a permission you need, this is the name of the attribute or
+ * operation you are accessing. For operations that do not reference
+ * an attribute or operation, the member is null.
+ *
+ * For a permission you have, this is either the name of an attribute
+ * or operation you can access, or it is empty or the single character
+ * "*
", both of which grant access to any member.
+ *
+ * There is a special case for actions {@code registerMBean} and
+ * {@code instantiate}, where for a permission you need, {@code member}
+ * indicates the name of the class for which you are trying
+ * to create, instantiate, or register an MBean instance. For a
+ * permission you have, it is a pattern that will be matched against
+ * the full class name of the MBean being created, instantiated, or
+ * registered.
+ *
+ *
+ *
+ * The object name.
+ *
+ * For a permission you need, this is the {@link ObjectName} of the
+ * MBean you are accessing. It is of the form {@code //}
+ * where {@code } is the name of the name space for which the
+ * permission is checked, and {@code } is the name of the MBean
+ * within that namespace.
+ *
+ * For operations that do not reference a
+ * single MBean, the object name is null. It is never an object
+ * name pattern.
+ *
+ *
+ * For a permission you have, this is the {@link ObjectName} of the
+ * MBean or MBeans you can access. It is of the form
+ * {@code //}
+ * where {@code } is the name of the name space for which the
+ * permission is checked, and
+ * {@code } is the name of the MBean
+ * within that namespace. Both {@code } and {@code }
+ * can be patterns. The object name
+ * may also be empty, which grants access to all MBeans whatever their
+ * name and namespace.
+ * When included in a namespace path the special path element
+ * **
matches any number of sub namespaces
+ * recursively, but only if used as a complete namespace path element,
+ * as in **//b//c//D:k=v
or a//**//c//D:k=v
+ * - see below.
+ *
+ *
+ *
+ *
+ *
+ * If you have a JMXNamespacePermission, it allows operations only
+ * if all four of the items match.
+ *
+ * The MBeanServer name,
+ * member, and object name
+ * can be written together
+ * as a single string, which is the name of this permission.
+ * The name of the permission is the string returned by {@link
+ * java.security.Permission#getName() getName()}.
+ * The format of the string is:
+ *
+ *
+ * {@code ::[//]}
+ *
+ *
+ *
+ * The {@code } is optional. If omitted, {@code "*"} is
+ * assumed, and these three permission names
+ * are thus equivalent:
+ *
+ *
+ * {@code *::[//]}
+ * {@code ::[//]}
+ * {@code [//]}
+ *
+ *
+ * The {@code //} string can be in the form
+ * of a traditional ObjectName
+ * pattern - meaning that ?
will match any single
+ * character, and *
will match any sequence of characters,
+ * except {@value
+ * javax.management.namespace.JMXNamespaces#NAMESPACE_SEPARATOR}
+ * In addition, when included in a namespace path the special
+ * path element **
matches any number of sub namespaces
+ * recursively.
+ * A {@code //} string of the form
+ * **//*:*
thus means that the permission is
+ * granted for all MBeans in all namespaces, recursively (see
+ * below for more details.
+ *
+ * Namespace permission checking may be tricky to configure, depending
+ * on whether the namespaces crossed to reach the MBean are local or
+ * remote.
+ * For instance, let a//b//D:k=v
be an MBean exposing an
+ * attribute Foo
.
+ * If namespace a
is a plain JMXNamespace pointing to
+ * a local MBeanServer in the same JVM, then the permissions you need
+ * to get the attribute Foo
will be:
+ *
+ *
+ * // granting permission to access attribute 'Foo' of MBean a//b//D:k=v
+ * // from MBeanServer named 'srv1'
+ * // This permission will be checked by the MBeanServer that contains 'a'.
+ * srv1::Foo[a//b//D:k=v]
+ *
+ * // Since a is local, you also need the following additional permission,
+ * // which will be checked by the MBeanServer 'srv2' that contains 'b':
+ * //
+ * // granting permission to access attribute 'Foo' of MBean b//D:k=v from
+ * // 'srv2'
+ * srv2::Foo[b//D:k=v]
+ *
+ * On the other hand, if namespace a
is a JMXRemoteNamespace
+ * pointing to an MBeanServer in a remote JVM, then the only permission you
+ * need to get the attribute Foo
will be:
+ *
+ *
+ * // granting permission to access attribute 'Foo' of MBean a//b//D:k=v
+ * // from 'srv1'
+ * srv1::Foo[a//b//D:k=v]
+ *
+ * The namespace b
resides in the remote JVM, and
+ * therefore the permissions concerning access to MBeans from
+ * namespace 'b' will only be checked in the remote JVM, if that JVM is
+ * configured to do so.
+ *
+ *
+ * The {@code } is written using the usual syntax for {@link
+ * ObjectName}. It may contain any legal characters, including
+ * ]
. It is terminated by a ]
character
+ * that is the last character in the string.
+ *
+ * Below are some examples of permission names:
+ *
+ * // allows access to Foo in 'a//b//*:*' from any MBeanServer in the JVM.
+ * Foo[a//b//*:*]
+ *
+ * // allows access to Foo in all subnamespaces of 'a//b', but only for
+ * // MBeanServers whose name matches 'myapp.*'
+ * myapp.*::Foo[a//b//**//*:*]
+ *
+ * // allows access to Foo from all namespaces in the MBeanServer named
+ * // 'myapp.srv1' - but not recursively.
+ * myapp.srv1::Foo[*//*:*]
+ *
+ * For instance, the first two permissions listed above
+ * will let through {@code getAttribute("a//b//D:k=v","Foo");} in
+ * all MBeanServers, but will block access to
+ * {@code getAttribute("a//b//c//D:k=v","Foo");} in MBeanServers whose
+ * name do not start with {@code "myapp."}.
+ *
+ *
+ *
+ * // allows access to Foo in all namespaces, recursively.
+ * //
+ * *::Foo[**//*:*]
+ *
+ * // This permission name is the equivalent to the permission names above:
+ * // Foo[**//*:*] and Foo[] are equivalent.
+ * //
+ * Foo[]
+ *
+ * // This permission name is the equivalent to the two permission names
+ * // above:
+ * // Foo[**//*:*], Foo[], Foo are equivalent.
+ * //
+ * Foo
+ *
+ * // allows access to Foo from all namespaces - but not recursively.
+ * // This wildcard permission complements the previous one: it allows
+ * // access to 'Foo' from an MBean directly registered in any local namespace.
+ * //
+ * Foo[*//*:*]
+ *
+ *
+ * Note on wildcards: In an object name pattern, a path element
+ * of exactly **
corresponds to a meta
+ * wildcard that will match any number of sub namespaces. Hence:
+ *
+ *
+ * pattern matches doesn't match
+ *
+ * **//D:k=v
+ * a//D:k=v
+ * a//b//D:k=v
+ * a//b//c//D:k=v
+ * D:k=v
+ * a//**//D:k=v
+ * a//b//D:k=v
+ * a//b//c//D:k=v
+ * b//b//c//D:k=v
+ * a//D:k=v
+ * D:k=v
+ * a//**//e//D:k=v
+ * a//b//e//D:k=v
+ * a//b//c//e//D:k=v
+ * a//b//c//c//D:k=v
+ * b//b//c//e//D:k=v
+ * a//e//D:k=v
+ * e//D:k=v
+ * a//b**//e//D:k=v
+ * a//b//e//D:k=v
+ * a//b//c//e//D:k=v
+ * because in that case b**
+ * is not a meta-wildcard - and b**
+ * is thus equivalent to b*
.
+ *
+ *
+ *
+ *
+ * If {@code ::} is omitted, then one of
+ * member
or object name
may be omitted.
+ * If the object name
is omitted,
+ * the []
may be too (but does not have to be). It is
+ * not legal to omit all items, that is to have a name
+ * which is the empty string.
+ * If {@code } is present, it must be followed by
+ * the {@code "::"} separator - otherwise it will be interpreted as
+ * a {@code member name}.
+ *
+ *
+ *
+ * One or more of the MBean Server name,
+ * member
+ * or object name may be the character "-
",
+ * which is equivalent to a null value. A null value is implied by
+ * any value (including another null value) but does not imply any
+ * other value.
+ *
+ *
+ * The possible actions are these:
+ *
+ *
+ * - addNotificationListener
+ * - getAttribute
+ * - getClassLoader
+ * - getClassLoaderFor
+ * - getClassLoaderRepository
+ * - getMBeanInfo
+ * - getObjectInstance
+ * - instantiate
+ * - invoke
+ * - isInstanceOf
+ * - queryMBeans
+ * - queryNames
+ * - registerMBean
+ * - removeNotificationListener
+ * - setAttribute
+ * - unregisterMBean
+ *
+ *
+ * In a comma-separated list of actions, spaces are allowed before
+ * and after each action.
+ *
+ * @since 1.7
+ */
+public class JMXNamespacePermission extends Permission {
+
+ private static final long serialVersionUID = -2416928705275160661L;
+
+ private static final String WILDPATH = "**" +
+ JMXNamespaces.NAMESPACE_SEPARATOR + "*";
+
+ /**
+ * Actions list.
+ */
+ private static final int AddNotificationListener = 0x00001;
+ private static final int GetAttribute = 0x00002;
+ private static final int GetClassLoader = 0x00004;
+ private static final int GetClassLoaderFor = 0x00008;
+ private static final int GetClassLoaderRepository = 0x00010;
+ // No GetDomains because it is not possible to route a call to
+ // getDomains() on a NamespaceInterceptor - getDomains() doesn't
+ // have any ObjectName.
+ // private static final int GetDomains = 0x00020;
+ private static final int GetMBeanInfo = 0x00040;
+ private static final int GetObjectInstance = 0x00080;
+ private static final int Instantiate = 0x00100;
+ private static final int Invoke = 0x00200;
+ private static final int IsInstanceOf = 0x00400;
+ private static final int QueryMBeans = 0x00800;
+ private static final int QueryNames = 0x01000;
+ private static final int RegisterMBean = 0x02000;
+ private static final int RemoveNotificationListener = 0x04000;
+ private static final int SetAttribute = 0x08000;
+ private static final int UnregisterMBean = 0x10000;
+
+ /**
+ * No actions.
+ */
+ private static final int NONE = 0x00000;
+
+ /**
+ * All actions.
+ */
+ // No GetDomains because it is not possible to route a call to
+ // getDomains() on a NamespaceInterceptor - getDomains() doesn't
+ // have any ObjectName.
+ //
+ private static final int ALL =
+ AddNotificationListener |
+ GetAttribute |
+ GetClassLoader |
+ GetClassLoaderFor |
+ GetClassLoaderRepository |
+ GetMBeanInfo |
+ GetObjectInstance |
+ Instantiate |
+ Invoke |
+ IsInstanceOf |
+ QueryMBeans |
+ QueryNames |
+ RegisterMBean |
+ RemoveNotificationListener |
+ SetAttribute |
+ UnregisterMBean;
+
+ /**
+ * The actions string.
+ */
+ private String actions;
+
+ /**
+ * The actions mask.
+ */
+ private transient int mask;
+
+ /**
+ * 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;
+
+ /**
+ * The member that must match. If null, is implied by any member
+ * but does not imply any non-null member.
+ */
+ private transient String member;
+
+ /**
+ * The objectName that must match. If null, is implied by any
+ * objectName but does not imply any non-null objectName.
+ */
+ private transient ObjectName objectName;
+
+ /**
+ * If objectName is missing from name, then allnames will be
+ * set to true.
+ */
+ private transient boolean allnames = false;
+
+ /**
+ * Parse actions
parameter.
+ */
+ private void parseActions() {
+
+ int amask;
+
+ if (actions == null)
+ throw new IllegalArgumentException("JMXNamespaceAccessPermission: " +
+ "actions can't be null");
+ if (actions.equals(""))
+ throw new IllegalArgumentException("JMXNamespaceAccessPermission: " +
+ "actions can't be empty");
+
+ amask = getMask(actions);
+
+ if ((amask & ALL) != amask)
+ throw new IllegalArgumentException("Invalid actions mask");
+ if (amask == NONE)
+ throw new IllegalArgumentException("Invalid actions mask");
+ this.mask = amask;
+ }
+
+ /**
+ * Parse name
parameter.
+ */
+ private void parseName() {
+ String name = getName();
+
+ if (name == null)
+ throw new IllegalArgumentException("JMXNamespaceAccessPermission name " +
+ "cannot be null");
+
+ if (name.equals(""))
+ throw new IllegalArgumentException("JMXNamespaceAccessPermission name " +
+ "cannot be empty");
+ final int sepIndex = name.indexOf("::");
+ if (sepIndex < 0) {
+ setMBeanServerName("*");
+ } else {
+ setMBeanServerName(name.substring(0,sepIndex));
+ }
+
+ /* The name looks like "mbeanServerName::member[objectname]".
+ We subtract elements from the right as we parse, so after
+ parsing the objectname we have "class#member" and after parsing the
+ member we have "class". Each element is optional. */
+
+ // Parse ObjectName
+
+ final int start = (sepIndex<0)?0:sepIndex+2;
+ int openingBracket = name.indexOf("[",start);
+ if (openingBracket == -1) {
+ // If "[on]" missing then ObjectName("*:*")
+ //
+ objectName = null;
+ allnames = true;
+ openingBracket=name.length();
+ } else {
+ if (!name.endsWith("]")) {
+ throw new IllegalArgumentException("JMXNamespaceAccessPermission: " +
+ "The ObjectName in the " +
+ "target name must be " +
+ "included in square " +
+ "brackets");
+ } else {
+ // Create ObjectName
+ //
+ String on = name.substring(openingBracket + 1,
+ name.length() - 1);
+ try {
+ // If "[]" then allnames are implied
+ //
+ final ObjectName target;
+ final boolean all;
+ if (on.equals("")) {
+ target = null;
+ all = true;
+ } else if (on.equals("-")) {
+ target = null;
+ all = false;
+ } else {
+ target = new ObjectName(on);
+ all = false;
+ }
+ setObjectName(target,all);
+ } catch (MalformedObjectNameException e) {
+ throw new IllegalArgumentException(
+ "JMXNamespaceAccessPermission: " +
+ "The target name does " +
+ "not specify a valid " +
+ "ObjectName", e);
+ }
+ }
+ }
+
+ final String memberName = name.substring(start,openingBracket);
+ setMember(memberName);
+ }
+
+ private void setObjectName(ObjectName target, boolean all) {
+ if (target != null &&
+ !Util.wildpathmatch(target.getDomain(), WILDPATH)) {
+ throw new IllegalArgumentException(
+ "The target name does not contain " +
+ "any namespace: "+String.valueOf(target));
+ } else if (target != null) {
+ final String domain = target.getDomain();
+ final int seplen = JMXNamespaces.NAMESPACE_SEPARATOR.length();
+ final int sepc = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
+ if (sepc < 0 || (sepc+seplen)==domain.length()) {
+ throw new IllegalArgumentException(String.valueOf(target)+
+ ": no namespace in domain");
+ }
+ }
+ objectName = target;
+ allnames = all;
+ }
+
+ /**
+ * Assign fields based on className, member, and objectName
+ * parameters.
+ */
+// private void initName(String namespaceName, String member,
+// ObjectName objectName, boolean allnames) {
+// setNamespace(namespaceName);
+ private void initName(String mbeanServerName, String member,
+ ObjectName mbeanName, boolean all) {
+ setMBeanServerName(mbeanServerName);
+ setMember(member);
+ setObjectName(mbeanName, all);
+ }
+
+ private void setMBeanServerName(String mbeanServerName) {
+ if (mbeanServerName == null || mbeanServerName.equals("-")) {
+ this.mbeanServerName = null;
+ } else if (mbeanServerName.equals("")) {
+ this.mbeanServerName = "*";
+ } else {
+ this.mbeanServerName = mbeanServerName;
+ }
+ }
+
+ private void setMember(String member) {
+ if (member == null || member.equals("-"))
+ this.member = null;
+ else if (member.equals(""))
+ this.member = "*";
+ else
+ this.member = member;
+ }
+
+ /**
+ * Create a new JMXNamespacePermission object with the
+ * specified target name and actions.
+ *
+ * The target name is of the form
+ * "mbeanServerName::member[objectName]
" where each part is
+ * optional. This target name must not be empty or null.
+ * If objectName
is present, it is of
+ * the form namespace//MBeanName
.
+ *
+ *
+ * For a permission you need, {@code mbeanServerName} is the
+ * name of the MBeanServer from
+ * which {@code objectName} is being accessed.
+ *
+ *
+ * For a permission you have, {@code mbeanServerName} is the
+ * name of the MBeanServer from
+ * which access to {@code objectName} is granted.
+ * It can also be a pattern, and if omitted, {@code "*"} is assumed,
+ * meaning that access to {@code objectName} is granted in all
+ * MBean servers in the JVM.
+ *
+ *
+ * The actions parameter contains a comma-separated list of the
+ * desired actions granted on the target name. It must not be
+ * empty or null.
+ *
+ * @param name the triplet "mbeanServerName::member[objectName]".
+ * If objectName
is present, it is of
+ * the form namespace//MBeanName
.
+ * @param actions the action string.
+ *
+ * @exception IllegalArgumentException if the name
or
+ * actions
is invalid.
+ */
+ public JMXNamespacePermission(String name, String actions) {
+ super(name);
+
+ parseName();
+
+ this.actions = actions;
+ parseActions();
+ }
+
+ /**
+ * Create a new JMXNamespacePermission object with the specified
+ * target name (namespace name, member, object name) and actions.
+ *
+ * The {@code MBeanServer} name, member and object name
+ * parameters define a target name of the form
+ * "mbeanServerName::member[objectName]
" where each
+ * part is optional. This will be the result of {@link #getName()} on the
+ * resultant JMXNamespacePermission.
+ * If the mbeanServerName
is empty or exactly {@code "*"}, then
+ * "{@code mbeanServerName::}" is omitted in that result.
+ *
+ *
+ * The actions parameter contains a comma-separated list of the
+ * desired actions granted on the target name. It must not be
+ * empty or null.
+ *
+ * @param mbeanServerName the name of the {@code MBeanServer} to which this
+ * permission applies.
+ * May be null or "-"
, which represents an MBeanServer name
+ * that is implied by any MBeanServer name but does not imply any other
+ * MBeanServer name.
+ * @param member the member to which this permission applies. May
+ * be null or "-"
, 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. If not null, the {@code objectName} must be of the
+ * form {@code //} - where {@code }
+ * can be a domain pattern, and {@code } can be an ObjectName
+ * pattern.
+ * For a permission you need, {@code } is the name of the
+ * name space for which the permission is checked, and {@code }
+ * is the name of the MBean in that namespace.
+ * The composed name {@code //} thus represents the
+ * name of the MBean as seen by the {@code mbeanServerName} containing
+ * {@code }.
+ *
+ * @param actions the action string.
+ */
+ public JMXNamespacePermission(
+ String mbeanServerName,
+ String member,
+ ObjectName objectName,
+ String actions) {
+ this(mbeanServerName, member, objectName, false, actions);
+// this(member, objectName, false, actions);
+ }
+
+ /**
+ * Create a new JMXNamespacePermission object with the specified
+ * MBean Server name, member, and actions.
+ *
+ * The {@code MBeanServer} name and member
+ * parameters define a target name of the form
+ * "mbeanServerName::member[]
" where each
+ * part is optional. This will be the result of {@link #getName()} on the
+ * resultant JMXNamespacePermission.
+ * If the mbeanServerName
is empty or exactly {@code "*"}, then
+ * "{@code mbeanServerName::}" is omitted in that result.
+ *
+ *
+ * The actions parameter contains a comma-separated list of the
+ * desired actions granted on the target name. It must not be
+ * empty or null.
+ *
+ * @param mbeanServerName the name of the {@code MBeanServer} to which this
+ * permission applies.
+ * May be null or "-"
, which represents an MBeanServer name
+ * that is implied by any MBeanServer name but does not imply any other
+ * MBeanServer name.
+ * @param member the member to which this permission applies. May
+ * be null or "-"
, which represents a member that is
+ * implied by any member but does not imply any other member.
+ * @param actions the action string.
+ */
+ public JMXNamespacePermission(String mbeanServerName,
+ String member,
+ String actions) {
+ this(mbeanServerName,member,null,true,actions);
+ // this(member,null,allnames,actions);
+ }
+
+ /**
+ * Create a new JMXNamespacePermission object with the specified
+ * target name (namespace name, member, object name) and actions.
+ *
+ * The MBean Server name, member and object name parameters define a
+ * target name of the form
+ * "mbeanServerName::member[objectName]
" where each part is
+ * optional. This will be the result of {@link
+ * java.security.Permission#getName() getName()} on the
+ * resultant JMXNamespacePermission.
+ *
+ * The actions parameter contains a comma-separated list of the
+ * desired actions granted on the target name. It must not be
+ * empty or null.
+ *
+ * @param mbeanServerName the name of the {@code MBeanServer} to which this
+ * permission applies.
+ * May be null or "-"
, which represents an MBeanServer name
+ * that is implied by any MBeanServer name but does not imply any other
+ * MBeanServer name.
+ * @param member the member to which this permission applies. May
+ * be null or "-"
, 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. If null, and allnames is false, represents an object
+ * name that is implied by any object name but does not imply any
+ * other object name. Otherwise, if allnames is true, it represents
+ * a meta wildcard that matches all object names. It is equivalent to
+ * a missing objectName ("[]") in the {@link
+ * java.security.Permission#getName() name} property.
+ * @param allnames represent a meta wildcard indicating that the
+ * objectName was not specified. This implies all objectnames
+ * that match "*:*" and all object names that match
+ * "**//*:*"
+ * @param actions the action string.
+ */
+ private JMXNamespacePermission(String mbeanServerName,
+ String member,
+ ObjectName objectName,
+ boolean allnames,
+ String actions) {
+
+ super(makeName(mbeanServerName,
+ member, objectName, allnames));
+ initName(mbeanServerName,
+ member, objectName, allnames);
+
+ this.actions = actions;
+ parseActions();
+ }
+
+ private static String makeName(String mbeanServerName,
+ String memberName, ObjectName objName, boolean allMBeans) {
+ final StringBuilder name = new StringBuilder();
+ if (mbeanServerName == null)
+ mbeanServerName = "-";
+ if (!mbeanServerName.equals("") && !mbeanServerName.equals("*"))
+ name.append(mbeanServerName).append("::");
+ if (memberName == null)
+ memberName = "-";
+ name.append(memberName);
+ if (objName == null) {
+ if (allMBeans)
+ name.append("[]");
+ else
+ name.append("[-]");
+ } else {
+ final String domain = objName.getDomain();
+ final int seplen = JMXNamespaces.NAMESPACE_SEPARATOR.length();
+ final int sepc = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
+ if (sepc < 0 || (sepc+seplen)==domain.length()) {
+ throw new IllegalArgumentException(String.valueOf(objName)+
+ ": no namespace in domain");
+ }
+ final String can = objName.getCanonicalName();
+ name.append("[").append(can).append("]");
+ }
+ return name.toString();
+ }
+
+ /**
+ * Returns the "canonical string representation" of the actions. That is,
+ * this method always returns actions in alphabetical order.
+ *
+ * @return the canonical string representation of the actions.
+ */
+ public String getActions() {
+
+ if (actions == null)
+ actions = getActions(this.mask);
+
+ return actions;
+ }
+
+ /**
+ * Returns the "canonical string representation"
+ * of the actions from the mask.
+ */
+ private static String getActions(int mask) {
+ final StringBuilder sb = new StringBuilder();
+ boolean comma = false;
+
+ if ((mask & AddNotificationListener) == AddNotificationListener) {
+ comma = true;
+ sb.append("addNotificationListener");
+ }
+
+ if ((mask & GetAttribute) == GetAttribute) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("getAttribute");
+ }
+
+ if ((mask & GetClassLoader) == GetClassLoader) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("getClassLoader");
+ }
+
+ if ((mask & GetClassLoaderFor) == GetClassLoaderFor) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("getClassLoaderFor");
+ }
+
+ if ((mask & GetClassLoaderRepository) == GetClassLoaderRepository) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("getClassLoaderRepository");
+ }
+
+ if ((mask & GetMBeanInfo) == GetMBeanInfo) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("getMBeanInfo");
+ }
+
+ if ((mask & GetObjectInstance) == GetObjectInstance) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("getObjectInstance");
+ }
+
+ if ((mask & Instantiate) == Instantiate) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("instantiate");
+ }
+
+ if ((mask & Invoke) == Invoke) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("invoke");
+ }
+
+ if ((mask & IsInstanceOf) == IsInstanceOf) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("isInstanceOf");
+ }
+
+ if ((mask & QueryMBeans) == QueryMBeans) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("queryMBeans");
+ }
+
+ if ((mask & QueryNames) == QueryNames) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("queryNames");
+ }
+
+ if ((mask & RegisterMBean) == RegisterMBean) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("registerMBean");
+ }
+
+ if ((mask & RemoveNotificationListener) == RemoveNotificationListener) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("removeNotificationListener");
+ }
+
+ if ((mask & SetAttribute) == SetAttribute) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("setAttribute");
+ }
+
+ if ((mask & UnregisterMBean) == UnregisterMBean) {
+ if (comma) sb.append(',');
+ else comma = true;
+ sb.append("unregisterMBean");
+ }
+
+ // No GetDomains because it is not possible to route a call to
+ // getDomains() on a NamespaceInterceptor - getDomains() doesn't
+ // have any ObjectName.
+
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return this.getName().hashCode() + this.getActions().hashCode();
+ }
+
+ /**
+ * Converts an action String to an integer action mask.
+ *
+ * @param action the action string.
+ * @return the action mask.
+ */
+ private static int getMask(String action) {
+
+ /*
+ * BE CAREFUL HERE! PARSING ORDER IS IMPORTANT IN THIS ALGORITHM.
+ *
+ * The 'string length' test must be performed for the lengthiest
+ * strings first.
+ *
+ * In this permission if the "unregisterMBean" string length test is
+ * performed after the "registerMBean" string length test the algorithm
+ * considers the 'unregisterMBean' action as being the 'registerMBean'
+ * action and a parsing error is returned.
+ */
+
+ int mask = NONE;
+
+ if (action == null) {
+ return mask;
+ }
+
+ if (action.equals("*")) {
+ return ALL;
+ }
+
+ char[] a = action.toCharArray();
+
+ int i = a.length - 1;
+ if (i < 0)
+ return mask;
+
+ while (i != -1) {
+ char c;
+
+ // skip whitespace
+ while ((i!=-1) && ((c = a[i]) == ' ' ||
+ c == '\r' ||
+ c == '\n' ||
+ c == '\f' ||
+ c == '\t'))
+ i--;
+
+ // check for the known strings
+ int matchlen;
+
+ // No GetDomains because it is not possible to route a call to
+ // getDomains() on a NamespaceInterceptor - getDomains() doesn't
+ // have any ObjectName.
+
+ if (i >= 25 && /* removeNotificationListener */
+ (a[i-25] == 'r') &&
+ (a[i-24] == 'e') &&
+ (a[i-23] == 'm') &&
+ (a[i-22] == 'o') &&
+ (a[i-21] == 'v') &&
+ (a[i-20] == 'e') &&
+ (a[i-19] == 'N') &&
+ (a[i-18] == 'o') &&
+ (a[i-17] == 't') &&
+ (a[i-16] == 'i') &&
+ (a[i-15] == 'f') &&
+ (a[i-14] == 'i') &&
+ (a[i-13] == 'c') &&
+ (a[i-12] == 'a') &&
+ (a[i-11] == 't') &&
+ (a[i-10] == 'i') &&
+ (a[i-9] == 'o') &&
+ (a[i-8] == 'n') &&
+ (a[i-7] == 'L') &&
+ (a[i-6] == 'i') &&
+ (a[i-5] == 's') &&
+ (a[i-4] == 't') &&
+ (a[i-3] == 'e') &&
+ (a[i-2] == 'n') &&
+ (a[i-1] == 'e') &&
+ (a[i] == 'r')) {
+ matchlen = 26;
+ mask |= RemoveNotificationListener;
+ } else if (i >= 23 && /* getClassLoaderRepository */
+ (a[i-23] == 'g') &&
+ (a[i-22] == 'e') &&
+ (a[i-21] == 't') &&
+ (a[i-20] == 'C') &&
+ (a[i-19] == 'l') &&
+ (a[i-18] == 'a') &&
+ (a[i-17] == 's') &&
+ (a[i-16] == 's') &&
+ (a[i-15] == 'L') &&
+ (a[i-14] == 'o') &&
+ (a[i-13] == 'a') &&
+ (a[i-12] == 'd') &&
+ (a[i-11] == 'e') &&
+ (a[i-10] == 'r') &&
+ (a[i-9] == 'R') &&
+ (a[i-8] == 'e') &&
+ (a[i-7] == 'p') &&
+ (a[i-6] == 'o') &&
+ (a[i-5] == 's') &&
+ (a[i-4] == 'i') &&
+ (a[i-3] == 't') &&
+ (a[i-2] == 'o') &&
+ (a[i-1] == 'r') &&
+ (a[i] == 'y')) {
+ matchlen = 24;
+ mask |= GetClassLoaderRepository;
+ } else if (i >= 22 && /* addNotificationListener */
+ (a[i-22] == 'a') &&
+ (a[i-21] == 'd') &&
+ (a[i-20] == 'd') &&
+ (a[i-19] == 'N') &&
+ (a[i-18] == 'o') &&
+ (a[i-17] == 't') &&
+ (a[i-16] == 'i') &&
+ (a[i-15] == 'f') &&
+ (a[i-14] == 'i') &&
+ (a[i-13] == 'c') &&
+ (a[i-12] == 'a') &&
+ (a[i-11] == 't') &&
+ (a[i-10] == 'i') &&
+ (a[i-9] == 'o') &&
+ (a[i-8] == 'n') &&
+ (a[i-7] == 'L') &&
+ (a[i-6] == 'i') &&
+ (a[i-5] == 's') &&
+ (a[i-4] == 't') &&
+ (a[i-3] == 'e') &&
+ (a[i-2] == 'n') &&
+ (a[i-1] == 'e') &&
+ (a[i] == 'r')) {
+ matchlen = 23;
+ mask |= AddNotificationListener;
+ } else if (i >= 16 && /* getClassLoaderFor */
+ (a[i-16] == 'g') &&
+ (a[i-15] == 'e') &&
+ (a[i-14] == 't') &&
+ (a[i-13] == 'C') &&
+ (a[i-12] == 'l') &&
+ (a[i-11] == 'a') &&
+ (a[i-10] == 's') &&
+ (a[i-9] == 's') &&
+ (a[i-8] == 'L') &&
+ (a[i-7] == 'o') &&
+ (a[i-6] == 'a') &&
+ (a[i-5] == 'd') &&
+ (a[i-4] == 'e') &&
+ (a[i-3] == 'r') &&
+ (a[i-2] == 'F') &&
+ (a[i-1] == 'o') &&
+ (a[i] == 'r')) {
+ matchlen = 17;
+ mask |= GetClassLoaderFor;
+ } else if (i >= 16 && /* getObjectInstance */
+ (a[i-16] == 'g') &&
+ (a[i-15] == 'e') &&
+ (a[i-14] == 't') &&
+ (a[i-13] == 'O') &&
+ (a[i-12] == 'b') &&
+ (a[i-11] == 'j') &&
+ (a[i-10] == 'e') &&
+ (a[i-9] == 'c') &&
+ (a[i-8] == 't') &&
+ (a[i-7] == 'I') &&
+ (a[i-6] == 'n') &&
+ (a[i-5] == 's') &&
+ (a[i-4] == 't') &&
+ (a[i-3] == 'a') &&
+ (a[i-2] == 'n') &&
+ (a[i-1] == 'c') &&
+ (a[i] == 'e')) {
+ matchlen = 17;
+ mask |= GetObjectInstance;
+ } else if (i >= 14 && /* unregisterMBean */
+ (a[i-14] == 'u') &&
+ (a[i-13] == 'n') &&
+ (a[i-12] == 'r') &&
+ (a[i-11] == 'e') &&
+ (a[i-10] == 'g') &&
+ (a[i-9] == 'i') &&
+ (a[i-8] == 's') &&
+ (a[i-7] == 't') &&
+ (a[i-6] == 'e') &&
+ (a[i-5] == 'r') &&
+ (a[i-4] == 'M') &&
+ (a[i-3] == 'B') &&
+ (a[i-2] == 'e') &&
+ (a[i-1] == 'a') &&
+ (a[i] == 'n')) {
+ matchlen = 15;
+ mask |= UnregisterMBean;
+ } else if (i >= 13 && /* getClassLoader */
+ (a[i-13] == 'g') &&
+ (a[i-12] == 'e') &&
+ (a[i-11] == 't') &&
+ (a[i-10] == 'C') &&
+ (a[i-9] == 'l') &&
+ (a[i-8] == 'a') &&
+ (a[i-7] == 's') &&
+ (a[i-6] == 's') &&
+ (a[i-5] == 'L') &&
+ (a[i-4] == 'o') &&
+ (a[i-3] == 'a') &&
+ (a[i-2] == 'd') &&
+ (a[i-1] == 'e') &&
+ (a[i] == 'r')) {
+ matchlen = 14;
+ mask |= GetClassLoader;
+ } else if (i >= 12 && /* registerMBean */
+ (a[i-12] == 'r') &&
+ (a[i-11] == 'e') &&
+ (a[i-10] == 'g') &&
+ (a[i-9] == 'i') &&
+ (a[i-8] == 's') &&
+ (a[i-7] == 't') &&
+ (a[i-6] == 'e') &&
+ (a[i-5] == 'r') &&
+ (a[i-4] == 'M') &&
+ (a[i-3] == 'B') &&
+ (a[i-2] == 'e') &&
+ (a[i-1] == 'a') &&
+ (a[i] == 'n')) {
+ matchlen = 13;
+ mask |= RegisterMBean;
+ } else if (i >= 11 && /* getAttribute */
+ (a[i-11] == 'g') &&
+ (a[i-10] == 'e') &&
+ (a[i-9] == 't') &&
+ (a[i-8] == 'A') &&
+ (a[i-7] == 't') &&
+ (a[i-6] == 't') &&
+ (a[i-5] == 'r') &&
+ (a[i-4] == 'i') &&
+ (a[i-3] == 'b') &&
+ (a[i-2] == 'u') &&
+ (a[i-1] == 't') &&
+ (a[i] == 'e')) {
+ matchlen = 12;
+ mask |= GetAttribute;
+ } else if (i >= 11 && /* getMBeanInfo */
+ (a[i-11] == 'g') &&
+ (a[i-10] == 'e') &&
+ (a[i-9] == 't') &&
+ (a[i-8] == 'M') &&
+ (a[i-7] == 'B') &&
+ (a[i-6] == 'e') &&
+ (a[i-5] == 'a') &&
+ (a[i-4] == 'n') &&
+ (a[i-3] == 'I') &&
+ (a[i-2] == 'n') &&
+ (a[i-1] == 'f') &&
+ (a[i] == 'o')) {
+ matchlen = 12;
+ mask |= GetMBeanInfo;
+ } else if (i >= 11 && /* isInstanceOf */
+ (a[i-11] == 'i') &&
+ (a[i-10] == 's') &&
+ (a[i-9] == 'I') &&
+ (a[i-8] == 'n') &&
+ (a[i-7] == 's') &&
+ (a[i-6] == 't') &&
+ (a[i-5] == 'a') &&
+ (a[i-4] == 'n') &&
+ (a[i-3] == 'c') &&
+ (a[i-2] == 'e') &&
+ (a[i-1] == 'O') &&
+ (a[i] == 'f')) {
+ matchlen = 12;
+ mask |= IsInstanceOf;
+ } else if (i >= 11 && /* setAttribute */
+ (a[i-11] == 's') &&
+ (a[i-10] == 'e') &&
+ (a[i-9] == 't') &&
+ (a[i-8] == 'A') &&
+ (a[i-7] == 't') &&
+ (a[i-6] == 't') &&
+ (a[i-5] == 'r') &&
+ (a[i-4] == 'i') &&
+ (a[i-3] == 'b') &&
+ (a[i-2] == 'u') &&
+ (a[i-1] == 't') &&
+ (a[i] == 'e')) {
+ matchlen = 12;
+ mask |= SetAttribute;
+ } else if (i >= 10 && /* instantiate */
+ (a[i-10] == 'i') &&
+ (a[i-9] == 'n') &&
+ (a[i-8] == 's') &&
+ (a[i-7] == 't') &&
+ (a[i-6] == 'a') &&
+ (a[i-5] == 'n') &&
+ (a[i-4] == 't') &&
+ (a[i-3] == 'i') &&
+ (a[i-2] == 'a') &&
+ (a[i-1] == 't') &&
+ (a[i] == 'e')) {
+ matchlen = 11;
+ mask |= Instantiate;
+ } else if (i >= 10 && /* queryMBeans */
+ (a[i-10] == 'q') &&
+ (a[i-9] == 'u') &&
+ (a[i-8] == 'e') &&
+ (a[i-7] == 'r') &&
+ (a[i-6] == 'y') &&
+ (a[i-5] == 'M') &&
+ (a[i-4] == 'B') &&
+ (a[i-3] == 'e') &&
+ (a[i-2] == 'a') &&
+ (a[i-1] == 'n') &&
+ (a[i] == 's')) {
+ matchlen = 11;
+ mask |= QueryMBeans;
+ } else if (i >= 9 && /* queryNames */
+ (a[i-9] == 'q') &&
+ (a[i-8] == 'u') &&
+ (a[i-7] == 'e') &&
+ (a[i-6] == 'r') &&
+ (a[i-5] == 'y') &&
+ (a[i-4] == 'N') &&
+ (a[i-3] == 'a') &&
+ (a[i-2] == 'm') &&
+ (a[i-1] == 'e') &&
+ (a[i] == 's')) {
+ matchlen = 10;
+ mask |= QueryNames;
+ } else if (i >= 5 && /* invoke */
+ (a[i-5] == 'i') &&
+ (a[i-4] == 'n') &&
+ (a[i-3] == 'v') &&
+ (a[i-2] == 'o') &&
+ (a[i-1] == 'k') &&
+ (a[i] == 'e')) {
+ matchlen = 6;
+ mask |= Invoke;
+ } else {
+ // parse error
+ throw new IllegalArgumentException("Invalid permission: " +
+ action);
+ }
+
+ // make sure we didn't just match the tail of a word
+ // like "ackbarfaccept". Also, skip to the comma.
+ boolean seencomma = false;
+ while (i >= matchlen && !seencomma) {
+ switch(a[i-matchlen]) {
+ case ',':
+ seencomma = true;
+ break;
+ case ' ': case '\r': case '\n':
+ case '\f': case '\t':
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid permission: " +
+ action);
+ }
+ i--;
+ }
+
+ // point i at the location of the comma minus one (or -1).
+ i -= matchlen;
+ }
+
+ return mask;
+ }
+
+ /**
+ * Checks if this JMXNamespacePermission object "implies" the
+ * specified permission.
+ *
+ * More specifically, this method returns true if:
+ *
+ *
+ *
+ * - p is an instance of JMXNamespacePermission; and
+ *
+ * - p has a null mbeanServerName or p's mbeanServerName
+ * matches this object's mbeanServerName; and
+ *
+ * - p has a null member or p's member matches this
+ * object's member; and
+ *
+ * - p has a null object name or p's
+ * object name matches this object's object name; and
+ *
+ * - p's actions are a subset of this object's actions
+ *
+ *
+ *
+ * If this object's mbeanServerName is a pattern, then p's
+ * mbeanServerName is matched against that pattern. An empty
+ * mbeanServerName is equivalent to "{@code *}". A null
+ * mbeanServerName is equivalent to "{@code -}".
+ * If this object's mbeanServerName is "*
" or is
+ * empty, p's mbeanServerName always matches it.
+ *
+ * If this object's member is "*
", p's
+ * member always matches it.
+ *
+ * If this object's objectName n1 is an object name pattern,
+ * p's objectName n2 matches it if
+ * {@link ObjectName#equals n1.equals(n2)} or if
+ * {@link ObjectName#apply n1.apply(n2)}.
+ *
+ * A permission that includes the queryMBeans
action
+ * is considered to include queryNames
as well.
+ *
+ * @param p the permission to check against.
+ * @return true if the specified permission is implied by this object,
+ * false if not.
+ */
+ public boolean implies(Permission p) {
+ if (!(p instanceof JMXNamespacePermission))
+ return false;
+
+ JMXNamespacePermission that = (JMXNamespacePermission) p;
+
+ // Actions
+ //
+ // The actions in 'this' permission must be a
+ // superset of the actions in 'that' permission
+ //
+
+ /* "queryMBeans" implies "queryNames" */
+ if ((this.mask & QueryMBeans) == QueryMBeans) {
+ if (((this.mask | QueryNames) & that.mask) != that.mask) {
+ //System.out.println("action [with QueryNames] does not imply");
+ return false;
+ }
+ } else {
+ if ((this.mask & that.mask) != that.mask) {
+ //System.out.println("action does not imply");
+ return false;
+ }
+ }
+
+ // 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 'member' check is true iff:
+ // 1) the member in 'this' member is omitted or "*", or
+ // 2) the member in 'that' member is omitted or "*", or
+ // 3) the member in 'this' permission equals the member in
+ // 'that' permission.
+ //
+ // The 'object name' check is true iff:
+ // 1) the object name in 'this' permission is omitted, or
+ // 2) the object name in 'that' permission is omitted, or
+ // 3) the object name in 'this' permission does pattern
+ // matching with the object name in 'that' permission.
+ //
+
+ 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
+ }
+
+ /* Check if this.member implies that.member */
+
+ if (that.member == null) {
+ // bottom is implied
+ } else if (this.member == null) {
+ // bottom implies nothing but itself
+ return false;
+ } else if (this.member.equals("*")) {
+ // wildcard implies everything (including itself)
+ } else if (this.member.equals(that.member)) {
+ // exact match
+ } else if (!Util.wildmatch(that.member,this.member)) {
+ return false; // no match
+ }
+
+ /* Check if this.objectName implies that.objectName */
+
+ if (that.objectName == null) {
+ // bottom is implied
+ } else if (this.objectName == null) {
+ // bottom implies nothing but itself
+ if (allnames == false) return false;
+ } else if (!this.objectName.apply(that.objectName)) {
+ /* ObjectName.apply returns false if that.objectName is a
+ wildcard so we also allow equals for that case. This
+ never happens during real permission checks, but means
+ the implies relation is reflexive. */
+ if (!this.objectName.equals(that.objectName))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks two JMXNamespacePermission objects for equality. Checks
+ * that obj is an JMXNamespacePermission, and has the same
+ * name and actions as this object.
+ *
+ * @param obj the object we are testing for equality with this object.
+ * @return true if obj is an JMXNamespacePermission, and has the
+ * same name and actions as this JMXNamespacePermission object.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+
+ if (! (obj instanceof JMXNamespacePermission))
+ return false;
+
+ JMXNamespacePermission that = (JMXNamespacePermission) obj;
+
+ return (this.mask == that.mask) &&
+ (this.getName().equals(that.getName()));
+ }
+
+ /**
+ * Deserialize this object based on its name and actions.
+ */
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ parseName();
+ parseActions();
+ }
+}
diff --git a/src/share/classes/javax/management/namespace/JMXNamespaceView.java b/src/share/classes/javax/management/namespace/JMXNamespaceView.java
new file mode 100644
index 0000000000000000000000000000000000000000..eacc0f4bce76a16992211a9794822a0271c5fba2
--- /dev/null
+++ b/src/share/classes/javax/management/namespace/JMXNamespaceView.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.management.namespace;
+
+import java.io.IOException;
+import java.util.Set;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+/**
+ * This class makes it possible to navigate easily within a hierarchical
+ * namespace view.
+ *
+ *
+ * MBeanServerConnnection rootConnection = ...;
+ *
+ * // create a view at the local root of the namespace hierarchy.
+ * //
+ * JMXNamespaceView view = new JMXNamespaceView(rootConnection);
+ *
+ * // list all top level namespaces
+ * String[] list = view.list();
+ *
+ * // select one namespace from the list
+ * String whereToGo = ... ;
+ *
+ * // go down to the selected namespace:
+ * view = view.down(whereToGo);
+ * System.out.println("I am now in: " + view.where());
+ * System.out.println("I can see these MBeans:" +
+ * view.getMBeanServerConnection().queryNames(null,null));
+ *
+ * // list sub namespaces in current view ('whereToGo')
+ * list = view.list();
+ * System.out.println("Here are the sub namespaces of "+view.where()+": "+
+ * Arrays.toString(list));
+ *
+ * // go up one level
+ * view = view.up();
+ * System.out.println("I am now back to: " +
+ * (view.isRoot() ? "root namespace" : view.where()));
+ *
+ * @since 1.7
+ */
+public class JMXNamespaceView {
+
+ private static final ObjectName ALL_NAMESPACES;
+ static {
+ try {
+ ALL_NAMESPACES = ObjectName.getInstance("*" +
+ JMXNamespaces.NAMESPACE_SEPARATOR + ":"+
+ JMXNamespace.TYPE_ASSIGNMENT);
+ } catch (MalformedObjectNameException x) {
+ throw new ExceptionInInitializerError(x);
+ }
+ }
+ private static final int NAMESPACE_SEPARATOR_LENGTH =
+ JMXNamespaces.NAMESPACE_SEPARATOR.length();
+
+ private final JMXNamespaceView parent;
+ private final MBeanServerConnection here;
+ private final String where;
+
+ private static MBeanServerConnection checkRoot(MBeanServerConnection root) {
+ if (root == null)
+ throw new IllegalArgumentException(
+ "namespaceRoot: null is not a valid value");
+ return root;
+ }
+
+ /**
+ * Creates a view at the top of a JMX namespace hierarchy.
+ * @param namespaceRoot The {@code MBeanServerConnection} at the
+ * top of the hierarchy.
+ */
+ public JMXNamespaceView(MBeanServerConnection namespaceRoot) {
+ this(null,checkRoot(namespaceRoot),"");
+ }
+
+ // This constructor should remain private. A user can only create
+ // JMXNamespaceView at the top of the hierarchy.
+ // JMXNamespaceView sub nodes are created by their parent nodes.
+ private JMXNamespaceView(JMXNamespaceView parent,
+ MBeanServerConnection here, String where) {
+ this.parent = parent;
+ this.here = here;
+ this.where = where;
+ }
+
+ /**
+ * Returns the path leading to the namespace in this view, from
+ * the top of the hierarchy.
+ * @return The path to the namespace in this view.
+ */
+ public String where() {
+ return where;
+ }
+
+ /**
+ * Lists all direct sub namespaces in this view. The returned strings
+ * do not contain the {@code //} separator.
+ *
+ * @return A list of direct sub name spaces accessible from this
+ * namespace.
+ * @throws IOException if the attempt to list the namespaces fails because
+ * of a communication problem.
+ */
+ public String[] list() throws IOException {
+ final Set names =
+ here.queryNames(ALL_NAMESPACES,null);
+ final String[] res = new String[names.size()];
+ int i = 0;
+ for (ObjectName dirName : names) {
+ final String dir = dirName.getDomain();
+ res[i++]=dir.substring(0,dir.length()-NAMESPACE_SEPARATOR_LENGTH);
+ }
+ return res;
+ }
+
+ /**
+ * Go down into a sub namespace.
+ * @param namespace the namespace to go down to. It can contain one or
+ * more {@code //} separators, to traverse intermediate namespaces, but
+ * it must not begin or end with {@code //} or contain an empty
+ * intermediate namespace. If it is the empty string, then {@code this} is
+ * returned.
+ * @return A view of the named sub namespace.
+ * @throws IllegalArgumentException if the {@code namespace} begins or
+ * ends with {@code //}.
+ */
+ public JMXNamespaceView down(String namespace) {
+ if (namespace.equals("")) return this;
+ if (namespace.startsWith(JMXNamespaces.NAMESPACE_SEPARATOR))
+ throw new IllegalArgumentException(namespace+": can't start with "+
+ JMXNamespaces.NAMESPACE_SEPARATOR);
+
+ // This is a convenience to handle paths like xxx//yyy
+ final String[] elts =
+ namespace.split(JMXNamespaces.NAMESPACE_SEPARATOR);
+
+ // Go down the path, creating all sub namespaces along the way.
+ // Usually there will be a single element in the given namespace
+ // name, but we don't want to forbid things like
+ // down("xxx//yyy/www");
+ //
+ JMXNamespaceView previous = this;
+ String cursor = where;
+ for (String elt : elts) {
+ // empty path elements are not allowed. It means we
+ // had something like "xxx////yyy"
+ if (elt.equals(""))
+ throw new IllegalArgumentException(namespace+
+ ": invalid path element");
+
+ // compute the "where" for the child.
+ cursor = JMXNamespaces.concat(cursor, elt);
+
+ // create the child...
+ final JMXNamespaceView next =
+ makeJMXNamespaceView(root(), previous, cursor);
+
+ // the current child will be the parent of the next child...
+ previous = next;
+ }
+
+ // We return the last child that was created.
+ return previous;
+ }
+
+ /**
+ * Go back up one level. If this view is at the root of the
+ * hierarchy, returns {@code null}.
+ * @return A view of the parent namespace, or {@code null} if we're at
+ * the root of the hierarchy.
+ */
+ public JMXNamespaceView up() {
+ return parent;
+ }
+
+ /**
+ * Tells whether this view is at the root of the hierarchy.
+ * @return {@code true} if this view is at the root of the hierachy.
+ */
+ public boolean isRoot() {
+ return parent == null;
+ }
+
+ /**
+ * Returns the view at the root of the hierarchy.
+ * If we are already at the root, this is {@code this}.
+ * @return the view at the root of the hierarchy.
+ */
+ public JMXNamespaceView root() {
+ if (parent == null) return this;
+ return parent.root();
+ }
+
+ /**
+ * A MBeanServerConnection to the namespace shown by this view.
+ * This is what would have been obtained by doing:
+ *
+ * JMX.narrowToNamespace(this.root().getMBeanServerConnection(),
+ * this.where());
+ *
+ * @return A MBeanServerConnection to the namespace shown by this view.
+ */
+ public MBeanServerConnection getMBeanServerConnection() {
+ return here;
+ }
+
+ /**
+ * Get the name of the JMXNamespaceMBean handling the namespace shown by
+ * this view, relative to the root of the hierarchy. If we are at the root
+ * of the hierarchy, this method returns {@code null}.
+ *
+ * You can use this method to make a proxy for the JMXNamespaceMBean
+ * as follows:
+ *
+ *
+ * JMXNamespaceView view = ...;
+ * ObjectName namespaceMBeanName = view.getJMXNamespaceMBeanName();
+ * JMXNamespaceMBean namespaceMBean = JMX.newMBeanProxy(
+ * view.root().getMBeanServerConnection(), namespaceMBeanName,
+ * JMXNamespaceMBean.class);
+ *
+ *
+ * @return The name of the {@code JMXNamespaceMBean} handling the namespace
+ * shown by this view, or {@code null}.
+ */
+ public ObjectName getJMXNamespaceMBeanName() {
+ if (parent == null)
+ return null;
+ else
+ return JMXNamespaces.getNamespaceObjectName(where);
+ }
+
+ @Override
+ public int hashCode() {
+ return where.hashCode();
+ }
+
+ /**
+ * Returns true if this object is equal to the given object. The
+ * two objects are equal if the other object is also a {@code
+ * JMXNamespaceView} and both objects have the same {@linkplain #root root}
+ * MBeanServerConnection and the same {@linkplain #where path}.
+ * @param o the other object to compare to.
+ * @return true if both objects are equal.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o==this) return true;
+ if (! (o instanceof JMXNamespaceView)) return false;
+ if (!where.equals(((JMXNamespaceView)o).where)) return false;
+ return root().getMBeanServerConnection().equals(
+ ((JMXNamespaceView)o).root().getMBeanServerConnection());
+ }
+
+ private JMXNamespaceView makeJMXNamespaceView(final JMXNamespaceView root,
+ final JMXNamespaceView directParent, final String pathFromRoot) {
+ if (pathFromRoot.equals("")) return root;
+
+ return new JMXNamespaceView(directParent,
+ narrowToNamespace(root.getMBeanServerConnection(),
+ pathFromRoot),pathFromRoot);
+ }
+
+ private MBeanServerConnection narrowToNamespace(MBeanServerConnection root,
+ String path) {
+ if (root instanceof MBeanServer)
+ return JMXNamespaces.narrowToNamespace((MBeanServer)root, path);
+ return JMXNamespaces.narrowToNamespace(root, path);
+ }
+
+}
diff --git a/src/share/classes/javax/management/namespace/JMXNamespaces.java b/src/share/classes/javax/management/namespace/JMXNamespaces.java
new file mode 100644
index 0000000000000000000000000000000000000000..429a9d466d6175a2f56e0f5b4d7c74d2b7fb8211
--- /dev/null
+++ b/src/share/classes/javax/management/namespace/JMXNamespaces.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.management.namespace;
+
+import com.sun.jmx.defaults.JmxProperties;
+import com.sun.jmx.namespace.JMXNamespaceUtils;
+import com.sun.jmx.namespace.ObjectNameRouter;
+import com.sun.jmx.namespace.serial.RewritingProcessor;
+import com.sun.jmx.namespace.RoutingConnectionProxy;
+import com.sun.jmx.namespace.RoutingServerProxy;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+
+/**
+ * Static constants and utility methods to help work with
+ * JMX name spaces. There are no instances of this class.
+ * @since 1.7
+ */
+public class JMXNamespaces {
+
+ /**
+ * A logger for this class.
+ **/
+ private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
+
+ /** Creates a new instance of JMXNamespaces */
+ private JMXNamespaces() {
+ }
+
+ /**
+ * The name space separator. This is an alias for {@link
+ * ObjectName#NAMESPACE_SEPARATOR}.
+ **/
+ public static final String NAMESPACE_SEPARATOR =
+ ObjectName.NAMESPACE_SEPARATOR;
+ private static final int NAMESPACE_SEPARATOR_LENGTH =
+ NAMESPACE_SEPARATOR.length();
+
+
+ /**
+ * Returns a connector connected to a sub name space exposed through
+ * the parent connector.
+ * @param parent the parent connector.
+ * @param namespace the {@linkplain javax.management.namespace name space}
+ * to which the returned connector is
+ * connected.
+ * @return A connector connected to a sub name space exposed through
+ * the parent connector.
+ **/
+ public static JMXConnector narrowToNamespace(final JMXConnector parent,
+ final String namespace)
+ throws IOException {
+
+ return JMXNamespaceUtils.cd(parent,namespace,true);
+ }
+
+ /**
+ * Creates a new {@code MBeanServerConnection} proxy on a
+ * {@linkplain javax.management.namespace sub name space}
+ * of the given parent.
+ *
+ * @param parent The parent {@code MBeanServerConnection} that contains
+ * the name space.
+ * @param namespace The {@linkplain javax.management.namespace
+ * name space} in which to narrow.
+ * @return A new {@code MBeanServerConnection} proxy that shows the content
+ * of that name space.
+ * @throws IllegalArgumentException if the name space does not exist, or
+ * if a proxy for that name space cannot be created.
+ */
+ public static MBeanServerConnection narrowToNamespace(
+ MBeanServerConnection parent,
+ String namespace) {
+ if (LOG.isLoggable(Level.FINER))
+ LOG.finer("Making MBeanServerConnection for: " +namespace);
+ return RoutingConnectionProxy.cd(parent,namespace);
+ }
+
+ /**
+ * Creates a new {@code MBeanServer} proxy on a
+ * {@linkplain javax.management.namespace sub name space}
+ * of the given parent.
+ *
+ * @param parent The parent {@code MBeanServer} that contains
+ * the name space.
+ * @param namespace The {@linkplain javax.management.namespace
+ * name space} in which to narrow.
+ * @return A new {@code MBeanServer} proxy that shows the content
+ * of that name space.
+ * @throws IllegalArgumentException if either argument is null,
+ * or the name space does not exist, or if a proxy for that name space
+ * cannot be created.
+ */
+ public static MBeanServer narrowToNamespace(MBeanServer parent,
+ String namespace) {
+ if (LOG.isLoggable(Level.FINER))
+ LOG.finer("Making NamespaceServerProxy for: " +namespace);
+ return RoutingServerProxy.cd(parent,namespace);
+ }
+
+ /**
+ * Returns an object that is the same as the given object except that
+ * any {@link ObjectName} it might contain has its domain modified.
+ * The returned object might be identical to the given object if it
+ * does not contain any {@code ObjectName} values or if none of them
+ * were modified.
+ * This method will replace a prefix ({@code toRemove}) from the path of
+ * the ObjectNames contained in {@code obj} by another prefix
+ * ({@code toAdd}).
+ * Therefore, all contained ObjectNames must have a path that start with
+ * the given {@code toRemove} prefix. If one of them doesn't, an {@link
+ * IllegalArgumentException} is thrown.
+ *
+ * For instance, if {@code obj} contains the ObjectName
+ * {@code x//y//z//d:k=x}, and {@code toAdd} is {@code v//w}, and
+ * {@code toRemove}
+ * is {@code x//y} this method will return a copy of {@code obj} that
+ * contains {@code v//w//z//d:k=x}.
+ * On the other hand, if {@code obj} contains the ObjectName
+ * {@code x//y//z//d:k=x}, and {@code toAdd} is {@code v//w}, and
+ * {@code toRemove} is {@code v} this method
+ * will raise an exception, because {@code x//y//z//d:k=x} doesn't start
+ * with {@code v}
+ *
+ * Note: the default implementation of this method can use the
+ * Java serialization framework to clone and replace ObjectNames in the
+ * provided {@code obj}. It will usually fail if {@code obj} is not
+ * Java serializable, or contains objects which are not Java
+ * serializable.
+ *
+ * @param obj The object to deep-rewrite
+ * @param toRemove a prefix already present in contained ObjectNames.
+ * If {@code toRemove} is the empty string {@code ""}, nothing
+ * will be removed from the contained ObjectNames.
+ * @param toAdd the prefix that will replace (@code toRemove} in contained
+ * ObjectNames.
+ * If {@code toAdd} is the empty string {@code ""}, nothing
+ * will be added to the contained ObjectNames.
+ * @return the rewritten object, or possibly {@code obj} if nothing needed
+ * to be changed.
+ * @throws IllegalArgumentException if {@code obj} couldn't be rewritten or
+ * if {@code toRemove} or {@code toAdd} is null.
+ **/
+ public static T deepReplaceHeadNamespace(T obj, String toRemove, String toAdd) {
+ final RewritingProcessor processor =
+ RewritingProcessor.newRewritingProcessor(toAdd,toRemove);
+ return processor.rewriteOutput(obj);
+ }
+
+ /**
+ * Appends {@code namespace} to {@code path}.
+ * This methods appends {@code namespace} to {@code path} to obtain a
+ * a full path, and normalizes the result thus obtained:
+ *
+ * - If {@code path} is empty, the full path is
+ * {@code namespace}.
+ * - Otherwise, if {@code namespace} is empty,
+ * the full path is {@code path}
+ * - Otherwise, and this is the regular case, the full path is the
+ * result of the concatenation of
+ * {@code path}+{@value #NAMESPACE_SEPARATOR}+{@code namespace}
+ * - finally, the full path is normalized: multiple consecutive
+ * occurrences of {@value #NAMESPACE_SEPARATOR} are replaced by a
+ * single {@value #NAMESPACE_SEPARATOR} in the result, and trailing
+ * occurences of {@value #NAMESPACE_SEPARATOR} are removed.
+ *
+ *
+ * @param path a name space path prefix
+ * @param namespace a name space name to append to the path
+ * @return a syntactically valid name space path, or "" if both parameters
+ * are null or empty.
+ * @throws IllegalArgumentException if either argument is null or ends with
+ * an odd number of {@code /} characters.
+ **/
+ public static String concat(String path, String namespace) {
+ if (path == null || namespace == null)
+ throw new IllegalArgumentException("Null argument");
+ checkTrailingSlashes(path);
+ checkTrailingSlashes(namespace);
+ final String result;
+ if (path.equals("")) result=namespace;
+ else if (namespace.equals("")) result=path;
+ else result=path+NAMESPACE_SEPARATOR+namespace;
+ return ObjectNameRouter.normalizeNamespacePath(result,false,true,false);
+ }
+
+ /**
+ * Returns a syntactically valid name space path.
+ * If the provided {@code namespace} ends with {@code "//"},
+ * recursively strips trailing {@code "//"}. Each sequence of an
+ * even number of {@code "/"} characters is also replaced by {@code "//"},
+ * for example {@code "foo//bar////baz/////buh"} will become
+ * {@code "foo//bar//baz///buh"}.
+ *
+ * @param namespace A name space path
+ * @return {@code ""} - if the provided {@code namespace} resolves to
+ * the empty string; otherwise a syntactically valid name space string
+ * stripped of trailing and redundant {@code "//"}.
+ * @throws IllegalArgumentException if {@code namespace} is null or
+ * is not syntactically valid (e.g. it contains
+ * invalid characters like ':', or it ends with an odd
+ * number of '/').
+ */
+ public static String normalizeNamespaceName(String namespace) {
+ if (namespace == null)
+ throw new IllegalArgumentException("Null namespace");
+ final String sourcePath =
+ ObjectNameRouter.normalizeNamespacePath(namespace,false,true,false);
+ if (sourcePath.equals("")) return sourcePath;
+
+ // Will throw an IllegalArgumentException if the namespace name
+ // is not syntactically valid...
+ //
+ getNamespaceObjectName(sourcePath);
+ return sourcePath;
+ }
+
+
+ /**
+ * Return a canonical handler name for the provided {@code namespace},
+ * The handler name returned will be
+ * {@link #normalizeNamespaceName normalizeNamespaceName}{@code (namespace) +
+ * "//:type=JMXNamespace"}.
+ *
+ * @param namespace A name space path
+ * @return a canonical ObjectName for a name space handler.
+ * @see #normalizeNamespaceName
+ * @throws IllegalArgumentException if the provided
+ * {@code namespace} is null or not valid.
+ */
+ public static ObjectName getNamespaceObjectName(String namespace) {
+ if (namespace == null || namespace.equals(""))
+ throw new IllegalArgumentException("Null or empty namespace");
+ final String sourcePath =
+ ObjectNameRouter.normalizeNamespacePath(namespace,false,
+ true,false);
+ try {
+ // We could use Util.newObjectName here - but throwing an
+ // IllegalArgumentException that contains just the supplied
+ // namespace instead of the whole ObjectName seems preferable.
+ return ObjectName.getInstance(sourcePath+
+ NAMESPACE_SEPARATOR+":"+
+ JMXNamespace.TYPE_ASSIGNMENT);
+ } catch (MalformedObjectNameException x) {
+ throw new IllegalArgumentException("Invalid namespace: " +
+ namespace,x);
+ }
+ }
+
+ /**
+ * Returns an ObjectName pattern that can be used to query for all MBeans
+ * contained in the given name space.
+ * For instance, if {@code namespace="foo//bar"}, this method will
+ * return {@code "foo//bar//*:*"}
+ * @return an ObjectName pattern that selects all MBeans in the given
+ * name space.
+ **/
+ public static ObjectName getWildcardFor(String namespace) {
+ return insertPath(namespace,ObjectName.WILDCARD);
+ }
+
+
+ /**
+ * Returns an ObjectName that can be used to access an MBean
+ * contained in the given name space.
+ * For instance, if {@code path="foo//bar"}, and
+ * {@code to="domain:type=Thing"} this method will
+ * return {@code "foo//bar//domain:type=Thing"}
+ * @return an ObjectName that can be used to invoke an MBean located in a
+ * sub name space.
+ * @throws IllegalArgumentException if {@code path} ends with an
+ * odd number of {@code /} characters.
+ **/
+ public static ObjectName insertPath(String path, ObjectName to) {
+ if (path == null || to == null)
+ throw new IllegalArgumentException("Null argument");
+ checkTrailingSlashes(path);
+ try {
+ String prefix = path;
+ if (!prefix.equals("")) prefix =
+ ObjectNameRouter.normalizeNamespacePath(
+ prefix + NAMESPACE_SEPARATOR,false,false,false);
+ return to.withDomain(
+ ObjectNameRouter.normalizeDomain(
+ prefix+to.getDomain(),false));
+ } catch (MalformedObjectNameException x) {
+ throw new IllegalArgumentException(path+": "+x,x);
+ }
+ }
+
+ /**
+ * Returns the normalized name space path of the name space expected to
+ * contain {@code ObjectName}.
+ * For instance, for {@code "foo//domain:type=Thing"} this will be
+ * {@code "foo"}. For {@code "//foo//bar//domain:type=Thing"} this will be
+ * {@code "foo//bar"}. For {@code //foo//bar//baz//domain:type=Thing}
+ * this will be {@code "foo//bar//baz"}. For
+ * {@code //foo//bar//baz//:type=JMXNamespace}
+ * this will be {@code "foo//bar"}.
+ *
+ * @param name an {@code ObjectName}
+ * @return the name space path of the name space that could contain such
+ * a name. If {@code name} has no name space, returns {@code ""}.
+ * @throws IllegalArgumentException if {@code name} is null.
+ **/
+ public static String getContainingNamespace(ObjectName name) {
+ return getNormalizedPath(name,true);
+ }
+
+
+ static String getNormalizedPath(ObjectName name,
+ boolean removeLeadingSep) {
+ if (name == null)
+ throw new IllegalArgumentException("Null name");
+ String domain =
+ ObjectNameRouter.normalizeDomain(name.getDomain(),removeLeadingSep);
+ int end = domain.length();
+
+ // special case of domain part being a single '/'
+ //
+ if (domain.endsWith(NAMESPACE_SEPARATOR+"/"))
+ return domain.substring(0,end-NAMESPACE_SEPARATOR_LENGTH-1);
+
+ // special case of namespace handler
+ //
+ if (domain.endsWith(NAMESPACE_SEPARATOR))
+ domain = domain.substring(0,end-NAMESPACE_SEPARATOR_LENGTH);
+
+ int last = domain.lastIndexOf(NAMESPACE_SEPARATOR);
+ if (last < 0) return "";
+ if (last == 0) return domain;
+
+ // special case of domain part starting with '/'
+ // last=0 is not possible - we took care of this above.
+ if (domain.charAt(last-1) == '/') last--;
+
+ return domain.substring(0,last);
+ }
+
+ private static void checkTrailingSlashes(String path) {
+ int i;
+ for (i = path.length() - 1; i >= 0 && path.charAt(i) == '/'; i--)
+ continue;
+ if (path.length() - i % 2 == 0)
+ throw new IllegalArgumentException("Path ends with odd number of /");
+ }
+}
diff --git a/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java b/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java
new file mode 100644
index 0000000000000000000000000000000000000000..6958f57f2d72db7a17c99e2acb93fb058c33b1f3
--- /dev/null
+++ b/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java
@@ -0,0 +1,734 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.management.namespace;
+
+import com.sun.jmx.defaults.JmxProperties;
+import com.sun.jmx.mbeanserver.Util;
+import com.sun.jmx.namespace.JMXNamespaceUtils;
+import com.sun.jmx.remote.util.EnvHelp;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.management.AttributeChangeNotification;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanServerConnection;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.event.EventClient;
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+/**
+ * A {@link JMXNamespace} that will connect to a remote MBeanServer
+ * by creating a {@link javax.management.remote.JMXConnector} from a
+ * {@link javax.management.remote.JMXServiceURL}.
+ *
+ * You can call {@link #connect() connect()} and {@link #close close()}
+ * several times. This MBean will emit an {@link AttributeChangeNotification}
+ * when the value of its {@link #isConnected Connected} attribute changes.
+ *
+ *
+ * The JMX Remote Namespace MBean is not connected until {@link
+ * #connect() connect()} is explicitly called. The usual sequence of code to
+ * create a JMX Remote Namespace is thus:
+ *
+ *
+ * final String namespace = "mynamespace";
+ * final ObjectName name = {@link JMXNamespaces#getNamespaceObjectName
+ * JMXNamespaces.getNamespaceObjectName(namespace)};
+ * final JMXServiceURL remoteServerURL = .... ;
+ * final Map optionsMap = .... ;
+ * final MBeanServer masterMBeanServer = .... ;
+ * final JMXRemoteNamespace namespaceMBean = {@link #newJMXRemoteNamespace
+ * JMXRemoteNamespace.newJMXRemoteNamespace(remoteServerURL, optionsMap)};
+ * masterMBeanServer.registerMBean(namespaceMBean, name);
+ * namespaceMBean.connect();
+ * // or: masterMBeanServer.invoke(name, {@link #connect() "connect"}, null, null);
+ *
+ *
+ * The JMX Remote Namespace MBean will register for {@linkplain
+ * JMXConnectionNotification JMX Connection Notifications} with its underlying
+ * {@link JMXConnector}. When a JMX Connection Notification indicates that
+ * the underlying connection has failed, the JMX Remote Namespace MBean
+ * closes its underlying connector and switches its {@link #isConnected
+ * Connected} attribute to false, emitting an {@link
+ * AttributeChangeNotification}.
+ *
+ *
+ * At this point, a managing application (or an administrator connected
+ * through a management console) can attempt to reconnect the
+ * JMX Remote Namespace MBean by calling its {@link #connect() connect()} method
+ * again.
+ *
+ * Note that when the connection with the remote namespace fails, or when
+ * {@link #close} is called, then any notification subscription to
+ * MBeans registered in that namespace will be lost - unless a custom
+ * {@linkplain javax.management.event event service} supporting connection-less
+ * mode was used.
+ *
+ * @since 1.7
+ */
+public class JMXRemoteNamespace
+ extends JMXNamespace
+ implements JMXRemoteNamespaceMBean, NotificationEmitter {
+
+ /**
+ * A logger for this class.
+ */
+ private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
+
+
+ // This connection listener is used to listen for connection events from
+ // the underlying JMXConnector. It is used in particular to maintain the
+ // "connected" state in this MBean.
+ //
+ private class ConnectionListener implements NotificationListener {
+ private ConnectionListener() {
+ }
+ public void handleNotification(Notification notification,
+ Object handback) {
+ if (!(notification instanceof JMXConnectionNotification))
+ return;
+ final JMXConnectionNotification cn =
+ (JMXConnectionNotification)notification;
+ final String type = cn.getType();
+ if (JMXConnectionNotification.CLOSED.equals(type)
+ || JMXConnectionNotification.FAILED.equals(type)) {
+ checkState(this,cn,(JMXConnector)handback);
+ }
+ }
+ }
+
+ // When the JMXRemoteNamespace is originally created, it is not connected,
+ // which means that the source MBeanServer should be one that throws
+ // exceptions for most methods. When it is subsequently connected,
+ // the methods should be forwarded to the MBeanServerConnection.
+ // We handle this using MBeanServerConnectionWrapper. The
+ // MBeanServerConnection that is supplied to the constructor of
+ // MBeanServerConnectionWrapper is ignored (and in fact it is null)
+ // because the one that is actually used is the one supplied by the
+ // override of getMBeanServerConnection().
+ private static class JMXRemoteNamespaceDelegate
+ extends MBeanServerConnectionWrapper {
+ private volatile JMXRemoteNamespace parent=null;
+
+ JMXRemoteNamespaceDelegate() {
+ super(null,null);
+ }
+ @Override
+ public MBeanServerConnection getMBeanServerConnection() {
+ return parent.getMBeanServerConnection();
+ }
+ @Override
+ public ClassLoader getDefaultClassLoader() {
+ return parent.getDefaultClassLoader();
+ }
+
+ // Because this class is instantiated in the super() call from the
+ // constructor of JMXRemoteNamespace, it cannot be an inner class.
+ // This method achieves the effect that an inner class would have
+ // had, of giving the class a reference to the outer "this".
+ synchronized void initParentOnce(JMXRemoteNamespace parent) {
+ if (this.parent != null)
+ throw new UnsupportedOperationException("parent already set");
+ this.parent=parent;
+
+ }
+
+ }
+
+ private static final MBeanNotificationInfo connectNotification =
+ new MBeanNotificationInfo(new String[] {
+ AttributeChangeNotification.ATTRIBUTE_CHANGE},
+ "Connected",
+ "Emitted when the Connected state of this object changes");
+
+ private static AtomicLong seqNumber = new AtomicLong(0);
+
+ private final NotificationBroadcasterSupport broadcaster;
+ private final ConnectionListener listener;
+ private final JMXServiceURL jmxURL;
+ private final Map optionsMap;
+
+ private volatile MBeanServerConnection server = null;
+ private volatile JMXConnector conn = null;
+ private volatile ClassLoader defaultClassLoader = null;
+
+ /**
+ * Creates a new instance of {@code JMXRemoteNamespace}.
+ *
+ * This constructor is provided for subclasses.
+ * To create a new instance of {@code JMXRemoteNamespace} call
+ * {@link #newJMXRemoteNamespace
+ * JMXRemoteNamespace.newJMXRemoteNamespace(sourceURL, optionsMap)}.
+ *
+ * @param sourceURL a JMX service URL that can be used to {@linkplain
+ * #connect() connect} to the
+ * source MBean Server. The source MBean Server is the remote
+ * MBean Server which contains the MBeans that will be mirrored
+ * in this namespace.
+ * @param optionsMap the options map that will be passed to the
+ * {@link JMXConnectorFactory} when {@linkplain
+ * JMXConnectorFactory#newJMXConnector creating} the
+ * {@link JMXConnector} used to {@linkplain #connect() connect}
+ * to the remote source MBean Server. Can be null, which is
+ * equivalent to an empty map.
+ * @see #newJMXRemoteNamespace JMXRemoteNamespace.newJMXRemoteNamespace
+ * @see #connect
+ */
+ protected JMXRemoteNamespace(JMXServiceURL sourceURL,
+ Map optionsMap) {
+ super(new JMXRemoteNamespaceDelegate());
+ ((JMXRemoteNamespaceDelegate)super.getSourceServer()).
+ initParentOnce(this);
+
+ // URL must not be null.
+ this.jmxURL = JMXNamespaceUtils.checkNonNull(sourceURL,"url");
+ this.broadcaster =
+ new NotificationBroadcasterSupport(connectNotification);
+
+ // handles options
+ this.optionsMap = JMXNamespaceUtils.unmodifiableMap(optionsMap);
+
+ // handles (dis)connection events
+ this.listener = new ConnectionListener();
+ }
+
+ /**
+ * Returns the {@code JMXServiceURL} that is (or will be) used to
+ * connect to the remote name space.
+ * @see #connect
+ * @return The {@code JMXServiceURL} used to connect to the remote
+ * name space.
+ */
+ public JMXServiceURL getJMXServiceURL() {
+ return jmxURL;
+ }
+
+ /**
+ * In this class, this method never returns {@code null}, and the
+ * address returned is the {@link #getJMXServiceURL JMXServiceURL}
+ * that is used by this object to {@linkplain #connect} to the remote
+ * name space.
+ * This behaviour might be overriden by subclasses, if needed.
+ * For instance, a subclass might want to return {@code null} if it
+ * doesn't want to expose that JMXServiceURL.
+ */
+ public JMXServiceURL getAddress() {
+ return getJMXServiceURL();
+ }
+
+ private Map getEnvMap() {
+ return optionsMap;
+ }
+
+ public void addNotificationListener(NotificationListener listener,
+ NotificationFilter filter, Object handback) {
+ broadcaster.addNotificationListener(listener, filter, handback);
+ }
+
+ /**
+ * A subclass that needs to send its own notifications must override
+ * this method in order to return an {@link MBeanNotificationInfo
+ * MBeanNotificationInfo[]} array containing both its own notification
+ * infos and the notification infos of its super class.
+ * The implementation should probably look like:
+ *
+ * final MBeanNotificationInfo[] myOwnNotifs = { .... };
+ * final MBeanNotificationInfo[] parentNotifs =
+ * super.getNotificationInfo();
+ * final Set mergedResult =
+ * new HashSet();
+ * mergedResult.addAll(Arrays.asList(myOwnNotifs));
+ * mergedResult.addAll(Arrays.asList(parentNotifs));
+ * return mergeResult.toArray(
+ * new MBeanNotificationInfo[mergedResult.size()]);
+ *
+ */
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return broadcaster.getNotificationInfo();
+ }
+
+ public void removeNotificationListener(NotificationListener listener)
+ throws ListenerNotFoundException {
+ broadcaster.removeNotificationListener(listener);
+ }
+
+ public void removeNotificationListener(NotificationListener listener,
+ NotificationFilter filter, Object handback)
+ throws ListenerNotFoundException {
+ broadcaster.removeNotificationListener(listener, filter, handback);
+ }
+
+ private static long getNextSeqNumber() {
+ return seqNumber.getAndIncrement();
+ }
+
+
+ /**
+ * Sends a notification to registered listeners. Before the notification
+ * is sent, the following steps are performed:
+ * -
+ * If {@code n.getSequenceNumber() <= 0} set it to the next available
+ * sequence number.
+ * - If {@code n.getSource() == null}, set it to the value returned by {@link
+ * #getObjectName getObjectName()}.
+ *
+ * This method can be called by subclasses in order to send their own
+ * notifications.
+ * In that case, these subclasses might also need to override
+ * {@link #getNotificationInfo} in order to declare their own
+ * {@linkplain MBeanNotificationInfo notification types}.
+ *
+ * @param n The notification to send to registered listeners.
+ * @see javax.management.NotificationBroadcasterSupport
+ * @see #getNotificationInfo
+ **/
+ protected void sendNotification(Notification n) {
+ if (n.getSequenceNumber()<=0)
+ n.setSequenceNumber(getNextSeqNumber());
+ if (n.getSource()==null)
+ n.setSource(getObjectName());
+ broadcaster.sendNotification(n);
+ }
+
+ private void checkState(ConnectionListener listener,
+ JMXConnectionNotification cn,
+ JMXConnector emittingConnector) {
+
+ // Due to the asynchronous handling of notifications, it is
+ // possible that this method is called for a JMXConnector
+ // (or connection) which is already closed and replaced by a newer
+ // one.
+ //
+ // This method attempts to determine the real state of the
+ // connection - which might be different from what the notification
+ // says.
+ //
+ // This is quite complex logic - because we try not to hold any
+ // lock while evaluating the true value of the connected state,
+ // while anyone might also call close() or connect() from a
+ // different thread.
+ // The method switchConnection() (called from here too) also has the
+ // same kind of complex logic:
+ //
+ // We use the JMXConnector has a handback to the notification listener
+ // (emittingConnector) in order to be able to determine whether the
+ // notification concerns the current connector in use, or an older
+ // one. The 'emittingConnector' is the connector from which the
+ // notification originated. This could be an 'old' connector - as
+ // closed() and connect() could already have been called before the
+ // notification arrived. So what we do is to compare the
+ // 'emittingConnector' with the current connector, to see if the
+ // notification actually comes from the curent connector.
+ //
+ boolean remove = false;
+
+ // whether the emittingConnector is already 'removed'
+ synchronized (this) {
+ if (this.conn != emittingConnector ||
+ JMXConnectionNotification.FAILED.equals(cn.getType()))
+ remove = true;
+ }
+
+ // We need to unregister our listener from this 'removed' connector.
+ // This is the only place where we remove the listener.
+ //
+ if (remove) {
+ try {
+ // This may fail if the connector is already closed.
+ // But better unregister anyway...
+ //
+ emittingConnector.removeConnectionNotificationListener(
+ listener,null,
+ emittingConnector);
+ } catch (Exception x) {
+ LOG.log(Level.FINE,
+ "Failed to unregister connection listener"+x);
+ LOG.log(Level.FINEST,
+ "Failed to unregister connection listener",x);
+ }
+ try {
+ // This may fail if the connector is already closed.
+ // But better call close twice and get an exception than
+ // leaking...
+ //
+ emittingConnector.close();
+ } catch (Exception x) {
+ LOG.log(Level.FINEST,
+ "Failed to close old connector " +
+ "(failure was expected): "+x);
+ }
+ }
+
+ // Now we checked whether our current connector is still alive.
+ //
+ boolean closed = false;
+ final JMXConnector thisconn = this.conn;
+ try {
+ if (thisconn != null)
+ thisconn.getConnectionId();
+ } catch (IOException x) {
+ LOG.finest("Connector already closed: "+x);
+ closed = true;
+ }
+
+ // We got an IOException - the connector is not connected.
+ // Need to forget it and switch our state to closed.
+ //
+ if (closed) {
+ switchConnection(thisconn,null,null);
+ try {
+ // Usually this will fail... Better call close twice
+ // and get an exception than leaking...
+ //
+ if (thisconn != emittingConnector || !remove)
+ thisconn.close();
+ } catch (IOException x) {
+ LOG.log(Level.FINEST,
+ "Failed to close connector (failure was expected): "
+ +x);
+ }
+ }
+ }
+
+ private final void switchConnection(JMXConnector oldc,
+ JMXConnector newc,
+ MBeanServerConnection mbs) {
+ boolean connect = false;
+ boolean close = false;
+ synchronized (this) {
+ if (oldc != conn) {
+ if (newc != null) {
+ try {
+ newc.close();
+ } catch (IOException x) {
+ LOG.log(Level.FINEST,
+ "Failed to close connector",x);
+ }
+ }
+ return;
+ }
+ if (conn == null && newc != null) connect=true;
+ if (newc == null && conn != null) close = true;
+ conn = newc;
+ server = mbs;
+ }
+ if (connect || close) {
+ boolean oldstate = close;
+ boolean newstate = connect;
+ final ObjectName myName = getObjectName();
+
+ // In the uncommon case where the MBean is connected before
+ // being registered, myName can be null...
+ // If myName is null - we use 'this' as the source instead...
+ //
+ final Object source = (myName==null)?this:myName;
+ final AttributeChangeNotification acn =
+ new AttributeChangeNotification(source,
+ getNextSeqNumber(),System.currentTimeMillis(),
+ String.valueOf(source)+
+ (newstate?" connected":" closed"),
+ "Connected",
+ "boolean",
+ Boolean.valueOf(oldstate),
+ Boolean.valueOf(newstate));
+ sendNotification(acn);
+ }
+ }
+
+ private void close(JMXConnector c) {
+ try {
+ if (c != null) c.close();
+ } catch (Exception x) {
+ // OK: we're gonna throw the original exception later.
+ LOG.finest("Ignoring exception when closing connector: "+x);
+ }
+ }
+
+ JMXConnector connect(JMXServiceURL url, Map env)
+ throws IOException {
+ final JMXConnector c = newJMXConnector(jmxURL, env);
+ c.connect(env);
+ return c;
+ }
+
+ /**
+ * Creates a new JMXConnector with the specified {@code url} and
+ * {@code env} options map.
+ *
+ * This method first calls {@link JMXConnectorFactory#newJMXConnector
+ * JMXConnectorFactory.newJMXConnector(jmxURL, env)} to obtain a new
+ * JMX connector, and returns that.
+ *
+ *
+ * A subclass of {@link JMXRemoteNamespace} can provide an implementation
+ * that connects to a sub namespace of the remote server by subclassing
+ * this class in the following way:
+ *
+ * class JMXRemoteSubNamespace extends JMXRemoteNamespace {
+ * private final String subnamespace;
+ * JMXRemoteSubNamespace(JMXServiceURL url,
+ * Map{@code } env, String subnamespace) {
+ * super(url,options);
+ * this.subnamespace = subnamespace;
+ * }
+ * protected JMXConnector newJMXConnector(JMXServiceURL url,
+ * Map env) throws IOException {
+ * final JMXConnector inner = super.newJMXConnector(url,env);
+ * return {@link JMXNamespaces#narrowToNamespace(JMXConnector,String)
+ * JMXNamespaces.narrowToNamespace(inner,subnamespace)};
+ * }
+ * }
+ *
+ *
+ *
+ * Some connectors, like the JMXMP connector server defined by the
+ * version 1.2 of the JMX API may not have been upgraded to use the
+ * new {@linkplain javax.management.event Event Service} defined in this
+ * version of the JMX API.
+ *
+ * In that case, and if the remote server to which this JMXRemoteNamespace
+ * connects also contains namespaces, it may be necessary to configure
+ * explicitly an {@linkplain
+ * javax.management.event.EventClientDelegate#newForwarder()
+ * Event Client Forwarder} on the remote server side, and to force the use
+ * of an {@link EventClient} on this client side.
+ *
+ * A subclass of {@link JMXRemoteNamespace} can provide an implementation
+ * of {@code newJMXConnector} that will force notification subscriptions
+ * to flow through an {@link EventClient} over a legacy protocol by
+ * overriding this method in the following way:
+ *
+ *
+ * class JMXRemoteEventClientNamespace extends JMXRemoteNamespace {
+ * JMXRemoteSubNamespaceConnector(JMXServiceURL url,
+ * Map env) {
+ * super(url,options);
+ * }
+ * protected JMXConnector newJMXConnector(JMXServiceURL url,
+ * Map env) throws IOException {
+ * final JMXConnector inner = super.newJMXConnector(url,env);
+ * return {@link EventClient#withEventClient(
+ * JMXConnector) EventClient.withEventClient(inner)};
+ * }
+ * }
+ *
+ *
+ * Note that the remote server also needs to provide an {@link
+ * javax.management.event.EventClientDelegateMBean}: only configuring
+ * the client side (this object) is not enough.
+ * In summary, this technique should be used if the remote server
+ * supports JMX namespaces, but uses a JMX Connector Server whose
+ * implementation does not transparently use the new Event Service
+ * (as would be the case with the JMXMPConnectorServer implementation
+ * from the reference implementation of the JMX Remote API 1.0
+ * specification).
+ *
+ * @param url The JMXServiceURL of the remote server.
+ * @param optionsMap An unmodifiable options map that will be passed to the
+ * {@link JMXConnectorFactory} when {@linkplain
+ * JMXConnectorFactory#newJMXConnector creating} the
+ * {@link JMXConnector} that can connect to the remote source
+ * MBean Server.
+ * @return An unconnected JMXConnector to use to connect to the remote
+ * server
+ * @throws java.io.IOException if the connector could not be created.
+ * @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map)
+ * @see #JMXRemoteNamespace
+ */
+ protected JMXConnector newJMXConnector(JMXServiceURL url,
+ Map optionsMap) throws IOException {
+ final JMXConnector c =
+ JMXConnectorFactory.newJMXConnector(jmxURL, optionsMap);
+// TODO: uncomment this when contexts are added
+// return ClientContext.withDynamicContext(c);
+ return c;
+ }
+
+ public void connect() throws IOException {
+ LOG.fine("connecting...");
+ final Map env =
+ new HashMap(getEnvMap());
+ try {
+ // XXX: We should probably document this...
+ // This allows to specify a loader name - which will be
+ // retrieved from the paret MBeanServer.
+ defaultClassLoader =
+ EnvHelp.resolveServerClassLoader(env,getMBeanServer());
+ } catch (InstanceNotFoundException x) {
+ final IOException io =
+ new IOException("ClassLoader not found");
+ io.initCause(x);
+ throw io;
+ }
+ env.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,defaultClassLoader);
+ final JMXServiceURL url = getJMXServiceURL();
+ final JMXConnector aconn = connect(url,env);
+ final MBeanServerConnection msc;
+ try {
+ msc = aconn.getMBeanServerConnection();
+ aconn.addConnectionNotificationListener(listener,null,aconn);
+ } catch (IOException io) {
+ close(aconn);
+ throw io;
+ } catch (RuntimeException x) {
+ close(aconn);
+ throw x;
+ }
+
+ switchConnection(conn,aconn,msc);
+
+ LOG.fine("connected.");
+ }
+
+ public void close() throws IOException {
+ if (conn == null) return;
+ LOG.fine("closing...");
+ // System.err.println(toString()+": closing...");
+ conn.close();
+ // System.err.println(toString()+": connector closed");
+ switchConnection(conn,null,null);
+ LOG.fine("closed.");
+ // System.err.println(toString()+": closed");
+ }
+
+ MBeanServerConnection getMBeanServerConnection() {
+ if (conn == null)
+ throw newRuntimeIOException("getMBeanServerConnection: not connected");
+ return server;
+ }
+
+ // Better than throwing UndeclaredThrowableException ...
+ private RuntimeException newRuntimeIOException(String msg) {
+ final IllegalStateException illegal = new IllegalStateException(msg);
+ return Util.newRuntimeIOException(new IOException(msg,illegal));
+ }
+
+ /**
+ * Returns the default class loader used by the underlying
+ * {@link JMXConnector}.
+ * @return the default class loader used when communicating with the
+ * remote source MBean server.
+ **/
+ ClassLoader getDefaultClassLoader() {
+ if (conn == null)
+ throw newRuntimeIOException("getMBeanServerConnection: not connected");
+ return defaultClassLoader;
+ }
+
+ public boolean isConnected() {
+ // This is a pleonasm
+ return (conn != null) && (server != null);
+ }
+
+
+ /**
+ * This name space handler will automatically {@link #close} its
+ * connection with the remote source in {@code preDeregister}.
+ **/
+ @Override
+ public void preDeregister() throws Exception {
+ try {
+ close();
+ } catch (IOException x) {
+ LOG.fine("Failed to close properly - exception ignored: " + x);
+ LOG.log(Level.FINEST,
+ "Failed to close properly - exception ignored",x);
+ }
+ super.preDeregister();
+ }
+
+ /**
+ * This method calls {@link
+ * javax.management.MBeanServerConnection#getMBeanCount
+ * getMBeanCount()} on the remote namespace.
+ * @throws java.io.IOException if an {@link IOException} is raised when
+ * communicating with the remote source namespace.
+ */
+ @Override
+ public Integer getMBeanCount() throws IOException {
+ return getMBeanServerConnection().getMBeanCount();
+ }
+
+ /**
+ * This method returns the result of calling {@link
+ * javax.management.MBeanServerConnection#getDomains
+ * getDomains()} on the remote namespace.
+ * @throws java.io.IOException if an {@link IOException} is raised when
+ * communicating with the remote source namespace.
+ */
+ @Override
+ public String[] getDomains() throws IOException {
+ return getMBeanServerConnection().getDomains();
+ }
+
+ /**
+ * This method returns the result of calling {@link
+ * javax.management.MBeanServerConnection#getDefaultDomain
+ * getDefaultDomain()} on the remote namespace.
+ * @throws java.io.IOException if an {@link IOException} is raised when
+ * communicating with the remote source namespace.
+ */
+ @Override
+ public String getDefaultDomain() throws IOException {
+ return getMBeanServerConnection().getDefaultDomain();
+ }
+
+ /**
+ * Creates a new instance of {@code JMXRemoteNamespace}.
+ * @param sourceURL a JMX service URL that can be used to connect to the
+ * source MBean Server. The source MBean Server is the remote
+ * MBean Server which contains the MBeans that will be mirrored
+ * in this namespace.
+ * @param optionsMap An options map that will be passed to the
+ * {@link JMXConnectorFactory} when {@linkplain
+ * JMXConnectorFactory#newJMXConnector creating} the
+ * {@link JMXConnector} used to connect to the remote source
+ * MBean Server. Can be null, which is equivalent to an empty map.
+ * @see #JMXRemoteNamespace JMXRemoteNamespace(sourceURL,optionsMap)
+ * @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map)
+ */
+ public static JMXRemoteNamespace newJMXRemoteNamespace(
+ JMXServiceURL sourceURL,
+ Map optionsMap) {
+ return new JMXRemoteNamespace(sourceURL, optionsMap);
+ }
+}
diff --git a/src/share/classes/javax/management/namespace/JMXRemoteNamespaceMBean.java b/src/share/classes/javax/management/namespace/JMXRemoteNamespaceMBean.java
new file mode 100644
index 0000000000000000000000000000000000000000..18b0fb86dfeeb4ecda2e8e69d24eb88f2887446e
--- /dev/null
+++ b/src/share/classes/javax/management/namespace/JMXRemoteNamespaceMBean.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.management.namespace;
+
+import java.io.IOException;
+import javax.management.remote.JMXServiceURL;
+
+/**
+ * A {@link JMXNamespaceMBean} that will connect to a remote MBeanServer
+ * by creating a {@link javax.management.remote.JMXConnector} from a
+ * {@link javax.management.remote.JMXServiceURL}.
+ * You can call {@link #connect connect()} and {@link #close close()}
+ * several times.
+ * @since 1.7
+ */
+public interface JMXRemoteNamespaceMBean
+ extends JMXNamespaceMBean {
+
+ /**
+ * Connects to the underlying remote source name space, if not already
+ * {@link #isConnected connected}.
+ * If connected, do nothing. Otherwise, creates a new connector from the
+ * {@link javax.management.remote.JMXServiceURL JMXServiceURL} provided at
+ * creation time, and connects to the remote source name space.
+ *
+ * The source MBeans will not appear in the target name space until the
+ * JMXRemoteNamespaceMBean is connected.
+ *
+ * It is possible to call {@code connect()}, {@link #close close()}, and
+ * {@code connect()} again.
+ * However, closing the connection with the remote name space may cause
+ * notification listeners to be lost, unless the client explicitly uses
+ * the new {@linkplain javax.management.event JMX event service}.
+ *
+ * @throws IOException if connection to the remote source name space fails.
+ * @see #isConnected isConnected
+ **/
+ public void connect()
+ throws IOException;
+
+ /**
+ * Closes the connection with the remote source name space.
+ * If the connection is already closed, do nothing.
+ * Otherwise, closes the underlying {@link
+ * javax.management.remote.JMXConnector}.
+ *
Once closed, it is possible to reopen the connection by
+ * calling {@link #connect connect}.
+ *
+ * @throws IOException if the connection to the remote source name space
+ * can't be closed properly.
+ * @see #isConnected isConnected
+ **/
+ public void close()
+ throws IOException;
+
+ /**
+ * Tells whether the connection to the remote source name space is opened.
+ * @see #connect connect
+ * @see #close close
+ * @return {@code true} if connected.
+ **/
+ public boolean isConnected();
+
+ /**
+ * Returns the {@link JMXServiceURL} address that points to the remote name
+ * space mirrored by this {@link JMXNamespaceMBean JMXNamespace MBean},
+ * if available.
+ * @return The {@link JMXServiceURL} address that points to the remote name
+ * space mirrored by this {@link JMXNamespaceMBean JMXNamespace MBean},
+ * or {@code null}.
+ */
+ public JMXServiceURL getAddress();
+}
diff --git a/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java b/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..7eeda961e31756773b635df5aa45fb44c2fc3207
--- /dev/null
+++ b/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java
@@ -0,0 +1,702 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.management.namespace;
+
+import com.sun.jmx.mbeanserver.Util;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.Set;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.NotCompliantMBeanException;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.OperationsException;
+import javax.management.QueryExp;
+import javax.management.ReflectionException;
+import javax.management.loading.ClassLoaderRepository;
+
+/**
+ * An object of this class implements the MBeanServer interface
+ * and, for each of its methods forwards the request to a wrapped
+ * {@link MBeanServerConnection} object.
+ * Some methods of the {@link MBeanServer} interface do not have
+ * any equivalent in {@link MBeanServerConnection}. In that case, an
+ * {@link UnsupportedOperationException} will be thrown.
+ *
+ *
A typical use of this class is to apply a {@link QueryExp} object locally,
+ * on an MBean that resides in a remote MBeanServer. Since an
+ * MBeanServerConnection is not an MBeanServer, it cannot be passed
+ * to the setMBeanServer()
method of the {@link QueryExp}
+ * object. However, this object can.
+ *
+ * @since 1.7
+ */
+public class MBeanServerConnectionWrapper
+ implements MBeanServer {
+
+ private final MBeanServerConnection wrapped;
+ private final ClassLoader defaultCl;
+
+ /**
+ * Construct a new object that implements {@link MBeanServer} by
+ * forwarding its methods to the given {@link MBeanServerConnection}.
+ * This constructor is equivalent to {@link #MBeanServerConnectionWrapper(
+ * MBeanServerConnection, ClassLoader) MBeanServerConnectionWrapper(wrapped,
+ * null)}.
+ *
+ * @param wrapped the {@link MBeanServerConnection} to which methods
+ * are to be forwarded. This parameter can be null, in which case the
+ * {@code MBeanServerConnection} will typically be supplied by overriding
+ * {@link #getMBeanServerConnection}.
+ */
+ public MBeanServerConnectionWrapper(MBeanServerConnection wrapped) {
+ this(wrapped, null);
+ }
+
+ /**
+ * Construct a new object that implements {@link MBeanServer} by
+ * forwarding its methods to the given {@link MBeanServerConnection}.
+ * The {@code defaultCl} parameter specifies the value to be returned
+ * by {@link #getDefaultClassLoader}. A null value is equivalent to
+ * {@link Thread#getContextClassLoader()}.
+ *
+ * @param wrapped the {@link MBeanServerConnection} to which methods
+ * are to be forwarded. This parameter can be null, in which case the
+ * {@code MBeanServerConnection} will typically be supplied by overriding
+ * {@link #getMBeanServerConnection}.
+ * @param defaultCl the value to be returned by {@link
+ * #getDefaultClassLoader}. A null value is equivalent to the current
+ * thread's {@linkplain Thread#getContextClassLoader()}.
+ */
+ public MBeanServerConnectionWrapper(MBeanServerConnection wrapped,
+ ClassLoader defaultCl) {
+ this.wrapped = wrapped;
+ this.defaultCl = (defaultCl == null) ?
+ Thread.currentThread().getContextClassLoader() : defaultCl;
+ }
+
+ /**
+ * Returns an MBeanServerConnection. This method is called each time
+ * an operation must be invoked on the underlying MBeanServerConnection.
+ * The default implementation returns the MBeanServerConnection that
+ * was supplied to the constructor of this MBeanServerConnectionWrapper.
+ **/
+ protected MBeanServerConnection getMBeanServerConnection() {
+ return wrapped;
+ }
+
+ /**
+ * Returns the default class loader passed to the constructor. If the
+ * value passed was null, then the returned value will be the
+ * {@linkplain Thread#getContextClassLoader() context class loader} at the
+ * time this object was constructed.
+ *
+ * @return the ClassLoader that was passed to the constructor.
+ **/
+ public ClassLoader getDefaultClassLoader() {
+ return defaultCl;
+ }
+
+ /**
+ * This method is called each time an IOException is raised when
+ * trying to forward an operation to the underlying
+ * MBeanServerConnection, as a result of calling
+ * {@link #getMBeanServerConnection()} or as a result of invoking the
+ * operation on the returned connection. Since the methods in
+ * {@link MBeanServer} are not declared to throw {@code IOException},
+ * this method must return a {@code RuntimeException} to be thrown
+ * instead. Typically, the original {@code IOException} will be in the
+ * {@linkplain Throwable#getCause() cause chain} of the {@code
+ * RuntimeException}.
+ *
+ * Subclasses may redefine this method if they need to perform any
+ * specific handling of IOException (logging etc...).
+ *
+ * @param x The raised IOException.
+ * @param method The name of the method in which the exception was
+ * raised. This is one of the methods of the MBeanServer
+ * interface.
+ *
+ * @return A RuntimeException that should be thrown by the caller.
+ * In this default implementation, this is a
+ * {@link RuntimeException} wrapping x.
+ **/
+ protected RuntimeException wrapIOException(IOException x, String method) {
+ return Util.newRuntimeIOException(x);
+ }
+
+ // Take care of getMBeanServerConnection returning null.
+ //
+ private synchronized MBeanServerConnection connection()
+ throws IOException {
+ final MBeanServerConnection c = getMBeanServerConnection();
+ if (c == null)
+ throw new IOException("MBeanServerConnection unavailable");
+ return c;
+ }
+
+ //--------------------------------------------
+ //--------------------------------------------
+ //
+ // Implementation of the MBeanServer interface
+ //
+ //--------------------------------------------
+ //--------------------------------------------
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public void addNotificationListener(ObjectName name,
+ NotificationListener listener,
+ NotificationFilter filter,
+ Object handback)
+ throws InstanceNotFoundException {
+ try {
+ connection().addNotificationListener(name, listener,
+ filter, handback);
+ } catch (IOException x) {
+ throw wrapIOException(x,"addNotificationListener");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public void addNotificationListener(ObjectName name,
+ ObjectName listener,
+ NotificationFilter filter,
+ Object handback)
+ throws InstanceNotFoundException {
+ try {
+ connection().addNotificationListener(name, listener,
+ filter, handback);
+ } catch (IOException x) {
+ throw wrapIOException(x,"addNotificationListener");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public ObjectInstance createMBean(String className, ObjectName name)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException {
+ try {
+ return connection().createMBean(className, name);
+ } catch (IOException x) {
+ throw wrapIOException(x,"createMBean");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public ObjectInstance createMBean(String className, ObjectName name,
+ Object params[], String signature[])
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException {
+ try {
+ return connection().createMBean(className, name,
+ params, signature);
+ } catch (IOException x) {
+ throw wrapIOException(x,"createMBean");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ ObjectName loaderName)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ InstanceNotFoundException {
+ try {
+ return connection().createMBean(className, name, loaderName);
+ } catch (IOException x) {
+ throw wrapIOException(x,"createMBean");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ ObjectName loaderName,
+ Object params[],
+ String signature[])
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ InstanceNotFoundException {
+ try {
+ return connection().createMBean(className, name, loaderName,
+ params, signature);
+ } catch (IOException x) {
+ throw wrapIOException(x,"createMBean");
+ }
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException}. This behavior can
+ * be changed by subclasses.
+ * @deprecated see {@link MBeanServer#deserialize(ObjectName,byte[])
+ * MBeanServer}
+ */
+ @Deprecated
+ public ObjectInputStream deserialize(ObjectName name, byte[] data)
+ throws InstanceNotFoundException, OperationsException {
+ throw new UnsupportedOperationException("deserialize");
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException}. This behavior can
+ * be changed by subclasses.
+ * @deprecated see {@link MBeanServer#deserialize(String,byte[])
+ * MBeanServer}
+ */
+ @Deprecated
+ public ObjectInputStream deserialize(String className, byte[] data)
+ throws OperationsException, ReflectionException {
+ throw new UnsupportedOperationException("deserialize");
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException}. This behavior can
+ * be changed by subclasses.
+ * @deprecated see {@link MBeanServer#deserialize(String,ObjectName,byte[])
+ * MBeanServer}
+ */
+ @Deprecated
+ public ObjectInputStream deserialize(String className,
+ ObjectName loaderName,
+ byte[] data)
+ throws
+ InstanceNotFoundException,
+ OperationsException,
+ ReflectionException {
+ throw new UnsupportedOperationException("deserialize");
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public Object getAttribute(ObjectName name, String attribute)
+ throws
+ MBeanException,
+ AttributeNotFoundException,
+ InstanceNotFoundException,
+ ReflectionException {
+ try {
+ return connection().getAttribute(name, attribute);
+ } catch (IOException x) {
+ throw wrapIOException(x,"getAttribute");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public AttributeList getAttributes(ObjectName name, String[] attributes)
+ throws InstanceNotFoundException, ReflectionException {
+ try {
+ return connection().getAttributes(name, attributes);
+ } catch (IOException x) {
+ throw wrapIOException(x,"getAttributes");
+ }
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException}. This behavior can
+ * be changed by subclasses.
+ */
+ public ClassLoader getClassLoader(ObjectName loaderName)
+ throws InstanceNotFoundException {
+ throw new UnsupportedOperationException("getClassLoader");
+ }
+
+ /**
+ * Returns the {@linkplain #getDefaultClassLoader() default class loader}.
+ * This behavior can be changed by subclasses.
+ */
+ public ClassLoader getClassLoaderFor(ObjectName mbeanName)
+ throws InstanceNotFoundException {
+ return getDefaultClassLoader();
+ }
+
+ /**
+ * Returns a {@link ClassLoaderRepository} based on the class loader
+ * returned by {@link #getDefaultClassLoader()}.
+ * @return a {@link ClassLoaderRepository} that contains a single
+ * class loader, returned by {@link #getDefaultClassLoader()}.
+ **/
+ public ClassLoaderRepository getClassLoaderRepository() {
+ // We return a new ClassLoaderRepository each time this method is
+ // called. This is by design, because there's no guarantee that
+ // getDefaultClassLoader() will always return the same class loader.
+ return Util.getSingleClassLoaderRepository(getDefaultClassLoader());
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public String getDefaultDomain() {
+ try {
+ return connection().getDefaultDomain();
+ } catch (IOException x) {
+ throw wrapIOException(x,"getDefaultDomain");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public String[] getDomains() {
+ try {
+ return connection().getDomains();
+ } catch (IOException x) {
+ throw wrapIOException(x,"getDomains");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public Integer getMBeanCount() {
+ try {
+ return connection().getMBeanCount();
+ } catch (IOException x) {
+ throw wrapIOException(x,"getMBeanCount");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public MBeanInfo getMBeanInfo(ObjectName name)
+ throws
+ InstanceNotFoundException,
+ IntrospectionException,
+ ReflectionException {
+ try {
+ return connection().getMBeanInfo(name);
+ } catch (IOException x) {
+ throw wrapIOException(x,"getMBeanInfo");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public ObjectInstance getObjectInstance(ObjectName name)
+ throws InstanceNotFoundException {
+ try {
+ return connection().getObjectInstance(name);
+ } catch (IOException x) {
+ throw wrapIOException(x,"getObjectInstance");
+ }
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException}. This behavior can
+ * be changed by subclasses.
+ */
+ public Object instantiate(String className)
+ throws ReflectionException, MBeanException {
+ throw new UnsupportedOperationException("instantiate");
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException}. This behavior can
+ * be changed by subclasses.
+ */
+ public Object instantiate(String className,
+ Object params[],
+ String signature[])
+ throws ReflectionException, MBeanException {
+ throw new UnsupportedOperationException("instantiate");
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException}. This behavior can
+ * be changed by subclasses.
+ */
+ public Object instantiate(String className, ObjectName loaderName)
+ throws ReflectionException, MBeanException,
+ InstanceNotFoundException {
+ throw new UnsupportedOperationException("instantiate");
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException}. This behavior can
+ * be changed by subclasses.
+ */
+ public Object instantiate(String className, ObjectName loaderName,
+ Object params[], String signature[])
+ throws ReflectionException, MBeanException,
+ InstanceNotFoundException {
+ throw new UnsupportedOperationException("instantiate");
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public Object invoke(ObjectName name, String operationName,
+ Object params[], String signature[])
+ throws
+ InstanceNotFoundException,
+ MBeanException,
+ ReflectionException {
+ try {
+ return connection().invoke(name,operationName,params,signature);
+ } catch (IOException x) {
+ throw wrapIOException(x,"invoke");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public boolean isInstanceOf(ObjectName name, String className)
+ throws InstanceNotFoundException {
+ try {
+ return connection().isInstanceOf(name, className);
+ } catch (IOException x) {
+ throw wrapIOException(x,"isInstanceOf");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public boolean isRegistered(ObjectName name) {
+ try {
+ return connection().isRegistered(name);
+ } catch (IOException x) {
+ throw wrapIOException(x,"isRegistered");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ * If an IOException is raised, returns an empty Set.
+ */
+ public Set queryMBeans(ObjectName name, QueryExp query) {
+ try {
+ return connection().queryMBeans(name, query);
+ } catch (IOException x) {
+ throw wrapIOException(x,"queryMBeans");
+ //return Collections.emptySet();
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ * If an IOException is raised, returns an empty Set.
+ */
+ public Set queryNames(ObjectName name, QueryExp query) {
+ try {
+ return connection().queryNames(name, query);
+ } catch (IOException x) {
+ throw wrapIOException(x,"queryNames");
+ //return Collections.emptySet();
+ }
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException}. This behavior can
+ * be changed by subclasses.
+ */
+ public ObjectInstance registerMBean(Object object, ObjectName name)
+ throws
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ NotCompliantMBeanException {
+ throw new UnsupportedOperationException("registerMBean");
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public void removeNotificationListener(ObjectName name,
+ NotificationListener listener)
+ throws InstanceNotFoundException, ListenerNotFoundException {
+ try {
+ connection().removeNotificationListener(name, listener);
+ } catch (IOException x) {
+ throw wrapIOException(x,"removeNotificationListener");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public void removeNotificationListener(ObjectName name,
+ NotificationListener listener,
+ NotificationFilter filter,
+ Object handback)
+ throws InstanceNotFoundException, ListenerNotFoundException {
+ try {
+ connection().removeNotificationListener(name, listener,
+ filter, handback);
+ } catch (IOException x) {
+ throw wrapIOException(x,"removeNotificationListener");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public void removeNotificationListener(ObjectName name,
+ ObjectName listener)
+ throws InstanceNotFoundException, ListenerNotFoundException {
+ try {
+ connection().removeNotificationListener(name, listener);
+ } catch (IOException x) {
+ throw wrapIOException(x,"removeNotificationListener");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public void removeNotificationListener(ObjectName name,
+ ObjectName listener,
+ NotificationFilter filter,
+ Object handback)
+ throws InstanceNotFoundException, ListenerNotFoundException {
+ try {
+ connection().removeNotificationListener(name, listener,
+ filter, handback);
+ } catch (IOException x) {
+ throw wrapIOException(x,"removeNotificationListener");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public void setAttribute(ObjectName name, Attribute attribute)
+ throws
+ InstanceNotFoundException,
+ AttributeNotFoundException,
+ InvalidAttributeValueException,
+ MBeanException,
+ ReflectionException {
+ try {
+ connection().setAttribute(name, attribute);
+ } catch (IOException x) {
+ throw wrapIOException(x,"setAttribute");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public AttributeList setAttributes(ObjectName name,
+ AttributeList attributes)
+ throws InstanceNotFoundException, ReflectionException {
+ try {
+ return connection().setAttributes(name, attributes);
+ } catch (IOException x) {
+ throw wrapIOException(x,"setAttributes");
+ }
+ }
+
+ /**
+ * Forward this method to the
+ * wrapped object.
+ */
+ public void unregisterMBean(ObjectName name)
+ throws InstanceNotFoundException, MBeanRegistrationException {
+ try {
+ connection().unregisterMBean(name);
+ } catch (IOException x) {
+ throw wrapIOException(x,"unregisterMBean");
+ }
+ }
+
+ //----------------
+ // PRIVATE METHODS
+ //----------------
+
+}
diff --git a/src/share/classes/com/sun/jmx/interceptor/MBeanServerSupport.java b/src/share/classes/javax/management/namespace/MBeanServerSupport.java
similarity index 98%
rename from src/share/classes/com/sun/jmx/interceptor/MBeanServerSupport.java
rename to src/share/classes/javax/management/namespace/MBeanServerSupport.java
index e7144cf36e19da7cf16adf628e8c7dd7f3434a32..903be3c308f1029a76777a1cbb18efa7a0de2a92 100644
--- a/src/share/classes/com/sun/jmx/interceptor/MBeanServerSupport.java
+++ b/src/share/classes/javax/management/namespace/MBeanServerSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,9 @@
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
-package com.sun.jmx.interceptor;
+package javax.management.namespace;
+import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.mbeanserver.Util;
import java.io.ObjectInputStream;
import java.util.Collections;
@@ -47,7 +48,6 @@ import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationEmitter;
@@ -193,14 +193,6 @@ import javax.management.loading.ClassLoaderRepository;
* }
*
* public class PropsMBS extends MBeanServerSupport {
- * private static ObjectName newObjectName(String name) {
- * try {
- * return new ObjectName(name);
- * } catch (MalformedObjectNameException e) {
- * throw new AssertionError(e);
- * }
- * }
- *
* public static class PropertyImpl implements PropertyMBean {
* private final String name;
*
@@ -219,7 +211,7 @@ import javax.management.loading.ClassLoaderRepository;
* throws InstanceNotFoundException {
*
* // Check that the name is a legal one for a Property MBean
- * ObjectName namePattern = newObjectName(
+ * ObjectName namePattern = ObjectName.valueOf(
* "com.example:type=Property,name=\"*\"");
* if (!namePattern.apply(name))
* throw new InstanceNotFoundException(name);
@@ -239,7 +231,7 @@ import javax.management.loading.ClassLoaderRepository;
* {@code Set names = new TreeSet();}
* Properties props = System.getProperties();
* for (String propName : props.stringPropertyNames()) {
- * ObjectName objectName = newObjectName(
+ * ObjectName objectName = ObjectName.valueOf(
* "com.example:type=Property,name=" +
* ObjectName.quote(propName));
* names.add(objectName);
@@ -278,7 +270,7 @@ import javax.management.loading.ClassLoaderRepository;
* }
*
* public void propertyChanged(String name, String newValue) {
- * ObjectName objectName = newObjectName(
+ * ObjectName objectName = ObjectName.valueOf(
* "com.example:type=Property,name=" + ObjectName.quote(name));
* Notification n = new Notification(
* "com.example.property.changed", objectName, 0L,
@@ -343,7 +335,7 @@ import javax.management.loading.ClassLoaderRepository;
* vem.publish}(name, n)
. See the example
* above.
*
- * @since Java SE 7
+ * @since 1.7
*/
public abstract class MBeanServerSupport implements MBeanServer {
@@ -351,7 +343,7 @@ public abstract class MBeanServerSupport implements MBeanServer {
* A logger for this class.
*/
private static final Logger LOG =
- Logger.getLogger(MBeanServerSupport.class.getName());
+ JmxProperties.NAMESPACE_LOGGER;
/**
* Make a new {@code MBeanServerSupport} instance.
@@ -1314,9 +1306,7 @@ public abstract class MBeanServerSupport implements MBeanServer {
if (name.getDomain().equals("")) {
String defaultDomain = getDefaultDomain();
try {
- // XXX change to ObjectName.switchDomain
- // current code DOES NOT PRESERVE the order of keys
- name = new ObjectName(defaultDomain, name.getKeyPropertyList());
+ name = name.withDomain(getDefaultDomain());
} catch (Exception e) {
throw newIllegalArgumentException(
"Illegal default domain: " + defaultDomain);
diff --git a/src/share/classes/javax/management/namespace/VirtualEventManager.java b/src/share/classes/javax/management/namespace/VirtualEventManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..336f37565cba35728219ba18a5b53edda1415845
--- /dev/null
+++ b/src/share/classes/javax/management/namespace/VirtualEventManager.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.management.namespace;
+
+import com.sun.jmx.remote.util.ClassLogger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.management.InstanceNotFoundException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.Notification;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.event.EventConsumer;
+
+/**
+ * This class maintains a list of subscribers for ObjectName patterns and
+ * allows a notification to be sent to all subscribers for a given ObjectName.
+ * It is typically used in conjunction with {@link MBeanServerSupport}
+ * to implement a namespace with Virtual MBeans that can emit notifications.
+ * The {@code VirtualEventManager} keeps track of the listeners that have been
+ * added to each Virtual MBean. When an event occurs that should trigger a
+ * notification from a Virtual MBean, the {@link #publish publish} method can
+ * be used to send it to the appropriate listeners.
+ * @since 1.7
+ */
+public class VirtualEventManager implements EventConsumer {
+ /**
+ * Create a new {@code VirtualEventManager}.
+ */
+ public VirtualEventManager() {
+ }
+
+ public void subscribe(
+ ObjectName name,
+ NotificationListener listener,
+ NotificationFilter filter,
+ Object handback) {
+
+ if (logger.traceOn())
+ logger.trace("subscribe", "" + name);
+
+ if (name == null)
+ throw new IllegalArgumentException("Null MBean name");
+
+ if (listener == null)
+ throw new IllegalArgumentException("Null listener");
+
+ Map> map =
+ name.isPattern() ? patternSubscriptionMap : exactSubscriptionMap;
+
+ final ListenerInfo li = new ListenerInfo(listener, filter, handback);
+ List list;
+
+ synchronized (map) {
+ list = map.get(name);
+ if (list == null) {
+ list = new ArrayList();
+ map.put(name, list);
+ }
+ list.add(li);
+ }
+ }
+
+ public void unsubscribe(
+ ObjectName name, NotificationListener listener)
+ throws ListenerNotFoundException {
+
+ if (logger.traceOn())
+ logger.trace("unsubscribe2", "" + name);
+
+ if (name == null)
+ throw new IllegalArgumentException("Null MBean name");
+
+ if (listener == null)
+ throw new ListenerNotFoundException();
+
+ Map> map =
+ name.isPattern() ? patternSubscriptionMap : exactSubscriptionMap;
+
+ final ListenerInfo li = new ListenerInfo(listener, null, null);
+ List list;
+ synchronized (map) {
+ list = map.get(name);
+ if (list == null || !list.remove(li))
+ throw new ListenerNotFoundException();
+
+ if (list.isEmpty())
+ map.remove(name);
+ }
+ }
+
+ /**
+ * Unsubscribes a listener which is listening to an MBean or a set of
+ * MBeans represented by an {@code ObjectName} pattern.
+ *
+ * The listener to be removed must have been added by the {@link
+ * #subscribe subscribe} method with the given {@code name}, {@code filter},
+ * and {@code handback}. If the {@code
+ * name} is a pattern, then the {@code subscribe} must have used the same
+ * pattern. If the same listener has been subscribed more than once to the
+ * {@code name} with the same filter and handback, only one listener is
+ * removed.
+ *
+ * @param name The name of the MBean or an {@code ObjectName} pattern
+ * representing a set of MBeans to which the listener was subscribed.
+ * @param listener A listener that was previously subscribed to the
+ * MBean(s).
+ *
+ * @throws ListenerNotFoundException The given {@code listener} was not
+ * subscribed to the given {@code name}.
+ *
+ * @see #subscribe
+ */
+ public void unsubscribe(
+ ObjectName name, NotificationListener listener,
+ NotificationFilter filter, Object handback)
+ throws ListenerNotFoundException {
+
+ if (logger.traceOn())
+ logger.trace("unsubscribe4", "" + name);
+
+ if (name == null)
+ throw new IllegalArgumentException("Null MBean name");
+
+ if (listener == null)
+ throw new ListenerNotFoundException();
+
+ Map> map =
+ name.isPattern() ? patternSubscriptionMap : exactSubscriptionMap;
+
+ List list;
+ synchronized (map) {
+ list = map.get(name);
+ boolean removed = false;
+ for (Iterator it = list.iterator(); it.hasNext(); ) {
+ ListenerInfo li = it.next();
+ if (li.equals(listener, filter, handback)) {
+ it.remove();
+ removed = true;
+ break;
+ }
+ }
+ if (!removed)
+ throw new ListenerNotFoundException();
+
+ if (list.isEmpty())
+ map.remove(name);
+ }
+ }
+
+ /**
+ * Sends a notification to the subscribers for a given MBean.
+ *
+ * For each listener subscribed with an {@code ObjectName} that either
+ * is equal to {@code emitterName} or is a pattern that matches {@code
+ * emitterName}, if the associated filter accepts the notification then it
+ * is forwarded to the listener.
+ *
+ * @param emitterName The name of the MBean emitting the notification.
+ * @param n The notification being sent by the MBean called
+ * {@code emitterName}.
+ *
+ * @throws IllegalArgumentException If the emitterName of the
+ * notification is null or is an {@code ObjectName} pattern.
+ */
+ public void publish(ObjectName emitterName, Notification n) {
+ if (logger.traceOn())
+ logger.trace("publish", "" + emitterName);
+
+ if (n == null)
+ throw new IllegalArgumentException("Null notification");
+
+ if (emitterName == null) {
+ throw new IllegalArgumentException(
+ "Null emitter name");
+ } else if (emitterName.isPattern()) {
+ throw new IllegalArgumentException(
+ "The emitter must not be an ObjectName pattern");
+ }
+
+ final List listeners = new ArrayList();
+
+ // If there are listeners for this exact name, add them.
+ synchronized (exactSubscriptionMap) {
+ List exactListeners =
+ exactSubscriptionMap.get(emitterName);
+ if (exactListeners != null)
+ listeners.addAll(exactListeners);
+ }
+
+ // Loop over subscription patterns, and add all listeners for each
+ // one that matches the emitterName name.
+ synchronized (patternSubscriptionMap) {
+ for (ObjectName on : patternSubscriptionMap.keySet()) {
+ if (on.apply(emitterName))
+ listeners.addAll(patternSubscriptionMap.get(on));
+ }
+ }
+
+ // Send the notification to all the listeners we found.
+ sendNotif(listeners, n);
+ }
+
+ /**
+ * Returns a {@link NotificationEmitter} object which can be used to
+ * subscribe or unsubscribe for notifications with the named
+ * mbean. The returned object implements {@link
+ * NotificationEmitter#addNotificationListener
+ * addNotificationListener(listener, filter, handback)} as
+ * {@link #subscribe this.subscribe(name, listener, filter, handback)}
+ * and the two {@code removeNotificationListener} methods from {@link
+ * NotificationEmitter} as the corresponding {@code unsubscribe} methods
+ * from this class.
+ *
+ * @param name The name of the MBean whose notifications are being
+ * subscribed, or unsuscribed.
+ *
+ * @return A {@link NotificationEmitter}
+ * that can be used to subscribe or unsubscribe for
+ * notifications emitted by the named MBean, or {@code null} if
+ * the MBean does not emit notifications and should not
+ * be considered as a {@code NotificationBroadcaster}. This class
+ * never returns null but a subclass is allowed to.
+ *
+ * @throws InstanceNotFoundException if {@code name} does not exist.
+ * This implementation never throws {@code InstanceNotFoundException} but
+ * a subclass is allowed to override this method to do so.
+ */
+ public NotificationEmitter
+ getNotificationEmitterFor(final ObjectName name)
+ throws InstanceNotFoundException {
+ final NotificationEmitter emitter = new NotificationEmitter() {
+ public void addNotificationListener(NotificationListener listener,
+ NotificationFilter filter, Object handback)
+ throws IllegalArgumentException {
+ subscribe(name, listener, filter, handback);
+ }
+
+ public void removeNotificationListener(
+ NotificationListener listener)
+ throws ListenerNotFoundException {
+ unsubscribe(name, listener);
+ }
+
+ public void removeNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object handback)
+ throws ListenerNotFoundException {
+ unsubscribe(name, listener, filter, handback);
+ }
+
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ // Never called.
+ return null;
+ }
+ };
+ return emitter;
+ }
+
+ // ---------------------------------
+ // private stuff
+ // ---------------------------------
+
+ private static class ListenerInfo {
+ public final NotificationListener listener;
+ public final NotificationFilter filter;
+ public final Object handback;
+
+ public ListenerInfo(NotificationListener listener,
+ NotificationFilter filter,
+ Object handback) {
+
+ if (listener == null) {
+ throw new IllegalArgumentException("Null listener.");
+ }
+
+ this.listener = listener;
+ this.filter = filter;
+ this.handback = handback;
+ }
+
+ /* Two ListenerInfo instances are equal if they have the same
+ * NotificationListener. This means that we can use List.remove
+ * to implement the two-argument removeNotificationListener.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (!(o instanceof ListenerInfo)) {
+ return false;
+ }
+
+ return listener.equals(((ListenerInfo)o).listener);
+ }
+
+ /* Method that compares all four fields, appropriate for the
+ * four-argument removeNotificationListener.
+ */
+ boolean equals(
+ NotificationListener listener,
+ NotificationFilter filter,
+ Object handback) {
+ return (this.listener == listener && same(this.filter, filter)
+ && same(this.handback, handback));
+ }
+
+ private static boolean same(Object x, Object y) {
+ if (x == y)
+ return true;
+ if (x == null)
+ return false;
+ return x.equals(y);
+ }
+
+ @Override
+ public int hashCode() {
+ return listener.hashCode();
+ }
+ }
+
+ private static void sendNotif(List listeners, Notification n) {
+ for (ListenerInfo li : listeners) {
+ if (li.filter == null ||
+ li.filter.isNotificationEnabled(n)) {
+ try {
+ li.listener.handleNotification(n, li.handback);
+ } catch (Exception e) {
+ logger.trace("sendNotif", "handleNotification", e);
+ }
+ }
+ }
+ }
+
+ // ---------------------------------
+ // private variables
+ // ---------------------------------
+
+ private final Map> exactSubscriptionMap =
+ new HashMap>();
+ private final Map> patternSubscriptionMap =
+ new HashMap>();
+
+ // trace issue
+ private static final ClassLogger logger =
+ new ClassLogger("javax.management.event", "EventManager");
+}
diff --git a/src/share/classes/javax/management/namespace/package-info.java b/src/share/classes/javax/management/namespace/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..df8354bab635379c29f3340676192c2c1b0a5238
--- /dev/null
+++ b/src/share/classes/javax/management/namespace/package-info.java
@@ -0,0 +1,597 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * The javax.management.namespace
package makes it possible
+ * to federate MBeanServers into a hierarchical name space.
+ *
+ * What Is a Name Space?
+ *
+ * A name space is like an {@link javax.management.MBeanServer} within
+ * an {@code MBeanServer}. Just as a file system folder can contain
+ * another file system folder, an {@code MBeanServer} can contain another
+ * {@code MBeanServer}. Similarly, just as a remote folder on a remote
+ * disk can be mounted on a parent folder on a local disk, a remote name
+ * space in a remote {@code MBeanServer} can be mounted on a name
+ * space in a local parent {@code MBeanServer}.
+ *
+ *
+ * The javax.management.namespace
API thus makes it possible to
+ * create a hierarchy of MBean servers federated in a hierarchical name
+ * space inside a single {@code MBeanServer}.
+ *
+ * How To Create a Name Space?
+ *
+ * To create a name space, you only need to register a
+ * {@link javax.management.namespace.JMXNamespace} MBean in
+ * an MBean server. We have seen that a namespace is like
+ * an {@code MBeanServer} within an {@code MBeanServer}, and
+ * therefore, it is possible to create a namespace that shows the
+ * content of another {@code MBeanServer}. The simplest case is
+ * when that {@code MBeanServer} is another {@code MBeanServer}
+ * created by the {@link javax.management.MBeanServerFactory} as
+ * shown in the extract below:
+ *
+ *
+ * final MBeanServer server = ....;
+ * final String namespace = "foo";
+ * final ObjectName namespaceName = {@link javax.management.namespace.JMXNamespaces#getNamespaceObjectName
+ * JMXNamespaces.getNamespaceObjectName(namespace)};
+ * server.registerMBean(new JMXNamespace(MBeanServerFactory.newMBeanServer()),
+ * namespaceName);
+ *
+ *
+ * To navigate in namespaces and view their content, the easiest way is
+ * to use an instance of {@link javax.management.namespace.JMXNamespaceView}. For instance, given
+ * the {@code server} above, in which we created a namespace {@code "foo"},
+ * it is possible to create a {@code JMXNamespaceView} that will make it
+ * possible to navigate easily in the namespaces and sub-namespaces of that
+ * server:
+ *
+ *
+ * // create a namespace view for 'server'
+ * final JMXNamespaceView view = new JMXNamespaceView(server);
+ *
+ * // list all top level namespaces in 'server'
+ * System.out.println("List of namespaces: " + Arrays.toString({@link javax.management.namespace.JMXNamespaceView#list() view.list()}));
+ *
+ * // go down into namespace 'foo': provides a namespace view of 'foo' and its
+ * // sub namespaces...
+ * final JMXNamespaceView foo = {@link javax.management.namespace.JMXNamespaceView#down view.down("foo")};
+ *
+ * // list all MBeans contained in namespace 'foo'
+ * System.out.println({@link javax.management.namespace.JMXNamespaceView#where() foo.where()} + " contains: " +
+ * {@link javax.management.namespace.JMXNamespaceView#getMBeanServerConnection foo.getMBeanServerConnection()}.queryNames(null,null));
+ *
+ *
+ * It is also possible to create more complex namespaces, such as namespaces
+ * that point to MBean servers located in remote JVMs.
+ *
+ *
+ * For instance, to mount the MBeanServer accessible
+ * at service:jmx:rmi:///jndi/rmi://localhost:9000/jmxrmi
+ * in a name space {@code "foo"} inside the {@linkplain
+ * java.lang.management.ManagementFactory#getPlatformMBeanServer platform
+ * MBeanServer} you would write the following piece of code:
+ *
+ *
+ * final JMXServiceURL sourceURL =
+ * new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9000/jmxrmi");
+ * final MBeanServer platform = ManagementFactory.getPlatformMBeanServer();
+ * final Map<String,Object> options = Collections.emptyMap();
+ * final JMXRemoteNamespace mbean = {@link
+ * javax.management.namespace.JMXRemoteNamespace JMXRemoteNamespace}.
+ * {@link javax.management.namespace.JMXRemoteNamespace#newJMXRemoteNamespace newJMXRemoteNamespace(sourceURL, options)};
+ * final ObjectName name = {@link javax.management.namespace.JMXNamespaces JMXNamespaces}.{@link javax.management.namespace.JMXNamespaces#getNamespaceObjectName(String) getNamespaceObjectName("foo")};
+ * final ObjectInstance ref = platform.registerMBean(mbean,name);
+ * platform.invoke(ref.getObjectName(),"connect",null,null);
+ *
+ *
+ * What Does a Name Space Look Like?
+ *
+ *
+ * We have seen that {@link javax.management.namespace.JMXNamespaceView} class
+ * provides an easy way to navigate within namespaces. It is however also
+ * possible to interact with namespaces directly from the top level
+ * {@code MBeanServer} in which they have been created.
+ * From the outside, a name space only appears as a special MBean in
+ * the MBean server. There's nothing much you can do with this MBean
+ * directly.
+ *
+ *
+ * For instance, let's assume you have registered a {@link
+ * javax.management.namespace.JMXRemoteNamespaceMBean
+ * JMXRemoteNamespaceMBean} to manage the name space {@code "foo"}.
+ *
If you query for
+ * platform.queryNames("*//:*",null)
, then you will see
+ * one MBean named {@code "foo//:type=JMXNamespace"}.
+ *
This is the {@link javax.management.namespace.JMXNamespace}
+ * MBean which is in charge of handling the namespace {@code "foo"}.
+ *
+ *
+ * In fact, name space handler MBeans are instances of
+ * the class {@link javax.management.namespace.JMXNamespace} - or
+ * instances of a subclass of that class.
+ * They have a special {@link javax.management.ObjectName} defined by
+ * {@link javax.management.namespace.JMXNamespaces#getNamespaceObjectName
+ * JMXNamespaces.getNamespaceObjectName}.
+ * {@link javax.management.namespace.JMXNamespace} instances are able
+ * to return an {@link
+ * javax.management.namespace.JMXNamespace#getSourceServer MBeanServer}
+ * which corresponds to the MBeanServer within (= the name space itself).
+ *
+ *
+ * So how does it work? How can you see the MBeans contained in the new
+ * name space?
+ *
+ * In order to address scalability issues, MBeans registered in
+ * namespaces (such as our namespace {@code "foo"} above) can not be
+ * seen with {@code mbeanServer.queryNames("*:*",null)}. To see the MBeans
+ * contained in a namespace, you can use one of these methods:
+ *
+ *
+ * -
+ * You can use the {@link javax.management.namespace.JMXNamespaceView}
+ * class shown above,
+ *
+ * -
+ * or you can directly look for MBeans
+ * whose names match
+ * {@code "foo//*:*"},
+ *
+ * -
+ * or you can narrow down to the namespace
+ * and obtain an MBeanServer
+ * proxy that corresponds to an MBeanServer view of that namespace.
+ * The JMXNamespaces class provides a static method that
+ * allows you to narrow down to a name space, by calling
+ * {@link javax.management.namespace.JMXNamespaces#narrowToNamespace(MBeanServer,String)
+ * JMXNamespaces.narrowToNamespace}.
+ *
+ *
+ *
+ * Using Name Space Prefixes
+ *
+ * As we have explained above, MBeans contained in name
+ * spaces are not returned by {@code server.queryNames(null,null)} - or
+ * server.queryNames({@link javax.management.ObjectName#WILDCARD ObjectName.WILDCARD},null)
.
+ *
+ * However, these MBeans can still be accessed from the top level
+ * {@code MBeanServer} interface, without using any API specific to the
+ * version 2.0 of the JMX API, simply by using object names with
+ * name space prefixes:
+ *
To list MBeans contained in a namespace {@code "foo"} you can
+ * query for MBeans whose names match {@code "foo//*:*"}, as shown
+ * earlier in this document:
+ *
+ * server.queryNames(new ObjectName("foo//*:*", null);
+ * // or equivalently:
+ * server.queryNames(JMXNamespaces.getWildcardFor("foo"), null);
+ *
+ * This will return a list of MBean names whose domain name starts
+ * with {@code foo//}.
+ *
+ * Using these names, you can invoke any operation on the corresponding
+ * MBeans. For instance, to get the {@link javax.management.MBeanInfo
+ * MBeanInfo} of an MBean
+ * contained in name space {@code "foo"} (assuming
+ * the name of the MBean within its name space is domain:type=Thing,
+ * then simply call:
+ *
+ * server.getMBeanInfo(new ObjectName("foo//domain:type=Thing"));
+ *
+ * An easier way to access MBeans contained in a name space is to
+ * cd inside the name space, as shown in the following paragraph.
+ *
+ *
+ * Narrowing Down Into a Name Spaces
+ *
+ * As we have seen, name spaces are like MBean servers within MBean servers.
+ * Therefore, it is possible to view a name space just as if it were
+ * an other MBean server. This is similar to opening a sub
+ * folder from a parent folder.
+ * This operation is illustrated in the code extract below:
+ *
+ * final MBeanServer foo =
+ * JMXNamespaces.narrowToNamespace(platform, "foo");
+ * final MBeanInfo info =
+ * foo.getMBeanInfo(new ObjectName("domain:type=Thing"));
+ *
+ * The {@code MBeanServer} returned by {@link
+ * javax.management.namespace.JMXNamespaces#narrowToNamespace(MBeanServer,String)
+ * JMXNamespaces.narrowToNamespace} is an {@code MBeanServer} view that
+ * narrows down into a given namespace. The MBeans contained inside that
+ * namespace can now be accessed by their regular local name.
+ * The MBean server obtained by narrowing down
+ * to name space {@code "foo"} behaves just like a regular MBean server.
+ * However, it may sometimes throw an {@link
+ * java.lang.UnsupportedOperationException UnsupportedOperationException}
+ * wrapped in a JMX exception if you try to call an operation which is not
+ * supported by the underlying name space handler.
+ *
For instance, {@link javax.management.MBeanServer#registerMBean
+ * registerMBean} is not supported for name spaces mounted from remote
+ * MBean servers.
+ *
+ *
+ * Note: If you have a deep hierarchy of namespaces, and if you
+ * are switching from one namespace to another in the course of your
+ * application, it might be more convenient to use a
+ * {@link javax.management.namespace.JMXNamespaceView}
+ * in order to navigate in your namespaces.
+ *
+ *
+ * Different Types of Name Spaces
+ *
+ * This API lets you create several types of name spaces:
+ *
+ * -
+ * You can use the {@link
+ * javax.management.namespace.JMXRemoteNamespace
+ * JMXRemoteNamespace} to create
+ * remote name spaces, mounted from
+ * a remote sub {@code MBeanServer} source, as shown
+ * earlier in this document.
+ *
+ * -
+ * You can also use {@link
+ * javax.management.namespace.JMXNamespace
+ * JMXNamespace} to create
+ * local name spaces,
+ * by providing a direct reference to another {@code MBeanServer}
+ * instance living in the same JVM.
+ *
+ * -
+ * Finally, you can create
+ * name spaces containing virtual MBeans,
+ * by subclassing the {@link
+ * javax.management.namespace.MBeanServerSupport
+ * MBeanServerSupport}, and passing an instance of
+ * your own subclass to a {@link
+ * javax.management.namespace.JMXNamespace JMXNamespace}.
+ *
+ * -
+ * If none of these classes suit your needs, you can also provide
+ * your own subclass of {@link
+ * javax.management.namespace.JMXNamespace
+ * JMXNamespace}. This is however discouraged.
+ *
+ *
+ *
+ *
+ * Name Spaces And Special Operations
+ *
+ * MBean Naming considerations aside, Name Spaces are transparent for
+ * most {@code MBeanServer} operations. There are however a few
+ * exceptions:
+ *
+ *
+ * -
+ *
MBeanServer only operations - these are the operations which are
+ * supported by {@link javax.management.MBeanServer MBeanServer} but
+ * are not present in {@link
+ * javax.management.MBeanServerConnection
+ * MBeanServerConnection}. Since a name space can be a local view of
+ * a remote {@code MBeanServer}, accessible only through an
+ * {@code MBeanServerConnection}, these
+ * kinds of operations are not always supported.
+ *
+ * -
+ *
registerMBean:
+ * The {@link javax.management.MBeanServer#registerMBean
+ * registerMBean}
+ * operation is not supported by most name spaces. A call
+ * to
+ *
+ * MBeanServer server = ....;
+ * ThingMBean mbean = new Thing(...);
+ * ObjectName name = new ObjectName("foo//domain:type=Thing");
+ * server.registerMBean(mbean, name);
+ *
+ * will usually fail, unless the name space
+ * {@code "foo"} is a local name
+ * space. In the case where you attempt to cross
+ * multiple name spaces, then all name spaces in the
+ * path must support the {@code registerMBean} operation
+ * in order for it to succeed.
+ * To create an MBean inside a name space, it is
+ * usually safer to use {@code createMBean} -
+ * although some special
+ * considerations can also apply.
+ *
+ *
+ *
+ * -
+ *
getClassLoader:
+ * Similarly to registerMBean,
+ * and for the same reasons, {@link
+ * javax.management.MBeanServer#getClassLoader
+ * getClassLoader} will usually fail, unless the
+ * class loader is an MBean registered in a
+ * local name space.
+ *
+ *
+ * -
+ *
getClassLoaderFor:
+ * The implementation of {@link
+ * javax.management.MBeanServer#getClassLoaderFor
+ * getClassLoaderFor} also depends on which
+ * type of name space
+ * handler is used across the namespace path.
+ *
+ *
+ * A local name space will usually
+ * be able to implement this method just as a real
+ * {@code MBeanServer} would. A
+ * remote name space will usually
+ * return the default class loader configured on the
+ * internal {@link javax.management.remote.JMXConnector
+ * JMXConnector} used to connect to the remote server.
+ * When a {@link
+ * javax.management.namespace.JMXRemoteNamespace
+ * JMXRemoteNamespace} is used to connect to a
+ * remote server that contains MBeans which export
+ * custom types, the {@link
+ * javax.management.namespace.JMXRemoteNamespace
+ * JMXRemoteNamespace} must thus be configured with
+ * an options map such that the underlying connector
+ * can obtain a default class loader able
+ * to handle those types.
+ *
+ *
+ * Other types of name spaces
+ * may implement this method
+ * as best as they can.
+ *
+ *
+ *
+ *
+ * -
+ *
MBean creation
+ * MBean creation through {@link
+ * javax.management.MBeanServerConnection#createMBean
+ * createMBean} might not be supported by all
+ * name spaces: local name spaces and
+ * remote name spaces will usually
+ * support it, but virtual name
+ * spaces and custom name
+ * spaces might not.
+ *
+ *
+ * In that case, they will throw an {@link
+ * java.lang.UnsupportedOperationException
+ * UnsupportedOperationException} usually wrapped into an {@link
+ * javax.management.MBeanRegistrationException}.
+ *
+ *
+ * -
+ *
Notifications
+ * Some namespaces might not support JMX Notifications. In that
+ * case, a call to add or remove notification listener for an
+ * MBean contained in that name space will raise a
+ * {@link javax.management.RuntimeOperationsException
+ * RuntimeOperationsException} wrapping an {@link
+ * java.lang.UnsupportedOperationException
+ * UnsupportedOperationException} exception.
+ *
+ *
+ *
+ *
+ * Crossing Several Name Spaces
+ *
+ * Just as folders can contain other folders, name spaces can contain
+ * other name spaces. For instance, if an {@code MBeanServer} S1
+ * containing a name space {@code "bar"} is mounted in another
+ * {@code MBeanServer} S2 with name space {@code "foo"}, then
+ * an MBean M1 named {@code "domain:type=Thing"} in namespace
+ * {@code "bar"} will appear as {@code "foo//bar//domain:type=Thing"} in
+ * {@code MBeanServer} S2.
+ *
+ *
+ * When accessing the MBean M1 from server S2, the
+ * method call will traverse in a cascade {@code MBeanServer} S2,
+ * then the name space handler for name space {@code "foo"}, then
+ * {@code MBeanServer} S1, before coming to the name space
+ * handler for name space {@code "bar"}. Any operation invoked
+ * on the MBean from a "top-level" name space will therefore need to
+ * traverse all the name spaces along the name space path until
+ * it eventually reaches the named MBean. This means that an operation
+ * like registerMBean for instance,
+ * can only succeed if all the name spaces along the path support it.
+ *
+ *
+ * Narrowing to a nested name space works just the same as narrowing
+ * to a top level name space:
+ *
+ * final MBeanServer S2 = .... ;
+ * final MBeanServer bar =
+ * JMXNamespaces.narrowToNamespace(S2, "foo//bar");
+ * final MBeanInfo info =
+ * foo.getMBeanInfo(new ObjectName("domain:type=Thing"));
+ *
+ *
+ *
+ * Name Spaces And Operation Results
+ *
+ * Operation results, as well as attribute values returned by an MBean
+ * contained in a name space must be interpreted in the context of that
+ * name space.
+ * In other words, if an MBean in name space "foo" has an attribute of
+ * type {@code ObjectName}, then it must be assumed that the
+ * {@code ObjectName} returned by that MBean is relative to
+ * name space "foo".
+ * The same rule aplies for MBean names that can be returned by
+ * operations invoked on such an MBean. If one of the MBean operations
+ * return, say, a {@code Set} then those MBean names must
+ * also be assumed to be relative to name space "foo".
+ *
+ *
+ * In the usual case, a JMX client will first
+ * narrow to a name space before invoking
+ * any operation on the MBeans it contains. In that case the names
+ * returned by the MBean invoked can be directly fed back to the
+ * narrowed connection.
+ *
+ * If however, the JMX client directly invoked the MBean from a higher
+ * name space, without having narrowed to that name space first, then
+ * the names that might be returned by that MBean will not be directly
+ * usable - the JMX client will need to either
+ * narrow to the name space before using the
+ * returned names, or convert the names to the higher level name space
+ * context.
+ *
+ * The {@link javax.management.namespace.JMXNamespaces JMXNamespaces}
+ * class provides methods that can be used to perform that conversion.
+ *
+ *
+ * Name Spaces And Notifications
+ *
+ * As already explained, name spaces are very
+ * similar to {@code MBeanServer}s. It is thus possible to get
+ * {@link javax.management.MBeanServerNotification MBeanServerNotifications}
+ * when MBeans are added or removed within a name space, by registering
+ * with the {@link javax.management.MBeanServerDelegate
+ * MBeanServerDelegate} MBean of the corresponding name space.
+ * However, it must be noted that the notifications emitted by a
+ * name space must be interpreted in the context of that name space.
+ * For instance, if an MBean {@code "domain:type=Thing"} contained in
+ * namespace "foo//bar" emits a notification, the source of the
+ * notification will be {@code "domain:type=Thing"}, not
+ * {@code "foo//bar//domain:type=Thing"}.
+ * It is therefore recommended to keep track of the name space
+ * information when registering a listener with an MBean contained in
+ * a name space, especially if the same listener is used to receive
+ * notifications from different name spaces. An easy solution is to
+ * use the handback, as illustrated in the code below.
+ *
+ * final MBeanServer server = ...;
+ * final NotificationListener listener = new NotificationListener() {
+ * public void handleNotification(Notification n, Object handback) {
+ * if (!(n instanceof MBeanServerNotification)) {
+ * System.err.println("Error: expected MBeanServerNotification");
+ * return;
+ * }
+ * final MBeanServerNotification mbsn =
+ * (MBeanServerNotification) n;
+ *
+ * // We will pass the namespace path in the handback.
+ * //
+ * // The received notification must be interpreted in
+ * // the context of its source - therefore
+ * // mbsn.getMBeanName() does not include the name space
+ * // path...
+ * //
+ * final String namespace = (String) handback;
+ * System.out.println("Received " + mbsn.getType() +
+ * " for MBean " + mbsn.getMBeanName() +
+ * " from name space " + namespace);
+ * }
+ * };
+ * server.addNotificationListener(JMXNamespaces.insertPath("foo//bar",
+ * MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//bar");
+ * server.addNotificationListener(JMXNamespaces.insertPath("foo//joe",
+ * MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//joe");
+ *
+ *
+ *
+ * JMX Connectors may require some configuration in order to be able
+ * to forward notifications from MBeans located in name spaces.
+ * The RMI JMX Connector Server
+ * in the Java SE 7 platform is configured by default to internally
+ * use the new {@linkplain javax.management.event event service} on
+ * the server side.
+ * When the connector server is configured in this way, JMX clients
+ * which use the old JMX Notifications mechanism (such as clients
+ * running on prior versions of the JDK) will be able to
+ * to receive notifications from MBeans located in sub name spaces.
+ * This is because the connector server will transparently delegate
+ * their subscriptions to the underlying {@linkplain
+ * javax.management.event event service}. In summary:
+ *
+ * -
+ * On the server side: When exporting an {@code MBeanServer}
+ * through a JMX Connector, you will need to make sure that the
+ * connector server uses the new {@linkplain javax.management.event
+ * event service} in order to register for notifications. If the
+ * connector server doesn't use the event service, only clients
+ * which explicitly use the new {@linkplain javax.management.event
+ * event service} will be able to register for notifications
+ * with MBeans located in sub name spaces.
+ *
+ * -
+ * On the client side: if the JMX Connector server (on the remote
+ * server side) was configured to internally use the new
+ * {@linkplain javax.management.event
+ * event service}, then clients can continue to use the old
+ * {@code MBeanServerConnection} add / remove notification
+ * listener methods transparently. Otherwise, only clients which
+ * explicitly use the new {@linkplain javax.management.event
+ * event service} will be able to receive notifications from
+ * MBeans contained in sub name spaces.
+ *
+ *
+ *
+ *
+ * These configuration issues apply at each node in the name space path,
+ * whenever the name space points to a remote server. The
+ * {@link javax.management.namespace.JMXRemoteNamespace
+ * JMXRemoteNamespace} can be configured in such a way that it will
+ * explicitly use an {@link javax.management.event.EventClient EventClient}
+ * when forwarding subscription to the remote side. Note that this can be
+ * unnecessary (and a waste of resources) if the underlying JMXConnector
+ * returned by the JMXConnectorFactory (client side) already uses the
+ * {@linkplain javax.management.event event service} to register for
+ * notifications with the server side.
+ *
+ *
+ * Name Spaces And Access Control
+ *
+ * Access to MBeans exposed through JMX namespaces is controlled by
+ * {@linkplain javax.management.namespace.JMXNamespacePermission
+ * jmx namespace permissions}. These permissions are checked by the
+ * MBeanServer in which the {@link
+ * javax.management.namespace.JMXNamespace JMXNamespace} MBean is registered.
+ * This is described in
+ * details in the {@link
+ * javax.management.namespace.JMXNamespace JMXNamespace} class.
+ *
+ *
+ * To implement a "firewall-like" access control in a JMX agent you
+ * can also place an {@link
+ * javax.management.remote.MBeanServerForwarder} in the JMX Connector
+ * Server which exposes the top-level MBeanServer of your application.
+ * This {@code MBeanServerForwarder} will be able to perform
+ * authorization checks for all MBeans, including those located in
+ * sub name spaces.
+ *
+ *
+ * For a tighter access control we recommend using a {@link
+ * java.lang.SecurityManager security manager}.
+ *
+ * @since 1.7
+ *
+ **/
+
+package javax.management.namespace;
+
diff --git a/src/share/classes/javax/management/openmbean/CompositeType.java b/src/share/classes/javax/management/openmbean/CompositeType.java
index b513b0faa9af1aaae461d123ab53c81d9b122388..b4c662ec9bce8a7f0e91a112c990fa6f3dc666fb 100644
--- a/src/share/classes/javax/management/openmbean/CompositeType.java
+++ b/src/share/classes/javax/management/openmbean/CompositeType.java
@@ -89,7 +89,7 @@ public class CompositeType extends OpenType {
*
* @param itemNames The names of the items contained in the
* composite data values described by this CompositeType
instance;
- * cannot be null and should contain at least one element; no element can be a null or empty string.
+ * cannot be null; no element can be null or an empty string.
* Note that the order in which the item names are given is not important to differentiate a
* CompositeType
instance from another;
* the item names are internally stored sorted in ascending alphanumeric order.
@@ -97,7 +97,7 @@ public class CompositeType extends OpenType {
* @param itemDescriptions The descriptions, in the same order as itemNames, of the items contained in the
* composite data values described by this CompositeType
instance;
* should be of the same size as itemNames;
- * no element can be a null or empty string.
+ * no element can be null or an empty string.
*
* @param itemTypes The open type instances, in the same order as itemNames, describing the items contained
* in the composite data values described by this CompositeType
instance;
@@ -125,7 +125,7 @@ public class CompositeType extends OpenType {
//
super(CompositeData.class.getName(), typeName, description, false);
- // Check the 3 arrays are not null or empty (ie length==0) and that there is no null element or empty string in them
+ // Check the 3 arrays are not null and that there is no null element or empty string in them
//
checkForNullElement(itemNames, "itemNames");
checkForNullElement(itemDescriptions, "itemDescriptions");
diff --git a/src/share/classes/javax/management/remote/JMXConnectorFactory.java b/src/share/classes/javax/management/remote/JMXConnectorFactory.java
index 23003f007c596acd6bec82154846f7bb4ce30c23..219865b603c9dc1e07d5b8fb5aaaceb841c65b11 100644
--- a/src/share/classes/javax/management/remote/JMXConnectorFactory.java
+++ b/src/share/classes/javax/management/remote/JMXConnectorFactory.java
@@ -268,6 +268,14 @@ public class JMXConnectorFactory {
return conn;
}
+ private static Map newHashMap() {
+ return new HashMap();
+ }
+
+ private static Map newHashMap(Map map) {
+ return new HashMap(map);
+ }
+
/**
* Creates a connector client for the connector server at the
* given address. The resultant client is not connected until its
@@ -300,16 +308,18 @@ public class JMXConnectorFactory {
public static JMXConnector newJMXConnector(JMXServiceURL serviceURL,
Map environment)
throws IOException {
- Map envcopy;
+
+ final Map envcopy;
if (environment == null)
- envcopy = new HashMap();
+ envcopy = newHashMap();
else {
EnvHelp.checkAttributes(environment);
- envcopy = new HashMap(environment);
+ envcopy = newHashMap(environment);
}
final ClassLoader loader = resolveClassLoader(envcopy);
- final Class targetInterface = JMXConnectorProvider.class;
+ final Class targetInterface =
+ JMXConnectorProvider.class;
final String protocol = serviceURL.getProtocol();
final String providerClassName = "ClientProvider";
@@ -351,9 +361,10 @@ public class JMXConnectorFactory {
}
}
- envcopy = Collections.unmodifiableMap(envcopy);
+ final Map fixedenv =
+ Collections.unmodifiableMap(envcopy);
- return provider.newJMXConnector(serviceURL, envcopy);
+ return provider.newJMXConnector(serviceURL, fixedenv);
}
private static String resolvePkgs(Map env) throws JMXProviderException {
@@ -365,8 +376,8 @@ public class JMXConnectorFactory {
if (pkgsObject == null)
pkgsObject =
- AccessController.doPrivileged(new PrivilegedAction